793 lines · cpp
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-exception6//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 25using namespace lldb;26using namespace lldb_private;27 28const 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 40const 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 54DYLDRendezvous::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 63addr_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 might75 // 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 the80 // 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%" PRIx64133 " returned a null value",134 __FUNCTION__, info_location);135 return LLDB_INVALID_ADDRESS;136 }137 138 return info_addr;139}140 141void 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 158void 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 = %" PRIu64161 " (%s), ldbase = 0x%16.16" PRIx64, label ? label : "", version,162 map_addr, brk, state, StateToCStr((RendezvousState)state), ldbase);163}164 165bool 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 else185 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 224bool DYLDRendezvous::IsValid() {225 return m_rendezvous_addr != LLDB_INVALID_ADDRESS;226}227 228DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const {229 // If we have a core file, we will read the current rendezvous state230 // from the core file's memory into m_current which can be in an inconsistent231 // state, so we can't rely on its state to determine what we should do. We232 // always need it to load all of the shared libraries one time when we attach233 // 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 first242 // time we have been asked to update. Just take a snapshot of the243 // currently loaded modules.244 case eConsistent:245 return eTakeSnapshot;246 // If we are about to add or remove a shared object clear out the current247 // 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 visible257 // symbol named "_r_debug", then it will cause problems once the executable258 // that contains the symbol is loaded into the process. The correct259 // "_r_debug" structure is currently found by LLDB by looking through260 // the .dynamic section in the main executable and finding the DT_DEBUG tag261 // 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 a270 // new "_r_debug" structure and it causes problems once the executable is271 // loaded due to the way symbol lookups happen in linux: the shared library272 // 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 dynamic274 // loader is always last in this list. So at some point the dynamic loader275 // will start updating the copy of "_r_debug" that gets found first. The276 // issue is that LLDB will only look at the copy that is pointed to by the277 // 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 the282 // .dynamic section and this points to the "_r_debug" in ld.so283 // - ld.so uodates its copy of "_r_debug" with "state = eAdd" before it284 // loads the dependent shared libraries for the main executable and285 // any dependencies of all shared libraries from the executable's list286 // and ld.so code calls the debugger notification function287 // that LLDB has set a breakpoint on.288 // - LLDB hits the breakpoint and the breakpoint has a callback function289 // where we read the _r_debug.state (eAdd) state and we do nothing as the290 // "eAdd" state indicates that the shared libraries are about to be added.291 // - ld.so finishes loading the main executable and any dependent shared292 // libraries and it will update the "_r_debug.state" member with a293 // "eConsistent", but it now updates the "_r_debug" in the a.out program294 // and it calls the debugger notification function.295 // - lldb hits the notification breakpoint and checks the ld.so copy of296 // "_r_debug.state" which still has a state of "eAdd", but LLDB needs to see a297 // "eConsistent" state to trigger the shared libraries to get loaded into298 // the debug session, but LLDB the ld.so _r_debug.state which still299 // 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 issue304 // and we now load shared libraries correctly and will emit a log message305 // in the "log enable lldb dyld" log channel which states there might be306 // multiple "_r_debug" structs causing problems.307 //308 // The correct solution is that no one should be adding a duplicate309 // publicly visible "_r_debug" symbols to their binaries, but we have310 // programs that are doing this already and since it can be done, we should311 // 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 existing314 // "_r_debug" structure as it is defined in this header file as "extern315 // 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 332bool 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 to344 // 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 370bool 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 390bool 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 ModuleInfos410 entry.next = 0;411 entry.prev = 0;412 entry.path_addr = 0;413 414 return true;415}416 417bool 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 435bool 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 465bool 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 498bool 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 526bool 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 544bool 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 as558 // 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 567bool 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 592addr_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 602addr_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 612std::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 the625// given entry. This function is used to handle cases where we want to work626// around a bug in the system linker.627static 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 637void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,638 std::string const &file_path) {639 // If the load bias reported by the linker is incorrect then fetch the load640 // 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 651void 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 664bool 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 and673 // NetBSD (need to validate other OSes).674 // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57675 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 706bool 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 and720 // fallback to reading from read only sections from the object files. Here we721 // are reading read only data from libpthread.so to find data in the thread722 // specific area for the data we want and this won't be saved into process723 // 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 bytes732 733 return true;734}735 736const 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 756void 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 790bool DYLDRendezvous::IsCoreFile() const {791 return !m_process->IsLiveDebugSession();792}793