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
14using namespace lldb;
15using namespace lldb_private;
16
17
18class ExceptionSearchFilter : public SearchFilter
19{
20public:
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
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
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
51    Search (Searcher &searcher)
52    {
53        UpdateModuleListIfNeeded ();
54        if (m_filter_sp)
55            m_filter_sp->Search (searcher);
56    }
57
58    virtual void
59    GetDescription (Stream *s)
60    {
61        UpdateModuleListIfNeeded ();
62        if (m_filter_sp)
63            m_filter_sp->GetDescription (s);
64    }
65
66protected:
67    LanguageType m_language;
68    LanguageRuntime *m_language_runtime;
69    SearchFilterSP m_filter_sp;
70
71    void
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.
108class ExceptionBreakpointResolver : public BreakpointResolver
109{
110public:
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
123    ~ExceptionBreakpointResolver()
124    {
125    }
126
127    virtual Searcher::CallbackReturn
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
141    GetDepth ()
142    {
143        if (SetActualResolver())
144            return m_actual_resolver_sp->GetDepth();
145        else
146            return eDepthTarget;
147    }
148
149    virtual void
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
167    Dump (Stream *s) const
168    {
169    }
170
171    /// Methods for support type inquiry through isa, cast, and dyn_cast:
172    static inline bool classof(const BreakpointResolverName *) { return true; }
173    static inline bool classof(const BreakpointResolver *V) {
174        return V->getResolverID() == BreakpointResolver::ExceptionResolver;
175    }
176protected:
177    bool
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
228LanguageRuntime*
229LanguageRuntime::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//----------------------------------------------------------------------
250LanguageRuntime::LanguageRuntime(Process *process) :
251    m_process (process)
252{
253}
254
255//----------------------------------------------------------------------
256// Destructor
257//----------------------------------------------------------------------
258LanguageRuntime::~LanguageRuntime()
259{
260}
261
262BreakpointSP
263LanguageRuntime::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
279struct language_name_pair {
280    const char *name;
281    LanguageType type;
282};
283
284struct 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
314static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
315
316LanguageType
317LanguageRuntime::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
327const char *
328LanguageRuntime::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
336lldb::SearchFilterSP
337LanguageRuntime::CreateExceptionSearchFilter ()
338{
339    return m_process->GetTarget().GetSearchFilterForModule(NULL);
340}
341
342
343
344