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