180814287SRaphael Isemann //===-- LanguageRuntime.cpp -----------------------------------------------===//
22277701cSJim Ingham //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62277701cSJim Ingham //
72277701cSJim Ingham //===----------------------------------------------------------------------===//
82277701cSJim Ingham 
92277701cSJim Ingham #include "lldb/Target/LanguageRuntime.h"
102277701cSJim Ingham #include "lldb/Core/PluginManager.h"
1133df7cd3SJim Ingham #include "lldb/Core/SearchFilter.h"
12c9c55a26SColin Riley #include "lldb/Interpreter/CommandInterpreter.h"
13d2284128SAlex Langford #include "lldb/Target/Language.h"
14b9c1b51eSKate Stone #include "lldb/Target/Target.h"
152277701cSJim Ingham 
162277701cSJim Ingham using namespace lldb;
172277701cSJim Ingham using namespace lldb_private;
182277701cSJim Ingham 
19056f6f18SAlex Langford char LanguageRuntime::ID = 0;
20056f6f18SAlex Langford 
ExceptionSearchFilter(const lldb::TargetSP & target_sp,lldb::LanguageType language,bool update_module_list)21e14dc268SJim Ingham ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,
2233df7cd3SJim Ingham                                              lldb::LanguageType language,
23e14dc268SJim Ingham                                              bool update_module_list)
24e14dc268SJim Ingham     : SearchFilter(target_sp, FilterTy::Exception), m_language(language),
25b9c1b51eSKate Stone       m_language_runtime(nullptr), m_filter_sp() {
2633df7cd3SJim Ingham   if (update_module_list)
27bff7825aSGreg Clayton     UpdateModuleListIfNeeded();
28bff7825aSGreg Clayton }
29bff7825aSGreg Clayton 
ModulePasses(const lldb::ModuleSP & module_sp)30e14dc268SJim Ingham bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
31bff7825aSGreg Clayton   UpdateModuleListIfNeeded();
32bff7825aSGreg Clayton   if (m_filter_sp)
33bff7825aSGreg Clayton     return m_filter_sp->ModulePasses(module_sp);
34bff7825aSGreg Clayton   return false;
35bff7825aSGreg Clayton }
36bff7825aSGreg Clayton 
ModulePasses(const FileSpec & spec)37e14dc268SJim Ingham bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
38bff7825aSGreg Clayton   UpdateModuleListIfNeeded();
39bff7825aSGreg Clayton   if (m_filter_sp)
40bff7825aSGreg Clayton     return m_filter_sp->ModulePasses(spec);
41bff7825aSGreg Clayton   return false;
42bff7825aSGreg Clayton }
43bff7825aSGreg Clayton 
Search(Searcher & searcher)44e14dc268SJim Ingham void ExceptionSearchFilter::Search(Searcher &searcher) {
45bff7825aSGreg Clayton   UpdateModuleListIfNeeded();
46bff7825aSGreg Clayton   if (m_filter_sp)
47bff7825aSGreg Clayton     m_filter_sp->Search(searcher);
48bff7825aSGreg Clayton }
49bff7825aSGreg Clayton 
GetDescription(Stream * s)50e14dc268SJim Ingham void ExceptionSearchFilter::GetDescription(Stream *s) {
51bff7825aSGreg Clayton   UpdateModuleListIfNeeded();
52bff7825aSGreg Clayton   if (m_filter_sp)
53bff7825aSGreg Clayton     m_filter_sp->GetDescription(s);
54bff7825aSGreg Clayton }
55bff7825aSGreg Clayton 
UpdateModuleListIfNeeded()56e14dc268SJim Ingham void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
57bff7825aSGreg Clayton   ProcessSP process_sp(m_target_sp->GetProcessSP());
58b9c1b51eSKate Stone   if (process_sp) {
59bff7825aSGreg Clayton     bool refreash_filter = !m_filter_sp;
60b9c1b51eSKate Stone     if (m_language_runtime == nullptr) {
61bff7825aSGreg Clayton       m_language_runtime = process_sp->GetLanguageRuntime(m_language);
62bff7825aSGreg Clayton       refreash_filter = true;
63b9c1b51eSKate Stone     } else {
64b9c1b51eSKate Stone       LanguageRuntime *language_runtime =
65b9c1b51eSKate Stone           process_sp->GetLanguageRuntime(m_language);
66b9c1b51eSKate Stone       if (m_language_runtime != language_runtime) {
67bff7825aSGreg Clayton         m_language_runtime = language_runtime;
68bff7825aSGreg Clayton         refreash_filter = true;
69bff7825aSGreg Clayton       }
70bff7825aSGreg Clayton     }
71bff7825aSGreg Clayton 
72b9c1b51eSKate Stone     if (refreash_filter && m_language_runtime) {
73bff7825aSGreg Clayton       m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
74bff7825aSGreg Clayton     }
75b9c1b51eSKate Stone   } else {
76bff7825aSGreg Clayton     m_filter_sp.reset();
779394d772SEugene Zelenko     m_language_runtime = nullptr;
78bff7825aSGreg Clayton   }
79bff7825aSGreg Clayton }
80e14dc268SJim Ingham 
DoCreateCopy()817fb06796STatyana Krasnukha SearchFilterSP ExceptionSearchFilter::DoCreateCopy() {
82e14dc268SJim Ingham   return SearchFilterSP(
83e14dc268SJim Ingham       new ExceptionSearchFilter(TargetSP(), m_language, false));
84e14dc268SJim Ingham }
85e14dc268SJim Ingham 
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)86e14dc268SJim Ingham SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
8797206d57SZachary Turner     Target &target, const StructuredData::Dictionary &data_dict,
8897206d57SZachary Turner     Status &error) {
89e14dc268SJim Ingham   SearchFilter *result = nullptr;
90e14dc268SJim Ingham   return result;
91e14dc268SJim Ingham }
92e14dc268SJim Ingham 
SerializeToStructuredData()93e14dc268SJim Ingham StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
94e14dc268SJim Ingham   StructuredData::ObjectSP result_sp;
95e14dc268SJim Ingham 
96e14dc268SJim Ingham   return result_sp;
97e14dc268SJim Ingham }
98bff7825aSGreg Clayton 
99bff7825aSGreg Clayton // The Target is the one that knows how to create breakpoints, so this function
100b9c1b51eSKate Stone // is meant to be used either by the target or internally in
101b9c1b51eSKate Stone // Set/ClearExceptionBreakpoints.
102b9c1b51eSKate Stone class ExceptionBreakpointResolver : public BreakpointResolver {
103bff7825aSGreg Clayton public:
ExceptionBreakpointResolver(lldb::LanguageType language,bool catch_bp,bool throw_bp)104b9c1b51eSKate Stone   ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,
105b9c1b51eSKate Stone                               bool throw_bp)
106b9c1b51eSKate Stone       : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),
107*28c878aeSShafik Yaghmour         m_language(language), m_catch_bp(catch_bp), m_throw_bp(throw_bp) {}
108bff7825aSGreg Clayton 
1098f30a65cSEugene Zelenko   ~ExceptionBreakpointResolver() override = default;
110bff7825aSGreg Clayton 
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)111b9c1b51eSKate Stone   Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
11295e264fcSRaphael Isemann                                           SymbolContext &context,
11395e264fcSRaphael Isemann                                           Address *addr) override {
114bff7825aSGreg Clayton 
115bff7825aSGreg Clayton     if (SetActualResolver())
11695e264fcSRaphael Isemann       return m_actual_resolver_sp->SearchCallback(filter, context, addr);
117bff7825aSGreg Clayton     else
118bff7825aSGreg Clayton       return eCallbackReturnStop;
119bff7825aSGreg Clayton   }
120bff7825aSGreg Clayton 
GetDepth()1214911d36aSJim Ingham   lldb::SearchDepth GetDepth() override {
122bff7825aSGreg Clayton     if (SetActualResolver())
123bff7825aSGreg Clayton       return m_actual_resolver_sp->GetDepth();
124bff7825aSGreg Clayton     else
1254911d36aSJim Ingham       return lldb::eSearchDepthTarget;
126bff7825aSGreg Clayton   }
127bff7825aSGreg Clayton 
GetDescription(Stream * s)128b9c1b51eSKate Stone   void GetDescription(Stream *s) override {
129a2023571SJim Ingham     Language *language_plugin = Language::FindPlugin(m_language);
130a2023571SJim Ingham     if (language_plugin)
131b9c1b51eSKate Stone       language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
132b9c1b51eSKate Stone                                                        *s);
133a2023571SJim Ingham     else
134b9c1b51eSKate Stone       Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
135b9c1b51eSKate Stone                                                        *s);
136bff7825aSGreg Clayton 
137bff7825aSGreg Clayton     SetActualResolver();
138b9c1b51eSKate Stone     if (m_actual_resolver_sp) {
139bff7825aSGreg Clayton       s->Printf(" using: ");
140bff7825aSGreg Clayton       m_actual_resolver_sp->GetDescription(s);
141b9c1b51eSKate Stone     } else
142b9c1b51eSKate Stone       s->Printf(" the correct runtime exception handler will be determined "
143b9c1b51eSKate Stone                 "when you run");
144bff7825aSGreg Clayton   }
145bff7825aSGreg Clayton 
Dump(Stream * s) const146b9c1b51eSKate Stone   void Dump(Stream *s) const override {}
147bff7825aSGreg Clayton 
148bff7825aSGreg Clayton   /// Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const BreakpointResolverName *)149bff7825aSGreg Clayton   static inline bool classof(const BreakpointResolverName *) { return true; }
classof(const BreakpointResolver * V)150bff7825aSGreg Clayton   static inline bool classof(const BreakpointResolver *V) {
151bff7825aSGreg Clayton     return V->getResolverID() == BreakpointResolver::ExceptionResolver;
152bff7825aSGreg Clayton   }
1538f30a65cSEugene Zelenko 
154bff7825aSGreg Clayton protected:
CopyForBreakpoint(BreakpointSP & breakpoint)1556c17cc53STatyana Krasnukha   BreakpointResolverSP CopyForBreakpoint(BreakpointSP &breakpoint) override {
1560b0dca9fSMartin Svensson     BreakpointResolverSP ret_sp(
157b9c1b51eSKate Stone         new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
1586c17cc53STatyana Krasnukha     ret_sp->SetBreakpoint(breakpoint);
1590b0dca9fSMartin Svensson     return ret_sp;
16033df7cd3SJim Ingham   }
16133df7cd3SJim Ingham 
SetActualResolver()162b9c1b51eSKate Stone   bool SetActualResolver() {
1636c17cc53STatyana Krasnukha     BreakpointSP breakpoint_sp = GetBreakpoint();
1646c17cc53STatyana Krasnukha     if (breakpoint_sp) {
1656c17cc53STatyana Krasnukha       ProcessSP process_sp = breakpoint_sp->GetTarget().GetProcessSP();
166b9c1b51eSKate Stone       if (process_sp) {
167bff7825aSGreg Clayton         bool refreash_resolver = !m_actual_resolver_sp;
168b9c1b51eSKate Stone         if (m_language_runtime == nullptr) {
169bff7825aSGreg Clayton           m_language_runtime = process_sp->GetLanguageRuntime(m_language);
170bff7825aSGreg Clayton           refreash_resolver = true;
171b9c1b51eSKate Stone         } else {
172b9c1b51eSKate Stone           LanguageRuntime *language_runtime =
173b9c1b51eSKate Stone               process_sp->GetLanguageRuntime(m_language);
174b9c1b51eSKate Stone           if (m_language_runtime != language_runtime) {
175bff7825aSGreg Clayton             m_language_runtime = language_runtime;
176bff7825aSGreg Clayton             refreash_resolver = true;
177bff7825aSGreg Clayton           }
178bff7825aSGreg Clayton         }
179bff7825aSGreg Clayton 
180b9c1b51eSKate Stone         if (refreash_resolver && m_language_runtime) {
181b9c1b51eSKate Stone           m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver(
1826c17cc53STatyana Krasnukha               breakpoint_sp, m_catch_bp, m_throw_bp);
183bff7825aSGreg Clayton         }
184b9c1b51eSKate Stone       } else {
185bff7825aSGreg Clayton         m_actual_resolver_sp.reset();
1869394d772SEugene Zelenko         m_language_runtime = nullptr;
187bff7825aSGreg Clayton       }
188b9c1b51eSKate Stone     } else {
189bff7825aSGreg Clayton       m_actual_resolver_sp.reset();
1909394d772SEugene Zelenko       m_language_runtime = nullptr;
191bff7825aSGreg Clayton     }
192bff7825aSGreg Clayton     return (bool)m_actual_resolver_sp;
193bff7825aSGreg Clayton   }
1949394d772SEugene Zelenko 
195bff7825aSGreg Clayton   lldb::BreakpointResolverSP m_actual_resolver_sp;
196bff7825aSGreg Clayton   lldb::LanguageType m_language;
197*28c878aeSShafik Yaghmour   LanguageRuntime *m_language_runtime = nullptr;
198bff7825aSGreg Clayton   bool m_catch_bp;
199bff7825aSGreg Clayton   bool m_throw_bp;
200bff7825aSGreg Clayton };
201bff7825aSGreg Clayton 
FindPlugin(Process * process,lldb::LanguageType language)202b9c1b51eSKate Stone LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
203b9c1b51eSKate Stone                                              lldb::LanguageType language) {
2042277701cSJim Ingham   LanguageRuntimeCreateInstance create_callback;
2052277701cSJim Ingham   for (uint32_t idx = 0;
206b9c1b51eSKate Stone        (create_callback =
207b9c1b51eSKate Stone             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
208b9c1b51eSKate Stone        nullptr;
209b9c1b51eSKate Stone        ++idx) {
21099996213SJonas Devlieghere     if (LanguageRuntime *runtime = create_callback(process, language))
21199996213SJonas Devlieghere       return runtime;
2122277701cSJim Ingham   }
2139394d772SEugene Zelenko   return nullptr;
2142277701cSJim Ingham }
2152277701cSJim Ingham 
LanguageRuntime(Process * process)21634d4c8a5SJonas Devlieghere LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {}
2172277701cSJim Ingham 
2187f9c9f22SAlex Langford BreakpointPreconditionSP
GetExceptionPrecondition(LanguageType language,bool throw_bp)2197f9c9f22SAlex Langford LanguageRuntime::GetExceptionPrecondition(LanguageType language,
2207f9c9f22SAlex Langford                                           bool throw_bp) {
2217f9c9f22SAlex Langford   LanguageRuntimeCreateInstance create_callback;
2227f9c9f22SAlex Langford   for (uint32_t idx = 0;
2237f9c9f22SAlex Langford        (create_callback =
2247f9c9f22SAlex Langford             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
2257f9c9f22SAlex Langford        nullptr;
2267f9c9f22SAlex Langford        idx++) {
2277f9c9f22SAlex Langford     if (auto precondition_callback =
2287f9c9f22SAlex Langford             PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(
2297f9c9f22SAlex Langford                 idx)) {
2307f9c9f22SAlex Langford       if (BreakpointPreconditionSP precond =
2317f9c9f22SAlex Langford               precondition_callback(language, throw_bp))
2327f9c9f22SAlex Langford         return precond;
233a72b31c7SJim Ingham     }
2347f9c9f22SAlex Langford   }
2357f9c9f22SAlex Langford   return BreakpointPreconditionSP();
236a72b31c7SJim Ingham }
237a72b31c7SJim Ingham 
CreateExceptionBreakpoint(Target & target,lldb::LanguageType language,bool catch_bp,bool throw_bp,bool is_internal)238b9c1b51eSKate Stone BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
239b9c1b51eSKate Stone     Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
240b9c1b51eSKate Stone     bool is_internal) {
241b9c1b51eSKate Stone   BreakpointResolverSP resolver_sp(
242b9c1b51eSKate Stone       new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
243b9c1b51eSKate Stone   SearchFilterSP filter_sp(
244b9c1b51eSKate Stone       new ExceptionSearchFilter(target.shared_from_this(), language));
245eb023e75SGreg Clayton   bool hardware = false;
2461460e4bfSJim Ingham   bool resolve_indirect_functions = false;
247b9c1b51eSKate Stone   BreakpointSP exc_breakpt_sp(
248b9c1b51eSKate Stone       target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware,
249b9c1b51eSKate Stone                               resolve_indirect_functions));
250b9c1b51eSKate Stone   if (exc_breakpt_sp) {
2517f9c9f22SAlex Langford     if (auto precond = GetExceptionPrecondition(language, throw_bp))
2527f9c9f22SAlex Langford       exc_breakpt_sp->SetPrecondition(precond);
253a72b31c7SJim Ingham 
2542995077dSJim Ingham     if (is_internal)
2552995077dSJim Ingham       exc_breakpt_sp->SetBreakpointKind("exception");
256a72b31c7SJim Ingham   }
257219ba196SJim Ingham 
258219ba196SJim Ingham   return exc_breakpt_sp;
259219ba196SJim Ingham }
260219ba196SJim Ingham 
261266bb78fSJason Molenda UnwindPlanSP
GetRuntimeUnwindPlan(Thread & thread,RegisterContext * regctx,bool & behaves_like_zeroth_frame)262266bb78fSJason Molenda LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx,
263266bb78fSJason Molenda                                       bool &behaves_like_zeroth_frame) {
264d82ecb0aSJason Molenda   ProcessSP process_sp = thread.GetProcess();
265d82ecb0aSJason Molenda   if (!process_sp.get())
266d82ecb0aSJason Molenda     return UnwindPlanSP();
267dd453a13SJason Molenda   if (process_sp->GetDisableLangRuntimeUnwindPlans() == true)
268dd453a13SJason Molenda     return UnwindPlanSP();
269d82ecb0aSJason Molenda   for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {
270d82ecb0aSJason Molenda     if (LanguageRuntime *runtime = process_sp->GetLanguageRuntime(lang_type)) {
271266bb78fSJason Molenda       UnwindPlanSP plan_sp = runtime->GetRuntimeUnwindPlan(
272266bb78fSJason Molenda           process_sp, regctx, behaves_like_zeroth_frame);
273d82ecb0aSJason Molenda       if (plan_sp.get())
274d82ecb0aSJason Molenda         return plan_sp;
275d82ecb0aSJason Molenda     }
276d82ecb0aSJason Molenda   }
277d82ecb0aSJason Molenda   return UnwindPlanSP();
278d82ecb0aSJason Molenda }
279d82ecb0aSJason Molenda 
InitializeCommands(CommandObject * parent)280b9c1b51eSKate Stone void LanguageRuntime::InitializeCommands(CommandObject *parent) {
281c9c55a26SColin Riley   if (!parent)
282c9c55a26SColin Riley     return;
283c9c55a26SColin Riley 
284c9c55a26SColin Riley   if (!parent->IsMultiwordObject())
285c9c55a26SColin Riley     return;
286c9c55a26SColin Riley 
287c9c55a26SColin Riley   LanguageRuntimeCreateInstance create_callback;
288c9c55a26SColin Riley 
289c9c55a26SColin Riley   for (uint32_t idx = 0;
290b9c1b51eSKate Stone        (create_callback =
291b9c1b51eSKate Stone             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
292b9c1b51eSKate Stone        nullptr;
293b9c1b51eSKate Stone        ++idx) {
294c9c55a26SColin Riley     if (LanguageRuntimeGetCommandObject command_callback =
295b9c1b51eSKate Stone             PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
296b9c1b51eSKate Stone       CommandObjectSP command =
297b9c1b51eSKate Stone           command_callback(parent->GetCommandInterpreter());
298b9c1b51eSKate Stone       if (command) {
299b9c1b51eSKate Stone         // the CommandObject vended by a Language plugin cannot be created once
300a449698cSZachary Turner         // and cached because we may create multiple debuggers and need one
301a449698cSZachary Turner         // instance of the command each - the implementing function is meant to
302a449698cSZachary Turner         // create a new instance of the command each time it is invoked.
303a449698cSZachary Turner         parent->LoadSubCommand(command->GetCommandName().str().c_str(), command);
304c9c55a26SColin Riley       }
305c9c55a26SColin Riley     }
306c9c55a26SColin Riley   }
307c9c55a26SColin Riley }
308