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:
ExceptionSearchFilter(const lldb::TargetSP & target_sp,lldb::LanguageType language,bool update_module_list=true)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
~ExceptionSearchFilter()37 ~ExceptionSearchFilter() {};
38
39 bool
ModulePasses(const lldb::ModuleSP & module_sp)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
ModulePasses(const FileSpec & spec)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
Search(Searcher & searcher)59 Search (Searcher &searcher) override
60 {
61 UpdateModuleListIfNeeded ();
62 if (m_filter_sp)
63 m_filter_sp->Search (searcher);
64 }
65
66 void
GetDescription(Stream * s)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
DoCopyForBreakpoint(Breakpoint & breakpoint)80 DoCopyForBreakpoint(Breakpoint &breakpoint) override
81 {
82 return SearchFilterSP(new ExceptionSearchFilter(TargetSP(), m_language, false));
83 }
84
85 void
UpdateModuleListIfNeeded()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:
ExceptionBreakpointResolver(lldb::LanguageType language,bool catch_bp,bool throw_bp)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
~ExceptionBreakpointResolver()137 ~ExceptionBreakpointResolver()
138 {
139 }
140
141 Searcher::CallbackReturn
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr,bool containing)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
GetDepth()155 GetDepth () override
156 {
157 if (SetActualResolver())
158 return m_actual_resolver_sp->GetDepth();
159 else
160 return eDepthTarget;
161 }
162
163 void
GetDescription(Stream * s)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
Dump(Stream * s) const181 Dump (Stream *s) const override
182 {
183 }
184
185 /// Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const BreakpointResolverName *)186 static inline bool classof(const BreakpointResolverName *) { return true; }
classof(const BreakpointResolver * V)187 static inline bool classof(const BreakpointResolver *V) {
188 return V->getResolverID() == BreakpointResolver::ExceptionResolver;
189 }
190 protected:
191 BreakpointResolverSP
CopyForBreakpoint(Breakpoint & breakpoint)192 CopyForBreakpoint (Breakpoint &breakpoint) override
193 {
194 return BreakpointResolverSP(new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
195 }
196
197 bool
SetActualResolver()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*
FindPlugin(Process * process,lldb::LanguageType language)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 //----------------------------------------------------------------------
LanguageRuntime(Process * process)270 LanguageRuntime::LanguageRuntime(Process *process) :
271 m_process (process)
272 {
273 }
274
275 //----------------------------------------------------------------------
276 // Destructor
277 //----------------------------------------------------------------------
~LanguageRuntime()278 LanguageRuntime::~LanguageRuntime()
279 {
280 }
281
282 Breakpoint::BreakpointPreconditionSP
CreateExceptionPrecondition(lldb::LanguageType language,bool catch_bp,bool throw_bp)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
CreateExceptionBreakpoint(Target & target,lldb::LanguageType language,bool catch_bp,bool throw_bp,bool is_internal)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
GetLanguageTypeFromString(const char * string)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 *
GetNameForLanguageType(LanguageType language)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
PrintAllLanguages(Stream & s,const char * prefix,const char * suffix)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
LanguageIsCPlusPlus(LanguageType language)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
InitializeCommands(CommandObject * parent)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
CreateExceptionSearchFilter()451 LanguageRuntime::CreateExceptionSearchFilter ()
452 {
453 return m_process->GetTarget().GetSearchFilterForModule(NULL);
454 }
455
456
457
458