Coverage Report

Created: 2022-01-18 06:27

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