1 //===-- DYLDRendezvous.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/Core/Module.h" 10 #include "lldb/Symbol/ObjectFile.h" 11 #include "lldb/Symbol/Symbol.h" 12 #include "lldb/Symbol/SymbolContext.h" 13 #include "lldb/Target/Platform.h" 14 #include "lldb/Target/Process.h" 15 #include "lldb/Target/Target.h" 16 #include "lldb/Utility/ArchSpec.h" 17 #include "lldb/Utility/LLDBLog.h" 18 #include "lldb/Utility/Log.h" 19 #include "lldb/Utility/Status.h" 20 21 #include "llvm/Support/Path.h" 22 23 #include "DYLDRendezvous.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 const char *DYLDRendezvous::StateToCStr(RendezvousState state) { 29 switch (state) { 30 case DYLDRendezvous::eConsistent: 31 return "eConsistent"; 32 case DYLDRendezvous::eAdd: 33 return "eAdd"; 34 case DYLDRendezvous::eDelete: 35 return "eDelete"; 36 } 37 return "<invalid RendezvousState>"; 38 } 39 40 const char *DYLDRendezvous::ActionToCStr(RendezvousAction action) { 41 switch (action) { 42 case DYLDRendezvous::RendezvousAction::eTakeSnapshot: 43 return "eTakeSnapshot"; 44 case DYLDRendezvous::RendezvousAction::eAddModules: 45 return "eAddModules"; 46 case DYLDRendezvous::RendezvousAction::eRemoveModules: 47 return "eRemoveModules"; 48 case DYLDRendezvous::RendezvousAction::eNoAction: 49 return "eNoAction"; 50 } 51 return "<invalid RendezvousAction>"; 52 } 53 54 DYLDRendezvous::DYLDRendezvous(Process *process) 55 : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), 56 m_executable_interpreter(false), m_current(), m_previous(), 57 m_loaded_modules(), m_soentries(), m_added_soentries(), 58 m_removed_soentries() { 59 m_thread_info.valid = false; 60 UpdateExecutablePath(); 61 } 62 63 addr_t DYLDRendezvous::ResolveRendezvousAddress() { 64 Log *log = GetLog(LLDBLog::DynamicLoader); 65 addr_t info_location; 66 addr_t info_addr; 67 Status error; 68 69 if (!m_process) { 70 LLDB_LOGF(log, "%s null process provided", __FUNCTION__); 71 return LLDB_INVALID_ADDRESS; 72 } 73 74 // Try to get it from our process. This might be a remote process and might 75 // grab it via some remote-specific mechanism. 76 info_location = m_process->GetImageInfoAddress(); 77 LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); 78 79 // If the process fails to return an address, fall back to seeing if the 80 // local object file can help us find it. 81 if (info_location == LLDB_INVALID_ADDRESS) { 82 Target *target = &m_process->GetTarget(); 83 if (target) { 84 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); 85 Address addr = obj_file->GetImageInfoAddress(target); 86 87 if (addr.IsValid()) { 88 info_location = addr.GetLoadAddress(target); 89 LLDB_LOGF(log, 90 "%s resolved via direct object file approach to 0x%" PRIx64, 91 __FUNCTION__, info_location); 92 } else { 93 const Symbol *_r_debug = 94 target->GetExecutableModule()->FindFirstSymbolWithNameAndType( 95 ConstString("_r_debug")); 96 if (_r_debug) { 97 info_addr = _r_debug->GetAddress().GetLoadAddress(target); 98 if (info_addr != LLDB_INVALID_ADDRESS) { 99 LLDB_LOGF(log, 100 "%s resolved by finding symbol '_r_debug' whose value is " 101 "0x%" PRIx64, 102 __FUNCTION__, info_addr); 103 m_executable_interpreter = true; 104 return info_addr; 105 } 106 } 107 LLDB_LOGF(log, 108 "%s FAILED - direct object file approach did not yield a " 109 "valid address", 110 __FUNCTION__); 111 } 112 } 113 } 114 115 if (info_location == LLDB_INVALID_ADDRESS) { 116 LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__); 117 return LLDB_INVALID_ADDRESS; 118 } 119 120 LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, 121 __FUNCTION__, m_process->GetAddressByteSize(), info_location); 122 123 info_addr = m_process->ReadPointerFromMemory(info_location, error); 124 if (error.Fail()) { 125 LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s", 126 __FUNCTION__, error.AsCString()); 127 return LLDB_INVALID_ADDRESS; 128 } 129 130 if (info_addr == 0) { 131 LLDB_LOGF(log, 132 "%s FAILED - the rendezvous address contained at 0x%" PRIx64 133 " returned a null value", 134 __FUNCTION__, info_location); 135 return LLDB_INVALID_ADDRESS; 136 } 137 138 return info_addr; 139 } 140 141 void DYLDRendezvous::UpdateExecutablePath() { 142 if (m_process) { 143 Log *log = GetLog(LLDBLog::DynamicLoader); 144 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer(); 145 if (exe_mod) { 146 m_exe_file_spec = exe_mod->GetPlatformFileSpec(); 147 LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'", 148 __FUNCTION__, m_exe_file_spec.GetPath().c_str()); 149 } else { 150 LLDB_LOGF(log, 151 "DYLDRendezvous::%s cannot cache exe module path: null " 152 "executable module pointer", 153 __FUNCTION__); 154 } 155 } 156 } 157 158 void DYLDRendezvous::Rendezvous::DumpToLog(Log *log, const char *label) { 159 LLDB_LOGF(log, "%s Rendezvous: version = %" PRIu64 ", map_addr = 0x%16.16" 160 PRIx64 ", brk = 0x%16.16" PRIx64 ", state = %" PRIu64 161 " (%s), ldbase = 0x%16.16" PRIx64, label ? label : "", version, 162 map_addr, brk, state, StateToCStr((RendezvousState)state), ldbase); 163 } 164 165 bool DYLDRendezvous::Resolve() { 166 Log *log = GetLog(LLDBLog::DynamicLoader); 167 168 const size_t word_size = 4; 169 Rendezvous info; 170 size_t address_size; 171 size_t padding; 172 addr_t info_addr; 173 addr_t cursor; 174 175 address_size = m_process->GetAddressByteSize(); 176 padding = address_size - word_size; 177 LLDB_LOGF(log, 178 "DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, 179 __FUNCTION__, uint64_t(address_size), uint64_t(padding)); 180 181 if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) 182 cursor = info_addr = 183 ResolveRendezvousAddress(); 184 else 185 cursor = info_addr = m_rendezvous_addr; 186 LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, 187 cursor); 188 189 if (cursor == LLDB_INVALID_ADDRESS) 190 return false; 191 192 if (!(cursor = ReadWord(cursor, &info.version, word_size))) 193 return false; 194 195 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr))) 196 return false; 197 198 if (!(cursor = ReadPointer(cursor, &info.brk))) 199 return false; 200 201 if (!(cursor = ReadWord(cursor, &info.state, word_size))) 202 return false; 203 204 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase))) 205 return false; 206 207 // The rendezvous was successfully read. Update our internal state. 208 m_rendezvous_addr = info_addr; 209 m_previous = m_current; 210 m_current = info; 211 212 m_previous.DumpToLog(log, "m_previous"); 213 m_current.DumpToLog(log, "m_current "); 214 215 if (m_current.map_addr == 0) 216 return false; 217 218 if (UpdateSOEntriesFromRemote()) 219 return true; 220 221 return UpdateSOEntries(); 222 } 223 224 bool DYLDRendezvous::IsValid() { 225 return m_rendezvous_addr != LLDB_INVALID_ADDRESS; 226 } 227 228 DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { 229 // If we have a core file, we will read the current rendezvous state 230 // from the core file's memory into m_current which can be in an inconsistent 231 // state, so we can't rely on its state to determine what we should do. We 232 // always need it to load all of the shared libraries one time when we attach 233 // to a core file. 234 if (IsCoreFile()) 235 return eTakeSnapshot; 236 237 switch (m_current.state) { 238 239 case eConsistent: 240 switch (m_previous.state) { 241 // When the previous and current states are consistent this is the first 242 // time we have been asked to update. Just take a snapshot of the 243 // currently loaded modules. 244 case eConsistent: 245 return eTakeSnapshot; 246 // If we are about to add or remove a shared object clear out the current 247 // state and take a snapshot of the currently loaded images. 248 case eAdd: 249 return eAddModules; 250 case eDelete: 251 return eRemoveModules; 252 } 253 break; 254 255 case eAdd: 256 // If the main executable or a shared library defines a publicly visible 257 // symbol named "_r_debug", then it will cause problems once the executable 258 // that contains the symbol is loaded into the process. The correct 259 // "_r_debug" structure is currently found by LLDB by looking through 260 // the .dynamic section in the main executable and finding the DT_DEBUG tag 261 // entry. 262 // 263 // An issue comes up if someone defines another publicly visible "_r_debug" 264 // struct in their program. Sample code looks like: 265 // 266 // #include <link.h> 267 // r_debug _r_debug; 268 // 269 // If code like this is in an executable or shared library, this creates a 270 // new "_r_debug" structure and it causes problems once the executable is 271 // loaded due to the way symbol lookups happen in linux: the shared library 272 // list from _r_debug.r_map will be searched for a symbol named "_r_debug" 273 // and the first match will be the new version that is used. The dynamic 274 // loader is always last in this list. So at some point the dynamic loader 275 // will start updating the copy of "_r_debug" that gets found first. The 276 // issue is that LLDB will only look at the copy that is pointed to by the 277 // DT_DEBUG entry, or the initial version from the ld.so binary. 278 // 279 // Steps that show the problem are: 280 // 281 // - LLDB finds the "_r_debug" structure via the DT_DEBUG entry in the 282 // .dynamic section and this points to the "_r_debug" in ld.so 283 // - ld.so uodates its copy of "_r_debug" with "state = eAdd" before it 284 // loads the dependent shared libraries for the main executable and 285 // any dependencies of all shared libraries from the executable's list 286 // and ld.so code calls the debugger notification function 287 // that LLDB has set a breakpoint on. 288 // - LLDB hits the breakpoint and the breakpoint has a callback function 289 // where we read the _r_debug.state (eAdd) state and we do nothing as the 290 // "eAdd" state indicates that the shared libraries are about to be added. 291 // - ld.so finishes loading the main executable and any dependent shared 292 // libraries and it will update the "_r_debug.state" member with a 293 // "eConsistent", but it now updates the "_r_debug" in the a.out program 294 // and it calls the debugger notification function. 295 // - lldb hits the notification breakpoint and checks the ld.so copy of 296 // "_r_debug.state" which still has a state of "eAdd", but LLDB needs to see a 297 // "eConsistent" state to trigger the shared libraries to get loaded into 298 // the debug session, but LLDB the ld.so _r_debug.state which still 299 // contains "eAdd" and doesn't do anyhing and library load is missed. 300 // The "_r_debug" in a.out has the state set correctly to "eConsistent" 301 // but LLDB is still looking at the "_r_debug" from ld.so. 302 // 303 // So if we detect two "eAdd" states in a row, we assume this is the issue 304 // and we now load shared libraries correctly and will emit a log message 305 // in the "log enable lldb dyld" log channel which states there might be 306 // multiple "_r_debug" structs causing problems. 307 // 308 // The correct solution is that no one should be adding a duplicate 309 // publicly visible "_r_debug" symbols to their binaries, but we have 310 // programs that are doing this already and since it can be done, we should 311 // be able to work with this and keep debug sessions working as expected. 312 // 313 // If a user includes the <link.h> file, they can just use the existing 314 // "_r_debug" structure as it is defined in this header file as "extern 315 // struct r_debug _r_debug;" and no local copies need to be made. 316 if (m_previous.state == eAdd) { 317 Log *log = GetLog(LLDBLog::DynamicLoader); 318 LLDB_LOG(log, "DYLDRendezvous::GetAction() found two eAdd states in a " 319 "row, check process for multiple \"_r_debug\" symbols. " 320 "Returning eAddModules to ensure shared libraries get loaded " 321 "correctly"); 322 return eAddModules; 323 } 324 return eNoAction; 325 case eDelete: 326 return eNoAction; 327 } 328 329 return eNoAction; 330 } 331 332 bool DYLDRendezvous::UpdateSOEntriesFromRemote() { 333 const auto action = GetAction(); 334 Log *log = GetLog(LLDBLog::DynamicLoader); 335 LLDB_LOG(log, "{0} action = {1}", LLVM_PRETTY_FUNCTION, ActionToCStr(action)); 336 337 if (action == eNoAction) 338 return false; 339 340 m_added_soentries.clear(); 341 m_removed_soentries.clear(); 342 if (action == eTakeSnapshot) { 343 // We already have the loaded list from the previous update so no need to 344 // find all the modules again. 345 if (!m_loaded_modules.m_list.empty()) 346 return true; 347 } 348 349 llvm::Expected<LoadedModuleInfoList> module_list = 350 m_process->GetLoadedModuleList(); 351 if (!module_list) { 352 llvm::consumeError(module_list.takeError()); 353 return false; 354 } 355 356 switch (action) { 357 case eTakeSnapshot: 358 m_soentries.clear(); 359 return SaveSOEntriesFromRemote(*module_list); 360 case eAddModules: 361 return AddSOEntriesFromRemote(*module_list); 362 case eRemoveModules: 363 return RemoveSOEntriesFromRemote(*module_list); 364 case eNoAction: 365 return false; 366 } 367 llvm_unreachable("Fully covered switch above!"); 368 } 369 370 bool DYLDRendezvous::UpdateSOEntries() { 371 m_added_soentries.clear(); 372 m_removed_soentries.clear(); 373 const auto action = GetAction(); 374 Log *log = GetLog(LLDBLog::DynamicLoader); 375 LLDB_LOG(log, "{0} action = {1}", LLVM_PRETTY_FUNCTION, ActionToCStr(action)); 376 switch (action) { 377 case eTakeSnapshot: 378 m_soentries.clear(); 379 return TakeSnapshot(m_soentries); 380 case eAddModules: 381 return AddSOEntries(); 382 case eRemoveModules: 383 return RemoveSOEntries(); 384 case eNoAction: 385 return false; 386 } 387 llvm_unreachable("Fully covered switch above!"); 388 } 389 390 bool DYLDRendezvous::FillSOEntryFromModuleInfo( 391 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) { 392 addr_t link_map_addr; 393 addr_t base_addr; 394 addr_t dyn_addr; 395 std::string name; 396 397 if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) || 398 !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name)) 399 return false; 400 401 entry.link_addr = link_map_addr; 402 entry.base_addr = base_addr; 403 entry.dyn_addr = dyn_addr; 404 405 entry.file_spec.SetFile(name, FileSpec::Style::native); 406 407 UpdateBaseAddrIfNecessary(entry, name); 408 409 // not needed if we're using ModuleInfos 410 entry.next = 0; 411 entry.prev = 0; 412 entry.path_addr = 0; 413 414 return true; 415 } 416 417 bool DYLDRendezvous::SaveSOEntriesFromRemote( 418 const LoadedModuleInfoList &module_list) { 419 for (auto const &modInfo : module_list.m_list) { 420 SOEntry entry; 421 if (!FillSOEntryFromModuleInfo(modInfo, entry)) 422 return false; 423 424 // Only add shared libraries and not the executable. 425 if (!SOEntryIsMainExecutable(entry)) { 426 UpdateFileSpecIfNecessary(entry); 427 m_soentries.push_back(entry); 428 } 429 } 430 431 m_loaded_modules = module_list; 432 return true; 433 } 434 435 bool DYLDRendezvous::AddSOEntriesFromRemote( 436 const LoadedModuleInfoList &module_list) { 437 for (auto const &modInfo : module_list.m_list) { 438 bool found = false; 439 for (auto const &existing : m_loaded_modules.m_list) { 440 if (modInfo == existing) { 441 found = true; 442 break; 443 } 444 } 445 446 if (found) 447 continue; 448 449 SOEntry entry; 450 if (!FillSOEntryFromModuleInfo(modInfo, entry)) 451 return false; 452 453 // Only add shared libraries and not the executable. 454 if (!SOEntryIsMainExecutable(entry)) { 455 UpdateFileSpecIfNecessary(entry); 456 m_soentries.push_back(entry); 457 m_added_soentries.push_back(entry); 458 } 459 } 460 461 m_loaded_modules = module_list; 462 return true; 463 } 464 465 bool DYLDRendezvous::RemoveSOEntriesFromRemote( 466 const LoadedModuleInfoList &module_list) { 467 for (auto const &existing : m_loaded_modules.m_list) { 468 bool found = false; 469 for (auto const &modInfo : module_list.m_list) { 470 if (modInfo == existing) { 471 found = true; 472 break; 473 } 474 } 475 476 if (found) 477 continue; 478 479 SOEntry entry; 480 if (!FillSOEntryFromModuleInfo(existing, entry)) 481 return false; 482 483 // Only add shared libraries and not the executable. 484 if (!SOEntryIsMainExecutable(entry)) { 485 auto pos = llvm::find(m_soentries, entry); 486 if (pos == m_soentries.end()) 487 return false; 488 489 m_soentries.erase(pos); 490 m_removed_soentries.push_back(entry); 491 } 492 } 493 494 m_loaded_modules = module_list; 495 return true; 496 } 497 498 bool DYLDRendezvous::AddSOEntries() { 499 SOEntry entry; 500 iterator pos; 501 502 assert(m_previous.state == eAdd); 503 504 if (m_current.map_addr == 0) 505 return false; 506 507 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) { 508 if (!ReadSOEntryFromMemory(cursor, entry)) 509 return false; 510 511 // Only add shared libraries and not the executable. 512 if (SOEntryIsMainExecutable(entry)) 513 continue; 514 515 UpdateFileSpecIfNecessary(entry); 516 517 if (!llvm::is_contained(m_soentries, entry)) { 518 m_soentries.push_back(entry); 519 m_added_soentries.push_back(entry); 520 } 521 } 522 523 return true; 524 } 525 526 bool DYLDRendezvous::RemoveSOEntries() { 527 SOEntryList entry_list; 528 iterator pos; 529 530 assert(m_previous.state == eDelete); 531 532 if (!TakeSnapshot(entry_list)) 533 return false; 534 535 for (iterator I = begin(); I != end(); ++I) { 536 if (!llvm::is_contained(entry_list, *I)) 537 m_removed_soentries.push_back(*I); 538 } 539 540 m_soentries = entry_list; 541 return true; 542 } 543 544 bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) { 545 // On some systes the executable is indicated by an empty path in the entry. 546 // On others it is the full path to the executable. 547 548 auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); 549 switch (triple.getOS()) { 550 case llvm::Triple::FreeBSD: 551 case llvm::Triple::NetBSD: 552 case llvm::Triple::OpenBSD: 553 return entry.file_spec == m_exe_file_spec; 554 case llvm::Triple::Linux: 555 if (triple.isAndroid()) 556 return entry.file_spec == m_exe_file_spec; 557 // If we are debugging ld.so, then all SOEntries should be treated as 558 // libraries, including the "main" one (denoted by an empty string). 559 if (!entry.file_spec && m_executable_interpreter) 560 return false; 561 return !entry.file_spec; 562 default: 563 return false; 564 } 565 } 566 567 bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) { 568 SOEntry entry; 569 570 if (m_current.map_addr == 0) 571 return false; 572 573 // Clear previous entries since we are about to obtain an up to date list. 574 entry_list.clear(); 575 576 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) { 577 if (!ReadSOEntryFromMemory(cursor, entry)) 578 return false; 579 580 // Only add shared libraries and not the executable. 581 if (SOEntryIsMainExecutable(entry)) 582 continue; 583 584 UpdateFileSpecIfNecessary(entry); 585 586 entry_list.push_back(entry); 587 } 588 589 return true; 590 } 591 592 addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) { 593 Status error; 594 595 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error); 596 if (error.Fail()) 597 return 0; 598 599 return addr + size; 600 } 601 602 addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) { 603 Status error; 604 605 *dst = m_process->ReadPointerFromMemory(addr, error); 606 if (error.Fail()) 607 return 0; 608 609 return addr + m_process->GetAddressByteSize(); 610 } 611 612 std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) { 613 std::string str; 614 Status error; 615 616 if (addr == LLDB_INVALID_ADDRESS) 617 return std::string(); 618 619 m_process->ReadCStringFromMemory(addr, str, error); 620 621 return str; 622 } 623 624 // Returns true if the load bias reported by the linker is incorrect for the 625 // given entry. This function is used to handle cases where we want to work 626 // around a bug in the system linker. 627 static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) { 628 // On Android L (API 21, 22) the load address of the "/system/bin/linker" 629 // isn't filled in correctly. 630 unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor(); 631 return target.GetArchitecture().GetTriple().isAndroid() && 632 (os_major == 21 || os_major == 22) && 633 (file_path == "/system/bin/linker" || 634 file_path == "/system/bin/linker64"); 635 } 636 637 void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry, 638 std::string const &file_path) { 639 // If the load bias reported by the linker is incorrect then fetch the load 640 // address of the file from the proc file system. 641 if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) { 642 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 643 bool is_loaded = false; 644 Status error = 645 m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr); 646 if (error.Success() && is_loaded) 647 entry.base_addr = load_addr; 648 } 649 } 650 651 void DYLDRendezvous::UpdateFileSpecIfNecessary(SOEntry &entry) { 652 // Updates filename if empty. It is useful while debugging ld.so, 653 // when the link map returns empty string for the main executable. 654 if (!entry.file_spec) { 655 MemoryRegionInfo region; 656 Status region_status = 657 m_process->GetMemoryRegionInfo(entry.dyn_addr, region); 658 if (!region.GetName().IsEmpty()) 659 entry.file_spec.SetFile(region.GetName().AsCString(), 660 FileSpec::Style::native); 661 } 662 } 663 664 bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { 665 entry.clear(); 666 667 entry.link_addr = addr; 668 669 if (!(addr = ReadPointer(addr, &entry.base_addr))) 670 return false; 671 672 // mips adds an extra load offset field to the link map struct on FreeBSD and 673 // NetBSD (need to validate other OSes). 674 // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57 675 const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); 676 if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD || 677 arch.GetTriple().getOS() == llvm::Triple::NetBSD) && 678 arch.IsMIPS()) { 679 addr_t mips_l_offs; 680 if (!(addr = ReadPointer(addr, &mips_l_offs))) 681 return false; 682 if (mips_l_offs != 0 && mips_l_offs != entry.base_addr) 683 return false; 684 } 685 686 if (!(addr = ReadPointer(addr, &entry.path_addr))) 687 return false; 688 689 if (!(addr = ReadPointer(addr, &entry.dyn_addr))) 690 return false; 691 692 if (!(addr = ReadPointer(addr, &entry.next))) 693 return false; 694 695 if (!(addr = ReadPointer(addr, &entry.prev))) 696 return false; 697 698 std::string file_path = ReadStringFromMemory(entry.path_addr); 699 entry.file_spec.SetFile(file_path, FileSpec::Style::native); 700 701 UpdateBaseAddrIfNecessary(entry, file_path); 702 703 return true; 704 } 705 706 bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field, 707 uint32_t &value) { 708 Target &target = m_process->GetTarget(); 709 710 SymbolContextList list; 711 target.GetImages().FindSymbolsWithNameAndType(ConstString(name), 712 eSymbolTypeAny, list); 713 if (list.IsEmpty()) 714 return false; 715 716 Address address = list[0].symbol->GetAddress(); 717 address.SetOffset(address.GetOffset() + field * sizeof(uint32_t)); 718 719 // Read from target memory as this allows us to try process memory and 720 // fallback to reading from read only sections from the object files. Here we 721 // are reading read only data from libpthread.so to find data in the thread 722 // specific area for the data we want and this won't be saved into process 723 // memory due to it being read only. 724 Status error; 725 value = 726 target.ReadUnsignedIntegerFromMemory(address, sizeof(uint32_t), 0, error); 727 if (error.Fail()) 728 return false; 729 730 if (field == eSize) 731 value /= 8; // convert bits to bytes 732 733 return true; 734 } 735 736 const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() { 737 if (!m_thread_info.valid) { 738 bool ok = true; 739 740 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset, 741 m_thread_info.dtv_offset); 742 ok &= 743 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size); 744 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset, 745 m_thread_info.modid_offset); 746 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset, 747 m_thread_info.tls_offset); 748 749 if (ok) 750 m_thread_info.valid = true; 751 } 752 753 return m_thread_info; 754 } 755 756 void DYLDRendezvous::DumpToLog(Log *log) const { 757 int state = GetState(); 758 759 if (!log) 760 return; 761 762 log->PutCString("DYLDRendezvous:"); 763 LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress()); 764 LLDB_LOGF(log, " Version: %" PRIu64, GetVersion()); 765 LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress()); 766 LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress()); 767 LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase()); 768 LLDB_LOGF(log, " State : %s", 769 (state == eConsistent) 770 ? "consistent" 771 : (state == eAdd) ? "add" 772 : (state == eDelete) ? "delete" : "unknown"); 773 774 iterator I = begin(); 775 iterator E = end(); 776 777 if (I != E) 778 log->PutCString("DYLDRendezvous SOEntries:"); 779 780 for (int i = 1; I != E; ++I, ++i) { 781 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetPath().c_str()); 782 LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); 783 LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); 784 LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); 785 LLDB_LOGF(log, " Next : %" PRIx64, I->next); 786 LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); 787 } 788 } 789 790 bool DYLDRendezvous::IsCoreFile() const { 791 return !m_process->IsLiveDebugSession(); 792 } 793