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