Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
39653 views
1
//===-- DynamicLoaderHexagonDYLD.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/Breakpoint/BreakpointLocation.h"
10
#include "lldb/Core/Module.h"
11
#include "lldb/Core/ModuleSpec.h"
12
#include "lldb/Core/PluginManager.h"
13
#include "lldb/Core/Section.h"
14
#include "lldb/Symbol/ObjectFile.h"
15
#include "lldb/Target/Process.h"
16
#include "lldb/Target/Target.h"
17
#include "lldb/Target/Thread.h"
18
#include "lldb/Target/ThreadPlanRunToAddress.h"
19
#include "lldb/Utility/LLDBLog.h"
20
#include "lldb/Utility/Log.h"
21
22
#include "DynamicLoaderHexagonDYLD.h"
23
24
#include <memory>
25
26
using namespace lldb;
27
using namespace lldb_private;
28
29
LLDB_PLUGIN_DEFINE(DynamicLoaderHexagonDYLD)
30
31
// Aidan 21/05/2014
32
//
33
// Notes about hexagon dynamic loading:
34
//
35
// When we connect to a target we find the dyld breakpoint address. We put
36
// a
37
// breakpoint there with a callback 'RendezvousBreakpointHit()'.
38
//
39
// It is possible to find the dyld structure address from the ELF symbol
40
// table,
41
// but in the case of the simulator it has not been initialized before the
42
// target calls dlinit().
43
//
44
// We can only safely parse the dyld structure after we hit the dyld
45
// breakpoint
46
// since at that time we know dlinit() must have been called.
47
//
48
49
// Find the load address of a symbol
50
static lldb::addr_t findSymbolAddress(Process *proc, ConstString findName) {
51
assert(proc != nullptr);
52
53
ModuleSP module = proc->GetTarget().GetExecutableModule();
54
assert(module.get() != nullptr);
55
56
ObjectFile *exe = module->GetObjectFile();
57
assert(exe != nullptr);
58
59
lldb_private::Symtab *symtab = exe->GetSymtab();
60
assert(symtab != nullptr);
61
62
for (size_t i = 0; i < symtab->GetNumSymbols(); i++) {
63
const Symbol *sym = symtab->SymbolAtIndex(i);
64
assert(sym != nullptr);
65
ConstString symName = sym->GetName();
66
67
if (ConstString::Compare(findName, symName) == 0) {
68
Address addr = sym->GetAddress();
69
return addr.GetLoadAddress(&proc->GetTarget());
70
}
71
}
72
return LLDB_INVALID_ADDRESS;
73
}
74
75
void DynamicLoaderHexagonDYLD::Initialize() {
76
PluginManager::RegisterPlugin(GetPluginNameStatic(),
77
GetPluginDescriptionStatic(), CreateInstance);
78
}
79
80
void DynamicLoaderHexagonDYLD::Terminate() {}
81
82
llvm::StringRef DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic() {
83
return "Dynamic loader plug-in that watches for shared library "
84
"loads/unloads in Hexagon processes.";
85
}
86
87
DynamicLoader *DynamicLoaderHexagonDYLD::CreateInstance(Process *process,
88
bool force) {
89
bool create = force;
90
if (!create) {
91
const llvm::Triple &triple_ref =
92
process->GetTarget().GetArchitecture().GetTriple();
93
if (triple_ref.getArch() == llvm::Triple::hexagon)
94
create = true;
95
}
96
97
if (create)
98
return new DynamicLoaderHexagonDYLD(process);
99
return nullptr;
100
}
101
102
DynamicLoaderHexagonDYLD::DynamicLoaderHexagonDYLD(Process *process)
103
: DynamicLoader(process), m_rendezvous(process),
104
m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS),
105
m_dyld_bid(LLDB_INVALID_BREAK_ID) {}
106
107
DynamicLoaderHexagonDYLD::~DynamicLoaderHexagonDYLD() {
108
if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
109
m_process->GetTarget().RemoveBreakpointByID(m_dyld_bid);
110
m_dyld_bid = LLDB_INVALID_BREAK_ID;
111
}
112
}
113
114
void DynamicLoaderHexagonDYLD::DidAttach() {
115
ModuleSP executable;
116
addr_t load_offset;
117
118
executable = GetTargetExecutable();
119
120
// Find the difference between the desired load address in the elf file and
121
// the real load address in memory
122
load_offset = ComputeLoadOffset();
123
124
// Check that there is a valid executable
125
if (executable.get() == nullptr)
126
return;
127
128
// Disable JIT for hexagon targets because its not supported
129
m_process->SetCanJIT(false);
130
131
// Enable Interpreting of function call expressions
132
m_process->SetCanInterpretFunctionCalls(true);
133
134
// Add the current executable to the module list
135
ModuleList module_list;
136
module_list.Append(executable);
137
138
// Map the loaded sections of this executable
139
if (load_offset != LLDB_INVALID_ADDRESS)
140
UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
141
142
// AD: confirm this?
143
// Load into LLDB all of the currently loaded executables in the stub
144
LoadAllCurrentModules();
145
146
// AD: confirm this?
147
// Callback for the target to give it the loaded module list
148
m_process->GetTarget().ModulesDidLoad(module_list);
149
150
// Try to set a breakpoint at the rendezvous breakpoint. DidLaunch uses
151
// ProbeEntry() instead. That sets a breakpoint, at the dyld breakpoint
152
// address, with a callback so that when hit, the dyld structure can be
153
// parsed.
154
if (!SetRendezvousBreakpoint()) {
155
// fail
156
}
157
}
158
159
void DynamicLoaderHexagonDYLD::DidLaunch() {}
160
161
/// Checks to see if the target module has changed, updates the target
162
/// accordingly and returns the target executable module.
163
ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() {
164
Target &target = m_process->GetTarget();
165
ModuleSP executable = target.GetExecutableModule();
166
167
// There is no executable
168
if (!executable.get())
169
return executable;
170
171
// The target executable file does not exits
172
if (!FileSystem::Instance().Exists(executable->GetFileSpec()))
173
return executable;
174
175
// Prep module for loading
176
ModuleSpec module_spec(executable->GetFileSpec(),
177
executable->GetArchitecture());
178
ModuleSP module_sp(new Module(module_spec));
179
180
// Check if the executable has changed and set it to the target executable if
181
// they differ.
182
if (module_sp.get() && module_sp->GetUUID().IsValid() &&
183
executable->GetUUID().IsValid()) {
184
// if the executable has changed ??
185
if (module_sp->GetUUID() != executable->GetUUID())
186
executable.reset();
187
} else if (executable->FileHasChanged())
188
executable.reset();
189
190
if (executable.get())
191
return executable;
192
193
// TODO: What case is this code used?
194
executable = target.GetOrCreateModule(module_spec, true /* notify */);
195
if (executable.get() != target.GetExecutableModulePointer()) {
196
// Don't load dependent images since we are in dyld where we will know and
197
// find out about all images that are loaded
198
target.SetExecutableModule(executable, eLoadDependentsNo);
199
}
200
201
return executable;
202
}
203
204
// AD: Needs to be updated?
205
Status DynamicLoaderHexagonDYLD::CanLoadImage() { return Status(); }
206
207
void DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module,
208
addr_t link_map_addr,
209
addr_t base_addr,
210
bool base_addr_is_offset) {
211
Target &target = m_process->GetTarget();
212
const SectionList *sections = GetSectionListFromModule(module);
213
214
assert(sections && "SectionList missing from loaded module.");
215
216
m_loaded_modules[module] = link_map_addr;
217
218
const size_t num_sections = sections->GetSize();
219
220
for (unsigned i = 0; i < num_sections; ++i) {
221
SectionSP section_sp(sections->GetSectionAtIndex(i));
222
lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr;
223
224
// AD: 02/05/14
225
// since our memory map starts from address 0, we must not ignore
226
// sections that load to address 0. This violates the reference
227
// ELF spec, however is used for Hexagon.
228
229
// If the file address of the section is zero then this is not an
230
// allocatable/loadable section (property of ELF sh_addr). Skip it.
231
// if (new_load_addr == base_addr)
232
// continue;
233
234
target.SetSectionLoadAddress(section_sp, new_load_addr);
235
}
236
}
237
238
/// Removes the loaded sections from the target in \p module.
239
///
240
/// \param module The module to traverse.
241
void DynamicLoaderHexagonDYLD::UnloadSections(const ModuleSP module) {
242
Target &target = m_process->GetTarget();
243
const SectionList *sections = GetSectionListFromModule(module);
244
245
assert(sections && "SectionList missing from unloaded module.");
246
247
m_loaded_modules.erase(module);
248
249
const size_t num_sections = sections->GetSize();
250
for (size_t i = 0; i < num_sections; ++i) {
251
SectionSP section_sp(sections->GetSectionAtIndex(i));
252
target.SetSectionUnloaded(section_sp);
253
}
254
}
255
256
// Place a breakpoint on <_rtld_debug_state>
257
bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() {
258
Log *log = GetLog(LLDBLog::DynamicLoader);
259
260
// This is the original code, which want to look in the rendezvous structure
261
// to find the breakpoint address. Its backwards for us, since we can easily
262
// find the breakpoint address, since it is exported in our executable. We
263
// however know that we cant read the Rendezvous structure until we have hit
264
// the breakpoint once.
265
const ConstString dyldBpName("_rtld_debug_state");
266
addr_t break_addr = findSymbolAddress(m_process, dyldBpName);
267
268
Target &target = m_process->GetTarget();
269
270
// Do not try to set the breakpoint if we don't know where to put it
271
if (break_addr == LLDB_INVALID_ADDRESS) {
272
LLDB_LOGF(log, "Unable to locate _rtld_debug_state breakpoint address");
273
274
return false;
275
}
276
277
// Save the address of the rendezvous structure
278
m_rendezvous.SetBreakAddress(break_addr);
279
280
// If we haven't set the breakpoint before then set it
281
if (m_dyld_bid == LLDB_INVALID_BREAK_ID) {
282
Breakpoint *dyld_break =
283
target.CreateBreakpoint(break_addr, true, false).get();
284
dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
285
dyld_break->SetBreakpointKind("shared-library-event");
286
m_dyld_bid = dyld_break->GetID();
287
288
// Make sure our breakpoint is at the right address.
289
assert(target.GetBreakpointByID(m_dyld_bid)
290
->FindLocationByAddress(break_addr)
291
->GetBreakpoint()
292
.GetID() == m_dyld_bid);
293
294
if (log && dyld_break == nullptr)
295
LLDB_LOGF(log, "Failed to create _rtld_debug_state breakpoint");
296
297
// check we have successfully set bp
298
return (dyld_break != nullptr);
299
} else
300
// rendezvous already set
301
return true;
302
}
303
304
// We have just hit our breakpoint at <_rtld_debug_state>
305
bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit(
306
void *baton, StoppointCallbackContext *context, user_id_t break_id,
307
user_id_t break_loc_id) {
308
Log *log = GetLog(LLDBLog::DynamicLoader);
309
310
LLDB_LOGF(log, "Rendezvous breakpoint hit!");
311
312
DynamicLoaderHexagonDYLD *dyld_instance = nullptr;
313
dyld_instance = static_cast<DynamicLoaderHexagonDYLD *>(baton);
314
315
// if the dyld_instance is still not valid then try to locate it on the
316
// symbol table
317
if (!dyld_instance->m_rendezvous.IsValid()) {
318
Process *proc = dyld_instance->m_process;
319
320
const ConstString dyldStructName("_rtld_debug");
321
addr_t structAddr = findSymbolAddress(proc, dyldStructName);
322
323
if (structAddr != LLDB_INVALID_ADDRESS) {
324
dyld_instance->m_rendezvous.SetRendezvousAddress(structAddr);
325
326
LLDB_LOGF(log, "Found _rtld_debug structure @ 0x%08" PRIx64, structAddr);
327
} else {
328
LLDB_LOGF(log, "Unable to resolve the _rtld_debug structure");
329
}
330
}
331
332
dyld_instance->RefreshModules();
333
334
// Return true to stop the target, false to just let the target run.
335
return dyld_instance->GetStopWhenImagesChange();
336
}
337
338
/// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
339
/// of loaded modules.
340
void DynamicLoaderHexagonDYLD::RefreshModules() {
341
Log *log = GetLog(LLDBLog::DynamicLoader);
342
343
if (!m_rendezvous.Resolve())
344
return;
345
346
HexagonDYLDRendezvous::iterator I;
347
HexagonDYLDRendezvous::iterator E;
348
349
ModuleList &loaded_modules = m_process->GetTarget().GetImages();
350
351
if (m_rendezvous.ModulesDidLoad()) {
352
ModuleList new_modules;
353
354
E = m_rendezvous.loaded_end();
355
for (I = m_rendezvous.loaded_begin(); I != E; ++I) {
356
FileSpec file(I->path);
357
FileSystem::Instance().Resolve(file);
358
ModuleSP module_sp =
359
LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
360
if (module_sp.get()) {
361
loaded_modules.AppendIfNeeded(module_sp);
362
new_modules.Append(module_sp);
363
}
364
365
if (log) {
366
LLDB_LOGF(log, "Target is loading '%s'", I->path.c_str());
367
if (!module_sp.get())
368
LLDB_LOGF(log, "LLDB failed to load '%s'", I->path.c_str());
369
else
370
LLDB_LOGF(log, "LLDB successfully loaded '%s'", I->path.c_str());
371
}
372
}
373
m_process->GetTarget().ModulesDidLoad(new_modules);
374
}
375
376
if (m_rendezvous.ModulesDidUnload()) {
377
ModuleList old_modules;
378
379
E = m_rendezvous.unloaded_end();
380
for (I = m_rendezvous.unloaded_begin(); I != E; ++I) {
381
FileSpec file(I->path);
382
FileSystem::Instance().Resolve(file);
383
ModuleSpec module_spec(file);
384
ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec);
385
386
if (module_sp.get()) {
387
old_modules.Append(module_sp);
388
UnloadSections(module_sp);
389
}
390
391
LLDB_LOGF(log, "Target is unloading '%s'", I->path.c_str());
392
}
393
loaded_modules.Remove(old_modules);
394
m_process->GetTarget().ModulesDidUnload(old_modules, false);
395
}
396
}
397
398
// AD: This is very different to the Static Loader code.
399
// It may be wise to look over this and its relation to stack
400
// unwinding.
401
ThreadPlanSP
402
DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread &thread,
403
bool stop) {
404
ThreadPlanSP thread_plan_sp;
405
406
StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
407
const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
408
Symbol *sym = context.symbol;
409
410
if (sym == nullptr || !sym->IsTrampoline())
411
return thread_plan_sp;
412
413
const ConstString sym_name =
414
sym->GetMangled().GetName(Mangled::ePreferMangled);
415
if (!sym_name)
416
return thread_plan_sp;
417
418
SymbolContextList target_symbols;
419
Target &target = thread.GetProcess()->GetTarget();
420
const ModuleList &images = target.GetImages();
421
422
images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
423
if (target_symbols.GetSize() == 0)
424
return thread_plan_sp;
425
426
typedef std::vector<lldb::addr_t> AddressVector;
427
AddressVector addrs;
428
for (const SymbolContext &context : target_symbols) {
429
AddressRange range;
430
context.GetAddressRange(eSymbolContextEverything, 0, false, range);
431
lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
432
if (addr != LLDB_INVALID_ADDRESS)
433
addrs.push_back(addr);
434
}
435
436
if (addrs.size() > 0) {
437
AddressVector::iterator start = addrs.begin();
438
AddressVector::iterator end = addrs.end();
439
440
llvm::sort(start, end);
441
addrs.erase(std::unique(start, end), end);
442
thread_plan_sp =
443
std::make_shared<ThreadPlanRunToAddress>(thread, addrs, stop);
444
}
445
446
return thread_plan_sp;
447
}
448
449
/// Helper for the entry breakpoint callback. Resolves the load addresses
450
/// of all dependent modules.
451
void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() {
452
HexagonDYLDRendezvous::iterator I;
453
HexagonDYLDRendezvous::iterator E;
454
ModuleList module_list;
455
456
if (!m_rendezvous.Resolve()) {
457
Log *log = GetLog(LLDBLog::DynamicLoader);
458
LLDB_LOGF(
459
log,
460
"DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address",
461
__FUNCTION__);
462
return;
463
}
464
465
// The rendezvous class doesn't enumerate the main module, so track that
466
// ourselves here.
467
ModuleSP executable = GetTargetExecutable();
468
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
469
470
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) {
471
const char *module_path = I->path.c_str();
472
FileSpec file(module_path);
473
ModuleSP module_sp =
474
LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
475
if (module_sp.get()) {
476
module_list.Append(module_sp);
477
} else {
478
Log *log = GetLog(LLDBLog::DynamicLoader);
479
LLDB_LOGF(log,
480
"DynamicLoaderHexagonDYLD::%s failed loading module %s at "
481
"0x%" PRIx64,
482
__FUNCTION__, module_path, I->base_addr);
483
}
484
}
485
486
m_process->GetTarget().ModulesDidLoad(module_list);
487
}
488
489
/// Computes a value for m_load_offset returning the computed address on
490
/// success and LLDB_INVALID_ADDRESS on failure.
491
addr_t DynamicLoaderHexagonDYLD::ComputeLoadOffset() {
492
// Here we could send a GDB packet to know the load offset
493
//
494
// send: $qOffsets#4b
495
// get: Text=0;Data=0;Bss=0
496
//
497
// Currently qOffsets is not supported by pluginProcessGDBRemote
498
//
499
return 0;
500
}
501
502
// Here we must try to read the entry point directly from the elf header. This
503
// is possible if the process is not relocatable or dynamically linked.
504
//
505
// an alternative is to look at the PC if we can be sure that we have connected
506
// when the process is at the entry point.
507
// I dont think that is reliable for us.
508
addr_t DynamicLoaderHexagonDYLD::GetEntryPoint() {
509
if (m_entry_point != LLDB_INVALID_ADDRESS)
510
return m_entry_point;
511
// check we have a valid process
512
if (m_process == nullptr)
513
return LLDB_INVALID_ADDRESS;
514
// Get the current executable module
515
Module &module = *(m_process->GetTarget().GetExecutableModule().get());
516
// Get the object file (elf file) for this module
517
lldb_private::ObjectFile &object = *(module.GetObjectFile());
518
// Check if the file is executable (ie, not shared object or relocatable)
519
if (object.IsExecutable()) {
520
// Get the entry point address for this object
521
lldb_private::Address entry = object.GetEntryPointAddress();
522
// Return the entry point address
523
return entry.GetFileAddress();
524
}
525
// No idea so back out
526
return LLDB_INVALID_ADDRESS;
527
}
528
529
const SectionList *DynamicLoaderHexagonDYLD::GetSectionListFromModule(
530
const ModuleSP module) const {
531
SectionList *sections = nullptr;
532
if (module.get()) {
533
ObjectFile *obj_file = module->GetObjectFile();
534
if (obj_file) {
535
sections = obj_file->GetSectionList();
536
}
537
}
538
return sections;
539
}
540
541
static int ReadInt(Process *process, addr_t addr) {
542
Status error;
543
int value = (int)process->ReadUnsignedIntegerFromMemory(
544
addr, sizeof(uint32_t), 0, error);
545
if (error.Fail())
546
return -1;
547
else
548
return value;
549
}
550
551
lldb::addr_t
552
DynamicLoaderHexagonDYLD::GetThreadLocalData(const lldb::ModuleSP module,
553
const lldb::ThreadSP thread,
554
lldb::addr_t tls_file_addr) {
555
auto it = m_loaded_modules.find(module);
556
if (it == m_loaded_modules.end())
557
return LLDB_INVALID_ADDRESS;
558
559
addr_t link_map = it->second;
560
if (link_map == LLDB_INVALID_ADDRESS)
561
return LLDB_INVALID_ADDRESS;
562
563
const HexagonDYLDRendezvous::ThreadInfo &metadata =
564
m_rendezvous.GetThreadInfo();
565
if (!metadata.valid)
566
return LLDB_INVALID_ADDRESS;
567
568
// Get the thread pointer.
569
addr_t tp = thread->GetThreadPointer();
570
if (tp == LLDB_INVALID_ADDRESS)
571
return LLDB_INVALID_ADDRESS;
572
573
// Find the module's modid.
574
int modid = ReadInt(m_process, link_map + metadata.modid_offset);
575
if (modid == -1)
576
return LLDB_INVALID_ADDRESS;
577
578
// Lookup the DTV structure for this thread.
579
addr_t dtv_ptr = tp + metadata.dtv_offset;
580
addr_t dtv = ReadPointer(dtv_ptr);
581
if (dtv == LLDB_INVALID_ADDRESS)
582
return LLDB_INVALID_ADDRESS;
583
584
// Find the TLS block for this module.
585
addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid;
586
addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset);
587
588
Module *mod = module.get();
589
Log *log = GetLog(LLDBLog::DynamicLoader);
590
LLDB_LOGF(log,
591
"DynamicLoaderHexagonDYLD::Performed TLS lookup: "
592
"module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64
593
", modid=%i, tls_block=0x%" PRIx64,
594
mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
595
596
if (tls_block == LLDB_INVALID_ADDRESS)
597
return LLDB_INVALID_ADDRESS;
598
else
599
return tls_block + tls_file_addr;
600
}
601
602