1 //===-- LanguageRuntime.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 "lldb/Target/LanguageRuntime.h"
11 #include "lldb/Target/ObjCLanguageRuntime.h"
12 #include "lldb/Target/Target.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Core/SearchFilter.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 
21 class ExceptionSearchFilter : public SearchFilter
22 {
23 public:
24     ExceptionSearchFilter (const lldb::TargetSP &target_sp,
25                            lldb::LanguageType language,
26                            bool update_module_list = true) :
27         SearchFilter (target_sp),
28         m_language (language),
29         m_language_runtime (NULL),
30         m_filter_sp ()
31     {
32         if (update_module_list)
33             UpdateModuleListIfNeeded ();
34     }
35 
36     virtual
37     ~ExceptionSearchFilter() {};
38 
39     bool
40     ModulePasses (const lldb::ModuleSP &module_sp) override
41     {
42         UpdateModuleListIfNeeded ();
43         if (m_filter_sp)
44             return m_filter_sp->ModulePasses (module_sp);
45         return false;
46     }
47 
48     bool
49     ModulePasses (const FileSpec &spec) override
50     {
51         UpdateModuleListIfNeeded ();
52         if (m_filter_sp)
53             return m_filter_sp->ModulePasses (spec);
54         return false;
55 
56     }
57 
58     void
59     Search (Searcher &searcher) override
60     {
61         UpdateModuleListIfNeeded ();
62         if (m_filter_sp)
63             m_filter_sp->Search (searcher);
64     }
65 
66     void
67     GetDescription (Stream *s) override
68     {
69         UpdateModuleListIfNeeded ();
70         if (m_filter_sp)
71             m_filter_sp->GetDescription (s);
72     }
73 
74 protected:
75     LanguageType m_language;
76     LanguageRuntime *m_language_runtime;
77     SearchFilterSP m_filter_sp;
78 
79     SearchFilterSP
80     DoCopyForBreakpoint(Breakpoint &breakpoint) override
81     {
82         return SearchFilterSP(new ExceptionSearchFilter(TargetSP(), m_language, false));
83     }
84 
85     void
86     UpdateModuleListIfNeeded ()
87     {
88         ProcessSP process_sp (m_target_sp->GetProcessSP());
89         if (process_sp)
90         {
91             bool refreash_filter = !m_filter_sp;
92             if (m_language_runtime == NULL)
93             {
94                 m_language_runtime = process_sp->GetLanguageRuntime(m_language);
95                 refreash_filter = true;
96             }
97             else
98             {
99                 LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(m_language);
100                 if (m_language_runtime != language_runtime)
101                 {
102                     m_language_runtime = language_runtime;
103                     refreash_filter = true;
104                 }
105             }
106 
107             if (refreash_filter && m_language_runtime)
108             {
109                 m_filter_sp = m_language_runtime->CreateExceptionSearchFilter ();
110             }
111         }
112         else
113         {
114             m_filter_sp.reset();
115             m_language_runtime = NULL;
116         }
117     }
118 };
119 
120 // The Target is the one that knows how to create breakpoints, so this function
121 // is meant to be used either by the target or internally in Set/ClearExceptionBreakpoints.
122 class ExceptionBreakpointResolver : public BreakpointResolver
123 {
124 public:
125     ExceptionBreakpointResolver (lldb::LanguageType language,
126                                  bool catch_bp,
127                                  bool throw_bp) :
128         BreakpointResolver (NULL, BreakpointResolver::ExceptionResolver),
129         m_language (language),
130         m_language_runtime (NULL),
131         m_catch_bp (catch_bp),
132         m_throw_bp (throw_bp)
133     {
134     }
135 
136     virtual
137     ~ExceptionBreakpointResolver()
138     {
139     }
140 
141     Searcher::CallbackReturn
142     SearchCallback (SearchFilter &filter,
143                     SymbolContext &context,
144                     Address *addr,
145                     bool containing) override
146     {
147 
148         if (SetActualResolver())
149             return m_actual_resolver_sp->SearchCallback (filter, context, addr, containing);
150         else
151             return eCallbackReturnStop;
152     }
153 
154     Searcher::Depth
155     GetDepth () override
156     {
157         if (SetActualResolver())
158             return m_actual_resolver_sp->GetDepth();
159         else
160             return eDepthTarget;
161     }
162 
163     void
164     GetDescription (Stream *s) override
165     {
166         s->Printf ("Exception breakpoint (catch: %s throw: %s)",
167                    m_catch_bp ? "on" : "off",
168                    m_throw_bp ? "on" : "off");
169 
170         SetActualResolver();
171         if (m_actual_resolver_sp)
172         {
173             s->Printf (" using: ");
174             m_actual_resolver_sp->GetDescription (s);
175         }
176         else
177             s->Printf (" the correct runtime exception handler will be determined when you run");
178     }
179 
180     void
181     Dump (Stream *s) const override
182     {
183     }
184 
185     /// Methods for support type inquiry through isa, cast, and dyn_cast:
186     static inline bool classof(const BreakpointResolverName *) { return true; }
187     static inline bool classof(const BreakpointResolver *V) {
188         return V->getResolverID() == BreakpointResolver::ExceptionResolver;
189     }
190 protected:
191     BreakpointResolverSP
192     CopyForBreakpoint (Breakpoint &breakpoint) override
193     {
194         return BreakpointResolverSP(new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
195     }
196 
197     bool
198     SetActualResolver()
199     {
200         ProcessSP process_sp;
201         if (m_breakpoint)
202         {
203             process_sp = m_breakpoint->GetTarget().GetProcessSP();
204             if (process_sp)
205             {
206                 bool refreash_resolver = !m_actual_resolver_sp;
207                 if (m_language_runtime == NULL)
208                 {
209                     m_language_runtime = process_sp->GetLanguageRuntime(m_language);
210                     refreash_resolver = true;
211                 }
212                 else
213                 {
214                     LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(m_language);
215                     if (m_language_runtime != language_runtime)
216                     {
217                         m_language_runtime = language_runtime;
218                         refreash_resolver = true;
219                     }
220                 }
221 
222                 if (refreash_resolver && m_language_runtime)
223                 {
224                     m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver (m_breakpoint, m_catch_bp, m_throw_bp);
225                 }
226             }
227             else
228             {
229                 m_actual_resolver_sp.reset();
230                 m_language_runtime = NULL;
231             }
232         }
233         else
234         {
235             m_actual_resolver_sp.reset();
236             m_language_runtime = NULL;
237         }
238         return (bool)m_actual_resolver_sp;
239     }
240     lldb::BreakpointResolverSP m_actual_resolver_sp;
241     lldb::LanguageType m_language;
242     LanguageRuntime *m_language_runtime;
243     bool m_catch_bp;
244     bool m_throw_bp;
245 };
246 
247 
248 LanguageRuntime*
249 LanguageRuntime::FindPlugin (Process *process, lldb::LanguageType language)
250 {
251     std::unique_ptr<LanguageRuntime> language_runtime_ap;
252     LanguageRuntimeCreateInstance create_callback;
253 
254     for (uint32_t idx = 0;
255          (create_callback = PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != NULL;
256          ++idx)
257     {
258         language_runtime_ap.reset (create_callback(process, language));
259 
260         if (language_runtime_ap.get())
261             return language_runtime_ap.release();
262     }
263 
264     return NULL;
265 }
266 
267 //----------------------------------------------------------------------
268 // Constructor
269 //----------------------------------------------------------------------
270 LanguageRuntime::LanguageRuntime(Process *process) :
271     m_process (process)
272 {
273 }
274 
275 //----------------------------------------------------------------------
276 // Destructor
277 //----------------------------------------------------------------------
278 LanguageRuntime::~LanguageRuntime()
279 {
280 }
281 
282 Breakpoint::BreakpointPreconditionSP
283 LanguageRuntime::CreateExceptionPrecondition (lldb::LanguageType language,
284                                               bool catch_bp,
285                                               bool throw_bp)
286 {
287     switch (language)
288     {
289     case eLanguageTypeObjC:
290         if (throw_bp)
291             return Breakpoint::BreakpointPreconditionSP(new ObjCLanguageRuntime::ObjCExceptionPrecondition ());
292         break;
293     default:
294         break;
295     }
296     return Breakpoint::BreakpointPreconditionSP();
297 }
298 
299 BreakpointSP
300 LanguageRuntime::CreateExceptionBreakpoint (Target &target,
301                                             lldb::LanguageType language,
302                                             bool catch_bp,
303                                             bool throw_bp,
304                                             bool is_internal)
305 {
306     BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
307     SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language));
308     bool hardware = false;
309     bool resolve_indirect_functions = false;
310     BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions));
311     if (exc_breakpt_sp)
312     {
313         Breakpoint::BreakpointPreconditionSP precondition_sp = CreateExceptionPrecondition(language, catch_bp, throw_bp);
314         if (precondition_sp)
315             exc_breakpt_sp->SetPrecondition(precondition_sp);
316 
317         if (is_internal)
318             exc_breakpt_sp->SetBreakpointKind("exception");
319     }
320 
321     return exc_breakpt_sp;
322 }
323 
324 struct language_name_pair {
325     const char *name;
326     LanguageType type;
327 };
328 
329 struct language_name_pair language_names[] =
330 {
331     // To allow GetNameForLanguageType to be a simple array lookup, the first
332     // part of this array must follow enum LanguageType exactly.
333     {   "unknown",          eLanguageTypeUnknown        },
334     {   "c89",              eLanguageTypeC89            },
335     {   "c",                eLanguageTypeC              },
336     {   "ada83",            eLanguageTypeAda83          },
337     {   "c++",              eLanguageTypeC_plus_plus    },
338     {   "cobol74",          eLanguageTypeCobol74        },
339     {   "cobol85",          eLanguageTypeCobol85        },
340     {   "fortran77",        eLanguageTypeFortran77      },
341     {   "fortran90",        eLanguageTypeFortran90      },
342     {   "pascal83",         eLanguageTypePascal83       },
343     {   "modula2",          eLanguageTypeModula2        },
344     {   "java",             eLanguageTypeJava           },
345     {   "c99",              eLanguageTypeC99            },
346     {   "ada95",            eLanguageTypeAda95          },
347     {   "fortran95",        eLanguageTypeFortran95      },
348     {   "pli",              eLanguageTypePLI            },
349     {   "objective-c",      eLanguageTypeObjC           },
350     {   "objective-c++",    eLanguageTypeObjC_plus_plus },
351     {   "upc",              eLanguageTypeUPC            },
352     {   "d",                eLanguageTypeD              },
353     {   "python",           eLanguageTypePython         },
354     {   "opencl",           eLanguageTypeOpenCL         },
355     {   "go",               eLanguageTypeGo             },
356     {   "modula3",          eLanguageTypeModula3        },
357     {   "haskell",          eLanguageTypeHaskell        },
358     {   "c++03",            eLanguageTypeC_plus_plus_03 },
359     {   "c++11",            eLanguageTypeC_plus_plus_11 },
360     {   "ocaml",            eLanguageTypeOCaml          },
361     {   "rust",             eLanguageTypeRust           },
362     {   "c11",              eLanguageTypeC11            },
363     {   "swift",            eLanguageTypeSwift          },
364     {   "julia",            eLanguageTypeJulia          },
365     {   "dylan",            eLanguageTypeDylan          },
366     {   "c++14",            eLanguageTypeC_plus_plus_14 },
367     {   "fortran03",        eLanguageTypeFortran03      },
368     {   "fortran08",        eLanguageTypeFortran08      },
369     // Vendor Extensions
370     {   "mipsassem",        eLanguageTypeMipsAssembler  },
371     {   "renderscript",     eLanguageTypeExtRenderScript},
372     // Now synonyms, in arbitrary order
373     {   "objc",             eLanguageTypeObjC           },
374     {   "objc++",           eLanguageTypeObjC_plus_plus }
375 };
376 
377 static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
378 
379 LanguageType
380 LanguageRuntime::GetLanguageTypeFromString (const char *string)
381 {
382     for (uint32_t i = 0; i < num_languages; i++)
383     {
384         if (strcasecmp (language_names[i].name, string) == 0)
385             return (LanguageType) language_names[i].type;
386     }
387     return eLanguageTypeUnknown;
388 }
389 
390 const char *
391 LanguageRuntime::GetNameForLanguageType (LanguageType language)
392 {
393     if (language < num_languages)
394         return language_names[language].name;
395     else
396         return language_names[eLanguageTypeUnknown].name;
397 }
398 
399 void
400 LanguageRuntime::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
401 {
402     for (uint32_t i = 1; i < num_languages; i++)
403     {
404         s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
405     }
406 }
407 
408 bool
409 LanguageRuntime::LanguageIsCPlusPlus (LanguageType language)
410 {
411     switch (language)
412     {
413         case eLanguageTypeC_plus_plus:
414         case eLanguageTypeC_plus_plus_03:
415         case eLanguageTypeC_plus_plus_11:
416         case eLanguageTypeC_plus_plus_14:
417             return true;
418         default:
419             return false;
420     }
421 }
422 
423 void
424 LanguageRuntime::InitializeCommands (CommandObject* parent)
425 {
426     if (!parent)
427         return;
428 
429     if (!parent->IsMultiwordObject())
430         return;
431 
432     LanguageRuntimeCreateInstance create_callback;
433 
434     for (uint32_t idx = 0;
435          (create_callback = PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != nullptr;
436          ++idx)
437     {
438         if (LanguageRuntimeGetCommandObject command_callback =
439                 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx))
440         {
441             CommandObjectSP command = command_callback(parent->GetCommandInterpreter());
442             if (command)
443             {
444                 parent->LoadSubCommand(command->GetCommandName(), command);
445             }
446         }
447     }
448 }
449 
450 lldb::SearchFilterSP
451 LanguageRuntime::CreateExceptionSearchFilter ()
452 {
453     return m_process->GetTarget().GetSearchFilterForModule(NULL);
454 }
455 
456 
457 
458