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