xref: /openbsd-src/gnu/llvm/lldb/source/Target/LanguageRuntime.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- LanguageRuntime.cpp -----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Target/LanguageRuntime.h"
10061da546Spatrick #include "lldb/Core/PluginManager.h"
11061da546Spatrick #include "lldb/Core/SearchFilter.h"
12061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
13061da546Spatrick #include "lldb/Target/Language.h"
14061da546Spatrick #include "lldb/Target/Target.h"
15061da546Spatrick 
16061da546Spatrick using namespace lldb;
17061da546Spatrick using namespace lldb_private;
18061da546Spatrick 
19061da546Spatrick char LanguageRuntime::ID = 0;
20061da546Spatrick 
ExceptionSearchFilter(const lldb::TargetSP & target_sp,lldb::LanguageType language,bool update_module_list)21061da546Spatrick ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,
22061da546Spatrick                                              lldb::LanguageType language,
23061da546Spatrick                                              bool update_module_list)
24061da546Spatrick     : SearchFilter(target_sp, FilterTy::Exception), m_language(language),
25061da546Spatrick       m_language_runtime(nullptr), m_filter_sp() {
26061da546Spatrick   if (update_module_list)
27061da546Spatrick     UpdateModuleListIfNeeded();
28061da546Spatrick }
29061da546Spatrick 
ModulePasses(const lldb::ModuleSP & module_sp)30061da546Spatrick bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
31061da546Spatrick   UpdateModuleListIfNeeded();
32061da546Spatrick   if (m_filter_sp)
33061da546Spatrick     return m_filter_sp->ModulePasses(module_sp);
34061da546Spatrick   return false;
35061da546Spatrick }
36061da546Spatrick 
ModulePasses(const FileSpec & spec)37061da546Spatrick bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
38061da546Spatrick   UpdateModuleListIfNeeded();
39061da546Spatrick   if (m_filter_sp)
40061da546Spatrick     return m_filter_sp->ModulePasses(spec);
41061da546Spatrick   return false;
42061da546Spatrick }
43061da546Spatrick 
Search(Searcher & searcher)44061da546Spatrick void ExceptionSearchFilter::Search(Searcher &searcher) {
45061da546Spatrick   UpdateModuleListIfNeeded();
46061da546Spatrick   if (m_filter_sp)
47061da546Spatrick     m_filter_sp->Search(searcher);
48061da546Spatrick }
49061da546Spatrick 
GetDescription(Stream * s)50061da546Spatrick void ExceptionSearchFilter::GetDescription(Stream *s) {
51061da546Spatrick   UpdateModuleListIfNeeded();
52061da546Spatrick   if (m_filter_sp)
53061da546Spatrick     m_filter_sp->GetDescription(s);
54061da546Spatrick }
55061da546Spatrick 
UpdateModuleListIfNeeded()56061da546Spatrick void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
57061da546Spatrick   ProcessSP process_sp(m_target_sp->GetProcessSP());
58061da546Spatrick   if (process_sp) {
59061da546Spatrick     bool refreash_filter = !m_filter_sp;
60061da546Spatrick     if (m_language_runtime == nullptr) {
61061da546Spatrick       m_language_runtime = process_sp->GetLanguageRuntime(m_language);
62061da546Spatrick       refreash_filter = true;
63061da546Spatrick     } else {
64061da546Spatrick       LanguageRuntime *language_runtime =
65061da546Spatrick           process_sp->GetLanguageRuntime(m_language);
66061da546Spatrick       if (m_language_runtime != language_runtime) {
67061da546Spatrick         m_language_runtime = language_runtime;
68061da546Spatrick         refreash_filter = true;
69061da546Spatrick       }
70061da546Spatrick     }
71061da546Spatrick 
72061da546Spatrick     if (refreash_filter && m_language_runtime) {
73061da546Spatrick       m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
74061da546Spatrick     }
75061da546Spatrick   } else {
76061da546Spatrick     m_filter_sp.reset();
77061da546Spatrick     m_language_runtime = nullptr;
78061da546Spatrick   }
79061da546Spatrick }
80061da546Spatrick 
DoCreateCopy()81dda28197Spatrick SearchFilterSP ExceptionSearchFilter::DoCreateCopy() {
82061da546Spatrick   return SearchFilterSP(
83061da546Spatrick       new ExceptionSearchFilter(TargetSP(), m_language, false));
84061da546Spatrick }
85061da546Spatrick 
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)86061da546Spatrick SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
87061da546Spatrick     Target &target, const StructuredData::Dictionary &data_dict,
88061da546Spatrick     Status &error) {
89061da546Spatrick   SearchFilter *result = nullptr;
90061da546Spatrick   return result;
91061da546Spatrick }
92061da546Spatrick 
SerializeToStructuredData()93061da546Spatrick StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
94061da546Spatrick   StructuredData::ObjectSP result_sp;
95061da546Spatrick 
96061da546Spatrick   return result_sp;
97061da546Spatrick }
98061da546Spatrick 
99061da546Spatrick // The Target is the one that knows how to create breakpoints, so this function
100061da546Spatrick // is meant to be used either by the target or internally in
101061da546Spatrick // Set/ClearExceptionBreakpoints.
102061da546Spatrick class ExceptionBreakpointResolver : public BreakpointResolver {
103061da546Spatrick public:
ExceptionBreakpointResolver(lldb::LanguageType language,bool catch_bp,bool throw_bp)104061da546Spatrick   ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,
105061da546Spatrick                               bool throw_bp)
106061da546Spatrick       : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),
107*f6aab3d8Srobert         m_language(language), m_catch_bp(catch_bp), m_throw_bp(throw_bp) {}
108061da546Spatrick 
109061da546Spatrick   ~ExceptionBreakpointResolver() override = default;
110061da546Spatrick 
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)111061da546Spatrick   Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
112061da546Spatrick                                           SymbolContext &context,
113061da546Spatrick                                           Address *addr) override {
114061da546Spatrick 
115061da546Spatrick     if (SetActualResolver())
116061da546Spatrick       return m_actual_resolver_sp->SearchCallback(filter, context, addr);
117061da546Spatrick     else
118061da546Spatrick       return eCallbackReturnStop;
119061da546Spatrick   }
120061da546Spatrick 
GetDepth()121061da546Spatrick   lldb::SearchDepth GetDepth() override {
122061da546Spatrick     if (SetActualResolver())
123061da546Spatrick       return m_actual_resolver_sp->GetDepth();
124061da546Spatrick     else
125061da546Spatrick       return lldb::eSearchDepthTarget;
126061da546Spatrick   }
127061da546Spatrick 
GetDescription(Stream * s)128061da546Spatrick   void GetDescription(Stream *s) override {
129061da546Spatrick     Language *language_plugin = Language::FindPlugin(m_language);
130061da546Spatrick     if (language_plugin)
131061da546Spatrick       language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
132061da546Spatrick                                                        *s);
133061da546Spatrick     else
134061da546Spatrick       Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
135061da546Spatrick                                                        *s);
136061da546Spatrick 
137061da546Spatrick     SetActualResolver();
138061da546Spatrick     if (m_actual_resolver_sp) {
139061da546Spatrick       s->Printf(" using: ");
140061da546Spatrick       m_actual_resolver_sp->GetDescription(s);
141061da546Spatrick     } else
142061da546Spatrick       s->Printf(" the correct runtime exception handler will be determined "
143061da546Spatrick                 "when you run");
144061da546Spatrick   }
145061da546Spatrick 
Dump(Stream * s) const146061da546Spatrick   void Dump(Stream *s) const override {}
147061da546Spatrick 
148061da546Spatrick   /// Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const BreakpointResolverName *)149061da546Spatrick   static inline bool classof(const BreakpointResolverName *) { return true; }
classof(const BreakpointResolver * V)150061da546Spatrick   static inline bool classof(const BreakpointResolver *V) {
151061da546Spatrick     return V->getResolverID() == BreakpointResolver::ExceptionResolver;
152061da546Spatrick   }
153061da546Spatrick 
154061da546Spatrick protected:
CopyForBreakpoint(BreakpointSP & breakpoint)155dda28197Spatrick   BreakpointResolverSP CopyForBreakpoint(BreakpointSP &breakpoint) override {
156061da546Spatrick     BreakpointResolverSP ret_sp(
157061da546Spatrick         new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
158dda28197Spatrick     ret_sp->SetBreakpoint(breakpoint);
159061da546Spatrick     return ret_sp;
160061da546Spatrick   }
161061da546Spatrick 
SetActualResolver()162061da546Spatrick   bool SetActualResolver() {
163dda28197Spatrick     BreakpointSP breakpoint_sp = GetBreakpoint();
164dda28197Spatrick     if (breakpoint_sp) {
165dda28197Spatrick       ProcessSP process_sp = breakpoint_sp->GetTarget().GetProcessSP();
166061da546Spatrick       if (process_sp) {
167061da546Spatrick         bool refreash_resolver = !m_actual_resolver_sp;
168061da546Spatrick         if (m_language_runtime == nullptr) {
169061da546Spatrick           m_language_runtime = process_sp->GetLanguageRuntime(m_language);
170061da546Spatrick           refreash_resolver = true;
171061da546Spatrick         } else {
172061da546Spatrick           LanguageRuntime *language_runtime =
173061da546Spatrick               process_sp->GetLanguageRuntime(m_language);
174061da546Spatrick           if (m_language_runtime != language_runtime) {
175061da546Spatrick             m_language_runtime = language_runtime;
176061da546Spatrick             refreash_resolver = true;
177061da546Spatrick           }
178061da546Spatrick         }
179061da546Spatrick 
180061da546Spatrick         if (refreash_resolver && m_language_runtime) {
181061da546Spatrick           m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver(
182dda28197Spatrick               breakpoint_sp, m_catch_bp, m_throw_bp);
183061da546Spatrick         }
184061da546Spatrick       } else {
185061da546Spatrick         m_actual_resolver_sp.reset();
186061da546Spatrick         m_language_runtime = nullptr;
187061da546Spatrick       }
188061da546Spatrick     } else {
189061da546Spatrick       m_actual_resolver_sp.reset();
190061da546Spatrick       m_language_runtime = nullptr;
191061da546Spatrick     }
192061da546Spatrick     return (bool)m_actual_resolver_sp;
193061da546Spatrick   }
194061da546Spatrick 
195061da546Spatrick   lldb::BreakpointResolverSP m_actual_resolver_sp;
196061da546Spatrick   lldb::LanguageType m_language;
197*f6aab3d8Srobert   LanguageRuntime *m_language_runtime = nullptr;
198061da546Spatrick   bool m_catch_bp;
199061da546Spatrick   bool m_throw_bp;
200061da546Spatrick };
201061da546Spatrick 
FindPlugin(Process * process,lldb::LanguageType language)202061da546Spatrick LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
203061da546Spatrick                                              lldb::LanguageType language) {
204061da546Spatrick   LanguageRuntimeCreateInstance create_callback;
205061da546Spatrick   for (uint32_t idx = 0;
206061da546Spatrick        (create_callback =
207061da546Spatrick             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
208061da546Spatrick        nullptr;
209061da546Spatrick        ++idx) {
210be691f3bSpatrick     if (LanguageRuntime *runtime = create_callback(process, language))
211be691f3bSpatrick       return runtime;
212061da546Spatrick   }
213061da546Spatrick   return nullptr;
214061da546Spatrick }
215061da546Spatrick 
LanguageRuntime(Process * process)216be691f3bSpatrick LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {}
217061da546Spatrick 
218061da546Spatrick BreakpointPreconditionSP
GetExceptionPrecondition(LanguageType language,bool throw_bp)219061da546Spatrick LanguageRuntime::GetExceptionPrecondition(LanguageType language,
220061da546Spatrick                                           bool throw_bp) {
221061da546Spatrick   LanguageRuntimeCreateInstance create_callback;
222061da546Spatrick   for (uint32_t idx = 0;
223061da546Spatrick        (create_callback =
224061da546Spatrick             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
225061da546Spatrick        nullptr;
226061da546Spatrick        idx++) {
227061da546Spatrick     if (auto precondition_callback =
228061da546Spatrick             PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(
229061da546Spatrick                 idx)) {
230061da546Spatrick       if (BreakpointPreconditionSP precond =
231061da546Spatrick               precondition_callback(language, throw_bp))
232061da546Spatrick         return precond;
233061da546Spatrick     }
234061da546Spatrick   }
235061da546Spatrick   return BreakpointPreconditionSP();
236061da546Spatrick }
237061da546Spatrick 
CreateExceptionBreakpoint(Target & target,lldb::LanguageType language,bool catch_bp,bool throw_bp,bool is_internal)238061da546Spatrick BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
239061da546Spatrick     Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
240061da546Spatrick     bool is_internal) {
241061da546Spatrick   BreakpointResolverSP resolver_sp(
242061da546Spatrick       new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
243061da546Spatrick   SearchFilterSP filter_sp(
244061da546Spatrick       new ExceptionSearchFilter(target.shared_from_this(), language));
245061da546Spatrick   bool hardware = false;
246061da546Spatrick   bool resolve_indirect_functions = false;
247061da546Spatrick   BreakpointSP exc_breakpt_sp(
248061da546Spatrick       target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware,
249061da546Spatrick                               resolve_indirect_functions));
250061da546Spatrick   if (exc_breakpt_sp) {
251061da546Spatrick     if (auto precond = GetExceptionPrecondition(language, throw_bp))
252061da546Spatrick       exc_breakpt_sp->SetPrecondition(precond);
253061da546Spatrick 
254061da546Spatrick     if (is_internal)
255061da546Spatrick       exc_breakpt_sp->SetBreakpointKind("exception");
256061da546Spatrick   }
257061da546Spatrick 
258061da546Spatrick   return exc_breakpt_sp;
259061da546Spatrick }
260061da546Spatrick 
261be691f3bSpatrick UnwindPlanSP
GetRuntimeUnwindPlan(Thread & thread,RegisterContext * regctx,bool & behaves_like_zeroth_frame)262be691f3bSpatrick LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx,
263be691f3bSpatrick                                       bool &behaves_like_zeroth_frame) {
264be691f3bSpatrick   ProcessSP process_sp = thread.GetProcess();
265be691f3bSpatrick   if (!process_sp.get())
266be691f3bSpatrick     return UnwindPlanSP();
267be691f3bSpatrick   if (process_sp->GetDisableLangRuntimeUnwindPlans() == true)
268be691f3bSpatrick     return UnwindPlanSP();
269be691f3bSpatrick   for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {
270be691f3bSpatrick     if (LanguageRuntime *runtime = process_sp->GetLanguageRuntime(lang_type)) {
271be691f3bSpatrick       UnwindPlanSP plan_sp = runtime->GetRuntimeUnwindPlan(
272be691f3bSpatrick           process_sp, regctx, behaves_like_zeroth_frame);
273be691f3bSpatrick       if (plan_sp.get())
274be691f3bSpatrick         return plan_sp;
275be691f3bSpatrick     }
276be691f3bSpatrick   }
277be691f3bSpatrick   return UnwindPlanSP();
278be691f3bSpatrick }
279be691f3bSpatrick 
InitializeCommands(CommandObject * parent)280061da546Spatrick void LanguageRuntime::InitializeCommands(CommandObject *parent) {
281061da546Spatrick   if (!parent)
282061da546Spatrick     return;
283061da546Spatrick 
284061da546Spatrick   if (!parent->IsMultiwordObject())
285061da546Spatrick     return;
286061da546Spatrick 
287061da546Spatrick   LanguageRuntimeCreateInstance create_callback;
288061da546Spatrick 
289061da546Spatrick   for (uint32_t idx = 0;
290061da546Spatrick        (create_callback =
291061da546Spatrick             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
292061da546Spatrick        nullptr;
293061da546Spatrick        ++idx) {
294061da546Spatrick     if (LanguageRuntimeGetCommandObject command_callback =
295061da546Spatrick             PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
296061da546Spatrick       CommandObjectSP command =
297061da546Spatrick           command_callback(parent->GetCommandInterpreter());
298061da546Spatrick       if (command) {
299061da546Spatrick         // the CommandObject vended by a Language plugin cannot be created once
300061da546Spatrick         // and cached because we may create multiple debuggers and need one
301061da546Spatrick         // instance of the command each - the implementing function is meant to
302061da546Spatrick         // create a new instance of the command each time it is invoked.
303061da546Spatrick         parent->LoadSubCommand(command->GetCommandName().str().c_str(), command);
304061da546Spatrick       }
305061da546Spatrick     }
306061da546Spatrick   }
307061da546Spatrick }
308