• 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 #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