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