1 //===-- DynamicLoaderHexagonDYLD.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/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"
22 #include "DynamicLoaderHexagonDYLD.h"
27 using namespace lldb_private
;
29 LLDB_PLUGIN_DEFINE(DynamicLoaderHexagonDYLD
)
33 // Notes about hexagon dynamic loading:
35 // When we connect to a target we find the dyld breakpoint address. We put
37 // breakpoint there with a callback 'RendezvousBreakpointHit()'.
39 // It is possible to find the dyld structure address from the ELF symbol
41 // but in the case of the simulator it has not been initialized before the
42 // target calls dlinit().
44 // We can only safely parse the dyld structure after we hit the dyld
46 // since at that time we know dlinit() must have been called.
49 // Find the load address of a symbol
50 static lldb::addr_t
findSymbolAddress(Process
*proc
, ConstString findName
) {
51 assert(proc
!= nullptr);
53 ModuleSP module
= proc
->GetTarget().GetExecutableModule();
54 assert(module
.get() != nullptr);
56 ObjectFile
*exe
= module
->GetObjectFile();
57 assert(exe
!= nullptr);
59 lldb_private::Symtab
*symtab
= exe
->GetSymtab();
60 assert(symtab
!= nullptr);
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();
67 if (ConstString::Compare(findName
, symName
) == 0) {
68 Address addr
= sym
->GetAddress();
69 return addr
.GetLoadAddress(&proc
->GetTarget());
72 return LLDB_INVALID_ADDRESS
;
75 void DynamicLoaderHexagonDYLD::Initialize() {
76 PluginManager::RegisterPlugin(GetPluginNameStatic(),
77 GetPluginDescriptionStatic(), CreateInstance
);
80 void DynamicLoaderHexagonDYLD::Terminate() {}
82 llvm::StringRef
DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic() {
83 return "Dynamic loader plug-in that watches for shared library "
84 "loads/unloads in Hexagon processes.";
87 DynamicLoader
*DynamicLoaderHexagonDYLD::CreateInstance(Process
*process
,
91 const llvm::Triple
&triple_ref
=
92 process
->GetTarget().GetArchitecture().GetTriple();
93 if (triple_ref
.getArch() == llvm::Triple::hexagon
)
98 return new DynamicLoaderHexagonDYLD(process
);
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
) {}
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
;
114 void DynamicLoaderHexagonDYLD::DidAttach() {
118 executable
= GetTargetExecutable();
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();
124 // Check that there is a valid executable
125 if (executable
.get() == nullptr)
128 // Disable JIT for hexagon targets because its not supported
129 m_process
->SetCanJIT(false);
131 // Enable Interpreting of function call expressions
132 m_process
->SetCanInterpretFunctionCalls(true);
134 // Add the current executable to the module list
135 ModuleList module_list
;
136 module_list
.Append(executable
);
138 // Map the loaded sections of this executable
139 if (load_offset
!= LLDB_INVALID_ADDRESS
)
140 UpdateLoadedSections(executable
, LLDB_INVALID_ADDRESS
, load_offset
, true);
143 // Load into LLDB all of the currently loaded executables in the stub
144 LoadAllCurrentModules();
147 // Callback for the target to give it the loaded module list
148 m_process
->GetTarget().ModulesDidLoad(module_list
);
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
154 if (!SetRendezvousBreakpoint()) {
159 void DynamicLoaderHexagonDYLD::DidLaunch() {}
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();
167 // There is no executable
168 if (!executable
.get())
171 // The target executable file does not exits
172 if (!FileSystem::Instance().Exists(executable
->GetFileSpec()))
175 // Prep module for loading
176 ModuleSpec
module_spec(executable
->GetFileSpec(),
177 executable
->GetArchitecture());
178 ModuleSP
module_sp(new Module(module_spec
));
180 // Check if the executable has changed and set it to the target executable if
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())
187 } else if (executable
->FileHasChanged())
190 if (executable
.get())
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
);
204 // AD: Needs to be updated?
205 Status
DynamicLoaderHexagonDYLD::CanLoadImage() { return Status(); }
207 void DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module
,
208 addr_t link_map_addr
,
210 bool base_addr_is_offset
) {
211 Target
&target
= m_process
->GetTarget();
212 const SectionList
*sections
= GetSectionListFromModule(module
);
214 assert(sections
&& "SectionList missing from loaded module.");
216 m_loaded_modules
[module
] = link_map_addr
;
218 const size_t num_sections
= sections
->GetSize();
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
;
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.
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)
234 target
.SetSectionLoadAddress(section_sp
, new_load_addr
);
238 /// Removes the loaded sections from the target in \p module.
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
);
245 assert(sections
&& "SectionList missing from unloaded module.");
247 m_loaded_modules
.erase(module
);
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
);
256 // Place a breakpoint on <_rtld_debug_state>
257 bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() {
258 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
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
);
268 Target
&target
= m_process
->GetTarget();
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");
277 // Save the address of the rendezvous structure
278 m_rendezvous
.SetBreakAddress(break_addr
);
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();
288 // Make sure our breakpoint is at the right address.
289 assert(target
.GetBreakpointByID(m_dyld_bid
)
290 ->FindLocationByAddress(break_addr
)
292 .GetID() == m_dyld_bid
);
294 if (log
&& dyld_break
== nullptr)
295 LLDB_LOGF(log
, "Failed to create _rtld_debug_state breakpoint");
297 // check we have successfully set bp
298 return (dyld_break
!= nullptr);
300 // rendezvous already set
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
);
310 LLDB_LOGF(log
, "Rendezvous breakpoint hit!");
312 DynamicLoaderHexagonDYLD
*dyld_instance
= nullptr;
313 dyld_instance
= static_cast<DynamicLoaderHexagonDYLD
*>(baton
);
315 // if the dyld_instance is still not valid then try to locate it on the
317 if (!dyld_instance
->m_rendezvous
.IsValid()) {
318 Process
*proc
= dyld_instance
->m_process
;
320 const ConstString
dyldStructName("_rtld_debug");
321 addr_t structAddr
= findSymbolAddress(proc
, dyldStructName
);
323 if (structAddr
!= LLDB_INVALID_ADDRESS
) {
324 dyld_instance
->m_rendezvous
.SetRendezvousAddress(structAddr
);
326 LLDB_LOGF(log
, "Found _rtld_debug structure @ 0x%08" PRIx64
, structAddr
);
328 LLDB_LOGF(log
, "Unable to resolve the _rtld_debug structure");
332 dyld_instance
->RefreshModules();
334 // Return true to stop the target, false to just let the target run.
335 return dyld_instance
->GetStopWhenImagesChange();
338 /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
339 /// of loaded modules.
340 void DynamicLoaderHexagonDYLD::RefreshModules() {
341 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
343 if (!m_rendezvous
.Resolve())
346 HexagonDYLDRendezvous::iterator I
;
347 HexagonDYLDRendezvous::iterator E
;
349 ModuleList
&loaded_modules
= m_process
->GetTarget().GetImages();
351 if (m_rendezvous
.ModulesDidLoad()) {
352 ModuleList new_modules
;
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
);
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
);
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());
370 LLDB_LOGF(log
, "LLDB successfully loaded '%s'", I
->path
.c_str());
373 m_process
->GetTarget().ModulesDidLoad(new_modules
);
376 if (m_rendezvous
.ModulesDidUnload()) {
377 ModuleList old_modules
;
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
);
386 if (module_sp
.get()) {
387 old_modules
.Append(module_sp
);
388 UnloadSections(module_sp
);
391 LLDB_LOGF(log
, "Target is unloading '%s'", I
->path
.c_str());
393 loaded_modules
.Remove(old_modules
);
394 m_process
->GetTarget().ModulesDidUnload(old_modules
, false);
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
402 DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread
&thread
,
404 ThreadPlanSP thread_plan_sp
;
406 StackFrame
*frame
= thread
.GetStackFrameAtIndex(0).get();
407 const SymbolContext
&context
= frame
->GetSymbolContext(eSymbolContextSymbol
);
408 Symbol
*sym
= context
.symbol
;
410 if (sym
== nullptr || !sym
->IsTrampoline())
411 return thread_plan_sp
;
413 const ConstString sym_name
=
414 sym
->GetMangled().GetName(Mangled::ePreferMangled
);
416 return thread_plan_sp
;
418 SymbolContextList target_symbols
;
419 Target
&target
= thread
.GetProcess()->GetTarget();
420 const ModuleList
&images
= target
.GetImages();
422 images
.FindSymbolsWithNameAndType(sym_name
, eSymbolTypeCode
, target_symbols
);
423 if (target_symbols
.GetSize() == 0)
424 return thread_plan_sp
;
426 typedef std::vector
<lldb::addr_t
> AddressVector
;
428 for (const SymbolContext
&context
: target_symbols
) {
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
);
436 if (addrs
.size() > 0) {
437 AddressVector::iterator start
= addrs
.begin();
438 AddressVector::iterator end
= addrs
.end();
440 llvm::sort(start
, end
);
441 addrs
.erase(std::unique(start
, end
), end
);
443 std::make_shared
<ThreadPlanRunToAddress
>(thread
, addrs
, stop
);
446 return thread_plan_sp
;
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
;
456 if (!m_rendezvous
.Resolve()) {
457 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
460 "DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address",
465 // The rendezvous class doesn't enumerate the main module, so track that
467 ModuleSP executable
= GetTargetExecutable();
468 m_loaded_modules
[executable
] = m_rendezvous
.GetLinkMapAddress();
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
);
474 LoadModuleAtAddress(file
, I
->link_addr
, I
->base_addr
, true);
475 if (module_sp
.get()) {
476 module_list
.Append(module_sp
);
478 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
480 "DynamicLoaderHexagonDYLD::%s failed loading module %s at "
482 __FUNCTION__
, module_path
, I
->base_addr
);
486 m_process
->GetTarget().ModulesDidLoad(module_list
);
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
494 // send: $qOffsets#4b
495 // get: Text=0;Data=0;Bss=0
497 // Currently qOffsets is not supported by pluginProcessGDBRemote
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.
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();
525 // No idea so back out
526 return LLDB_INVALID_ADDRESS
;
529 const SectionList
*DynamicLoaderHexagonDYLD::GetSectionListFromModule(
530 const ModuleSP module
) const {
531 SectionList
*sections
= nullptr;
533 ObjectFile
*obj_file
= module
->GetObjectFile();
535 sections
= obj_file
->GetSectionList();
541 static int ReadInt(Process
*process
, addr_t addr
) {
543 int value
= (int)process
->ReadUnsignedIntegerFromMemory(
544 addr
, sizeof(uint32_t), 0, error
);
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
;
559 addr_t link_map
= it
->second
;
560 if (link_map
== LLDB_INVALID_ADDRESS
)
561 return LLDB_INVALID_ADDRESS
;
563 const HexagonDYLDRendezvous::ThreadInfo
&metadata
=
564 m_rendezvous
.GetThreadInfo();
566 return LLDB_INVALID_ADDRESS
;
568 // Get the thread pointer.
569 addr_t tp
= thread
->GetThreadPointer();
570 if (tp
== LLDB_INVALID_ADDRESS
)
571 return LLDB_INVALID_ADDRESS
;
573 // Find the module's modid.
574 int modid
= ReadInt(m_process
, link_map
+ metadata
.modid_offset
);
576 return LLDB_INVALID_ADDRESS
;
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
;
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
);
588 Module
*mod
= module
.get();
589 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
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
);
596 if (tls_block
== LLDB_INVALID_ADDRESS
)
597 return LLDB_INVALID_ADDRESS
;
599 return tls_block
+ tls_file_addr
;