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