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