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