1 //===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <stdio.h>
11 #if HAVE_SYS_TYPES_H
12 #  include <sys/types.h>
13 #endif
14 
15 #include <cstdlib>
16 #include <string>
17 #include <map>
18 
19 #include "ClangUserExpression.h"
20 
21 #include "ASTResultSynthesizer.h"
22 #include "ClangExpressionDeclMap.h"
23 #include "ClangExpressionParser.h"
24 #include "ClangModulesDeclVendor.h"
25 #include "ClangPersistentVariables.h"
26 
27 #include "lldb/Core/ConstString.h"
28 #include "lldb/Core/Log.h"
29 #include "lldb/Core/Module.h"
30 #include "lldb/Core/StreamFile.h"
31 #include "lldb/Core/StreamString.h"
32 #include "lldb/Core/ValueObjectConstResult.h"
33 #include "lldb/Expression/ExpressionSourceCode.h"
34 #include "lldb/Expression/IRExecutionUnit.h"
35 #include "lldb/Expression/IRInterpreter.h"
36 #include "lldb/Expression/Materializer.h"
37 #include "lldb/Host/HostInfo.h"
38 #include "lldb/Symbol/Block.h"
39 #include "lldb/Symbol/ClangASTContext.h"
40 #include "lldb/Symbol/Function.h"
41 #include "lldb/Symbol/ObjectFile.h"
42 #include "lldb/Symbol/SymbolVendor.h"
43 #include "lldb/Symbol/Type.h"
44 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
45 #include "lldb/Symbol/VariableList.h"
46 #include "lldb/Target/ExecutionContext.h"
47 #include "lldb/Target/Process.h"
48 #include "lldb/Target/StackFrame.h"
49 #include "lldb/Target/Target.h"
50 #include "lldb/Target/ThreadPlan.h"
51 #include "lldb/Target/ThreadPlanCallUserExpression.h"
52 
53 #include "clang/AST/DeclCXX.h"
54 #include "clang/AST/DeclObjC.h"
55 
56 using namespace lldb_private;
57 
58 ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
59                                           const char *expr,
60                                           const char *expr_prefix,
61                                           lldb::LanguageType language,
62                                           ResultType desired_type,
63                                           const EvaluateExpressionOptions &options) :
64     LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options),
65     m_type_system_helper(*m_target_wp.lock().get())
66 {
67     switch (m_language)
68     {
69     case lldb::eLanguageTypeC_plus_plus:
70         m_allow_cxx = true;
71         break;
72     case lldb::eLanguageTypeObjC:
73         m_allow_objc = true;
74         break;
75     case lldb::eLanguageTypeObjC_plus_plus:
76     default:
77         m_allow_cxx = true;
78         m_allow_objc = true;
79         break;
80     }
81 }
82 
83 ClangUserExpression::~ClangUserExpression ()
84 {
85 }
86 
87 void
88 ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
89 {
90     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
91 
92     if (log)
93         log->Printf("ClangUserExpression::ScanContext()");
94 
95     m_target = exe_ctx.GetTargetPtr();
96 
97     if (!(m_allow_cxx || m_allow_objc))
98     {
99         if (log)
100             log->Printf("  [CUE::SC] Settings inhibit C++ and Objective-C");
101         return;
102     }
103 
104     StackFrame *frame = exe_ctx.GetFramePtr();
105     if (frame == NULL)
106     {
107         if (log)
108             log->Printf("  [CUE::SC] Null stack frame");
109         return;
110     }
111 
112     SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
113 
114     if (!sym_ctx.function)
115     {
116         if (log)
117             log->Printf("  [CUE::SC] Null function");
118         return;
119     }
120 
121     // Find the block that defines the function represented by "sym_ctx"
122     Block *function_block = sym_ctx.GetFunctionBlock();
123 
124     if (!function_block)
125     {
126         if (log)
127             log->Printf("  [CUE::SC] Null function block");
128         return;
129     }
130 
131     CompilerDeclContext decl_context = function_block->GetDeclContext();
132 
133     if (!decl_context)
134     {
135         if (log)
136             log->Printf("  [CUE::SC] Null decl context");
137         return;
138     }
139 
140     if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context))
141     {
142         if (m_allow_cxx && method_decl->isInstance())
143         {
144             if (m_enforce_valid_object)
145             {
146                 lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
147 
148                 const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
149 
150                 if (!variable_list_sp)
151                 {
152                     err.SetErrorString(thisErrorString);
153                     return;
154                 }
155 
156                 lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
157 
158                 if (!this_var_sp ||
159                     !this_var_sp->IsInScope(frame) ||
160                     !this_var_sp->LocationIsValidForFrame (frame))
161                 {
162                     err.SetErrorString(thisErrorString);
163                     return;
164                 }
165             }
166 
167             m_in_cplusplus_method = true;
168             m_needs_object_ptr = true;
169         }
170     }
171     else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context))
172     {
173         if (m_allow_objc)
174         {
175             if (m_enforce_valid_object)
176             {
177                 lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
178 
179                 const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
180 
181                 if (!variable_list_sp)
182                 {
183                     err.SetErrorString(selfErrorString);
184                     return;
185                 }
186 
187                 lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
188 
189                 if (!self_variable_sp ||
190                     !self_variable_sp->IsInScope(frame) ||
191                     !self_variable_sp->LocationIsValidForFrame (frame))
192                 {
193                     err.SetErrorString(selfErrorString);
194                     return;
195                 }
196             }
197 
198             m_in_objectivec_method = true;
199             m_needs_object_ptr = true;
200 
201             if (!method_decl->isInstanceMethod())
202                 m_in_static_method = true;
203         }
204     }
205     else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context))
206     {
207         // We might also have a function that said in the debug information that it captured an
208         // object pointer.  The best way to deal with getting to the ivars at present is by pretending
209         // that this is a method of a class in whatever runtime the debug info says the object pointer
210         // belongs to.  Do that here.
211 
212         ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl);
213         if (metadata && metadata->HasObjectPtr())
214         {
215             lldb::LanguageType language = metadata->GetObjectPtrLanguage();
216             if (language == lldb::eLanguageTypeC_plus_plus)
217             {
218                 if (m_enforce_valid_object)
219                 {
220                     lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
221 
222                     const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
223 
224                     if (!variable_list_sp)
225                     {
226                         err.SetErrorString(thisErrorString);
227                         return;
228                     }
229 
230                     lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
231 
232                     if (!this_var_sp ||
233                         !this_var_sp->IsInScope(frame) ||
234                         !this_var_sp->LocationIsValidForFrame (frame))
235                     {
236                         err.SetErrorString(thisErrorString);
237                         return;
238                     }
239                 }
240 
241                 m_in_cplusplus_method = true;
242                 m_needs_object_ptr = true;
243             }
244             else if (language == lldb::eLanguageTypeObjC)
245             {
246                 if (m_enforce_valid_object)
247                 {
248                     lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
249 
250                     const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
251 
252                     if (!variable_list_sp)
253                     {
254                         err.SetErrorString(selfErrorString);
255                         return;
256                     }
257 
258                     lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
259 
260                     if (!self_variable_sp ||
261                         !self_variable_sp->IsInScope(frame) ||
262                         !self_variable_sp->LocationIsValidForFrame (frame))
263                     {
264                         err.SetErrorString(selfErrorString);
265                         return;
266                     }
267 
268                     Type *self_type = self_variable_sp->GetType();
269 
270                     if (!self_type)
271                     {
272                         err.SetErrorString(selfErrorString);
273                         return;
274                     }
275 
276                     CompilerType self_clang_type = self_type->GetForwardCompilerType ();
277 
278                     if (!self_clang_type)
279                     {
280                         err.SetErrorString(selfErrorString);
281                         return;
282                     }
283 
284                     if (ClangASTContext::IsObjCClassType(self_clang_type))
285                     {
286                         return;
287                     }
288                     else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type))
289                     {
290                         m_in_objectivec_method = true;
291                         m_needs_object_ptr = true;
292                     }
293                     else
294                     {
295                         err.SetErrorString(selfErrorString);
296                         return;
297                     }
298                 }
299                 else
300                 {
301                     m_in_objectivec_method = true;
302                     m_needs_object_ptr = true;
303                 }
304             }
305         }
306     }
307 }
308 
309 // This is a really nasty hack, meant to fix Objective-C expressions of the form
310 // (int)[myArray count].  Right now, because the type information for count is
311 // not available, [myArray count] returns id, which can't be directly cast to
312 // int without causing a clang error.
313 static void
314 ApplyObjcCastHack(std::string &expr)
315 {
316 #define OBJC_CAST_HACK_FROM "(int)["
317 #define OBJC_CAST_HACK_TO   "(int)(long long)["
318 
319     size_t from_offset;
320 
321     while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
322         expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
323 
324 #undef OBJC_CAST_HACK_TO
325 #undef OBJC_CAST_HACK_FROM
326 }
327 
328 bool
329 ClangUserExpression::Parse (Stream &error_stream,
330                             ExecutionContext &exe_ctx,
331                             lldb_private::ExecutionPolicy execution_policy,
332                             bool keep_result_in_memory,
333                             bool generate_debug_info)
334 {
335     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
336 
337     Error err;
338 
339     InstallContext(exe_ctx);
340 
341     if (Target *target = exe_ctx.GetTargetPtr())
342     {
343         if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
344         {
345             m_result_delegate.RegisterPersistentState(persistent_state);
346         }
347         else
348         {
349             error_stream.PutCString ("error: couldn't start parsing (no persistent data)");
350             return false;
351         }
352     }
353     else
354     {
355         error_stream.PutCString ("error: couldn't start parsing (no target)");
356         return false;
357     }
358 
359     ScanContext(exe_ctx, err);
360 
361     if (!err.Success())
362     {
363         error_stream.Printf("warning: %s\n", err.AsCString());
364     }
365 
366     StreamString m_transformed_stream;
367 
368     ////////////////////////////////////
369     // Generate the expression
370     //
371 
372     ApplyObjcCastHack(m_expr_text);
373     //ApplyUnicharHack(m_expr_text);
374 
375     std::string prefix = m_expr_prefix;
376 
377     if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
378     {
379         const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules();
380         ClangModulesDeclVendor::ModuleVector modules_for_macros;
381 
382         for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
383         {
384             modules_for_macros.push_back(module);
385         }
386 
387         if (m_target->GetEnableAutoImportClangModules())
388         {
389             if (StackFrame *frame = exe_ctx.GetFramePtr())
390             {
391                 if (Block *block = frame->GetFrameBlock())
392                 {
393                     SymbolContext sc;
394 
395                     block->CalculateSymbolContext(&sc);
396 
397                     if (sc.comp_unit)
398                     {
399                         StreamString error_stream;
400 
401                         decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
402                     }
403                 }
404             }
405         }
406     }
407 
408     std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
409 
410     lldb::LanguageType lang_type;
411 
412     if (m_in_cplusplus_method)
413         lang_type = lldb::eLanguageTypeC_plus_plus;
414     else if (m_in_objectivec_method)
415         lang_type = lldb::eLanguageTypeObjC;
416     else
417         lang_type = lldb::eLanguageTypeC;
418 
419     if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
420     {
421         error_stream.PutCString ("error: couldn't construct expression body");
422         return false;
423     }
424 
425     if (log)
426         log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
427 
428     ////////////////////////////////////
429     // Set up the target and compiler
430     //
431 
432     Target *target = exe_ctx.GetTargetPtr();
433 
434     if (!target)
435     {
436         error_stream.PutCString ("error: invalid target\n");
437         return false;
438     }
439 
440     //////////////////////////
441     // Parse the expression
442     //
443 
444     m_materializer_ap.reset(new Materializer());
445 
446     ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
447 
448     class OnExit
449     {
450     public:
451         typedef std::function <void (void)> Callback;
452 
453         OnExit (Callback const &callback) :
454             m_callback(callback)
455         {
456         }
457 
458         ~OnExit ()
459         {
460             m_callback();
461         }
462     private:
463         Callback m_callback;
464     };
465 
466     OnExit on_exit([this]() { ResetDeclMap(); });
467 
468     if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get()))
469     {
470         error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
471 
472         ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
473 
474         return false;
475     }
476 
477     Process *process = exe_ctx.GetProcessPtr();
478     ExecutionContextScope *exe_scope = process;
479 
480     if (!exe_scope)
481         exe_scope = exe_ctx.GetTargetPtr();
482 
483     ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
484 
485     unsigned num_errors = parser.Parse (error_stream);
486 
487     if (num_errors)
488     {
489         error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
490 
491         ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
492 
493         return false;
494     }
495 
496     //////////////////////////////////////////////////////////////////////////////////////////
497     // Prepare the output of the parser for execution, evaluating it statically if possible
498     //
499 
500     Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
501                                                   m_jit_end_addr,
502                                                   m_execution_unit_sp,
503                                                   exe_ctx,
504                                                   m_can_interpret,
505                                                   execution_policy);
506 
507     if (generate_debug_info)
508     {
509         lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
510 
511         if (jit_module_sp)
512         {
513             ConstString const_func_name(FunctionName());
514             FileSpec jit_file;
515             jit_file.GetFilename() = const_func_name;
516             jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
517             m_jit_module_wp = jit_module_sp;
518             target->GetImages().Append(jit_module_sp);
519         }
520 //        lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
521 //        StreamFile strm (stdout, false);
522 //        if (jit_obj_file)
523 //        {
524 //            jit_obj_file->GetSectionList();
525 //            jit_obj_file->GetSymtab();
526 //            jit_obj_file->Dump(&strm);
527 //        }
528 //        lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
529 //        if (jit_sym_vendor)
530 //        {
531 //            lldb_private::SymbolContextList sc_list;
532 //            jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
533 //            sc_list.Dump(&strm, target);
534 //            jit_sym_vendor->Dump(&strm);
535 //        }
536     }
537 
538     ResetDeclMap(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any ClangASTImporter::Minions.
539 
540     if (jit_error.Success())
541     {
542         if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
543             m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
544         return true;
545     }
546     else
547     {
548         const char *error_cstr = jit_error.AsCString();
549         if (error_cstr && error_cstr[0])
550             error_stream.Printf ("error: %s\n", error_cstr);
551         else
552             error_stream.Printf ("error: expression can't be interpreted or run\n");
553         return false;
554     }
555 }
556 
557 bool
558 ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
559                                    std::vector<lldb::addr_t> &args,
560                                    lldb::addr_t struct_address,
561                                    Stream &error_stream)
562 {
563     lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
564     lldb::addr_t cmd_ptr    = LLDB_INVALID_ADDRESS;
565 
566     if (m_needs_object_ptr)
567     {
568         lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
569         if (!frame_sp)
570             return true;
571 
572         ConstString object_name;
573 
574         if (m_in_cplusplus_method)
575         {
576             object_name.SetCString("this");
577         }
578         else if (m_in_objectivec_method)
579         {
580             object_name.SetCString("self");
581         }
582         else
583         {
584             error_stream.Printf("Need object pointer but don't know the language\n");
585             return false;
586         }
587 
588         Error object_ptr_error;
589 
590         object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
591 
592         if (!object_ptr_error.Success())
593         {
594             error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
595             object_ptr = 0;
596         }
597 
598         if (m_in_objectivec_method)
599         {
600             ConstString cmd_name("_cmd");
601 
602             cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
603 
604             if (!object_ptr_error.Success())
605             {
606                 error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
607                 cmd_ptr = 0;
608             }
609         }
610         if (object_ptr)
611             args.push_back(object_ptr);
612 
613         if (m_in_objectivec_method)
614             args.push_back(cmd_ptr);
615 
616         args.push_back(struct_address);
617     }
618     else
619     {
620         args.push_back(struct_address);
621     }
622     return true;
623 }
624 
625 lldb::ExpressionVariableSP
626 ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope)
627 {
628     return m_result_delegate.GetVariable();
629 }
630 
631 void
632 ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory)
633 {
634     m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx));
635 }
636 
637 clang::ASTConsumer *
638 ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough)
639 {
640     m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough,
641                                                            m_target));
642 
643     return m_result_synthesizer_up.get();
644 }
645 
646 ClangUserExpression::ResultDelegate::ResultDelegate()
647 {
648 }
649 
650 ConstString
651 ClangUserExpression::ResultDelegate::GetName()
652 {
653     return m_persistent_state->GetNextPersistentVariableName();
654 }
655 
656 void
657 ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable)
658 {
659     m_variable = variable;
660 }
661 
662 void
663 ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state)
664 {
665     m_persistent_state = persistent_state;
666 }
667 
668 lldb::ExpressionVariableSP &
669 ClangUserExpression::ResultDelegate::GetVariable()
670 {
671     return m_variable;
672 }
673 
674