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 void
325 LanguageRuntime::InitializeCommands (CommandObject* parent)
326 {
327     if (!parent)
328         return;
329 
330     if (!parent->IsMultiwordObject())
331         return;
332 
333     LanguageRuntimeCreateInstance create_callback;
334 
335     for (uint32_t idx = 0;
336          (create_callback = PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != nullptr;
337          ++idx)
338     {
339         if (LanguageRuntimeGetCommandObject command_callback =
340                 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx))
341         {
342             CommandObjectSP command = command_callback(parent->GetCommandInterpreter());
343             if (command)
344             {
345                 parent->LoadSubCommand(command->GetCommandName(), command);
346             }
347         }
348     }
349 }
350 
351 lldb::SearchFilterSP
352 LanguageRuntime::CreateExceptionSearchFilter ()
353 {
354     return m_process->GetTarget().GetSearchFilterForModule(NULL);
355 }
356