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
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 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
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 = %" PRIu64
161            " (%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  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
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 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
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 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
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 ModuleInfos
410  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 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
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 the
625// given entry. This function is used to handle cases where we want to work
626// 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 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
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 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
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 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
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