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
DYLDRendezvous(Process * process)28 DYLDRendezvous::DYLDRendezvous(Process *process)
29 : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS),
30 m_executable_interpreter(false), m_current(), m_previous(),
31 m_loaded_modules(), m_soentries(), m_added_soentries(),
32 m_removed_soentries() {
33 m_thread_info.valid = false;
34 UpdateExecutablePath();
35 }
36
ResolveRendezvousAddress()37 addr_t DYLDRendezvous::ResolveRendezvousAddress() {
38 Log *log = GetLog(LLDBLog::DynamicLoader);
39 addr_t info_location;
40 addr_t info_addr;
41 Status error;
42
43 if (!m_process) {
44 LLDB_LOGF(log, "%s null process provided", __FUNCTION__);
45 return LLDB_INVALID_ADDRESS;
46 }
47
48 // Try to get it from our process. This might be a remote process and might
49 // grab it via some remote-specific mechanism.
50 info_location = m_process->GetImageInfoAddress();
51 LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
52
53 // If the process fails to return an address, fall back to seeing if the
54 // local object file can help us find it.
55 if (info_location == LLDB_INVALID_ADDRESS) {
56 Target *target = &m_process->GetTarget();
57 if (target) {
58 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
59 Address addr = obj_file->GetImageInfoAddress(target);
60
61 if (addr.IsValid()) {
62 info_location = addr.GetLoadAddress(target);
63 LLDB_LOGF(log,
64 "%s resolved via direct object file approach to 0x%" PRIx64,
65 __FUNCTION__, info_location);
66 } else {
67 const Symbol *_r_debug =
68 target->GetExecutableModule()->FindFirstSymbolWithNameAndType(
69 ConstString("_r_debug"));
70 if (_r_debug) {
71 info_addr = _r_debug->GetAddress().GetLoadAddress(target);
72 if (info_addr != LLDB_INVALID_ADDRESS) {
73 LLDB_LOGF(log,
74 "%s resolved by finding symbol '_r_debug' whose value is "
75 "0x%" PRIx64,
76 __FUNCTION__, info_addr);
77 m_executable_interpreter = true;
78 return info_addr;
79 }
80 }
81 LLDB_LOGF(log,
82 "%s FAILED - direct object file approach did not yield a "
83 "valid address",
84 __FUNCTION__);
85 }
86 }
87 }
88
89 if (info_location == LLDB_INVALID_ADDRESS) {
90 LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__);
91 return LLDB_INVALID_ADDRESS;
92 }
93
94 LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64,
95 __FUNCTION__, m_process->GetAddressByteSize(), info_location);
96
97 info_addr = m_process->ReadPointerFromMemory(info_location, error);
98 if (error.Fail()) {
99 LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s",
100 __FUNCTION__, error.AsCString());
101 return LLDB_INVALID_ADDRESS;
102 }
103
104 if (info_addr == 0) {
105 LLDB_LOGF(log,
106 "%s FAILED - the rendezvous address contained at 0x%" PRIx64
107 " returned a null value",
108 __FUNCTION__, info_location);
109 return LLDB_INVALID_ADDRESS;
110 }
111
112 return info_addr;
113 }
114
UpdateExecutablePath()115 void DYLDRendezvous::UpdateExecutablePath() {
116 if (m_process) {
117 Log *log = GetLog(LLDBLog::DynamicLoader);
118 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
119 if (exe_mod) {
120 m_exe_file_spec = exe_mod->GetPlatformFileSpec();
121 LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'",
122 __FUNCTION__, m_exe_file_spec.GetPath().c_str());
123 } else {
124 LLDB_LOGF(log,
125 "DYLDRendezvous::%s cannot cache exe module path: null "
126 "executable module pointer",
127 __FUNCTION__);
128 }
129 }
130 }
131
Resolve()132 bool DYLDRendezvous::Resolve() {
133 Log *log = GetLog(LLDBLog::DynamicLoader);
134
135 const size_t word_size = 4;
136 Rendezvous info;
137 size_t address_size;
138 size_t padding;
139 addr_t info_addr;
140 addr_t cursor;
141
142 address_size = m_process->GetAddressByteSize();
143 padding = address_size - word_size;
144 LLDB_LOGF(log,
145 "DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64,
146 __FUNCTION__, uint64_t(address_size), uint64_t(padding));
147
148 if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
149 cursor = info_addr =
150 ResolveRendezvousAddress();
151 else
152 cursor = info_addr = m_rendezvous_addr;
153 LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__,
154 cursor);
155
156 if (cursor == LLDB_INVALID_ADDRESS)
157 return false;
158
159 if (!(cursor = ReadWord(cursor, &info.version, word_size)))
160 return false;
161
162 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
163 return false;
164
165 if (!(cursor = ReadPointer(cursor, &info.brk)))
166 return false;
167
168 if (!(cursor = ReadWord(cursor, &info.state, word_size)))
169 return false;
170
171 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
172 return false;
173
174 // The rendezvous was successfully read. Update our internal state.
175 m_rendezvous_addr = info_addr;
176 m_previous = m_current;
177 m_current = info;
178
179 if (m_current.map_addr == 0)
180 return false;
181
182 if (UpdateSOEntriesFromRemote())
183 return true;
184
185 return UpdateSOEntries();
186 }
187
IsValid()188 bool DYLDRendezvous::IsValid() {
189 return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
190 }
191
GetAction() const192 DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const {
193 // If we have a core file, we will read the current rendezvous state
194 // from the core file's memory into m_current which can be in an inconsistent
195 // state, so we can't rely on its state to determine what we should do. We
196 // always need it to load all of the shared libraries one time when we attach
197 // to a core file.
198 if (IsCoreFile())
199 return eTakeSnapshot;
200
201 switch (m_current.state) {
202
203 case eConsistent:
204 switch (m_previous.state) {
205 // When the previous and current states are consistent this is the first
206 // time we have been asked to update. Just take a snapshot of the
207 // currently loaded modules.
208 case eConsistent:
209 return eTakeSnapshot;
210 // If we are about to add or remove a shared object clear out the current
211 // state and take a snapshot of the currently loaded images.
212 case eAdd:
213 return eAddModules;
214 case eDelete:
215 return eRemoveModules;
216 }
217 break;
218
219 case eAdd:
220 case eDelete:
221 return eNoAction;
222 }
223
224 return eNoAction;
225 }
226
UpdateSOEntriesFromRemote()227 bool DYLDRendezvous::UpdateSOEntriesFromRemote() {
228 auto action = GetAction();
229
230 if (action == eNoAction)
231 return false;
232
233 m_added_soentries.clear();
234 m_removed_soentries.clear();
235 if (action == eTakeSnapshot) {
236 // We already have the loaded list from the previous update so no need to
237 // find all the modules again.
238 if (!m_loaded_modules.m_list.empty())
239 return true;
240 }
241
242 llvm::Expected<LoadedModuleInfoList> module_list =
243 m_process->GetLoadedModuleList();
244 if (!module_list) {
245 llvm::consumeError(module_list.takeError());
246 return false;
247 }
248
249 switch (action) {
250 case eTakeSnapshot:
251 m_soentries.clear();
252 return SaveSOEntriesFromRemote(*module_list);
253 case eAddModules:
254 return AddSOEntriesFromRemote(*module_list);
255 case eRemoveModules:
256 return RemoveSOEntriesFromRemote(*module_list);
257 case eNoAction:
258 return false;
259 }
260 llvm_unreachable("Fully covered switch above!");
261 }
262
UpdateSOEntries()263 bool DYLDRendezvous::UpdateSOEntries() {
264 m_added_soentries.clear();
265 m_removed_soentries.clear();
266 switch (GetAction()) {
267 case eTakeSnapshot:
268 m_soentries.clear();
269 return TakeSnapshot(m_soentries);
270 case eAddModules:
271 return AddSOEntries();
272 case eRemoveModules:
273 return RemoveSOEntries();
274 case eNoAction:
275 return false;
276 }
277 llvm_unreachable("Fully covered switch above!");
278 }
279
FillSOEntryFromModuleInfo(LoadedModuleInfoList::LoadedModuleInfo const & modInfo,SOEntry & entry)280 bool DYLDRendezvous::FillSOEntryFromModuleInfo(
281 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) {
282 addr_t link_map_addr;
283 addr_t base_addr;
284 addr_t dyn_addr;
285 std::string name;
286
287 if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) ||
288 !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name))
289 return false;
290
291 entry.link_addr = link_map_addr;
292 entry.base_addr = base_addr;
293 entry.dyn_addr = dyn_addr;
294
295 entry.file_spec.SetFile(name, FileSpec::Style::native);
296
297 UpdateBaseAddrIfNecessary(entry, name);
298
299 // not needed if we're using ModuleInfos
300 entry.next = 0;
301 entry.prev = 0;
302 entry.path_addr = 0;
303
304 return true;
305 }
306
SaveSOEntriesFromRemote(const LoadedModuleInfoList & module_list)307 bool DYLDRendezvous::SaveSOEntriesFromRemote(
308 const LoadedModuleInfoList &module_list) {
309 for (auto const &modInfo : module_list.m_list) {
310 SOEntry entry;
311 if (!FillSOEntryFromModuleInfo(modInfo, entry))
312 return false;
313
314 // Only add shared libraries and not the executable.
315 if (!SOEntryIsMainExecutable(entry)) {
316 UpdateFileSpecIfNecessary(entry);
317 m_soentries.push_back(entry);
318 }
319 }
320
321 m_loaded_modules = module_list;
322 return true;
323 }
324
AddSOEntriesFromRemote(const LoadedModuleInfoList & module_list)325 bool DYLDRendezvous::AddSOEntriesFromRemote(
326 const LoadedModuleInfoList &module_list) {
327 for (auto const &modInfo : module_list.m_list) {
328 bool found = false;
329 for (auto const &existing : m_loaded_modules.m_list) {
330 if (modInfo == existing) {
331 found = true;
332 break;
333 }
334 }
335
336 if (found)
337 continue;
338
339 SOEntry entry;
340 if (!FillSOEntryFromModuleInfo(modInfo, entry))
341 return false;
342
343 // Only add shared libraries and not the executable.
344 if (!SOEntryIsMainExecutable(entry)) {
345 UpdateFileSpecIfNecessary(entry);
346 m_soentries.push_back(entry);
347 m_added_soentries.push_back(entry);
348 }
349 }
350
351 m_loaded_modules = module_list;
352 return true;
353 }
354
RemoveSOEntriesFromRemote(const LoadedModuleInfoList & module_list)355 bool DYLDRendezvous::RemoveSOEntriesFromRemote(
356 const LoadedModuleInfoList &module_list) {
357 for (auto const &existing : m_loaded_modules.m_list) {
358 bool found = false;
359 for (auto const &modInfo : module_list.m_list) {
360 if (modInfo == existing) {
361 found = true;
362 break;
363 }
364 }
365
366 if (found)
367 continue;
368
369 SOEntry entry;
370 if (!FillSOEntryFromModuleInfo(existing, entry))
371 return false;
372
373 // Only add shared libraries and not the executable.
374 if (!SOEntryIsMainExecutable(entry)) {
375 auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
376 if (pos == m_soentries.end())
377 return false;
378
379 m_soentries.erase(pos);
380 m_removed_soentries.push_back(entry);
381 }
382 }
383
384 m_loaded_modules = module_list;
385 return true;
386 }
387
AddSOEntries()388 bool DYLDRendezvous::AddSOEntries() {
389 SOEntry entry;
390 iterator pos;
391
392 assert(m_previous.state == eAdd);
393
394 if (m_current.map_addr == 0)
395 return false;
396
397 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
398 if (!ReadSOEntryFromMemory(cursor, entry))
399 return false;
400
401 // Only add shared libraries and not the executable.
402 if (SOEntryIsMainExecutable(entry))
403 continue;
404
405 UpdateFileSpecIfNecessary(entry);
406
407 if (!llvm::is_contained(m_soentries, entry)) {
408 m_soentries.push_back(entry);
409 m_added_soentries.push_back(entry);
410 }
411 }
412
413 return true;
414 }
415
RemoveSOEntries()416 bool DYLDRendezvous::RemoveSOEntries() {
417 SOEntryList entry_list;
418 iterator pos;
419
420 assert(m_previous.state == eDelete);
421
422 if (!TakeSnapshot(entry_list))
423 return false;
424
425 for (iterator I = begin(); I != end(); ++I) {
426 if (!llvm::is_contained(entry_list, *I))
427 m_removed_soentries.push_back(*I);
428 }
429
430 m_soentries = entry_list;
431 return true;
432 }
433
SOEntryIsMainExecutable(const SOEntry & entry)434 bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) {
435 // On some systes the executable is indicated by an empty path in the entry.
436 // On others it is the full path to the executable.
437
438 auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
439 switch (triple.getOS()) {
440 case llvm::Triple::FreeBSD:
441 case llvm::Triple::NetBSD:
442 case llvm::Triple::OpenBSD:
443 return entry.file_spec == m_exe_file_spec;
444 case llvm::Triple::Linux:
445 if (triple.isAndroid())
446 return entry.file_spec == m_exe_file_spec;
447 // If we are debugging ld.so, then all SOEntries should be treated as
448 // libraries, including the "main" one (denoted by an empty string).
449 if (!entry.file_spec && m_executable_interpreter)
450 return false;
451 return !entry.file_spec;
452 default:
453 return false;
454 }
455 }
456
TakeSnapshot(SOEntryList & entry_list)457 bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
458 SOEntry entry;
459
460 if (m_current.map_addr == 0)
461 return false;
462
463 // Clear previous entries since we are about to obtain an up to date list.
464 entry_list.clear();
465
466 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
467 if (!ReadSOEntryFromMemory(cursor, entry))
468 return false;
469
470 // Only add shared libraries and not the executable.
471 if (SOEntryIsMainExecutable(entry))
472 continue;
473
474 UpdateFileSpecIfNecessary(entry);
475
476 entry_list.push_back(entry);
477 }
478
479 return true;
480 }
481
ReadWord(addr_t addr,uint64_t * dst,size_t size)482 addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) {
483 Status error;
484
485 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
486 if (error.Fail())
487 return 0;
488
489 return addr + size;
490 }
491
ReadPointer(addr_t addr,addr_t * dst)492 addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) {
493 Status error;
494
495 *dst = m_process->ReadPointerFromMemory(addr, error);
496 if (error.Fail())
497 return 0;
498
499 return addr + m_process->GetAddressByteSize();
500 }
501
ReadStringFromMemory(addr_t addr)502 std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {
503 std::string str;
504 Status error;
505
506 if (addr == LLDB_INVALID_ADDRESS)
507 return std::string();
508
509 m_process->ReadCStringFromMemory(addr, str, error);
510
511 return str;
512 }
513
514 // Returns true if the load bias reported by the linker is incorrect for the
515 // given entry. This function is used to handle cases where we want to work
516 // around a bug in the system linker.
isLoadBiasIncorrect(Target & target,const std::string & file_path)517 static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
518 // On Android L (API 21, 22) the load address of the "/system/bin/linker"
519 // isn't filled in correctly.
520 unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
521 return target.GetArchitecture().GetTriple().isAndroid() &&
522 (os_major == 21 || os_major == 22) &&
523 (file_path == "/system/bin/linker" ||
524 file_path == "/system/bin/linker64");
525 }
526
UpdateBaseAddrIfNecessary(SOEntry & entry,std::string const & file_path)527 void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
528 std::string const &file_path) {
529 // If the load bias reported by the linker is incorrect then fetch the load
530 // address of the file from the proc file system.
531 if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) {
532 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
533 bool is_loaded = false;
534 Status error =
535 m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
536 if (error.Success() && is_loaded)
537 entry.base_addr = load_addr;
538 }
539 }
540
UpdateFileSpecIfNecessary(SOEntry & entry)541 void DYLDRendezvous::UpdateFileSpecIfNecessary(SOEntry &entry) {
542 // Updates filename if empty. It is useful while debugging ld.so,
543 // when the link map returns empty string for the main executable.
544 if (!entry.file_spec) {
545 MemoryRegionInfo region;
546 Status region_status =
547 m_process->GetMemoryRegionInfo(entry.dyn_addr, region);
548 if (!region.GetName().IsEmpty())
549 entry.file_spec.SetFile(region.GetName().AsCString(),
550 FileSpec::Style::native);
551 }
552 }
553
ReadSOEntryFromMemory(lldb::addr_t addr,SOEntry & entry)554 bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
555 entry.clear();
556
557 entry.link_addr = addr;
558
559 if (!(addr = ReadPointer(addr, &entry.base_addr)))
560 return false;
561
562 // mips adds an extra load offset field to the link map struct on FreeBSD and
563 // NetBSD (need to validate other OSes).
564 // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
565 const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
566 if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
567 arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&
568 arch.IsMIPS()) {
569 addr_t mips_l_offs;
570 if (!(addr = ReadPointer(addr, &mips_l_offs)))
571 return false;
572 if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
573 return false;
574 }
575
576 if (!(addr = ReadPointer(addr, &entry.path_addr)))
577 return false;
578
579 if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
580 return false;
581
582 if (!(addr = ReadPointer(addr, &entry.next)))
583 return false;
584
585 if (!(addr = ReadPointer(addr, &entry.prev)))
586 return false;
587
588 std::string file_path = ReadStringFromMemory(entry.path_addr);
589 entry.file_spec.SetFile(file_path, FileSpec::Style::native);
590
591 UpdateBaseAddrIfNecessary(entry, file_path);
592
593 return true;
594 }
595
FindMetadata(const char * name,PThreadField field,uint32_t & value)596 bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field,
597 uint32_t &value) {
598 Target &target = m_process->GetTarget();
599
600 SymbolContextList list;
601 target.GetImages().FindSymbolsWithNameAndType(ConstString(name),
602 eSymbolTypeAny, list);
603 if (list.IsEmpty())
604 return false;
605
606 Address address = list[0].symbol->GetAddress();
607 addr_t addr = address.GetLoadAddress(&target);
608 if (addr == LLDB_INVALID_ADDRESS)
609 return false;
610
611 Status error;
612 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
613 addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
614 if (error.Fail())
615 return false;
616
617 if (field == eSize)
618 value /= 8; // convert bits to bytes
619
620 return true;
621 }
622
GetThreadInfo()623 const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() {
624 if (!m_thread_info.valid) {
625 bool ok = true;
626
627 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
628 m_thread_info.dtv_offset);
629 ok &=
630 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
631 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
632 m_thread_info.modid_offset);
633 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
634 m_thread_info.tls_offset);
635
636 if (ok)
637 m_thread_info.valid = true;
638 }
639
640 return m_thread_info;
641 }
642
DumpToLog(Log * log) const643 void DYLDRendezvous::DumpToLog(Log *log) const {
644 int state = GetState();
645
646 if (!log)
647 return;
648
649 log->PutCString("DYLDRendezvous:");
650 LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress());
651 LLDB_LOGF(log, " Version: %" PRIu64, GetVersion());
652 LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress());
653 LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress());
654 LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase());
655 LLDB_LOGF(log, " State : %s",
656 (state == eConsistent)
657 ? "consistent"
658 : (state == eAdd) ? "add"
659 : (state == eDelete) ? "delete" : "unknown");
660
661 iterator I = begin();
662 iterator E = end();
663
664 if (I != E)
665 log->PutCString("DYLDRendezvous SOEntries:");
666
667 for (int i = 1; I != E; ++I, ++i) {
668 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetPath().c_str());
669 LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr);
670 LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr);
671 LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr);
672 LLDB_LOGF(log, " Next : %" PRIx64, I->next);
673 LLDB_LOGF(log, " Prev : %" PRIx64, I->prev);
674 }
675 }
676
IsCoreFile() const677 bool DYLDRendezvous::IsCoreFile() const {
678 return !m_process->IsLiveDebugSession();
679 }
680