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