Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/unwind/src/AddressSpace.hpp
12346 views
1
//===------------------------- AddressSpace.hpp ---------------------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//
9
// Abstracts accessing local vs remote address spaces.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef __ADDRESSSPACE_HPP__
14
#define __ADDRESSSPACE_HPP__
15
16
#include <stdint.h>
17
#include <stdio.h>
18
#include <stdlib.h>
19
#include <string.h>
20
21
#ifndef _LIBUNWIND_USE_DLADDR
22
#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
23
#define _LIBUNWIND_USE_DLADDR 1
24
#else
25
#define _LIBUNWIND_USE_DLADDR 0
26
#endif
27
#endif
28
29
#if _LIBUNWIND_USE_DLADDR
30
#include <dlfcn.h>
31
#endif
32
33
#ifdef __APPLE__
34
#include <mach-o/getsect.h>
35
namespace libunwind {
36
bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
37
}
38
#endif
39
40
#include "libunwind.h"
41
#include "config.h"
42
#include "dwarf2.h"
43
#include "EHHeaderParser.hpp"
44
#include "Registers.hpp"
45
46
#ifdef __APPLE__
47
48
struct dyld_unwind_sections
49
{
50
const struct mach_header* mh;
51
const void* dwarf_section;
52
uintptr_t dwarf_section_length;
53
const void* compact_unwind_section;
54
uintptr_t compact_unwind_section_length;
55
};
56
#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
57
&& (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
58
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
59
// In 10.7.0 or later, libSystem.dylib implements this function.
60
extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
61
#else
62
// In 10.6.x and earlier, we need to implement this functionality. Note
63
// that this requires a newer version of libmacho (from cctools) than is
64
// present in libSystem on 10.6.x (for getsectiondata).
65
static inline bool _dyld_find_unwind_sections(void* addr,
66
dyld_unwind_sections* info) {
67
// Find mach-o image containing address.
68
Dl_info dlinfo;
69
if (!dladdr(addr, &dlinfo))
70
return false;
71
#if __LP64__
72
const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
73
#else
74
const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
75
#endif
76
77
// Initialize the return struct
78
info->mh = (const struct mach_header *)mh;
79
info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
80
info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
81
82
if (!info->dwarf_section) {
83
info->dwarf_section_length = 0;
84
}
85
86
if (!info->compact_unwind_section) {
87
info->compact_unwind_section_length = 0;
88
}
89
90
return true;
91
}
92
#endif
93
94
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
95
96
// When statically linked on bare-metal, the symbols for the EH table are looked
97
// up without going through the dynamic loader.
98
99
// The following linker script may be used to produce the necessary sections and symbols.
100
// Unless the --eh-frame-hdr linker option is provided, the section is not generated
101
// and does not take space in the output file.
102
//
103
// .eh_frame :
104
// {
105
// __eh_frame_start = .;
106
// KEEP(*(.eh_frame))
107
// __eh_frame_end = .;
108
// }
109
//
110
// .eh_frame_hdr :
111
// {
112
// KEEP(*(.eh_frame_hdr))
113
// }
114
//
115
// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
116
// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
117
118
extern char __eh_frame_start;
119
extern char __eh_frame_end;
120
121
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
122
extern char __eh_frame_hdr_start;
123
extern char __eh_frame_hdr_end;
124
#endif
125
126
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
127
128
// When statically linked on bare-metal, the symbols for the EH table are looked
129
// up without going through the dynamic loader.
130
extern char __exidx_start;
131
extern char __exidx_end;
132
133
#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
134
135
// ELF-based systems may use dl_iterate_phdr() to access sections
136
// containing unwinding information. The ElfW() macro for pointer-size
137
// independent ELF header traversal is not provided by <link.h> on some
138
// systems (e.g., FreeBSD). On these systems the data structures are
139
// just called Elf_XXX. Define ElfW() locally.
140
#ifndef _WIN32
141
#include <link.h>
142
#else
143
#include <windows.h>
144
#include <psapi.h>
145
#endif
146
#if !defined(ElfW)
147
#define ElfW(type) Elf_##type
148
#endif
149
150
#endif
151
152
namespace libunwind {
153
154
/// Used by findUnwindSections() to return info about needed sections.
155
struct UnwindInfoSections {
156
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
157
defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
158
// No dso_base for SEH or ARM EHABI.
159
uintptr_t dso_base;
160
#endif
161
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
162
uintptr_t dwarf_section;
163
uintptr_t dwarf_section_length;
164
#endif
165
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
166
uintptr_t dwarf_index_section;
167
uintptr_t dwarf_index_section_length;
168
#endif
169
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
170
uintptr_t compact_unwind_section;
171
uintptr_t compact_unwind_section_length;
172
#endif
173
#if defined(_LIBUNWIND_ARM_EHABI)
174
uintptr_t arm_section;
175
uintptr_t arm_section_length;
176
#endif
177
};
178
179
180
/// LocalAddressSpace is used as a template parameter to UnwindCursor when
181
/// unwinding a thread in the same process. The wrappers compile away,
182
/// making local unwinds fast.
183
class _LIBUNWIND_HIDDEN LocalAddressSpace {
184
public:
185
typedef uintptr_t pint_t;
186
typedef intptr_t sint_t;
187
uint8_t get8(pint_t addr) {
188
uint8_t val;
189
memcpy(&val, (void *)addr, sizeof(val));
190
return val;
191
}
192
uint16_t get16(pint_t addr) {
193
uint16_t val;
194
memcpy(&val, (void *)addr, sizeof(val));
195
return val;
196
}
197
uint32_t get32(pint_t addr) {
198
uint32_t val;
199
memcpy(&val, (void *)addr, sizeof(val));
200
return val;
201
}
202
uint64_t get64(pint_t addr) {
203
uint64_t val;
204
memcpy(&val, (void *)addr, sizeof(val));
205
return val;
206
}
207
double getDouble(pint_t addr) {
208
double val;
209
memcpy(&val, (void *)addr, sizeof(val));
210
return val;
211
}
212
v128 getVector(pint_t addr) {
213
v128 val;
214
memcpy(&val, (void *)addr, sizeof(val));
215
return val;
216
}
217
uintptr_t getP(pint_t addr);
218
uint64_t getRegister(pint_t addr);
219
static uint64_t getULEB128(pint_t &addr, pint_t end);
220
static int64_t getSLEB128(pint_t &addr, pint_t end);
221
222
pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
223
pint_t datarelBase = 0);
224
bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
225
unw_word_t *offset);
226
bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
227
bool findOtherFDE(pint_t targetAddr, pint_t &fde);
228
229
static LocalAddressSpace sThisAddressSpace;
230
};
231
232
inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
233
#if __SIZEOF_POINTER__ == 8
234
return get64(addr);
235
#else
236
return get32(addr);
237
#endif
238
}
239
240
inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
241
#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
242
return get64(addr);
243
#else
244
return get32(addr);
245
#endif
246
}
247
248
/// Read a ULEB128 into a 64-bit word.
249
inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
250
const uint8_t *p = (uint8_t *)addr;
251
const uint8_t *pend = (uint8_t *)end;
252
uint64_t result = 0;
253
int bit = 0;
254
do {
255
uint64_t b;
256
257
if (p == pend)
258
_LIBUNWIND_ABORT("truncated uleb128 expression");
259
260
b = *p & 0x7f;
261
262
if (bit >= 64 || b << bit >> bit != b) {
263
_LIBUNWIND_ABORT("malformed uleb128 expression");
264
} else {
265
result |= b << bit;
266
bit += 7;
267
}
268
} while (*p++ >= 0x80);
269
addr = (pint_t) p;
270
return result;
271
}
272
273
/// Read a SLEB128 into a 64-bit word.
274
inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
275
const uint8_t *p = (uint8_t *)addr;
276
const uint8_t *pend = (uint8_t *)end;
277
int64_t result = 0;
278
int bit = 0;
279
uint8_t byte;
280
do {
281
if (p == pend)
282
_LIBUNWIND_ABORT("truncated sleb128 expression");
283
byte = *p++;
284
result |= ((byte & 0x7f) << bit);
285
bit += 7;
286
} while (byte & 0x80);
287
// sign extend negative numbers
288
if ((byte & 0x40) != 0)
289
result |= (-1ULL) << bit;
290
addr = (pint_t) p;
291
return result;
292
}
293
294
inline LocalAddressSpace::pint_t
295
LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
296
pint_t datarelBase) {
297
pint_t startAddr = addr;
298
const uint8_t *p = (uint8_t *)addr;
299
pint_t result;
300
301
// first get value
302
switch (encoding & 0x0F) {
303
case DW_EH_PE_ptr:
304
result = getP(addr);
305
p += sizeof(pint_t);
306
addr = (pint_t) p;
307
break;
308
case DW_EH_PE_uleb128:
309
result = (pint_t)getULEB128(addr, end);
310
break;
311
case DW_EH_PE_udata2:
312
result = get16(addr);
313
p += 2;
314
addr = (pint_t) p;
315
break;
316
case DW_EH_PE_udata4:
317
result = get32(addr);
318
p += 4;
319
addr = (pint_t) p;
320
break;
321
case DW_EH_PE_udata8:
322
result = (pint_t)get64(addr);
323
p += 8;
324
addr = (pint_t) p;
325
break;
326
case DW_EH_PE_sleb128:
327
result = (pint_t)getSLEB128(addr, end);
328
break;
329
case DW_EH_PE_sdata2:
330
// Sign extend from signed 16-bit value.
331
result = (pint_t)(int16_t)get16(addr);
332
p += 2;
333
addr = (pint_t) p;
334
break;
335
case DW_EH_PE_sdata4:
336
// Sign extend from signed 32-bit value.
337
result = (pint_t)(int32_t)get32(addr);
338
p += 4;
339
addr = (pint_t) p;
340
break;
341
case DW_EH_PE_sdata8:
342
result = (pint_t)get64(addr);
343
p += 8;
344
addr = (pint_t) p;
345
break;
346
default:
347
_LIBUNWIND_ABORT("unknown pointer encoding");
348
}
349
350
// then add relative offset
351
switch (encoding & 0x70) {
352
case DW_EH_PE_absptr:
353
// do nothing
354
break;
355
case DW_EH_PE_pcrel:
356
result += startAddr;
357
break;
358
case DW_EH_PE_textrel:
359
_LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
360
break;
361
case DW_EH_PE_datarel:
362
// DW_EH_PE_datarel is only valid in a few places, so the parameter has a
363
// default value of 0, and we abort in the event that someone calls this
364
// function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
365
if (datarelBase == 0)
366
_LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
367
result += datarelBase;
368
break;
369
case DW_EH_PE_funcrel:
370
_LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
371
break;
372
case DW_EH_PE_aligned:
373
_LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
374
break;
375
default:
376
_LIBUNWIND_ABORT("unknown pointer encoding");
377
break;
378
}
379
380
if (encoding & DW_EH_PE_indirect)
381
result = getP(result);
382
383
return result;
384
}
385
386
inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
387
UnwindInfoSections &info) {
388
#ifdef __APPLE__
389
dyld_unwind_sections dyldInfo;
390
if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
391
info.dso_base = (uintptr_t)dyldInfo.mh;
392
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
393
info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
394
info.dwarf_section_length = dyldInfo.dwarf_section_length;
395
#endif
396
info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
397
info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
398
return true;
399
}
400
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
401
// Bare metal is statically linked, so no need to ask the dynamic loader
402
info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
403
info.dwarf_section = (uintptr_t)(&__eh_frame_start);
404
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
405
(void *)info.dwarf_section, (void *)info.dwarf_section_length);
406
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
407
info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
408
info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
409
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
410
(void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
411
#endif
412
if (info.dwarf_section_length)
413
return true;
414
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
415
// Bare metal is statically linked, so no need to ask the dynamic loader
416
info.arm_section = (uintptr_t)(&__exidx_start);
417
info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
418
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
419
(void *)info.arm_section, (void *)info.arm_section_length);
420
if (info.arm_section && info.arm_section_length)
421
return true;
422
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
423
HMODULE mods[1024];
424
HANDLE process = GetCurrentProcess();
425
DWORD needed;
426
427
if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
428
return false;
429
430
for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
431
PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
432
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
433
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
434
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
435
bool found_obj = false;
436
bool found_hdr = false;
437
438
info.dso_base = (uintptr_t)mods[i];
439
for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
440
uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
441
uintptr_t end = begin + pish->Misc.VirtualSize;
442
if (!strncmp((const char *)pish->Name, ".text",
443
IMAGE_SIZEOF_SHORT_NAME)) {
444
if (targetAddr >= begin && targetAddr < end)
445
found_obj = true;
446
} else if (!strncmp((const char *)pish->Name, ".eh_frame",
447
IMAGE_SIZEOF_SHORT_NAME)) {
448
info.dwarf_section = begin;
449
info.dwarf_section_length = pish->Misc.VirtualSize;
450
found_hdr = true;
451
}
452
if (found_obj && found_hdr)
453
return true;
454
}
455
}
456
return false;
457
#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
458
// Don't even bother, since Windows has functions that do all this stuff
459
// for us.
460
return true;
461
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \
462
(__ANDROID_API__ < 21)
463
int length = 0;
464
info.arm_section =
465
(uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
466
info.arm_section_length = (uintptr_t)length;
467
if (info.arm_section && info.arm_section_length)
468
return true;
469
#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
470
struct dl_iterate_cb_data {
471
LocalAddressSpace *addressSpace;
472
UnwindInfoSections *sects;
473
uintptr_t targetAddr;
474
};
475
476
dl_iterate_cb_data cb_data = {this, &info, targetAddr};
477
int found = dl_iterate_phdr(
478
[](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
479
auto cbdata = static_cast<dl_iterate_cb_data *>(data);
480
bool found_obj = false;
481
bool found_hdr = false;
482
483
assert(cbdata);
484
assert(cbdata->sects);
485
486
if (cbdata->targetAddr < pinfo->dlpi_addr) {
487
return false;
488
}
489
490
#if !defined(Elf_Half)
491
typedef ElfW(Half) Elf_Half;
492
#endif
493
#if !defined(Elf_Phdr)
494
typedef ElfW(Phdr) Elf_Phdr;
495
#endif
496
#if !defined(Elf_Addr) && defined(__ANDROID__)
497
typedef ElfW(Addr) Elf_Addr;
498
#endif
499
500
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
501
#if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
502
#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
503
#endif
504
size_t object_length;
505
#if defined(__ANDROID__)
506
Elf_Addr image_base =
507
pinfo->dlpi_phnum
508
? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
509
reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
510
->p_offset
511
: 0;
512
#endif
513
514
for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
515
const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
516
if (phdr->p_type == PT_LOAD) {
517
uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
518
#if defined(__ANDROID__)
519
if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
520
begin = begin + image_base;
521
#endif
522
uintptr_t end = begin + phdr->p_memsz;
523
if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
524
cbdata->sects->dso_base = begin;
525
object_length = phdr->p_memsz;
526
found_obj = true;
527
}
528
} else if (phdr->p_type == PT_GNU_EH_FRAME) {
529
EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
530
uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
531
#if defined(__ANDROID__)
532
if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
533
eh_frame_hdr_start = eh_frame_hdr_start + image_base;
534
#endif
535
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
536
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
537
found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
538
*cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
539
hdrInfo);
540
if (found_hdr)
541
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
542
}
543
}
544
545
if (found_obj && found_hdr) {
546
cbdata->sects->dwarf_section_length = object_length;
547
return true;
548
} else {
549
return false;
550
}
551
#else // defined(_LIBUNWIND_ARM_EHABI)
552
for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
553
const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
554
if (phdr->p_type == PT_LOAD) {
555
uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
556
uintptr_t end = begin + phdr->p_memsz;
557
if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
558
found_obj = true;
559
} else if (phdr->p_type == PT_ARM_EXIDX) {
560
uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
561
cbdata->sects->arm_section = exidx_start;
562
cbdata->sects->arm_section_length = phdr->p_memsz;
563
found_hdr = true;
564
}
565
}
566
return found_obj && found_hdr;
567
#endif
568
},
569
&cb_data);
570
return static_cast<bool>(found);
571
#endif
572
573
return false;
574
}
575
576
577
inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
578
#ifdef __APPLE__
579
return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
580
#else
581
// TO DO: if OS has way to dynamically register FDEs, check that.
582
(void)targetAddr;
583
(void)fde;
584
return false;
585
#endif
586
}
587
588
inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
589
size_t bufLen,
590
unw_word_t *offset) {
591
#if _LIBUNWIND_USE_DLADDR
592
Dl_info dyldInfo;
593
if (dladdr((void *)addr, &dyldInfo)) {
594
if (dyldInfo.dli_sname != NULL) {
595
snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
596
*offset = (addr - (pint_t) dyldInfo.dli_saddr);
597
return true;
598
}
599
}
600
#endif
601
return false;
602
}
603
604
605
606
#ifdef UNW_REMOTE
607
608
/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
609
/// unwinding a thread in the another process. The other process can be a
610
/// different endianness and a different pointer size which is handled by
611
/// the P template parameter.
612
template <typename P>
613
class RemoteAddressSpace {
614
public:
615
RemoteAddressSpace(task_t task) : fTask(task) {}
616
617
typedef typename P::uint_t pint_t;
618
619
uint8_t get8(pint_t addr);
620
uint16_t get16(pint_t addr);
621
uint32_t get32(pint_t addr);
622
uint64_t get64(pint_t addr);
623
pint_t getP(pint_t addr);
624
uint64_t getRegister(pint_t addr);
625
uint64_t getULEB128(pint_t &addr, pint_t end);
626
int64_t getSLEB128(pint_t &addr, pint_t end);
627
pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
628
pint_t datarelBase = 0);
629
bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
630
unw_word_t *offset);
631
bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
632
bool findOtherFDE(pint_t targetAddr, pint_t &fde);
633
private:
634
void *localCopy(pint_t addr);
635
636
task_t fTask;
637
};
638
639
template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
640
return *((uint8_t *)localCopy(addr));
641
}
642
643
template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
644
return P::E::get16(*(uint16_t *)localCopy(addr));
645
}
646
647
template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
648
return P::E::get32(*(uint32_t *)localCopy(addr));
649
}
650
651
template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
652
return P::E::get64(*(uint64_t *)localCopy(addr));
653
}
654
655
template <typename P>
656
typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
657
return P::getP(*(uint64_t *)localCopy(addr));
658
}
659
660
template <typename P>
661
typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
662
return P::getRegister(*(uint64_t *)localCopy(addr));
663
}
664
665
template <typename P>
666
uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
667
uintptr_t size = (end - addr);
668
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
669
LocalAddressSpace::pint_t sladdr = laddr;
670
uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
671
addr += (laddr - sladdr);
672
return result;
673
}
674
675
template <typename P>
676
int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
677
uintptr_t size = (end - addr);
678
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
679
LocalAddressSpace::pint_t sladdr = laddr;
680
uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
681
addr += (laddr - sladdr);
682
return result;
683
}
684
685
template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
686
// FIX ME
687
}
688
689
template <typename P>
690
bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
691
size_t bufLen,
692
unw_word_t *offset) {
693
// FIX ME
694
}
695
696
/// unw_addr_space is the base class that abstract unw_addr_space_t type in
697
/// libunwind.h points to.
698
struct unw_addr_space {
699
cpu_type_t cpuType;
700
task_t taskPort;
701
};
702
703
/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
704
/// to when examining
705
/// a 32-bit intel process.
706
struct unw_addr_space_i386 : public unw_addr_space {
707
unw_addr_space_i386(task_t task) : oas(task) {}
708
RemoteAddressSpace<Pointer32<LittleEndian>> oas;
709
};
710
711
/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
712
/// points to when examining
713
/// a 64-bit intel process.
714
struct unw_addr_space_x86_64 : public unw_addr_space {
715
unw_addr_space_x86_64(task_t task) : oas(task) {}
716
RemoteAddressSpace<Pointer64<LittleEndian>> oas;
717
};
718
719
/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
720
/// to when examining
721
/// a 32-bit PowerPC process.
722
struct unw_addr_space_ppc : public unw_addr_space {
723
unw_addr_space_ppc(task_t task) : oas(task) {}
724
RemoteAddressSpace<Pointer32<BigEndian>> oas;
725
};
726
727
/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
728
/// to when examining a 64-bit PowerPC process.
729
struct unw_addr_space_ppc64 : public unw_addr_space {
730
unw_addr_space_ppc64(task_t task) : oas(task) {}
731
RemoteAddressSpace<Pointer64<LittleEndian>> oas;
732
};
733
734
#endif // UNW_REMOTE
735
736
} // namespace libunwind
737
738
#endif // __ADDRESSSPACE_HPP__
739
740