1254721Semaste//===-- LanguageRuntime.cpp -------------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Target/LanguageRuntime.h"
11254721Semaste#include "lldb/Target/Target.h"
12254721Semaste#include "lldb/Core/PluginManager.h"
13254721Semaste
14254721Semasteusing namespace lldb;
15254721Semasteusing namespace lldb_private;
16254721Semaste
17254721Semaste
18254721Semasteclass ExceptionSearchFilter : public SearchFilter
19254721Semaste{
20254721Semastepublic:
21254721Semaste    ExceptionSearchFilter (const lldb::TargetSP &target_sp,
22254721Semaste                           lldb::LanguageType language) :
23254721Semaste        SearchFilter (target_sp),
24254721Semaste        m_language (language),
25254721Semaste        m_language_runtime (NULL),
26254721Semaste        m_filter_sp ()
27254721Semaste    {
28254721Semaste        UpdateModuleListIfNeeded ();
29254721Semaste    }
30254721Semaste
31254721Semaste    virtual bool
32254721Semaste    ModulePasses (const lldb::ModuleSP &module_sp)
33254721Semaste    {
34254721Semaste        UpdateModuleListIfNeeded ();
35254721Semaste        if (m_filter_sp)
36254721Semaste            return m_filter_sp->ModulePasses (module_sp);
37254721Semaste        return false;
38254721Semaste    }
39254721Semaste
40254721Semaste    virtual bool
41254721Semaste    ModulePasses (const FileSpec &spec)
42254721Semaste    {
43254721Semaste        UpdateModuleListIfNeeded ();
44254721Semaste        if (m_filter_sp)
45254721Semaste            return m_filter_sp->ModulePasses (spec);
46254721Semaste        return false;
47254721Semaste
48254721Semaste    }
49254721Semaste
50254721Semaste    virtual void
51254721Semaste    Search (Searcher &searcher)
52254721Semaste    {
53254721Semaste        UpdateModuleListIfNeeded ();
54254721Semaste        if (m_filter_sp)
55254721Semaste            m_filter_sp->Search (searcher);
56254721Semaste    }
57254721Semaste
58254721Semaste    virtual void
59254721Semaste    GetDescription (Stream *s)
60254721Semaste    {
61254721Semaste        UpdateModuleListIfNeeded ();
62254721Semaste        if (m_filter_sp)
63254721Semaste            m_filter_sp->GetDescription (s);
64254721Semaste    }
65254721Semaste
66254721Semasteprotected:
67254721Semaste    LanguageType m_language;
68254721Semaste    LanguageRuntime *m_language_runtime;
69254721Semaste    SearchFilterSP m_filter_sp;
70254721Semaste
71254721Semaste    void
72254721Semaste    UpdateModuleListIfNeeded ()
73254721Semaste    {
74254721Semaste        ProcessSP process_sp (m_target_sp->GetProcessSP());
75254721Semaste        if (process_sp)
76254721Semaste        {
77254721Semaste            bool refreash_filter = !m_filter_sp;
78254721Semaste            if (m_language_runtime == NULL)
79254721Semaste            {
80254721Semaste                m_language_runtime = process_sp->GetLanguageRuntime(m_language);
81254721Semaste                refreash_filter = true;
82254721Semaste            }
83254721Semaste            else
84254721Semaste            {
85254721Semaste                LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(m_language);
86254721Semaste                if (m_language_runtime != language_runtime)
87254721Semaste                {
88254721Semaste                    m_language_runtime = language_runtime;
89254721Semaste                    refreash_filter = true;
90254721Semaste                }
91254721Semaste            }
92254721Semaste
93254721Semaste            if (refreash_filter && m_language_runtime)
94254721Semaste            {
95254721Semaste                m_filter_sp = m_language_runtime->CreateExceptionSearchFilter ();
96254721Semaste            }
97254721Semaste        }
98254721Semaste        else
99254721Semaste        {
100254721Semaste            m_filter_sp.reset();
101254721Semaste            m_language_runtime = NULL;
102254721Semaste        }
103254721Semaste    }
104254721Semaste};
105254721Semaste
106254721Semaste// The Target is the one that knows how to create breakpoints, so this function
107254721Semaste// is meant to be used either by the target or internally in Set/ClearExceptionBreakpoints.
108254721Semasteclass ExceptionBreakpointResolver : public BreakpointResolver
109254721Semaste{
110254721Semastepublic:
111254721Semaste    ExceptionBreakpointResolver (lldb::LanguageType language,
112254721Semaste                                 bool catch_bp,
113254721Semaste                                 bool throw_bp) :
114254721Semaste        BreakpointResolver (NULL, BreakpointResolver::ExceptionResolver),
115254721Semaste        m_language (language),
116254721Semaste        m_language_runtime (NULL),
117254721Semaste        m_catch_bp (catch_bp),
118254721Semaste        m_throw_bp (throw_bp)
119254721Semaste    {
120254721Semaste    }
121254721Semaste
122254721Semaste    virtual
123254721Semaste    ~ExceptionBreakpointResolver()
124254721Semaste    {
125254721Semaste    }
126254721Semaste
127254721Semaste    virtual Searcher::CallbackReturn
128254721Semaste    SearchCallback (SearchFilter &filter,
129254721Semaste                    SymbolContext &context,
130254721Semaste                    Address *addr,
131254721Semaste                    bool containing)
132254721Semaste    {
133254721Semaste
134254721Semaste        if (SetActualResolver())
135254721Semaste            return m_actual_resolver_sp->SearchCallback (filter, context, addr, containing);
136254721Semaste        else
137254721Semaste            return eCallbackReturnStop;
138254721Semaste    }
139254721Semaste
140254721Semaste    virtual Searcher::Depth
141254721Semaste    GetDepth ()
142254721Semaste    {
143254721Semaste        if (SetActualResolver())
144254721Semaste            return m_actual_resolver_sp->GetDepth();
145254721Semaste        else
146254721Semaste            return eDepthTarget;
147254721Semaste    }
148254721Semaste
149254721Semaste    virtual void
150254721Semaste    GetDescription (Stream *s)
151254721Semaste    {
152254721Semaste        s->Printf ("Exception breakpoint (catch: %s throw: %s)",
153254721Semaste                   m_catch_bp ? "on" : "off",
154254721Semaste                   m_throw_bp ? "on" : "off");
155254721Semaste
156254721Semaste        SetActualResolver();
157254721Semaste        if (m_actual_resolver_sp)
158254721Semaste        {
159254721Semaste            s->Printf (" using: ");
160254721Semaste            m_actual_resolver_sp->GetDescription (s);
161254721Semaste        }
162254721Semaste        else
163254721Semaste            s->Printf (" the correct runtime exception handler will be determined when you run");
164254721Semaste    }
165254721Semaste
166254721Semaste    virtual void
167254721Semaste    Dump (Stream *s) const
168254721Semaste    {
169254721Semaste    }
170254721Semaste
171254721Semaste    /// Methods for support type inquiry through isa, cast, and dyn_cast:
172254721Semaste    static inline bool classof(const BreakpointResolverName *) { return true; }
173254721Semaste    static inline bool classof(const BreakpointResolver *V) {
174254721Semaste        return V->getResolverID() == BreakpointResolver::ExceptionResolver;
175254721Semaste    }
176254721Semasteprotected:
177254721Semaste    bool
178254721Semaste    SetActualResolver()
179254721Semaste    {
180254721Semaste        ProcessSP process_sp;
181254721Semaste        if (m_breakpoint)
182254721Semaste        {
183254721Semaste            process_sp = m_breakpoint->GetTarget().GetProcessSP();
184254721Semaste            if (process_sp)
185254721Semaste            {
186254721Semaste                bool refreash_resolver = !m_actual_resolver_sp;
187254721Semaste                if (m_language_runtime == NULL)
188254721Semaste                {
189254721Semaste                    m_language_runtime = process_sp->GetLanguageRuntime(m_language);
190254721Semaste                    refreash_resolver = true;
191254721Semaste                }
192254721Semaste                else
193254721Semaste                {
194254721Semaste                    LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(m_language);
195254721Semaste                    if (m_language_runtime != language_runtime)
196254721Semaste                    {
197254721Semaste                        m_language_runtime = language_runtime;
198254721Semaste                        refreash_resolver = true;
199254721Semaste                    }
200254721Semaste                }
201254721Semaste
202254721Semaste                if (refreash_resolver && m_language_runtime)
203254721Semaste                {
204254721Semaste                    m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver (m_breakpoint, m_catch_bp, m_throw_bp);
205254721Semaste                }
206254721Semaste            }
207254721Semaste            else
208254721Semaste            {
209254721Semaste                m_actual_resolver_sp.reset();
210254721Semaste                m_language_runtime = NULL;
211254721Semaste            }
212254721Semaste        }
213254721Semaste        else
214254721Semaste        {
215254721Semaste            m_actual_resolver_sp.reset();
216254721Semaste            m_language_runtime = NULL;
217254721Semaste        }
218254721Semaste        return (bool)m_actual_resolver_sp;
219254721Semaste    }
220254721Semaste    lldb::BreakpointResolverSP m_actual_resolver_sp;
221254721Semaste    lldb::LanguageType m_language;
222254721Semaste    LanguageRuntime *m_language_runtime;
223254721Semaste    bool m_catch_bp;
224254721Semaste    bool m_throw_bp;
225254721Semaste};
226254721Semaste
227254721Semaste
228254721SemasteLanguageRuntime*
229254721SemasteLanguageRuntime::FindPlugin (Process *process, lldb::LanguageType language)
230254721Semaste{
231254721Semaste    std::unique_ptr<LanguageRuntime> language_runtime_ap;
232254721Semaste    LanguageRuntimeCreateInstance create_callback;
233254721Semaste
234254721Semaste    for (uint32_t idx = 0;
235254721Semaste         (create_callback = PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != NULL;
236254721Semaste         ++idx)
237254721Semaste    {
238254721Semaste        language_runtime_ap.reset (create_callback(process, language));
239254721Semaste
240254721Semaste        if (language_runtime_ap.get())
241254721Semaste            return language_runtime_ap.release();
242254721Semaste    }
243254721Semaste
244254721Semaste    return NULL;
245254721Semaste}
246254721Semaste
247254721Semaste//----------------------------------------------------------------------
248254721Semaste// Constructor
249254721Semaste//----------------------------------------------------------------------
250254721SemasteLanguageRuntime::LanguageRuntime(Process *process) :
251254721Semaste    m_process (process)
252254721Semaste{
253254721Semaste}
254254721Semaste
255254721Semaste//----------------------------------------------------------------------
256254721Semaste// Destructor
257254721Semaste//----------------------------------------------------------------------
258254721SemasteLanguageRuntime::~LanguageRuntime()
259254721Semaste{
260254721Semaste}
261254721Semaste
262254721SemasteBreakpointSP
263254721SemasteLanguageRuntime::CreateExceptionBreakpoint (Target &target,
264254721Semaste                                            lldb::LanguageType language,
265254721Semaste                                            bool catch_bp,
266254721Semaste                                            bool throw_bp,
267254721Semaste                                            bool is_internal)
268254721Semaste{
269254721Semaste    BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
270254721Semaste    SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language));
271263363Semaste    bool hardware = false;
272269024Semaste    bool resolve_indirect_functions = false;
273269024Semaste    BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions));
274254721Semaste    if (is_internal)
275254721Semaste        exc_breakpt_sp->SetBreakpointKind("exception");
276254721Semaste
277254721Semaste    return exc_breakpt_sp;
278254721Semaste}
279254721Semaste
280254721Semastestruct language_name_pair {
281254721Semaste    const char *name;
282254721Semaste    LanguageType type;
283254721Semaste};
284254721Semaste
285254721Semastestruct language_name_pair language_names[] =
286254721Semaste{
287254721Semaste    // To allow GetNameForLanguageType to be a simple array lookup, the first
288254721Semaste    // part of this array must follow enum LanguageType exactly.
289254721Semaste    {   "unknown",          eLanguageTypeUnknown        },
290254721Semaste    {   "c89",              eLanguageTypeC89            },
291254721Semaste    {   "c",                eLanguageTypeC              },
292254721Semaste    {   "ada83",            eLanguageTypeAda83          },
293254721Semaste    {   "c++",              eLanguageTypeC_plus_plus    },
294254721Semaste    {   "cobol74",          eLanguageTypeCobol74        },
295254721Semaste    {   "cobol85",          eLanguageTypeCobol85        },
296254721Semaste    {   "fortran77",        eLanguageTypeFortran77      },
297254721Semaste    {   "fortran90",        eLanguageTypeFortran90      },
298254721Semaste    {   "pascal83",         eLanguageTypePascal83       },
299254721Semaste    {   "modula2",          eLanguageTypeModula2        },
300254721Semaste    {   "java",             eLanguageTypeJava           },
301254721Semaste    {   "c99",              eLanguageTypeC99            },
302254721Semaste    {   "ada95",            eLanguageTypeAda95          },
303254721Semaste    {   "fortran95",        eLanguageTypeFortran95      },
304254721Semaste    {   "pli",              eLanguageTypePLI            },
305254721Semaste    {   "objective-c",      eLanguageTypeObjC           },
306254721Semaste    {   "objective-c++",    eLanguageTypeObjC_plus_plus },
307254721Semaste    {   "upc",              eLanguageTypeUPC            },
308254721Semaste    {   "d",                eLanguageTypeD              },
309254721Semaste    {   "python",           eLanguageTypePython         },
310254721Semaste    // Now synonyms, in arbitrary order
311254721Semaste    {   "objc",             eLanguageTypeObjC           },
312254721Semaste    {   "objc++",           eLanguageTypeObjC_plus_plus }
313254721Semaste};
314254721Semaste
315254721Semastestatic uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
316254721Semaste
317254721SemasteLanguageType
318254721SemasteLanguageRuntime::GetLanguageTypeFromString (const char *string)
319254721Semaste{
320254721Semaste    for (uint32_t i = 0; i < num_languages; i++)
321254721Semaste    {
322254721Semaste        if (strcasecmp (language_names[i].name, string) == 0)
323254721Semaste            return (LanguageType) language_names[i].type;
324254721Semaste    }
325254721Semaste    return eLanguageTypeUnknown;
326254721Semaste}
327254721Semaste
328254721Semasteconst char *
329254721SemasteLanguageRuntime::GetNameForLanguageType (LanguageType language)
330254721Semaste{
331254721Semaste    if (language < num_languages)
332254721Semaste        return language_names[language].name;
333254721Semaste    else
334254721Semaste        return language_names[eLanguageTypeUnknown].name;
335254721Semaste}
336254721Semaste
337254721Semastelldb::SearchFilterSP
338254721SemasteLanguageRuntime::CreateExceptionSearchFilter ()
339254721Semaste{
340254721Semaste    return m_process->GetTarget().GetSearchFilterForModule(NULL);
341254721Semaste}
342254721Semaste
343254721Semaste
344254721Semaste
345