Path: blob/main/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
39653 views
//===-- DYLDRendezvous.cpp ------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Core/Module.h"9#include "lldb/Symbol/ObjectFile.h"10#include "lldb/Symbol/Symbol.h"11#include "lldb/Symbol/SymbolContext.h"12#include "lldb/Target/Platform.h"13#include "lldb/Target/Process.h"14#include "lldb/Target/Target.h"15#include "lldb/Utility/ArchSpec.h"16#include "lldb/Utility/LLDBLog.h"17#include "lldb/Utility/Log.h"18#include "lldb/Utility/Status.h"1920#include "llvm/Support/Path.h"2122#include "DYLDRendezvous.h"2324using namespace lldb;25using namespace lldb_private;2627const char *DYLDRendezvous::StateToCStr(RendezvousState state) {28switch (state) {29case DYLDRendezvous::eConsistent:30return "eConsistent";31case DYLDRendezvous::eAdd:32return "eAdd";33case DYLDRendezvous::eDelete:34return "eDelete";35}36return "<invalid RendezvousState>";37}3839const char *DYLDRendezvous::ActionToCStr(RendezvousAction action) {40switch (action) {41case DYLDRendezvous::RendezvousAction::eTakeSnapshot:42return "eTakeSnapshot";43case DYLDRendezvous::RendezvousAction::eAddModules:44return "eAddModules";45case DYLDRendezvous::RendezvousAction::eRemoveModules:46return "eRemoveModules";47case DYLDRendezvous::RendezvousAction::eNoAction:48return "eNoAction";49}50return "<invalid RendezvousAction>";51}5253DYLDRendezvous::DYLDRendezvous(Process *process)54: m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS),55m_executable_interpreter(false), m_current(), m_previous(),56m_loaded_modules(), m_soentries(), m_added_soentries(),57m_removed_soentries() {58m_thread_info.valid = false;59UpdateExecutablePath();60}6162addr_t DYLDRendezvous::ResolveRendezvousAddress() {63Log *log = GetLog(LLDBLog::DynamicLoader);64addr_t info_location;65addr_t info_addr;66Status error;6768if (!m_process) {69LLDB_LOGF(log, "%s null process provided", __FUNCTION__);70return LLDB_INVALID_ADDRESS;71}7273// Try to get it from our process. This might be a remote process and might74// grab it via some remote-specific mechanism.75info_location = m_process->GetImageInfoAddress();76LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);7778// If the process fails to return an address, fall back to seeing if the79// local object file can help us find it.80if (info_location == LLDB_INVALID_ADDRESS) {81Target *target = &m_process->GetTarget();82if (target) {83ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();84Address addr = obj_file->GetImageInfoAddress(target);8586if (addr.IsValid()) {87info_location = addr.GetLoadAddress(target);88LLDB_LOGF(log,89"%s resolved via direct object file approach to 0x%" PRIx64,90__FUNCTION__, info_location);91} else {92const Symbol *_r_debug =93target->GetExecutableModule()->FindFirstSymbolWithNameAndType(94ConstString("_r_debug"));95if (_r_debug) {96info_addr = _r_debug->GetAddress().GetLoadAddress(target);97if (info_addr != LLDB_INVALID_ADDRESS) {98LLDB_LOGF(log,99"%s resolved by finding symbol '_r_debug' whose value is "100"0x%" PRIx64,101__FUNCTION__, info_addr);102m_executable_interpreter = true;103return info_addr;104}105}106LLDB_LOGF(log,107"%s FAILED - direct object file approach did not yield a "108"valid address",109__FUNCTION__);110}111}112}113114if (info_location == LLDB_INVALID_ADDRESS) {115LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__);116return LLDB_INVALID_ADDRESS;117}118119LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64,120__FUNCTION__, m_process->GetAddressByteSize(), info_location);121122info_addr = m_process->ReadPointerFromMemory(info_location, error);123if (error.Fail()) {124LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s",125__FUNCTION__, error.AsCString());126return LLDB_INVALID_ADDRESS;127}128129if (info_addr == 0) {130LLDB_LOGF(log,131"%s FAILED - the rendezvous address contained at 0x%" PRIx64132" returned a null value",133__FUNCTION__, info_location);134return LLDB_INVALID_ADDRESS;135}136137return info_addr;138}139140void DYLDRendezvous::UpdateExecutablePath() {141if (m_process) {142Log *log = GetLog(LLDBLog::DynamicLoader);143Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();144if (exe_mod) {145m_exe_file_spec = exe_mod->GetPlatformFileSpec();146LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'",147__FUNCTION__, m_exe_file_spec.GetPath().c_str());148} else {149LLDB_LOGF(log,150"DYLDRendezvous::%s cannot cache exe module path: null "151"executable module pointer",152__FUNCTION__);153}154}155}156157void DYLDRendezvous::Rendezvous::DumpToLog(Log *log, const char *label) {158LLDB_LOGF(log, "%s Rendezvous: version = %" PRIu64 ", map_addr = 0x%16.16"159PRIx64 ", brk = 0x%16.16" PRIx64 ", state = %" PRIu64160" (%s), ldbase = 0x%16.16" PRIx64, label ? label : "", version,161map_addr, brk, state, StateToCStr((RendezvousState)state), ldbase);162}163164bool DYLDRendezvous::Resolve() {165Log *log = GetLog(LLDBLog::DynamicLoader);166167const size_t word_size = 4;168Rendezvous info;169size_t address_size;170size_t padding;171addr_t info_addr;172addr_t cursor;173174address_size = m_process->GetAddressByteSize();175padding = address_size - word_size;176LLDB_LOGF(log,177"DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64,178__FUNCTION__, uint64_t(address_size), uint64_t(padding));179180if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)181cursor = info_addr =182ResolveRendezvousAddress();183else184cursor = info_addr = m_rendezvous_addr;185LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__,186cursor);187188if (cursor == LLDB_INVALID_ADDRESS)189return false;190191if (!(cursor = ReadWord(cursor, &info.version, word_size)))192return false;193194if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))195return false;196197if (!(cursor = ReadPointer(cursor, &info.brk)))198return false;199200if (!(cursor = ReadWord(cursor, &info.state, word_size)))201return false;202203if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))204return false;205206// The rendezvous was successfully read. Update our internal state.207m_rendezvous_addr = info_addr;208m_previous = m_current;209m_current = info;210211m_previous.DumpToLog(log, "m_previous");212m_current.DumpToLog(log, "m_current ");213214if (m_current.map_addr == 0)215return false;216217if (UpdateSOEntriesFromRemote())218return true;219220return UpdateSOEntries();221}222223bool DYLDRendezvous::IsValid() {224return m_rendezvous_addr != LLDB_INVALID_ADDRESS;225}226227DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const {228// If we have a core file, we will read the current rendezvous state229// from the core file's memory into m_current which can be in an inconsistent230// state, so we can't rely on its state to determine what we should do. We231// always need it to load all of the shared libraries one time when we attach232// to a core file.233if (IsCoreFile())234return eTakeSnapshot;235236switch (m_current.state) {237238case eConsistent:239switch (m_previous.state) {240// When the previous and current states are consistent this is the first241// time we have been asked to update. Just take a snapshot of the242// currently loaded modules.243case eConsistent:244return eTakeSnapshot;245// If we are about to add or remove a shared object clear out the current246// state and take a snapshot of the currently loaded images.247case eAdd:248return eAddModules;249case eDelete:250return eRemoveModules;251}252break;253254case eAdd:255// If the main executable or a shared library defines a publicly visible256// symbol named "_r_debug", then it will cause problems once the executable257// that contains the symbol is loaded into the process. The correct258// "_r_debug" structure is currently found by LLDB by looking through259// the .dynamic section in the main executable and finding the DT_DEBUG tag260// entry.261//262// An issue comes up if someone defines another publicly visible "_r_debug"263// struct in their program. Sample code looks like:264//265// #include <link.h>266// r_debug _r_debug;267//268// If code like this is in an executable or shared library, this creates a269// new "_r_debug" structure and it causes problems once the executable is270// loaded due to the way symbol lookups happen in linux: the shared library271// list from _r_debug.r_map will be searched for a symbol named "_r_debug"272// and the first match will be the new version that is used. The dynamic273// loader is always last in this list. So at some point the dynamic loader274// will start updating the copy of "_r_debug" that gets found first. The275// issue is that LLDB will only look at the copy that is pointed to by the276// DT_DEBUG entry, or the initial version from the ld.so binary.277//278// Steps that show the problem are:279//280// - LLDB finds the "_r_debug" structure via the DT_DEBUG entry in the281// .dynamic section and this points to the "_r_debug" in ld.so282// - ld.so uodates its copy of "_r_debug" with "state = eAdd" before it283// loads the dependent shared libraries for the main executable and284// any dependencies of all shared libraries from the executable's list285// and ld.so code calls the debugger notification function286// that LLDB has set a breakpoint on.287// - LLDB hits the breakpoint and the breakpoint has a callback function288// where we read the _r_debug.state (eAdd) state and we do nothing as the289// "eAdd" state indicates that the shared libraries are about to be added.290// - ld.so finishes loading the main executable and any dependent shared291// libraries and it will update the "_r_debug.state" member with a292// "eConsistent", but it now updates the "_r_debug" in the a.out program293// and it calls the debugger notification function.294// - lldb hits the notification breakpoint and checks the ld.so copy of295// "_r_debug.state" which still has a state of "eAdd", but LLDB needs to see a296// "eConsistent" state to trigger the shared libraries to get loaded into297// the debug session, but LLDB the ld.so _r_debug.state which still298// contains "eAdd" and doesn't do anyhing and library load is missed.299// The "_r_debug" in a.out has the state set correctly to "eConsistent"300// but LLDB is still looking at the "_r_debug" from ld.so.301//302// So if we detect two "eAdd" states in a row, we assume this is the issue303// and we now load shared libraries correctly and will emit a log message304// in the "log enable lldb dyld" log channel which states there might be305// multiple "_r_debug" structs causing problems.306//307// The correct solution is that no one should be adding a duplicate308// publicly visible "_r_debug" symbols to their binaries, but we have309// programs that are doing this already and since it can be done, we should310// be able to work with this and keep debug sessions working as expected.311//312// If a user includes the <link.h> file, they can just use the existing313// "_r_debug" structure as it is defined in this header file as "extern314// struct r_debug _r_debug;" and no local copies need to be made.315if (m_previous.state == eAdd) {316Log *log = GetLog(LLDBLog::DynamicLoader);317LLDB_LOG(log, "DYLDRendezvous::GetAction() found two eAdd states in a "318"row, check process for multiple \"_r_debug\" symbols. "319"Returning eAddModules to ensure shared libraries get loaded "320"correctly");321return eAddModules;322}323return eNoAction;324case eDelete:325return eNoAction;326}327328return eNoAction;329}330331bool DYLDRendezvous::UpdateSOEntriesFromRemote() {332const auto action = GetAction();333Log *log = GetLog(LLDBLog::DynamicLoader);334LLDB_LOG(log, "{0} action = {1}", LLVM_PRETTY_FUNCTION, ActionToCStr(action));335336if (action == eNoAction)337return false;338339m_added_soentries.clear();340m_removed_soentries.clear();341if (action == eTakeSnapshot) {342// We already have the loaded list from the previous update so no need to343// find all the modules again.344if (!m_loaded_modules.m_list.empty())345return true;346}347348llvm::Expected<LoadedModuleInfoList> module_list =349m_process->GetLoadedModuleList();350if (!module_list) {351llvm::consumeError(module_list.takeError());352return false;353}354355switch (action) {356case eTakeSnapshot:357m_soentries.clear();358return SaveSOEntriesFromRemote(*module_list);359case eAddModules:360return AddSOEntriesFromRemote(*module_list);361case eRemoveModules:362return RemoveSOEntriesFromRemote(*module_list);363case eNoAction:364return false;365}366llvm_unreachable("Fully covered switch above!");367}368369bool DYLDRendezvous::UpdateSOEntries() {370m_added_soentries.clear();371m_removed_soentries.clear();372const auto action = GetAction();373Log *log = GetLog(LLDBLog::DynamicLoader);374LLDB_LOG(log, "{0} action = {1}", LLVM_PRETTY_FUNCTION, ActionToCStr(action));375switch (action) {376case eTakeSnapshot:377m_soentries.clear();378return TakeSnapshot(m_soentries);379case eAddModules:380return AddSOEntries();381case eRemoveModules:382return RemoveSOEntries();383case eNoAction:384return false;385}386llvm_unreachable("Fully covered switch above!");387}388389bool DYLDRendezvous::FillSOEntryFromModuleInfo(390LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) {391addr_t link_map_addr;392addr_t base_addr;393addr_t dyn_addr;394std::string name;395396if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) ||397!modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name))398return false;399400entry.link_addr = link_map_addr;401entry.base_addr = base_addr;402entry.dyn_addr = dyn_addr;403404entry.file_spec.SetFile(name, FileSpec::Style::native);405406UpdateBaseAddrIfNecessary(entry, name);407408// not needed if we're using ModuleInfos409entry.next = 0;410entry.prev = 0;411entry.path_addr = 0;412413return true;414}415416bool DYLDRendezvous::SaveSOEntriesFromRemote(417const LoadedModuleInfoList &module_list) {418for (auto const &modInfo : module_list.m_list) {419SOEntry entry;420if (!FillSOEntryFromModuleInfo(modInfo, entry))421return false;422423// Only add shared libraries and not the executable.424if (!SOEntryIsMainExecutable(entry)) {425UpdateFileSpecIfNecessary(entry);426m_soentries.push_back(entry);427}428}429430m_loaded_modules = module_list;431return true;432}433434bool DYLDRendezvous::AddSOEntriesFromRemote(435const LoadedModuleInfoList &module_list) {436for (auto const &modInfo : module_list.m_list) {437bool found = false;438for (auto const &existing : m_loaded_modules.m_list) {439if (modInfo == existing) {440found = true;441break;442}443}444445if (found)446continue;447448SOEntry entry;449if (!FillSOEntryFromModuleInfo(modInfo, entry))450return false;451452// Only add shared libraries and not the executable.453if (!SOEntryIsMainExecutable(entry)) {454UpdateFileSpecIfNecessary(entry);455m_soentries.push_back(entry);456m_added_soentries.push_back(entry);457}458}459460m_loaded_modules = module_list;461return true;462}463464bool DYLDRendezvous::RemoveSOEntriesFromRemote(465const LoadedModuleInfoList &module_list) {466for (auto const &existing : m_loaded_modules.m_list) {467bool found = false;468for (auto const &modInfo : module_list.m_list) {469if (modInfo == existing) {470found = true;471break;472}473}474475if (found)476continue;477478SOEntry entry;479if (!FillSOEntryFromModuleInfo(existing, entry))480return false;481482// Only add shared libraries and not the executable.483if (!SOEntryIsMainExecutable(entry)) {484auto pos = llvm::find(m_soentries, entry);485if (pos == m_soentries.end())486return false;487488m_soentries.erase(pos);489m_removed_soentries.push_back(entry);490}491}492493m_loaded_modules = module_list;494return true;495}496497bool DYLDRendezvous::AddSOEntries() {498SOEntry entry;499iterator pos;500501assert(m_previous.state == eAdd);502503if (m_current.map_addr == 0)504return false;505506for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {507if (!ReadSOEntryFromMemory(cursor, entry))508return false;509510// Only add shared libraries and not the executable.511if (SOEntryIsMainExecutable(entry))512continue;513514UpdateFileSpecIfNecessary(entry);515516if (!llvm::is_contained(m_soentries, entry)) {517m_soentries.push_back(entry);518m_added_soentries.push_back(entry);519}520}521522return true;523}524525bool DYLDRendezvous::RemoveSOEntries() {526SOEntryList entry_list;527iterator pos;528529assert(m_previous.state == eDelete);530531if (!TakeSnapshot(entry_list))532return false;533534for (iterator I = begin(); I != end(); ++I) {535if (!llvm::is_contained(entry_list, *I))536m_removed_soentries.push_back(*I);537}538539m_soentries = entry_list;540return true;541}542543bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) {544// On some systes the executable is indicated by an empty path in the entry.545// On others it is the full path to the executable.546547auto triple = m_process->GetTarget().GetArchitecture().GetTriple();548switch (triple.getOS()) {549case llvm::Triple::FreeBSD:550case llvm::Triple::NetBSD:551case llvm::Triple::OpenBSD:552return entry.file_spec == m_exe_file_spec;553case llvm::Triple::Linux:554if (triple.isAndroid())555return entry.file_spec == m_exe_file_spec;556// If we are debugging ld.so, then all SOEntries should be treated as557// libraries, including the "main" one (denoted by an empty string).558if (!entry.file_spec && m_executable_interpreter)559return false;560return !entry.file_spec;561default:562return false;563}564}565566bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {567SOEntry entry;568569if (m_current.map_addr == 0)570return false;571572// Clear previous entries since we are about to obtain an up to date list.573entry_list.clear();574575for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {576if (!ReadSOEntryFromMemory(cursor, entry))577return false;578579// Only add shared libraries and not the executable.580if (SOEntryIsMainExecutable(entry))581continue;582583UpdateFileSpecIfNecessary(entry);584585entry_list.push_back(entry);586}587588return true;589}590591addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) {592Status error;593594*dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);595if (error.Fail())596return 0;597598return addr + size;599}600601addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) {602Status error;603604*dst = m_process->ReadPointerFromMemory(addr, error);605if (error.Fail())606return 0;607608return addr + m_process->GetAddressByteSize();609}610611std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {612std::string str;613Status error;614615if (addr == LLDB_INVALID_ADDRESS)616return std::string();617618m_process->ReadCStringFromMemory(addr, str, error);619620return str;621}622623// Returns true if the load bias reported by the linker is incorrect for the624// given entry. This function is used to handle cases where we want to work625// around a bug in the system linker.626static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {627// On Android L (API 21, 22) the load address of the "/system/bin/linker"628// isn't filled in correctly.629unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();630return target.GetArchitecture().GetTriple().isAndroid() &&631(os_major == 21 || os_major == 22) &&632(file_path == "/system/bin/linker" ||633file_path == "/system/bin/linker64");634}635636void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,637std::string const &file_path) {638// If the load bias reported by the linker is incorrect then fetch the load639// address of the file from the proc file system.640if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) {641lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;642bool is_loaded = false;643Status error =644m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);645if (error.Success() && is_loaded)646entry.base_addr = load_addr;647}648}649650void DYLDRendezvous::UpdateFileSpecIfNecessary(SOEntry &entry) {651// Updates filename if empty. It is useful while debugging ld.so,652// when the link map returns empty string for the main executable.653if (!entry.file_spec) {654MemoryRegionInfo region;655Status region_status =656m_process->GetMemoryRegionInfo(entry.dyn_addr, region);657if (!region.GetName().IsEmpty())658entry.file_spec.SetFile(region.GetName().AsCString(),659FileSpec::Style::native);660}661}662663bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {664entry.clear();665666entry.link_addr = addr;667668if (!(addr = ReadPointer(addr, &entry.base_addr)))669return false;670671// mips adds an extra load offset field to the link map struct on FreeBSD and672// NetBSD (need to validate other OSes).673// http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57674const ArchSpec &arch = m_process->GetTarget().GetArchitecture();675if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||676arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&677arch.IsMIPS()) {678addr_t mips_l_offs;679if (!(addr = ReadPointer(addr, &mips_l_offs)))680return false;681if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)682return false;683}684685if (!(addr = ReadPointer(addr, &entry.path_addr)))686return false;687688if (!(addr = ReadPointer(addr, &entry.dyn_addr)))689return false;690691if (!(addr = ReadPointer(addr, &entry.next)))692return false;693694if (!(addr = ReadPointer(addr, &entry.prev)))695return false;696697std::string file_path = ReadStringFromMemory(entry.path_addr);698entry.file_spec.SetFile(file_path, FileSpec::Style::native);699700UpdateBaseAddrIfNecessary(entry, file_path);701702return true;703}704705bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field,706uint32_t &value) {707Target &target = m_process->GetTarget();708709SymbolContextList list;710target.GetImages().FindSymbolsWithNameAndType(ConstString(name),711eSymbolTypeAny, list);712if (list.IsEmpty())713return false;714715Address address = list[0].symbol->GetAddress();716address.SetOffset(address.GetOffset() + field * sizeof(uint32_t));717718// Read from target memory as this allows us to try process memory and719// fallback to reading from read only sections from the object files. Here we720// are reading read only data from libpthread.so to find data in the thread721// specific area for the data we want and this won't be saved into process722// memory due to it being read only.723Status error;724value =725target.ReadUnsignedIntegerFromMemory(address, sizeof(uint32_t), 0, error);726if (error.Fail())727return false;728729if (field == eSize)730value /= 8; // convert bits to bytes731732return true;733}734735const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() {736if (!m_thread_info.valid) {737bool ok = true;738739ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,740m_thread_info.dtv_offset);741ok &=742FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);743ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,744m_thread_info.modid_offset);745ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,746m_thread_info.tls_offset);747748if (ok)749m_thread_info.valid = true;750}751752return m_thread_info;753}754755void DYLDRendezvous::DumpToLog(Log *log) const {756int state = GetState();757758if (!log)759return;760761log->PutCString("DYLDRendezvous:");762LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress());763LLDB_LOGF(log, " Version: %" PRIu64, GetVersion());764LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress());765LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress());766LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase());767LLDB_LOGF(log, " State : %s",768(state == eConsistent)769? "consistent"770: (state == eAdd) ? "add"771: (state == eDelete) ? "delete" : "unknown");772773iterator I = begin();774iterator E = end();775776if (I != E)777log->PutCString("DYLDRendezvous SOEntries:");778779for (int i = 1; I != E; ++I, ++i) {780LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetPath().c_str());781LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr);782LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr);783LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr);784LLDB_LOGF(log, " Next : %" PRIx64, I->next);785LLDB_LOGF(log, " Prev : %" PRIx64, I->prev);786}787}788789bool DYLDRendezvous::IsCoreFile() const {790return !m_process->IsLiveDebugSession();791}792793794