1 //===-- LanguageRuntime.cpp -----------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/LanguageRuntime.h"
10 #include "lldb/Core/PluginManager.h"
11 #include "lldb/Core/SearchFilter.h"
12 #include "lldb/Interpreter/CommandInterpreter.h"
13 #include "lldb/Target/Language.h"
14 #include "lldb/Target/Target.h"
17 using namespace lldb_private
;
19 char LanguageRuntime::ID
= 0;
21 ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP
&target_sp
,
22 lldb::LanguageType language
,
23 bool update_module_list
)
24 : SearchFilter(target_sp
, FilterTy::Exception
), m_language(language
),
25 m_language_runtime(nullptr), m_filter_sp() {
26 if (update_module_list
)
27 UpdateModuleListIfNeeded();
30 bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP
&module_sp
) {
31 UpdateModuleListIfNeeded();
33 return m_filter_sp
->ModulePasses(module_sp
);
37 bool ExceptionSearchFilter::ModulePasses(const FileSpec
&spec
) {
38 UpdateModuleListIfNeeded();
40 return m_filter_sp
->ModulePasses(spec
);
44 void ExceptionSearchFilter::Search(Searcher
&searcher
) {
45 UpdateModuleListIfNeeded();
47 m_filter_sp
->Search(searcher
);
50 void ExceptionSearchFilter::GetDescription(Stream
*s
) {
51 UpdateModuleListIfNeeded();
53 m_filter_sp
->GetDescription(s
);
56 void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
57 ProcessSP
process_sp(m_target_sp
->GetProcessSP());
59 bool refreash_filter
= !m_filter_sp
;
60 if (m_language_runtime
== nullptr) {
61 m_language_runtime
= process_sp
->GetLanguageRuntime(m_language
);
62 refreash_filter
= true;
64 LanguageRuntime
*language_runtime
=
65 process_sp
->GetLanguageRuntime(m_language
);
66 if (m_language_runtime
!= language_runtime
) {
67 m_language_runtime
= language_runtime
;
68 refreash_filter
= true;
72 if (refreash_filter
&& m_language_runtime
) {
73 m_filter_sp
= m_language_runtime
->CreateExceptionSearchFilter();
77 m_language_runtime
= nullptr;
81 SearchFilterSP
ExceptionSearchFilter::DoCreateCopy() {
82 return SearchFilterSP(
83 new ExceptionSearchFilter(TargetSP(), m_language
, false));
86 SearchFilter
*ExceptionSearchFilter::CreateFromStructuredData(
87 Target
&target
, const StructuredData::Dictionary
&data_dict
,
89 SearchFilter
*result
= nullptr;
93 StructuredData::ObjectSP
ExceptionSearchFilter::SerializeToStructuredData() {
94 StructuredData::ObjectSP result_sp
;
99 // The Target is the one that knows how to create breakpoints, so this function
100 // is meant to be used either by the target or internally in
101 // Set/ClearExceptionBreakpoints.
102 class ExceptionBreakpointResolver
: public BreakpointResolver
{
104 ExceptionBreakpointResolver(lldb::LanguageType language
, bool catch_bp
,
106 : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver
),
107 m_language(language
), m_catch_bp(catch_bp
), m_throw_bp(throw_bp
) {}
109 ~ExceptionBreakpointResolver() override
= default;
111 Searcher::CallbackReturn
SearchCallback(SearchFilter
&filter
,
112 SymbolContext
&context
,
113 Address
*addr
) override
{
115 if (SetActualResolver())
116 return m_actual_resolver_sp
->SearchCallback(filter
, context
, addr
);
118 return eCallbackReturnStop
;
121 lldb::SearchDepth
GetDepth() override
{
122 if (SetActualResolver())
123 return m_actual_resolver_sp
->GetDepth();
125 return lldb::eSearchDepthTarget
;
128 void GetDescription(Stream
*s
) override
{
129 Language
*language_plugin
= Language::FindPlugin(m_language
);
131 language_plugin
->GetExceptionResolverDescription(m_catch_bp
, m_throw_bp
,
134 Language::GetDefaultExceptionResolverDescription(m_catch_bp
, m_throw_bp
,
138 if (m_actual_resolver_sp
) {
139 s
->Printf(" using: ");
140 m_actual_resolver_sp
->GetDescription(s
);
142 s
->Printf(" the correct runtime exception handler will be determined "
146 void Dump(Stream
*s
) const override
{}
148 /// Methods for support type inquiry through isa, cast, and dyn_cast:
149 static inline bool classof(const BreakpointResolverName
*) { return true; }
150 static inline bool classof(const BreakpointResolver
*V
) {
151 return V
->getResolverID() == BreakpointResolver::ExceptionResolver
;
155 BreakpointResolverSP
CopyForBreakpoint(BreakpointSP
&breakpoint
) override
{
156 BreakpointResolverSP
ret_sp(
157 new ExceptionBreakpointResolver(m_language
, m_catch_bp
, m_throw_bp
));
158 ret_sp
->SetBreakpoint(breakpoint
);
162 bool SetActualResolver() {
163 BreakpointSP breakpoint_sp
= GetBreakpoint();
165 ProcessSP process_sp
= breakpoint_sp
->GetTarget().GetProcessSP();
167 bool refreash_resolver
= !m_actual_resolver_sp
;
168 if (m_language_runtime
== nullptr) {
169 m_language_runtime
= process_sp
->GetLanguageRuntime(m_language
);
170 refreash_resolver
= true;
172 LanguageRuntime
*language_runtime
=
173 process_sp
->GetLanguageRuntime(m_language
);
174 if (m_language_runtime
!= language_runtime
) {
175 m_language_runtime
= language_runtime
;
176 refreash_resolver
= true;
180 if (refreash_resolver
&& m_language_runtime
) {
181 m_actual_resolver_sp
= m_language_runtime
->CreateExceptionResolver(
182 breakpoint_sp
, m_catch_bp
, m_throw_bp
);
185 m_actual_resolver_sp
.reset();
186 m_language_runtime
= nullptr;
189 m_actual_resolver_sp
.reset();
190 m_language_runtime
= nullptr;
192 return (bool)m_actual_resolver_sp
;
195 lldb::BreakpointResolverSP m_actual_resolver_sp
;
196 lldb::LanguageType m_language
;
197 LanguageRuntime
*m_language_runtime
= nullptr;
202 LanguageRuntime
*LanguageRuntime::FindPlugin(Process
*process
,
203 lldb::LanguageType language
) {
204 LanguageRuntimeCreateInstance create_callback
;
205 for (uint32_t idx
= 0;
207 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx
)) !=
210 if (LanguageRuntime
*runtime
= create_callback(process
, language
))
216 LanguageRuntime::LanguageRuntime(Process
*process
) : Runtime(process
) {}
218 BreakpointPreconditionSP
219 LanguageRuntime::GetExceptionPrecondition(LanguageType language
,
221 LanguageRuntimeCreateInstance create_callback
;
222 for (uint32_t idx
= 0;
224 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx
)) !=
227 if (auto precondition_callback
=
228 PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(
230 if (BreakpointPreconditionSP precond
=
231 precondition_callback(language
, throw_bp
))
235 return BreakpointPreconditionSP();
238 BreakpointSP
LanguageRuntime::CreateExceptionBreakpoint(
239 Target
&target
, lldb::LanguageType language
, bool catch_bp
, bool throw_bp
,
241 BreakpointResolverSP
resolver_sp(
242 new ExceptionBreakpointResolver(language
, catch_bp
, throw_bp
));
243 SearchFilterSP
filter_sp(
244 new ExceptionSearchFilter(target
.shared_from_this(), language
));
245 bool hardware
= false;
246 bool resolve_indirect_functions
= false;
247 BreakpointSP
exc_breakpt_sp(
248 target
.CreateBreakpoint(filter_sp
, resolver_sp
, is_internal
, hardware
,
249 resolve_indirect_functions
));
250 if (exc_breakpt_sp
) {
251 if (auto precond
= GetExceptionPrecondition(language
, throw_bp
))
252 exc_breakpt_sp
->SetPrecondition(precond
);
255 exc_breakpt_sp
->SetBreakpointKind("exception");
258 return exc_breakpt_sp
;
262 LanguageRuntime::GetRuntimeUnwindPlan(Thread
&thread
, RegisterContext
*regctx
,
263 bool &behaves_like_zeroth_frame
) {
264 ProcessSP process_sp
= thread
.GetProcess();
265 if (!process_sp
.get())
266 return UnwindPlanSP();
267 if (process_sp
->GetDisableLangRuntimeUnwindPlans() == true)
268 return UnwindPlanSP();
269 for (const lldb::LanguageType lang_type
: Language::GetSupportedLanguages()) {
270 if (LanguageRuntime
*runtime
= process_sp
->GetLanguageRuntime(lang_type
)) {
271 UnwindPlanSP plan_sp
= runtime
->GetRuntimeUnwindPlan(
272 process_sp
, regctx
, behaves_like_zeroth_frame
);
277 return UnwindPlanSP();
280 void LanguageRuntime::InitializeCommands(CommandObject
*parent
) {
284 if (!parent
->IsMultiwordObject())
287 LanguageRuntimeCreateInstance create_callback
;
289 for (uint32_t idx
= 0;
291 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx
)) !=
294 if (LanguageRuntimeGetCommandObject command_callback
=
295 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx
)) {
296 CommandObjectSP command
=
297 command_callback(parent
->GetCommandInterpreter());
299 // the CommandObject vended by a Language plugin cannot be created once
300 // and cached because we may create multiple debuggers and need one
301 // instance of the command each - the implementing function is meant to
302 // create a new instance of the command each time it is invoked.
303 parent
->LoadSubCommand(command
->GetCommandName().str().c_str(), command
);