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