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