xref: /src/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1cfca06d7SDimitry Andric //===-- LanguageRuntime.cpp -----------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Target/LanguageRuntime.h"
10f034231aSEd Maste #include "lldb/Core/PluginManager.h"
11205afe67SEd Maste #include "lldb/Core/SearchFilter.h"
125e95aa85SEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
135f29bb8aSDimitry Andric #include "lldb/Target/Language.h"
1414f1b3e8SDimitry Andric #include "lldb/Target/Target.h"
15f034231aSEd Maste 
16f034231aSEd Maste using namespace lldb;
17f034231aSEd Maste using namespace lldb_private;
18f034231aSEd Maste 
195f29bb8aSDimitry Andric char LanguageRuntime::ID = 0;
205f29bb8aSDimitry Andric 
ExceptionSearchFilter(const lldb::TargetSP & target_sp,lldb::LanguageType language,bool update_module_list)2114f1b3e8SDimitry Andric ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,
22205afe67SEd Maste                                              lldb::LanguageType language,
2314f1b3e8SDimitry Andric                                              bool update_module_list)
2414f1b3e8SDimitry Andric     : SearchFilter(target_sp, FilterTy::Exception), m_language(language),
2514f1b3e8SDimitry Andric       m_language_runtime(nullptr), m_filter_sp() {
26205afe67SEd Maste   if (update_module_list)
27f034231aSEd Maste     UpdateModuleListIfNeeded();
28f034231aSEd Maste }
29f034231aSEd Maste 
ModulePasses(const lldb::ModuleSP & module_sp)3014f1b3e8SDimitry Andric bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
31f034231aSEd Maste   UpdateModuleListIfNeeded();
32f034231aSEd Maste   if (m_filter_sp)
33f034231aSEd Maste     return m_filter_sp->ModulePasses(module_sp);
34f034231aSEd Maste   return false;
35f034231aSEd Maste }
36f034231aSEd Maste 
ModulePasses(const FileSpec & spec)3714f1b3e8SDimitry Andric bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
38f034231aSEd Maste   UpdateModuleListIfNeeded();
39f034231aSEd Maste   if (m_filter_sp)
40f034231aSEd Maste     return m_filter_sp->ModulePasses(spec);
41f034231aSEd Maste   return false;
42f034231aSEd Maste }
43f034231aSEd Maste 
Search(Searcher & searcher)4414f1b3e8SDimitry Andric void ExceptionSearchFilter::Search(Searcher &searcher) {
45f034231aSEd Maste   UpdateModuleListIfNeeded();
46f034231aSEd Maste   if (m_filter_sp)
47f034231aSEd Maste     m_filter_sp->Search(searcher);
48f034231aSEd Maste }
49f034231aSEd Maste 
GetDescription(Stream * s)5014f1b3e8SDimitry Andric void ExceptionSearchFilter::GetDescription(Stream *s) {
51f034231aSEd Maste   UpdateModuleListIfNeeded();
52f034231aSEd Maste   if (m_filter_sp)
53f034231aSEd Maste     m_filter_sp->GetDescription(s);
54f034231aSEd Maste }
55f034231aSEd Maste 
UpdateModuleListIfNeeded()5614f1b3e8SDimitry Andric void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
57f034231aSEd Maste   ProcessSP process_sp(m_target_sp->GetProcessSP());
5814f1b3e8SDimitry Andric   if (process_sp) {
59f034231aSEd Maste     bool refreash_filter = !m_filter_sp;
6014f1b3e8SDimitry Andric     if (m_language_runtime == nullptr) {
61f034231aSEd Maste       m_language_runtime = process_sp->GetLanguageRuntime(m_language);
62f034231aSEd Maste       refreash_filter = true;
6314f1b3e8SDimitry Andric     } else {
6414f1b3e8SDimitry Andric       LanguageRuntime *language_runtime =
6514f1b3e8SDimitry Andric           process_sp->GetLanguageRuntime(m_language);
6614f1b3e8SDimitry Andric       if (m_language_runtime != language_runtime) {
67f034231aSEd Maste         m_language_runtime = language_runtime;
68f034231aSEd Maste         refreash_filter = true;
69f034231aSEd Maste       }
70f034231aSEd Maste     }
71f034231aSEd Maste 
7214f1b3e8SDimitry Andric     if (refreash_filter && m_language_runtime) {
73f034231aSEd Maste       m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
74f034231aSEd Maste     }
7514f1b3e8SDimitry Andric   } else {
76f034231aSEd Maste     m_filter_sp.reset();
77f3fbd1c0SDimitry Andric     m_language_runtime = nullptr;
78f034231aSEd Maste   }
79f034231aSEd Maste }
8014f1b3e8SDimitry Andric 
DoCreateCopy()81cfca06d7SDimitry Andric SearchFilterSP ExceptionSearchFilter::DoCreateCopy() {
8214f1b3e8SDimitry Andric   return SearchFilterSP(
8314f1b3e8SDimitry Andric       new ExceptionSearchFilter(TargetSP(), m_language, false));
8414f1b3e8SDimitry Andric }
8514f1b3e8SDimitry Andric 
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)8614f1b3e8SDimitry Andric SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
87b76161e4SDimitry Andric     Target &target, const StructuredData::Dictionary &data_dict,
88b76161e4SDimitry Andric     Status &error) {
8914f1b3e8SDimitry Andric   SearchFilter *result = nullptr;
9014f1b3e8SDimitry Andric   return result;
9114f1b3e8SDimitry Andric }
9214f1b3e8SDimitry Andric 
SerializeToStructuredData()9314f1b3e8SDimitry Andric StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
9414f1b3e8SDimitry Andric   StructuredData::ObjectSP result_sp;
9514f1b3e8SDimitry Andric 
9614f1b3e8SDimitry Andric   return result_sp;
9714f1b3e8SDimitry Andric }
98f034231aSEd Maste 
99f034231aSEd Maste // The Target is the one that knows how to create breakpoints, so this function
10014f1b3e8SDimitry Andric // is meant to be used either by the target or internally in
10114f1b3e8SDimitry Andric // Set/ClearExceptionBreakpoints.
10214f1b3e8SDimitry Andric class ExceptionBreakpointResolver : public BreakpointResolver {
103f034231aSEd Maste public:
ExceptionBreakpointResolver(lldb::LanguageType language,bool catch_bp,bool throw_bp)10414f1b3e8SDimitry Andric   ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,
10514f1b3e8SDimitry Andric                               bool throw_bp)
10614f1b3e8SDimitry Andric       : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),
107145449b1SDimitry Andric         m_language(language), m_catch_bp(catch_bp), m_throw_bp(throw_bp) {}
108f034231aSEd Maste 
109e81d9d49SDimitry Andric   ~ExceptionBreakpointResolver() override = default;
110f034231aSEd Maste 
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)11114f1b3e8SDimitry Andric   Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
112ead24645SDimitry Andric                                           SymbolContext &context,
113ead24645SDimitry Andric                                           Address *addr) override {
114f034231aSEd Maste 
115f034231aSEd Maste     if (SetActualResolver())
116ead24645SDimitry Andric       return m_actual_resolver_sp->SearchCallback(filter, context, addr);
117f034231aSEd Maste     else
118f034231aSEd Maste       return eCallbackReturnStop;
119f034231aSEd Maste   }
120f034231aSEd Maste 
GetDepth()12194994d37SDimitry Andric   lldb::SearchDepth GetDepth() override {
122f034231aSEd Maste     if (SetActualResolver())
123f034231aSEd Maste       return m_actual_resolver_sp->GetDepth();
124f034231aSEd Maste     else
12594994d37SDimitry Andric       return lldb::eSearchDepthTarget;
126f034231aSEd Maste   }
127f034231aSEd Maste 
GetDescription(Stream * s)12814f1b3e8SDimitry Andric   void GetDescription(Stream *s) override {
129e81d9d49SDimitry Andric     Language *language_plugin = Language::FindPlugin(m_language);
130e81d9d49SDimitry Andric     if (language_plugin)
13114f1b3e8SDimitry Andric       language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
13214f1b3e8SDimitry Andric                                                        *s);
133e81d9d49SDimitry Andric     else
13414f1b3e8SDimitry Andric       Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
13514f1b3e8SDimitry Andric                                                        *s);
136f034231aSEd Maste 
137f034231aSEd Maste     SetActualResolver();
13814f1b3e8SDimitry Andric     if (m_actual_resolver_sp) {
139f034231aSEd Maste       s->Printf(" using: ");
140f034231aSEd Maste       m_actual_resolver_sp->GetDescription(s);
14114f1b3e8SDimitry Andric     } else
14214f1b3e8SDimitry Andric       s->Printf(" the correct runtime exception handler will be determined "
14314f1b3e8SDimitry Andric                 "when you run");
144f034231aSEd Maste   }
145f034231aSEd Maste 
Dump(Stream * s) const14614f1b3e8SDimitry Andric   void Dump(Stream *s) const override {}
147f034231aSEd Maste 
148f034231aSEd Maste   /// Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const BreakpointResolverName *)149f034231aSEd Maste   static inline bool classof(const BreakpointResolverName *) { return true; }
classof(const BreakpointResolver * V)150f034231aSEd Maste   static inline bool classof(const BreakpointResolver *V) {
151f034231aSEd Maste     return V->getResolverID() == BreakpointResolver::ExceptionResolver;
152f034231aSEd Maste   }
153e81d9d49SDimitry Andric 
154f034231aSEd Maste protected:
CopyForBreakpoint(BreakpointSP & breakpoint)155cfca06d7SDimitry Andric   BreakpointResolverSP CopyForBreakpoint(BreakpointSP &breakpoint) override {
156706b4fc4SDimitry Andric     BreakpointResolverSP ret_sp(
15714f1b3e8SDimitry Andric         new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
158cfca06d7SDimitry Andric     ret_sp->SetBreakpoint(breakpoint);
159706b4fc4SDimitry Andric     return ret_sp;
160205afe67SEd Maste   }
161205afe67SEd Maste 
SetActualResolver()16214f1b3e8SDimitry Andric   bool SetActualResolver() {
163cfca06d7SDimitry Andric     BreakpointSP breakpoint_sp = GetBreakpoint();
164cfca06d7SDimitry Andric     if (breakpoint_sp) {
165cfca06d7SDimitry Andric       ProcessSP process_sp = breakpoint_sp->GetTarget().GetProcessSP();
16614f1b3e8SDimitry Andric       if (process_sp) {
167f034231aSEd Maste         bool refreash_resolver = !m_actual_resolver_sp;
16814f1b3e8SDimitry Andric         if (m_language_runtime == nullptr) {
169f034231aSEd Maste           m_language_runtime = process_sp->GetLanguageRuntime(m_language);
170f034231aSEd Maste           refreash_resolver = true;
17114f1b3e8SDimitry Andric         } else {
17214f1b3e8SDimitry Andric           LanguageRuntime *language_runtime =
17314f1b3e8SDimitry Andric               process_sp->GetLanguageRuntime(m_language);
17414f1b3e8SDimitry Andric           if (m_language_runtime != language_runtime) {
175f034231aSEd Maste             m_language_runtime = language_runtime;
176f034231aSEd Maste             refreash_resolver = true;
177f034231aSEd Maste           }
178f034231aSEd Maste         }
179f034231aSEd Maste 
18014f1b3e8SDimitry Andric         if (refreash_resolver && m_language_runtime) {
18114f1b3e8SDimitry Andric           m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver(
182cfca06d7SDimitry Andric               breakpoint_sp, m_catch_bp, m_throw_bp);
183f034231aSEd Maste         }
18414f1b3e8SDimitry Andric       } else {
185f034231aSEd Maste         m_actual_resolver_sp.reset();
186f3fbd1c0SDimitry Andric         m_language_runtime = nullptr;
187f034231aSEd Maste       }
18814f1b3e8SDimitry Andric     } else {
189f034231aSEd Maste       m_actual_resolver_sp.reset();
190f3fbd1c0SDimitry Andric       m_language_runtime = nullptr;
191f034231aSEd Maste     }
192f034231aSEd Maste     return (bool)m_actual_resolver_sp;
193f034231aSEd Maste   }
194f3fbd1c0SDimitry Andric 
195f034231aSEd Maste   lldb::BreakpointResolverSP m_actual_resolver_sp;
196f034231aSEd Maste   lldb::LanguageType m_language;
197145449b1SDimitry Andric   LanguageRuntime *m_language_runtime = nullptr;
198f034231aSEd Maste   bool m_catch_bp;
199f034231aSEd Maste   bool m_throw_bp;
200f034231aSEd Maste };
201f034231aSEd Maste 
FindPlugin(Process * process,lldb::LanguageType language)20214f1b3e8SDimitry Andric LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
20314f1b3e8SDimitry Andric                                              lldb::LanguageType language) {
204f034231aSEd Maste   LanguageRuntimeCreateInstance create_callback;
205f034231aSEd Maste   for (uint32_t idx = 0;
20614f1b3e8SDimitry Andric        (create_callback =
20714f1b3e8SDimitry Andric             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
20814f1b3e8SDimitry Andric        nullptr;
20914f1b3e8SDimitry Andric        ++idx) {
210b60736ecSDimitry Andric     if (LanguageRuntime *runtime = create_callback(process, language))
211b60736ecSDimitry Andric       return runtime;
212f034231aSEd Maste   }
213f3fbd1c0SDimitry Andric   return nullptr;
214f034231aSEd Maste }
215f034231aSEd Maste 
LanguageRuntime(Process * process)216b60736ecSDimitry Andric LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {}
217f034231aSEd Maste 
2185f29bb8aSDimitry Andric BreakpointPreconditionSP
GetExceptionPrecondition(LanguageType language,bool throw_bp)2195f29bb8aSDimitry Andric LanguageRuntime::GetExceptionPrecondition(LanguageType language,
2205f29bb8aSDimitry Andric                                           bool throw_bp) {
2215f29bb8aSDimitry Andric   LanguageRuntimeCreateInstance create_callback;
2225f29bb8aSDimitry Andric   for (uint32_t idx = 0;
2235f29bb8aSDimitry Andric        (create_callback =
2245f29bb8aSDimitry Andric             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
2255f29bb8aSDimitry Andric        nullptr;
2265f29bb8aSDimitry Andric        idx++) {
2275f29bb8aSDimitry Andric     if (auto precondition_callback =
2285f29bb8aSDimitry Andric             PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(
2295f29bb8aSDimitry Andric                 idx)) {
2305f29bb8aSDimitry Andric       if (BreakpointPreconditionSP precond =
2315f29bb8aSDimitry Andric               precondition_callback(language, throw_bp))
2325f29bb8aSDimitry Andric         return precond;
2335e95aa85SEd Maste     }
2345f29bb8aSDimitry Andric   }
2355f29bb8aSDimitry Andric   return BreakpointPreconditionSP();
2365e95aa85SEd Maste }
2375e95aa85SEd Maste 
CreateExceptionBreakpoint(Target & target,lldb::LanguageType language,bool catch_bp,bool throw_bp,bool is_internal)23814f1b3e8SDimitry Andric BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
23914f1b3e8SDimitry Andric     Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
24014f1b3e8SDimitry Andric     bool is_internal) {
24114f1b3e8SDimitry Andric   BreakpointResolverSP resolver_sp(
24214f1b3e8SDimitry Andric       new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
24314f1b3e8SDimitry Andric   SearchFilterSP filter_sp(
24414f1b3e8SDimitry Andric       new ExceptionSearchFilter(target.shared_from_this(), language));
245f21a844fSEd Maste   bool hardware = false;
246866dcdacSEd Maste   bool resolve_indirect_functions = false;
24714f1b3e8SDimitry Andric   BreakpointSP exc_breakpt_sp(
24814f1b3e8SDimitry Andric       target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware,
24914f1b3e8SDimitry Andric                               resolve_indirect_functions));
25014f1b3e8SDimitry Andric   if (exc_breakpt_sp) {
2515f29bb8aSDimitry Andric     if (auto precond = GetExceptionPrecondition(language, throw_bp))
2525f29bb8aSDimitry Andric       exc_breakpt_sp->SetPrecondition(precond);
2535e95aa85SEd Maste 
254f034231aSEd Maste     if (is_internal)
255f034231aSEd Maste       exc_breakpt_sp->SetBreakpointKind("exception");
2565e95aa85SEd Maste   }
257f034231aSEd Maste 
258f034231aSEd Maste   return exc_breakpt_sp;
259f034231aSEd Maste }
260f034231aSEd Maste 
261344a3780SDimitry Andric UnwindPlanSP
GetRuntimeUnwindPlan(Thread & thread,RegisterContext * regctx,bool & behaves_like_zeroth_frame)262344a3780SDimitry Andric LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx,
263344a3780SDimitry Andric                                       bool &behaves_like_zeroth_frame) {
264344a3780SDimitry Andric   ProcessSP process_sp = thread.GetProcess();
265344a3780SDimitry Andric   if (!process_sp.get())
266344a3780SDimitry Andric     return UnwindPlanSP();
267344a3780SDimitry Andric   if (process_sp->GetDisableLangRuntimeUnwindPlans() == true)
268344a3780SDimitry Andric     return UnwindPlanSP();
269344a3780SDimitry Andric   for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {
270344a3780SDimitry Andric     if (LanguageRuntime *runtime = process_sp->GetLanguageRuntime(lang_type)) {
271344a3780SDimitry Andric       UnwindPlanSP plan_sp = runtime->GetRuntimeUnwindPlan(
272344a3780SDimitry Andric           process_sp, regctx, behaves_like_zeroth_frame);
273344a3780SDimitry Andric       if (plan_sp.get())
274344a3780SDimitry Andric         return plan_sp;
275344a3780SDimitry Andric     }
276344a3780SDimitry Andric   }
277344a3780SDimitry Andric   return UnwindPlanSP();
278344a3780SDimitry Andric }
279344a3780SDimitry Andric 
InitializeCommands(CommandObject * parent)28014f1b3e8SDimitry Andric void LanguageRuntime::InitializeCommands(CommandObject *parent) {
2815e95aa85SEd Maste   if (!parent)
2825e95aa85SEd Maste     return;
2835e95aa85SEd Maste 
2845e95aa85SEd Maste   if (!parent->IsMultiwordObject())
2855e95aa85SEd Maste     return;
2865e95aa85SEd Maste 
2875e95aa85SEd Maste   LanguageRuntimeCreateInstance create_callback;
2885e95aa85SEd Maste 
2895e95aa85SEd Maste   for (uint32_t idx = 0;
29014f1b3e8SDimitry Andric        (create_callback =
29114f1b3e8SDimitry Andric             PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
29214f1b3e8SDimitry Andric        nullptr;
29314f1b3e8SDimitry Andric        ++idx) {
2945e95aa85SEd Maste     if (LanguageRuntimeGetCommandObject command_callback =
29514f1b3e8SDimitry Andric             PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
29614f1b3e8SDimitry Andric       CommandObjectSP command =
29714f1b3e8SDimitry Andric           command_callback(parent->GetCommandInterpreter());
29814f1b3e8SDimitry Andric       if (command) {
29914f1b3e8SDimitry Andric         // the CommandObject vended by a Language plugin cannot be created once
30014f1b3e8SDimitry Andric         // and cached because we may create multiple debuggers and need one
30114f1b3e8SDimitry Andric         // instance of the command each - the implementing function is meant to
30214f1b3e8SDimitry Andric         // create a new instance of the command each time it is invoked.
30314f1b3e8SDimitry Andric         parent->LoadSubCommand(command->GetCommandName().str().c_str(), command);
3045e95aa85SEd Maste       }
3055e95aa85SEd Maste     }
3065e95aa85SEd Maste   }
3075e95aa85SEd Maste }
308