Home | History | Annotate | Download | only in src
      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).
     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;
    186   uint8_t         get8(pint_t addr) {
    187     uint8_t val;
    188     memcpy(&val, (void *)addr, sizeof(val));
    189     return val;
    190   }
    191   uint16_t         get16(pint_t addr) {
    192     uint16_t val;
    193     memcpy(&val, (void *)addr, sizeof(val));
    194     return val;
    195   }
    196   uint32_t         get32(pint_t addr) {
    197     uint32_t val;
    198     memcpy(&val, (void *)addr, sizeof(val));
    199     return val;
    200   }
    201   uint64_t         get64(pint_t addr) {
    202     uint64_t val;
    203     memcpy(&val, (void *)addr, sizeof(val));
    204     return val;
    205   }
    206   double           getDouble(pint_t addr) {
    207     double val;
    208     memcpy(&val, (void *)addr, sizeof(val));
    209     return val;
    210   }
    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 
    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 
    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.
    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.
    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
    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 
    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 
    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 
    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