Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
39644 views
1
//===-- JITLoaderGDB.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 "JITLoaderGDB.h"
10
#ifdef LLDB_ENABLE_ALL
11
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
12
#endif // LLDB_ENABLE_ALL
13
#include "lldb/Breakpoint/Breakpoint.h"
14
#include "lldb/Core/Module.h"
15
#include "lldb/Core/ModuleSpec.h"
16
#include "lldb/Core/PluginManager.h"
17
#include "lldb/Core/Section.h"
18
#include "lldb/Interpreter/OptionValueProperties.h"
19
#include "lldb/Symbol/ObjectFile.h"
20
#include "lldb/Symbol/Symbol.h"
21
#include "lldb/Symbol/SymbolContext.h"
22
#include "lldb/Symbol/SymbolVendor.h"
23
#include "lldb/Target/Process.h"
24
#include "lldb/Target/SectionLoadList.h"
25
#include "lldb/Target/Target.h"
26
#include "lldb/Utility/DataBufferHeap.h"
27
#include "lldb/Utility/LLDBAssert.h"
28
#include "lldb/Utility/LLDBLog.h"
29
#include "lldb/Utility/Log.h"
30
#include "lldb/Utility/StreamString.h"
31
#include "llvm/Support/MathExtras.h"
32
33
#include <memory>
34
35
using namespace lldb;
36
using namespace lldb_private;
37
38
LLDB_PLUGIN_DEFINE(JITLoaderGDB)
39
40
namespace {
41
// Debug Interface Structures
42
enum jit_actions_t { JIT_NOACTION = 0, JIT_REGISTER_FN, JIT_UNREGISTER_FN };
43
44
template <typename ptr_t> struct jit_code_entry {
45
ptr_t next_entry; // pointer
46
ptr_t prev_entry; // pointer
47
ptr_t symfile_addr; // pointer
48
uint64_t symfile_size;
49
};
50
51
template <typename ptr_t> struct jit_descriptor {
52
uint32_t version;
53
uint32_t action_flag; // Values are jit_action_t
54
ptr_t relevant_entry; // pointer
55
ptr_t first_entry; // pointer
56
};
57
58
enum EnableJITLoaderGDB {
59
eEnableJITLoaderGDBDefault,
60
eEnableJITLoaderGDBOn,
61
eEnableJITLoaderGDBOff,
62
};
63
64
static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] =
65
{
66
{
67
eEnableJITLoaderGDBDefault,
68
"default",
69
"Enable JIT compilation interface for all platforms except macOS",
70
},
71
{
72
eEnableJITLoaderGDBOn,
73
"on",
74
"Enable JIT compilation interface",
75
},
76
{
77
eEnableJITLoaderGDBOff,
78
"off",
79
"Disable JIT compilation interface",
80
},
81
};
82
83
#define LLDB_PROPERTIES_jitloadergdb
84
#include "JITLoaderGDBProperties.inc"
85
86
enum {
87
#define LLDB_PROPERTIES_jitloadergdb
88
#include "JITLoaderGDBPropertiesEnum.inc"
89
ePropertyEnableJITBreakpoint
90
};
91
92
class PluginProperties : public Properties {
93
public:
94
static llvm::StringRef GetSettingName() {
95
return JITLoaderGDB::GetPluginNameStatic();
96
}
97
98
PluginProperties() {
99
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
100
m_collection_sp->Initialize(g_jitloadergdb_properties);
101
}
102
103
EnableJITLoaderGDB GetEnable() const {
104
return GetPropertyAtIndexAs<EnableJITLoaderGDB>(
105
ePropertyEnable,
106
static_cast<EnableJITLoaderGDB>(
107
g_jitloadergdb_properties[ePropertyEnable].default_uint_value));
108
}
109
};
110
} // namespace
111
112
static PluginProperties &GetGlobalPluginProperties() {
113
static PluginProperties g_settings;
114
return g_settings;
115
}
116
117
template <typename ptr_t>
118
static bool ReadJITEntry(const addr_t from_addr, Process *process,
119
jit_code_entry<ptr_t> *entry) {
120
lldbassert(from_addr % sizeof(ptr_t) == 0);
121
122
ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore();
123
bool i386_target = ArchSpec::kCore_x86_32_first <= core &&
124
core <= ArchSpec::kCore_x86_32_last;
125
uint8_t uint64_align_bytes = i386_target ? 4 : 8;
126
const size_t data_byte_size =
127
llvm::alignTo(sizeof(ptr_t) * 3, uint64_align_bytes) + sizeof(uint64_t);
128
129
Status error;
130
DataBufferHeap data(data_byte_size, 0);
131
size_t bytes_read = process->ReadMemory(from_addr, data.GetBytes(),
132
data.GetByteSize(), error);
133
if (bytes_read != data_byte_size || !error.Success())
134
return false;
135
136
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
137
process->GetByteOrder(), sizeof(ptr_t));
138
lldb::offset_t offset = 0;
139
entry->next_entry = extractor.GetAddress(&offset);
140
entry->prev_entry = extractor.GetAddress(&offset);
141
entry->symfile_addr = extractor.GetAddress(&offset);
142
offset = llvm::alignTo(offset, uint64_align_bytes);
143
entry->symfile_size = extractor.GetU64(&offset);
144
145
return true;
146
}
147
148
JITLoaderGDB::JITLoaderGDB(lldb_private::Process *process)
149
: JITLoader(process), m_jit_objects(),
150
m_jit_break_id(LLDB_INVALID_BREAK_ID),
151
m_jit_descriptor_addr(LLDB_INVALID_ADDRESS) {}
152
153
JITLoaderGDB::~JITLoaderGDB() {
154
if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
155
m_process->GetTarget().RemoveBreakpointByID(m_jit_break_id);
156
}
157
158
void JITLoaderGDB::DebuggerInitialize(Debugger &debugger) {
159
if (!PluginManager::GetSettingForJITLoaderPlugin(
160
debugger, PluginProperties::GetSettingName())) {
161
const bool is_global_setting = true;
162
PluginManager::CreateSettingForJITLoaderPlugin(
163
debugger, GetGlobalPluginProperties().GetValueProperties(),
164
"Properties for the JIT LoaderGDB plug-in.", is_global_setting);
165
}
166
}
167
168
void JITLoaderGDB::DidAttach() {
169
Target &target = m_process->GetTarget();
170
ModuleList &module_list = target.GetImages();
171
SetJITBreakpoint(module_list);
172
}
173
174
void JITLoaderGDB::DidLaunch() {
175
Target &target = m_process->GetTarget();
176
ModuleList &module_list = target.GetImages();
177
SetJITBreakpoint(module_list);
178
}
179
180
void JITLoaderGDB::ModulesDidLoad(ModuleList &module_list) {
181
if (!DidSetJITBreakpoint() && m_process->IsAlive())
182
SetJITBreakpoint(module_list);
183
}
184
185
// Setup the JIT Breakpoint
186
void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) {
187
if (DidSetJITBreakpoint())
188
return;
189
190
Log *log = GetLog(LLDBLog::JITLoader);
191
LLDB_LOGF(log, "JITLoaderGDB::%s looking for JIT register hook",
192
__FUNCTION__);
193
194
addr_t jit_addr = GetSymbolAddress(
195
module_list, ConstString("__jit_debug_register_code"), eSymbolTypeCode);
196
if (jit_addr == LLDB_INVALID_ADDRESS)
197
return;
198
199
m_jit_descriptor_addr = GetSymbolAddress(
200
module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData);
201
if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) {
202
LLDB_LOGF(log, "JITLoaderGDB::%s failed to find JIT descriptor address",
203
__FUNCTION__);
204
return;
205
}
206
207
LLDB_LOGF(log, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__);
208
209
Breakpoint *bp =
210
m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
211
bp->SetCallback(JITDebugBreakpointHit, this, true);
212
bp->SetBreakpointKind("jit-debug-register");
213
m_jit_break_id = bp->GetID();
214
215
ReadJITDescriptor(true);
216
}
217
218
bool JITLoaderGDB::JITDebugBreakpointHit(void *baton,
219
StoppointCallbackContext *context,
220
user_id_t break_id,
221
user_id_t break_loc_id) {
222
Log *log = GetLog(LLDBLog::JITLoader);
223
LLDB_LOGF(log, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__);
224
JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
225
return instance->ReadJITDescriptor(false);
226
}
227
228
static void updateSectionLoadAddress(const SectionList &section_list,
229
Target &target, uint64_t symbolfile_addr,
230
uint64_t symbolfile_size,
231
uint64_t &vmaddrheuristic,
232
uint64_t &min_addr, uint64_t &max_addr) {
233
const uint32_t num_sections = section_list.GetSize();
234
for (uint32_t i = 0; i < num_sections; ++i) {
235
SectionSP section_sp(section_list.GetSectionAtIndex(i));
236
if (section_sp) {
237
if (section_sp->IsFake()) {
238
uint64_t lower = (uint64_t)-1;
239
uint64_t upper = 0;
240
updateSectionLoadAddress(section_sp->GetChildren(), target,
241
symbolfile_addr, symbolfile_size,
242
vmaddrheuristic, lower, upper);
243
if (lower < min_addr)
244
min_addr = lower;
245
if (upper > max_addr)
246
max_addr = upper;
247
const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress();
248
section_sp->Slide(slide_amount, false);
249
section_sp->GetChildren().Slide(-slide_amount, false);
250
section_sp->SetByteSize(upper - lower);
251
} else {
252
vmaddrheuristic += 2 << section_sp->GetLog2Align();
253
uint64_t lower;
254
if (section_sp->GetFileAddress() > vmaddrheuristic)
255
lower = section_sp->GetFileAddress();
256
else {
257
lower = symbolfile_addr + section_sp->GetFileOffset();
258
section_sp->SetFileAddress(symbolfile_addr +
259
section_sp->GetFileOffset());
260
}
261
target.SetSectionLoadAddress(section_sp, lower, true);
262
uint64_t upper = lower + section_sp->GetByteSize();
263
if (lower < min_addr)
264
min_addr = lower;
265
if (upper > max_addr)
266
max_addr = upper;
267
// This is an upper bound, but a good enough heuristic
268
vmaddrheuristic += section_sp->GetByteSize();
269
}
270
}
271
}
272
}
273
274
bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) {
275
if (m_process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
276
return ReadJITDescriptorImpl<uint64_t>(all_entries);
277
else
278
return ReadJITDescriptorImpl<uint32_t>(all_entries);
279
}
280
281
template <typename ptr_t>
282
bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) {
283
if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
284
return false;
285
286
Log *log = GetLog(LLDBLog::JITLoader);
287
Target &target = m_process->GetTarget();
288
ModuleList &module_list = target.GetImages();
289
290
jit_descriptor<ptr_t> jit_desc;
291
const size_t jit_desc_size = sizeof(jit_desc);
292
Status error;
293
size_t bytes_read = m_process->ReadMemory(m_jit_descriptor_addr, &jit_desc,
294
jit_desc_size, error);
295
if (bytes_read != jit_desc_size || !error.Success()) {
296
LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT descriptor",
297
__FUNCTION__);
298
return false;
299
}
300
301
jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
302
addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
303
if (all_entries) {
304
jit_action = JIT_REGISTER_FN;
305
jit_relevant_entry = (addr_t)jit_desc.first_entry;
306
}
307
308
while (jit_relevant_entry != 0) {
309
jit_code_entry<ptr_t> jit_entry;
310
if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) {
311
LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
312
__FUNCTION__, jit_relevant_entry);
313
return false;
314
}
315
316
const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
317
const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
318
ModuleSP module_sp;
319
320
if (jit_action == JIT_REGISTER_FN) {
321
LLDB_LOGF(log,
322
"JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
323
" (%" PRIu64 " bytes)",
324
__FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size);
325
326
char jit_name[64];
327
snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
328
module_sp = m_process->ReadModuleFromMemory(
329
FileSpec(jit_name), symbolfile_addr, symbolfile_size);
330
331
if (module_sp && module_sp->GetObjectFile()) {
332
// Object formats (like ELF) have no representation for a JIT type.
333
// We will get it wrong, if we deduce it from the header.
334
module_sp->GetObjectFile()->SetType(ObjectFile::eTypeJIT);
335
336
// load the symbol table right away
337
module_sp->GetObjectFile()->GetSymtab();
338
339
m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp));
340
#ifdef LLDB_ENABLE_ALL
341
if (auto image_object_file =
342
llvm::dyn_cast<ObjectFileMachO>(module_sp->GetObjectFile())) {
343
const SectionList *section_list = image_object_file->GetSectionList();
344
if (section_list) {
345
uint64_t vmaddrheuristic = 0;
346
uint64_t lower = (uint64_t)-1;
347
uint64_t upper = 0;
348
updateSectionLoadAddress(*section_list, target, symbolfile_addr,
349
symbolfile_size, vmaddrheuristic, lower,
350
upper);
351
}
352
} else
353
#endif // LLDB_ENABLE_ALL
354
{
355
bool changed = false;
356
module_sp->SetLoadAddress(target, 0, true, changed);
357
}
358
359
module_list.AppendIfNeeded(module_sp);
360
361
ModuleList module_list;
362
module_list.Append(module_sp);
363
target.ModulesDidLoad(module_list);
364
} else {
365
LLDB_LOGF(log,
366
"JITLoaderGDB::%s failed to load module for "
367
"JIT entry at 0x%" PRIx64,
368
__FUNCTION__, symbolfile_addr);
369
}
370
} else if (jit_action == JIT_UNREGISTER_FN) {
371
LLDB_LOGF(log, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
372
__FUNCTION__, symbolfile_addr);
373
374
JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
375
if (it != m_jit_objects.end()) {
376
module_sp = it->second;
377
ObjectFile *image_object_file = module_sp->GetObjectFile();
378
if (image_object_file) {
379
const SectionList *section_list = image_object_file->GetSectionList();
380
if (section_list) {
381
const uint32_t num_sections = section_list->GetSize();
382
for (uint32_t i = 0; i < num_sections; ++i) {
383
SectionSP section_sp(section_list->GetSectionAtIndex(i));
384
if (section_sp) {
385
target.GetSectionLoadList().SetSectionUnloaded(section_sp);
386
}
387
}
388
}
389
}
390
module_list.Remove(module_sp);
391
m_jit_objects.erase(it);
392
}
393
} else if (jit_action == JIT_NOACTION) {
394
// Nothing to do
395
} else {
396
assert(false && "Unknown jit action");
397
}
398
399
if (all_entries)
400
jit_relevant_entry = (addr_t)jit_entry.next_entry;
401
else
402
jit_relevant_entry = 0;
403
}
404
405
return false; // Continue Running.
406
}
407
408
// PluginInterface protocol
409
JITLoaderSP JITLoaderGDB::CreateInstance(Process *process, bool force) {
410
JITLoaderSP jit_loader_sp;
411
bool enable;
412
switch (GetGlobalPluginProperties().GetEnable()) {
413
case EnableJITLoaderGDB::eEnableJITLoaderGDBOn:
414
enable = true;
415
break;
416
case EnableJITLoaderGDB::eEnableJITLoaderGDBOff:
417
enable = false;
418
break;
419
case EnableJITLoaderGDB::eEnableJITLoaderGDBDefault:
420
ArchSpec arch(process->GetTarget().GetArchitecture());
421
enable = arch.GetTriple().getVendor() != llvm::Triple::Apple;
422
break;
423
}
424
if (enable)
425
jit_loader_sp = std::make_shared<JITLoaderGDB>(process);
426
return jit_loader_sp;
427
}
428
429
llvm::StringRef JITLoaderGDB::GetPluginDescriptionStatic() {
430
return "JIT loader plug-in that watches for JIT events using the GDB "
431
"interface.";
432
}
433
434
void JITLoaderGDB::Initialize() {
435
PluginManager::RegisterPlugin(GetPluginNameStatic(),
436
GetPluginDescriptionStatic(), CreateInstance,
437
DebuggerInitialize);
438
}
439
440
void JITLoaderGDB::Terminate() {
441
PluginManager::UnregisterPlugin(CreateInstance);
442
}
443
444
bool JITLoaderGDB::DidSetJITBreakpoint() const {
445
return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
446
}
447
448
addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list,
449
ConstString name,
450
SymbolType symbol_type) const {
451
SymbolContextList target_symbols;
452
Target &target = m_process->GetTarget();
453
454
module_list.FindSymbolsWithNameAndType(name, symbol_type, target_symbols);
455
if (target_symbols.IsEmpty())
456
return LLDB_INVALID_ADDRESS;
457
458
SymbolContext sym_ctx;
459
target_symbols.GetContextAtIndex(0, sym_ctx);
460
461
const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress();
462
if (!jit_descriptor_addr.IsValid())
463
return LLDB_INVALID_ADDRESS;
464
465
const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target);
466
return jit_addr;
467
}
468
469