Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp
39587 views
1
//===-- LanguageRuntime.cpp -----------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
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"
15
16
using namespace lldb;
17
using namespace lldb_private;
18
19
char LanguageRuntime::ID = 0;
20
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();
28
}
29
30
bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
31
UpdateModuleListIfNeeded();
32
if (m_filter_sp)
33
return m_filter_sp->ModulePasses(module_sp);
34
return false;
35
}
36
37
bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
38
UpdateModuleListIfNeeded();
39
if (m_filter_sp)
40
return m_filter_sp->ModulePasses(spec);
41
return false;
42
}
43
44
void ExceptionSearchFilter::Search(Searcher &searcher) {
45
UpdateModuleListIfNeeded();
46
if (m_filter_sp)
47
m_filter_sp->Search(searcher);
48
}
49
50
void ExceptionSearchFilter::GetDescription(Stream *s) {
51
UpdateModuleListIfNeeded();
52
if (m_filter_sp)
53
m_filter_sp->GetDescription(s);
54
}
55
56
void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
57
ProcessSP process_sp(m_target_sp->GetProcessSP());
58
if (process_sp) {
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;
63
} else {
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;
69
}
70
}
71
72
if (refreash_filter && m_language_runtime) {
73
m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
74
}
75
} else {
76
m_filter_sp.reset();
77
m_language_runtime = nullptr;
78
}
79
}
80
81
SearchFilterSP ExceptionSearchFilter::DoCreateCopy() {
82
return SearchFilterSP(
83
new ExceptionSearchFilter(TargetSP(), m_language, false));
84
}
85
86
SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
87
Target &target, const StructuredData::Dictionary &data_dict,
88
Status &error) {
89
SearchFilter *result = nullptr;
90
return result;
91
}
92
93
StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
94
StructuredData::ObjectSP result_sp;
95
96
return result_sp;
97
}
98
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 {
103
public:
104
ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,
105
bool throw_bp)
106
: BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),
107
m_language(language), m_catch_bp(catch_bp), m_throw_bp(throw_bp) {}
108
109
~ExceptionBreakpointResolver() override = default;
110
111
Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
112
SymbolContext &context,
113
Address *addr) override {
114
115
if (SetActualResolver())
116
return m_actual_resolver_sp->SearchCallback(filter, context, addr);
117
else
118
return eCallbackReturnStop;
119
}
120
121
lldb::SearchDepth GetDepth() override {
122
if (SetActualResolver())
123
return m_actual_resolver_sp->GetDepth();
124
else
125
return lldb::eSearchDepthTarget;
126
}
127
128
void GetDescription(Stream *s) override {
129
Language *language_plugin = Language::FindPlugin(m_language);
130
if (language_plugin)
131
language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
132
*s);
133
else
134
Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
135
*s);
136
137
SetActualResolver();
138
if (m_actual_resolver_sp) {
139
s->Printf(" using: ");
140
m_actual_resolver_sp->GetDescription(s);
141
} else
142
s->Printf(" the correct runtime exception handler will be determined "
143
"when you run");
144
}
145
146
void Dump(Stream *s) const override {}
147
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;
152
}
153
154
protected:
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);
159
return ret_sp;
160
}
161
162
bool SetActualResolver() {
163
BreakpointSP breakpoint_sp = GetBreakpoint();
164
if (breakpoint_sp) {
165
ProcessSP process_sp = breakpoint_sp->GetTarget().GetProcessSP();
166
if (process_sp) {
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;
171
} else {
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;
177
}
178
}
179
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);
183
}
184
} else {
185
m_actual_resolver_sp.reset();
186
m_language_runtime = nullptr;
187
}
188
} else {
189
m_actual_resolver_sp.reset();
190
m_language_runtime = nullptr;
191
}
192
return (bool)m_actual_resolver_sp;
193
}
194
195
lldb::BreakpointResolverSP m_actual_resolver_sp;
196
lldb::LanguageType m_language;
197
LanguageRuntime *m_language_runtime = nullptr;
198
bool m_catch_bp;
199
bool m_throw_bp;
200
};
201
202
LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
203
lldb::LanguageType language) {
204
LanguageRuntimeCreateInstance create_callback;
205
for (uint32_t idx = 0;
206
(create_callback =
207
PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
208
nullptr;
209
++idx) {
210
if (LanguageRuntime *runtime = create_callback(process, language))
211
return runtime;
212
}
213
return nullptr;
214
}
215
216
LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {}
217
218
BreakpointPreconditionSP
219
LanguageRuntime::GetExceptionPrecondition(LanguageType language,
220
bool throw_bp) {
221
LanguageRuntimeCreateInstance create_callback;
222
for (uint32_t idx = 0;
223
(create_callback =
224
PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
225
nullptr;
226
idx++) {
227
if (auto precondition_callback =
228
PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(
229
idx)) {
230
if (BreakpointPreconditionSP precond =
231
precondition_callback(language, throw_bp))
232
return precond;
233
}
234
}
235
return BreakpointPreconditionSP();
236
}
237
238
BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
239
Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
240
bool is_internal) {
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);
253
254
if (is_internal)
255
exc_breakpt_sp->SetBreakpointKind("exception");
256
}
257
258
return exc_breakpt_sp;
259
}
260
261
UnwindPlanSP
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);
273
if (plan_sp.get())
274
return plan_sp;
275
}
276
}
277
return UnwindPlanSP();
278
}
279
280
void LanguageRuntime::InitializeCommands(CommandObject *parent) {
281
if (!parent)
282
return;
283
284
if (!parent->IsMultiwordObject())
285
return;
286
287
LanguageRuntimeCreateInstance create_callback;
288
289
for (uint32_t idx = 0;
290
(create_callback =
291
PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
292
nullptr;
293
++idx) {
294
if (LanguageRuntimeGetCommandObject command_callback =
295
PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
296
CommandObjectSP command =
297
command_callback(parent->GetCommandInterpreter());
298
if (command) {
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);
304
}
305
}
306
}
307
}
308
309