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