brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.3 KiB · 1a9c459 Raw
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