10b57cec5SDimitry Andric //===------------------------- AddressSpace.hpp ---------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric // 80b57cec5SDimitry Andric // Abstracts accessing local vs remote address spaces. 90b57cec5SDimitry Andric // 100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #ifndef __ADDRESSSPACE_HPP__ 130b57cec5SDimitry Andric #define __ADDRESSSPACE_HPP__ 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include <stdint.h> 160b57cec5SDimitry Andric #include <stdio.h> 170b57cec5SDimitry Andric #include <stdlib.h> 180b57cec5SDimitry Andric #include <string.h> 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #ifndef _LIBUNWIND_USE_DLADDR 210b57cec5SDimitry Andric #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) 220b57cec5SDimitry Andric #define _LIBUNWIND_USE_DLADDR 1 230b57cec5SDimitry Andric #else 240b57cec5SDimitry Andric #define _LIBUNWIND_USE_DLADDR 0 250b57cec5SDimitry Andric #endif 260b57cec5SDimitry Andric #endif 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #if _LIBUNWIND_USE_DLADDR 290b57cec5SDimitry Andric #include <dlfcn.h> 30480093f4SDimitry Andric #if defined(__ELF__) && defined(_LIBUNWIND_LINK_DL_LIB) 310b57cec5SDimitry Andric #pragma comment(lib, "dl") 320b57cec5SDimitry Andric #endif 330b57cec5SDimitry Andric #endif 340b57cec5SDimitry Andric 35c2c6a179SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 36c2c6a179SDimitry Andric struct EHABIIndexEntry { 37c2c6a179SDimitry Andric uint32_t functionOffset; 38c2c6a179SDimitry Andric uint32_t data; 39c2c6a179SDimitry Andric }; 40c2c6a179SDimitry Andric #endif 41c2c6a179SDimitry Andric 420b57cec5SDimitry Andric #ifdef __APPLE__ 430b57cec5SDimitry Andric #include <mach-o/getsect.h> 440b57cec5SDimitry Andric namespace libunwind { 450b57cec5SDimitry Andric bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric #endif 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric #include "libunwind.h" 500b57cec5SDimitry Andric #include "config.h" 510b57cec5SDimitry Andric #include "dwarf2.h" 520b57cec5SDimitry Andric #include "EHHeaderParser.hpp" 530b57cec5SDimitry Andric #include "Registers.hpp" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric #ifdef __APPLE__ 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric struct dyld_unwind_sections 580b57cec5SDimitry Andric { 590b57cec5SDimitry Andric const struct mach_header* mh; 600b57cec5SDimitry Andric const void* dwarf_section; 610b57cec5SDimitry Andric uintptr_t dwarf_section_length; 620b57cec5SDimitry Andric const void* compact_unwind_section; 630b57cec5SDimitry Andric uintptr_t compact_unwind_section_length; 640b57cec5SDimitry Andric }; 650b57cec5SDimitry Andric #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ 660b57cec5SDimitry Andric && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ 670b57cec5SDimitry Andric || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 680b57cec5SDimitry Andric // In 10.7.0 or later, libSystem.dylib implements this function. 690b57cec5SDimitry Andric extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); 700b57cec5SDimitry Andric #else 710b57cec5SDimitry Andric // In 10.6.x and earlier, we need to implement this functionality. Note 720b57cec5SDimitry Andric // that this requires a newer version of libmacho (from cctools) than is 730b57cec5SDimitry Andric // present in libSystem on 10.6.x (for getsectiondata). 740b57cec5SDimitry Andric static inline bool _dyld_find_unwind_sections(void* addr, 750b57cec5SDimitry Andric dyld_unwind_sections* info) { 760b57cec5SDimitry Andric // Find mach-o image containing address. 770b57cec5SDimitry Andric Dl_info dlinfo; 780b57cec5SDimitry Andric if (!dladdr(addr, &dlinfo)) 790b57cec5SDimitry Andric return false; 800b57cec5SDimitry Andric #if __LP64__ 810b57cec5SDimitry Andric const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase; 820b57cec5SDimitry Andric #else 830b57cec5SDimitry Andric const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase; 840b57cec5SDimitry Andric #endif 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // Initialize the return struct 870b57cec5SDimitry Andric info->mh = (const struct mach_header *)mh; 880b57cec5SDimitry Andric info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length); 890b57cec5SDimitry Andric info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric if (!info->dwarf_section) { 920b57cec5SDimitry Andric info->dwarf_section_length = 0; 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric if (!info->compact_unwind_section) { 960b57cec5SDimitry Andric info->compact_unwind_section_length = 0; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric return true; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric #endif 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // When statically linked on bare-metal, the symbols for the EH table are looked 1060b57cec5SDimitry Andric // up without going through the dynamic loader. 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // The following linker script may be used to produce the necessary sections and symbols. 1090b57cec5SDimitry Andric // Unless the --eh-frame-hdr linker option is provided, the section is not generated 1100b57cec5SDimitry Andric // and does not take space in the output file. 1110b57cec5SDimitry Andric // 1120b57cec5SDimitry Andric // .eh_frame : 1130b57cec5SDimitry Andric // { 1140b57cec5SDimitry Andric // __eh_frame_start = .; 1150b57cec5SDimitry Andric // KEEP(*(.eh_frame)) 1160b57cec5SDimitry Andric // __eh_frame_end = .; 1170b57cec5SDimitry Andric // } 1180b57cec5SDimitry Andric // 1190b57cec5SDimitry Andric // .eh_frame_hdr : 1200b57cec5SDimitry Andric // { 1210b57cec5SDimitry Andric // KEEP(*(.eh_frame_hdr)) 1220b57cec5SDimitry Andric // } 1230b57cec5SDimitry Andric // 1240b57cec5SDimitry Andric // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; 1250b57cec5SDimitry Andric // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric extern char __eh_frame_start; 1280b57cec5SDimitry Andric extern char __eh_frame_end; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 1310b57cec5SDimitry Andric extern char __eh_frame_hdr_start; 1320b57cec5SDimitry Andric extern char __eh_frame_hdr_end; 1330b57cec5SDimitry Andric #endif 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric // When statically linked on bare-metal, the symbols for the EH table are looked 1380b57cec5SDimitry Andric // up without going through the dynamic loader. 1390b57cec5SDimitry Andric extern char __exidx_start; 1400b57cec5SDimitry Andric extern char __exidx_end; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // ELF-based systems may use dl_iterate_phdr() to access sections 1450b57cec5SDimitry Andric // containing unwinding information. The ElfW() macro for pointer-size 1460b57cec5SDimitry Andric // independent ELF header traversal is not provided by <link.h> on some 1470b57cec5SDimitry Andric // systems (e.g., FreeBSD). On these systems the data structures are 1480b57cec5SDimitry Andric // just called Elf_XXX. Define ElfW() locally. 1490b57cec5SDimitry Andric #ifndef _WIN32 1500b57cec5SDimitry Andric #include <link.h> 1510b57cec5SDimitry Andric #else 1520b57cec5SDimitry Andric #include <windows.h> 1530b57cec5SDimitry Andric #include <psapi.h> 1540b57cec5SDimitry Andric #endif 1550b57cec5SDimitry Andric #if !defined(ElfW) 1560b57cec5SDimitry Andric #define ElfW(type) Elf_##type 1570b57cec5SDimitry Andric #endif 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric #endif 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric namespace libunwind { 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// Used by findUnwindSections() to return info about needed sections. 1640b57cec5SDimitry Andric struct UnwindInfoSections { 1650b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ 1660b57cec5SDimitry Andric defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1670b57cec5SDimitry Andric // No dso_base for SEH or ARM EHABI. 1680b57cec5SDimitry Andric uintptr_t dso_base; 1690b57cec5SDimitry Andric #endif 1700b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1710b57cec5SDimitry Andric uintptr_t dwarf_section; 1720b57cec5SDimitry Andric uintptr_t dwarf_section_length; 1730b57cec5SDimitry Andric #endif 1740b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 1750b57cec5SDimitry Andric uintptr_t dwarf_index_section; 1760b57cec5SDimitry Andric uintptr_t dwarf_index_section_length; 1770b57cec5SDimitry Andric #endif 1780b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1790b57cec5SDimitry Andric uintptr_t compact_unwind_section; 1800b57cec5SDimitry Andric uintptr_t compact_unwind_section_length; 1810b57cec5SDimitry Andric #endif 1820b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 1830b57cec5SDimitry Andric uintptr_t arm_section; 1840b57cec5SDimitry Andric uintptr_t arm_section_length; 1850b57cec5SDimitry Andric #endif 1860b57cec5SDimitry Andric }; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric /// LocalAddressSpace is used as a template parameter to UnwindCursor when 1900b57cec5SDimitry Andric /// unwinding a thread in the same process. The wrappers compile away, 1910b57cec5SDimitry Andric /// making local unwinds fast. 1920b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN LocalAddressSpace { 1930b57cec5SDimitry Andric public: 1940b57cec5SDimitry Andric typedef uintptr_t pint_t; 1950b57cec5SDimitry Andric typedef intptr_t sint_t; 1960b57cec5SDimitry Andric uint8_t get8(pint_t addr) { 1970b57cec5SDimitry Andric uint8_t val; 1980b57cec5SDimitry Andric memcpy(&val, (void *)addr, sizeof(val)); 1990b57cec5SDimitry Andric return val; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric uint16_t get16(pint_t addr) { 2020b57cec5SDimitry Andric uint16_t val; 2030b57cec5SDimitry Andric memcpy(&val, (void *)addr, sizeof(val)); 2040b57cec5SDimitry Andric return val; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric uint32_t get32(pint_t addr) { 2070b57cec5SDimitry Andric uint32_t val; 2080b57cec5SDimitry Andric memcpy(&val, (void *)addr, sizeof(val)); 2090b57cec5SDimitry Andric return val; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric uint64_t get64(pint_t addr) { 2120b57cec5SDimitry Andric uint64_t val; 2130b57cec5SDimitry Andric memcpy(&val, (void *)addr, sizeof(val)); 2140b57cec5SDimitry Andric return val; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric double getDouble(pint_t addr) { 2170b57cec5SDimitry Andric double val; 2180b57cec5SDimitry Andric memcpy(&val, (void *)addr, sizeof(val)); 2190b57cec5SDimitry Andric return val; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric v128 getVector(pint_t addr) { 2220b57cec5SDimitry Andric v128 val; 2230b57cec5SDimitry Andric memcpy(&val, (void *)addr, sizeof(val)); 2240b57cec5SDimitry Andric return val; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric uintptr_t getP(pint_t addr); 2270b57cec5SDimitry Andric uint64_t getRegister(pint_t addr); 2280b57cec5SDimitry Andric static uint64_t getULEB128(pint_t &addr, pint_t end); 2290b57cec5SDimitry Andric static int64_t getSLEB128(pint_t &addr, pint_t end); 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 2320b57cec5SDimitry Andric pint_t datarelBase = 0); 2330b57cec5SDimitry Andric bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 2340b57cec5SDimitry Andric unw_word_t *offset); 2350b57cec5SDimitry Andric bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 2360b57cec5SDimitry Andric bool findOtherFDE(pint_t targetAddr, pint_t &fde); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric static LocalAddressSpace sThisAddressSpace; 2390b57cec5SDimitry Andric }; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric inline uintptr_t LocalAddressSpace::getP(pint_t addr) { 2420b57cec5SDimitry Andric #if __SIZEOF_POINTER__ == 8 2430b57cec5SDimitry Andric return get64(addr); 2440b57cec5SDimitry Andric #else 2450b57cec5SDimitry Andric return get32(addr); 2460b57cec5SDimitry Andric #endif 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric inline uint64_t LocalAddressSpace::getRegister(pint_t addr) { 2500b57cec5SDimitry Andric #if __SIZEOF_POINTER__ == 8 || defined(__mips64) 2510b57cec5SDimitry Andric return get64(addr); 2520b57cec5SDimitry Andric #else 2530b57cec5SDimitry Andric return get32(addr); 2540b57cec5SDimitry Andric #endif 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric /// Read a ULEB128 into a 64-bit word. 2580b57cec5SDimitry Andric inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { 2590b57cec5SDimitry Andric const uint8_t *p = (uint8_t *)addr; 2600b57cec5SDimitry Andric const uint8_t *pend = (uint8_t *)end; 2610b57cec5SDimitry Andric uint64_t result = 0; 2620b57cec5SDimitry Andric int bit = 0; 2630b57cec5SDimitry Andric do { 2640b57cec5SDimitry Andric uint64_t b; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric if (p == pend) 2670b57cec5SDimitry Andric _LIBUNWIND_ABORT("truncated uleb128 expression"); 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric b = *p & 0x7f; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric if (bit >= 64 || b << bit >> bit != b) { 2720b57cec5SDimitry Andric _LIBUNWIND_ABORT("malformed uleb128 expression"); 2730b57cec5SDimitry Andric } else { 2740b57cec5SDimitry Andric result |= b << bit; 2750b57cec5SDimitry Andric bit += 7; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric } while (*p++ >= 0x80); 2780b57cec5SDimitry Andric addr = (pint_t) p; 2790b57cec5SDimitry Andric return result; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric /// Read a SLEB128 into a 64-bit word. 2830b57cec5SDimitry Andric inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { 2840b57cec5SDimitry Andric const uint8_t *p = (uint8_t *)addr; 2850b57cec5SDimitry Andric const uint8_t *pend = (uint8_t *)end; 2860b57cec5SDimitry Andric int64_t result = 0; 2870b57cec5SDimitry Andric int bit = 0; 2880b57cec5SDimitry Andric uint8_t byte; 2890b57cec5SDimitry Andric do { 2900b57cec5SDimitry Andric if (p == pend) 2910b57cec5SDimitry Andric _LIBUNWIND_ABORT("truncated sleb128 expression"); 2920b57cec5SDimitry Andric byte = *p++; 2930b57cec5SDimitry Andric result |= ((byte & 0x7f) << bit); 2940b57cec5SDimitry Andric bit += 7; 2950b57cec5SDimitry Andric } while (byte & 0x80); 2960b57cec5SDimitry Andric // sign extend negative numbers 2970b57cec5SDimitry Andric if ((byte & 0x40) != 0) 2980b57cec5SDimitry Andric result |= (-1ULL) << bit; 2990b57cec5SDimitry Andric addr = (pint_t) p; 3000b57cec5SDimitry Andric return result; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric inline LocalAddressSpace::pint_t 3040b57cec5SDimitry Andric LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 3050b57cec5SDimitry Andric pint_t datarelBase) { 3060b57cec5SDimitry Andric pint_t startAddr = addr; 3070b57cec5SDimitry Andric const uint8_t *p = (uint8_t *)addr; 3080b57cec5SDimitry Andric pint_t result; 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric // first get value 3110b57cec5SDimitry Andric switch (encoding & 0x0F) { 3120b57cec5SDimitry Andric case DW_EH_PE_ptr: 3130b57cec5SDimitry Andric result = getP(addr); 3140b57cec5SDimitry Andric p += sizeof(pint_t); 3150b57cec5SDimitry Andric addr = (pint_t) p; 3160b57cec5SDimitry Andric break; 3170b57cec5SDimitry Andric case DW_EH_PE_uleb128: 3180b57cec5SDimitry Andric result = (pint_t)getULEB128(addr, end); 3190b57cec5SDimitry Andric break; 3200b57cec5SDimitry Andric case DW_EH_PE_udata2: 3210b57cec5SDimitry Andric result = get16(addr); 3220b57cec5SDimitry Andric p += 2; 3230b57cec5SDimitry Andric addr = (pint_t) p; 3240b57cec5SDimitry Andric break; 3250b57cec5SDimitry Andric case DW_EH_PE_udata4: 3260b57cec5SDimitry Andric result = get32(addr); 3270b57cec5SDimitry Andric p += 4; 3280b57cec5SDimitry Andric addr = (pint_t) p; 3290b57cec5SDimitry Andric break; 3300b57cec5SDimitry Andric case DW_EH_PE_udata8: 3310b57cec5SDimitry Andric result = (pint_t)get64(addr); 3320b57cec5SDimitry Andric p += 8; 3330b57cec5SDimitry Andric addr = (pint_t) p; 3340b57cec5SDimitry Andric break; 3350b57cec5SDimitry Andric case DW_EH_PE_sleb128: 3360b57cec5SDimitry Andric result = (pint_t)getSLEB128(addr, end); 3370b57cec5SDimitry Andric break; 3380b57cec5SDimitry Andric case DW_EH_PE_sdata2: 3390b57cec5SDimitry Andric // Sign extend from signed 16-bit value. 3400b57cec5SDimitry Andric result = (pint_t)(int16_t)get16(addr); 3410b57cec5SDimitry Andric p += 2; 3420b57cec5SDimitry Andric addr = (pint_t) p; 3430b57cec5SDimitry Andric break; 3440b57cec5SDimitry Andric case DW_EH_PE_sdata4: 3450b57cec5SDimitry Andric // Sign extend from signed 32-bit value. 3460b57cec5SDimitry Andric result = (pint_t)(int32_t)get32(addr); 3470b57cec5SDimitry Andric p += 4; 3480b57cec5SDimitry Andric addr = (pint_t) p; 3490b57cec5SDimitry Andric break; 3500b57cec5SDimitry Andric case DW_EH_PE_sdata8: 3510b57cec5SDimitry Andric result = (pint_t)get64(addr); 3520b57cec5SDimitry Andric p += 8; 3530b57cec5SDimitry Andric addr = (pint_t) p; 3540b57cec5SDimitry Andric break; 3550b57cec5SDimitry Andric default: 3560b57cec5SDimitry Andric _LIBUNWIND_ABORT("unknown pointer encoding"); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric // then add relative offset 3600b57cec5SDimitry Andric switch (encoding & 0x70) { 3610b57cec5SDimitry Andric case DW_EH_PE_absptr: 3620b57cec5SDimitry Andric // do nothing 3630b57cec5SDimitry Andric break; 3640b57cec5SDimitry Andric case DW_EH_PE_pcrel: 3650b57cec5SDimitry Andric result += startAddr; 3660b57cec5SDimitry Andric break; 3670b57cec5SDimitry Andric case DW_EH_PE_textrel: 3680b57cec5SDimitry Andric _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); 3690b57cec5SDimitry Andric break; 3700b57cec5SDimitry Andric case DW_EH_PE_datarel: 3710b57cec5SDimitry Andric // DW_EH_PE_datarel is only valid in a few places, so the parameter has a 3720b57cec5SDimitry Andric // default value of 0, and we abort in the event that someone calls this 3730b57cec5SDimitry Andric // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. 3740b57cec5SDimitry Andric if (datarelBase == 0) 3750b57cec5SDimitry Andric _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); 3760b57cec5SDimitry Andric result += datarelBase; 3770b57cec5SDimitry Andric break; 3780b57cec5SDimitry Andric case DW_EH_PE_funcrel: 3790b57cec5SDimitry Andric _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); 3800b57cec5SDimitry Andric break; 3810b57cec5SDimitry Andric case DW_EH_PE_aligned: 3820b57cec5SDimitry Andric _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); 3830b57cec5SDimitry Andric break; 3840b57cec5SDimitry Andric default: 3850b57cec5SDimitry Andric _LIBUNWIND_ABORT("unknown pointer encoding"); 3860b57cec5SDimitry Andric break; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric if (encoding & DW_EH_PE_indirect) 3900b57cec5SDimitry Andric result = getP(result); 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric return result; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3955ffd83dbSDimitry Andric #ifdef __APPLE__ 3965ffd83dbSDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) 3975ffd83dbSDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) 3985ffd83dbSDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) 3995ffd83dbSDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) 4005ffd83dbSDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) 4015ffd83dbSDimitry Andric // Code inside findUnwindSections handles all these cases. 4025ffd83dbSDimitry Andric // 4035ffd83dbSDimitry Andric // Although the above ifdef chain is ugly, there doesn't seem to be a cleaner 4045ffd83dbSDimitry Andric // way to handle it. The generalized boolean expression is: 4055ffd83dbSDimitry Andric // 4065ffd83dbSDimitry Andric // A OR (B AND C) OR (D AND C) OR (B AND E) OR (F AND E) OR (D AND G) 4075ffd83dbSDimitry Andric // 4085ffd83dbSDimitry Andric // Running it through various boolean expression simplifiers gives expressions 4095ffd83dbSDimitry Andric // that don't help at all. 4105ffd83dbSDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 4115ffd83dbSDimitry Andric 4125ffd83dbSDimitry Andric #if !defined(Elf_Half) 4135ffd83dbSDimitry Andric typedef ElfW(Half) Elf_Half; 4145ffd83dbSDimitry Andric #endif 4155ffd83dbSDimitry Andric #if !defined(Elf_Phdr) 4165ffd83dbSDimitry Andric typedef ElfW(Phdr) Elf_Phdr; 4175ffd83dbSDimitry Andric #endif 4185ffd83dbSDimitry Andric #if !defined(Elf_Addr) 4195ffd83dbSDimitry Andric typedef ElfW(Addr) Elf_Addr; 4205ffd83dbSDimitry Andric #endif 4215ffd83dbSDimitry Andric 4225ffd83dbSDimitry Andric static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { 4235ffd83dbSDimitry Andric Elf_Addr image_base = pinfo->dlpi_addr; 4245ffd83dbSDimitry Andric #if defined(__ANDROID__) && __ANDROID_API__ < 18 4255ffd83dbSDimitry Andric if (image_base == 0) { 4265ffd83dbSDimitry Andric // Normally, an image base of 0 indicates a non-PIE executable. On 4275ffd83dbSDimitry Andric // versions of Android prior to API 18, the dynamic linker reported a 4285ffd83dbSDimitry Andric // dlpi_addr of 0 for PIE executables. Compute the true image base 4295ffd83dbSDimitry Andric // using the PT_PHDR segment. 4305ffd83dbSDimitry Andric // See https://github.com/android/ndk/issues/505. 4315ffd83dbSDimitry Andric for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 4325ffd83dbSDimitry Andric const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 4335ffd83dbSDimitry Andric if (phdr->p_type == PT_PHDR) { 4345ffd83dbSDimitry Andric image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - 4355ffd83dbSDimitry Andric phdr->p_vaddr; 4365ffd83dbSDimitry Andric break; 4375ffd83dbSDimitry Andric } 4385ffd83dbSDimitry Andric } 4395ffd83dbSDimitry Andric } 4405ffd83dbSDimitry Andric #endif 4415ffd83dbSDimitry Andric return image_base; 4425ffd83dbSDimitry Andric } 4435ffd83dbSDimitry Andric 4445ffd83dbSDimitry Andric struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { 4455ffd83dbSDimitry Andric LocalAddressSpace *addressSpace; 4465ffd83dbSDimitry Andric UnwindInfoSections *sects; 4475ffd83dbSDimitry Andric uintptr_t targetAddr; 4485ffd83dbSDimitry Andric }; 4495ffd83dbSDimitry Andric 4505ffd83dbSDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 4515ffd83dbSDimitry Andric #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 4525ffd83dbSDimitry Andric #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." 4535ffd83dbSDimitry Andric #endif 4545ffd83dbSDimitry Andric 4559ff1cc58SDimitry Andric #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) 4565ffd83dbSDimitry Andric #include "FrameHeaderCache.hpp" 4575ffd83dbSDimitry Andric 4585ffd83dbSDimitry Andric // There should be just one of these per process. 4595ffd83dbSDimitry Andric static FrameHeaderCache ProcessFrameHeaderCache; 460*75b4d546SDimitry Andric #endif 4615ffd83dbSDimitry Andric 4625ffd83dbSDimitry Andric static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, 4635ffd83dbSDimitry Andric dl_iterate_cb_data *cbdata) { 4645ffd83dbSDimitry Andric if (phdr->p_type == PT_LOAD) { 4655ffd83dbSDimitry Andric uintptr_t begin = image_base + phdr->p_vaddr; 4665ffd83dbSDimitry Andric uintptr_t end = begin + phdr->p_memsz; 4675ffd83dbSDimitry Andric if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { 4685ffd83dbSDimitry Andric cbdata->sects->dso_base = begin; 4695ffd83dbSDimitry Andric cbdata->sects->dwarf_section_length = phdr->p_memsz; 4705ffd83dbSDimitry Andric return true; 4715ffd83dbSDimitry Andric } 4725ffd83dbSDimitry Andric } 4735ffd83dbSDimitry Andric return false; 4745ffd83dbSDimitry Andric } 4755ffd83dbSDimitry Andric 4765ffd83dbSDimitry Andric int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t pinfo_size, 4775ffd83dbSDimitry Andric void *data) { 4785ffd83dbSDimitry Andric auto cbdata = static_cast<dl_iterate_cb_data *>(data); 4795ffd83dbSDimitry Andric if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) 4805ffd83dbSDimitry Andric return 0; 4819ff1cc58SDimitry Andric #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) 4825ffd83dbSDimitry Andric if (ProcessFrameHeaderCache.find(pinfo, pinfo_size, data)) 4835ffd83dbSDimitry Andric return 1; 484*75b4d546SDimitry Andric #endif 4855ffd83dbSDimitry Andric 4865ffd83dbSDimitry Andric Elf_Addr image_base = calculateImageBase(pinfo); 4875ffd83dbSDimitry Andric bool found_obj = false; 4885ffd83dbSDimitry Andric bool found_hdr = false; 4895ffd83dbSDimitry Andric 4905ffd83dbSDimitry Andric // Third phdr is usually the executable phdr. 4915ffd83dbSDimitry Andric if (pinfo->dlpi_phnum > 2) 4925ffd83dbSDimitry Andric found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata); 4935ffd83dbSDimitry Andric 4945ffd83dbSDimitry Andric // PT_GNU_EH_FRAME is usually near the end. Iterate backward. We already know 4955ffd83dbSDimitry Andric // that there is one or more phdrs. 4965ffd83dbSDimitry Andric for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { 4975ffd83dbSDimitry Andric const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; 4985ffd83dbSDimitry Andric if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) { 4995ffd83dbSDimitry Andric EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; 5005ffd83dbSDimitry Andric uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; 5015ffd83dbSDimitry Andric cbdata->sects->dwarf_index_section = eh_frame_hdr_start; 5025ffd83dbSDimitry Andric cbdata->sects->dwarf_index_section_length = phdr->p_memsz; 5035ffd83dbSDimitry Andric found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr( 5045ffd83dbSDimitry Andric *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, 5055ffd83dbSDimitry Andric hdrInfo); 5065ffd83dbSDimitry Andric if (found_hdr) 5075ffd83dbSDimitry Andric cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; 5085ffd83dbSDimitry Andric } else if (!found_obj) { 5095ffd83dbSDimitry Andric found_obj = checkAddrInSegment(phdr, image_base, cbdata); 5105ffd83dbSDimitry Andric } 5115ffd83dbSDimitry Andric if (found_obj && found_hdr) { 5129ff1cc58SDimitry Andric #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) 5135ffd83dbSDimitry Andric ProcessFrameHeaderCache.add(cbdata->sects); 514*75b4d546SDimitry Andric #endif 5155ffd83dbSDimitry Andric return 1; 5165ffd83dbSDimitry Andric } 5175ffd83dbSDimitry Andric } 5185ffd83dbSDimitry Andric cbdata->sects->dwarf_section_length = 0; 5195ffd83dbSDimitry Andric return 0; 5205ffd83dbSDimitry Andric } 5215ffd83dbSDimitry Andric 5225ffd83dbSDimitry Andric #else // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) 5235ffd83dbSDimitry Andric // Given all the #ifdef's above, the code here is for 5245ffd83dbSDimitry Andric // defined(LIBUNWIND_ARM_EHABI) 5255ffd83dbSDimitry Andric 5265ffd83dbSDimitry Andric int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) { 5275ffd83dbSDimitry Andric auto *cbdata = static_cast<dl_iterate_cb_data *>(data); 5285ffd83dbSDimitry Andric bool found_obj = false; 5295ffd83dbSDimitry Andric bool found_hdr = false; 5305ffd83dbSDimitry Andric 5315ffd83dbSDimitry Andric assert(cbdata); 5325ffd83dbSDimitry Andric assert(cbdata->sects); 5335ffd83dbSDimitry Andric 5345ffd83dbSDimitry Andric if (cbdata->targetAddr < pinfo->dlpi_addr) 5355ffd83dbSDimitry Andric return 0; 5365ffd83dbSDimitry Andric 5375ffd83dbSDimitry Andric Elf_Addr image_base = calculateImageBase(pinfo); 5385ffd83dbSDimitry Andric 5395ffd83dbSDimitry Andric for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 5405ffd83dbSDimitry Andric const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 5415ffd83dbSDimitry Andric if (phdr->p_type == PT_LOAD) { 5425ffd83dbSDimitry Andric uintptr_t begin = image_base + phdr->p_vaddr; 5435ffd83dbSDimitry Andric uintptr_t end = begin + phdr->p_memsz; 5445ffd83dbSDimitry Andric if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) 5455ffd83dbSDimitry Andric found_obj = true; 5465ffd83dbSDimitry Andric } else if (phdr->p_type == PT_ARM_EXIDX) { 5475ffd83dbSDimitry Andric uintptr_t exidx_start = image_base + phdr->p_vaddr; 5485ffd83dbSDimitry Andric cbdata->sects->arm_section = exidx_start; 5495ffd83dbSDimitry Andric cbdata->sects->arm_section_length = phdr->p_memsz; 5505ffd83dbSDimitry Andric found_hdr = true; 5515ffd83dbSDimitry Andric } 5525ffd83dbSDimitry Andric } 5535ffd83dbSDimitry Andric return found_obj && found_hdr; 5545ffd83dbSDimitry Andric } 5555ffd83dbSDimitry Andric #endif // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) 5565ffd83dbSDimitry Andric #endif // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 5575ffd83dbSDimitry Andric 5585ffd83dbSDimitry Andric 5590b57cec5SDimitry Andric inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, 5600b57cec5SDimitry Andric UnwindInfoSections &info) { 5610b57cec5SDimitry Andric #ifdef __APPLE__ 5620b57cec5SDimitry Andric dyld_unwind_sections dyldInfo; 5630b57cec5SDimitry Andric if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { 5640b57cec5SDimitry Andric info.dso_base = (uintptr_t)dyldInfo.mh; 5650b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 5660b57cec5SDimitry Andric info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; 5670b57cec5SDimitry Andric info.dwarf_section_length = dyldInfo.dwarf_section_length; 5680b57cec5SDimitry Andric #endif 5690b57cec5SDimitry Andric info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; 5700b57cec5SDimitry Andric info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; 5710b57cec5SDimitry Andric return true; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) 5740b57cec5SDimitry Andric // Bare metal is statically linked, so no need to ask the dynamic loader 5750b57cec5SDimitry Andric info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); 5760b57cec5SDimitry Andric info.dwarf_section = (uintptr_t)(&__eh_frame_start); 5770b57cec5SDimitry Andric _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", 5780b57cec5SDimitry Andric (void *)info.dwarf_section, (void *)info.dwarf_section_length); 5790b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 5800b57cec5SDimitry Andric info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); 5810b57cec5SDimitry Andric info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); 5820b57cec5SDimitry Andric _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", 5830b57cec5SDimitry Andric (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); 5840b57cec5SDimitry Andric #endif 5850b57cec5SDimitry Andric if (info.dwarf_section_length) 5860b57cec5SDimitry Andric return true; 5870b57cec5SDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) 5880b57cec5SDimitry Andric // Bare metal is statically linked, so no need to ask the dynamic loader 5890b57cec5SDimitry Andric info.arm_section = (uintptr_t)(&__exidx_start); 5900b57cec5SDimitry Andric info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); 5910b57cec5SDimitry Andric _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", 5920b57cec5SDimitry Andric (void *)info.arm_section, (void *)info.arm_section_length); 5930b57cec5SDimitry Andric if (info.arm_section && info.arm_section_length) 5940b57cec5SDimitry Andric return true; 5950b57cec5SDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) 5960b57cec5SDimitry Andric HMODULE mods[1024]; 5970b57cec5SDimitry Andric HANDLE process = GetCurrentProcess(); 5980b57cec5SDimitry Andric DWORD needed; 5990b57cec5SDimitry Andric 600480093f4SDimitry Andric if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) { 601480093f4SDimitry Andric DWORD err = GetLastError(); 602480093f4SDimitry Andric _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, " 603480093f4SDimitry Andric "returned error %d", (int)err); 6040b57cec5SDimitry Andric return false; 605480093f4SDimitry Andric } 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { 6080b57cec5SDimitry Andric PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; 6090b57cec5SDimitry Andric PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew); 6100b57cec5SDimitry Andric PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader; 6110b57cec5SDimitry Andric PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); 6120b57cec5SDimitry Andric bool found_obj = false; 6130b57cec5SDimitry Andric bool found_hdr = false; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric info.dso_base = (uintptr_t)mods[i]; 6160b57cec5SDimitry Andric for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) { 6170b57cec5SDimitry Andric uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i]; 6180b57cec5SDimitry Andric uintptr_t end = begin + pish->Misc.VirtualSize; 6190b57cec5SDimitry Andric if (!strncmp((const char *)pish->Name, ".text", 6200b57cec5SDimitry Andric IMAGE_SIZEOF_SHORT_NAME)) { 6210b57cec5SDimitry Andric if (targetAddr >= begin && targetAddr < end) 6220b57cec5SDimitry Andric found_obj = true; 6230b57cec5SDimitry Andric } else if (!strncmp((const char *)pish->Name, ".eh_frame", 6240b57cec5SDimitry Andric IMAGE_SIZEOF_SHORT_NAME)) { 6250b57cec5SDimitry Andric info.dwarf_section = begin; 6260b57cec5SDimitry Andric info.dwarf_section_length = pish->Misc.VirtualSize; 6270b57cec5SDimitry Andric found_hdr = true; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric if (found_obj && found_hdr) 6300b57cec5SDimitry Andric return true; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric return false; 6340b57cec5SDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) 6350b57cec5SDimitry Andric // Don't even bother, since Windows has functions that do all this stuff 6360b57cec5SDimitry Andric // for us. 6370b57cec5SDimitry Andric (void)targetAddr; 6380b57cec5SDimitry Andric (void)info; 6390b57cec5SDimitry Andric return true; 640c2c6a179SDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) 641c2c6a179SDimitry Andric // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After 642c2c6a179SDimitry Andric // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. 6430b57cec5SDimitry Andric int length = 0; 6440b57cec5SDimitry Andric info.arm_section = 6450b57cec5SDimitry Andric (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); 646c2c6a179SDimitry Andric info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); 6470b57cec5SDimitry Andric if (info.arm_section && info.arm_section_length) 6480b57cec5SDimitry Andric return true; 6490b57cec5SDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 6500b57cec5SDimitry Andric dl_iterate_cb_data cb_data = {this, &info, targetAddr}; 6515ffd83dbSDimitry Andric int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); 6520b57cec5SDimitry Andric return static_cast<bool>(found); 6530b57cec5SDimitry Andric #endif 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric return false; 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { 6600b57cec5SDimitry Andric #ifdef __APPLE__ 6610b57cec5SDimitry Andric return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); 6620b57cec5SDimitry Andric #else 6630b57cec5SDimitry Andric // TO DO: if OS has way to dynamically register FDEs, check that. 6640b57cec5SDimitry Andric (void)targetAddr; 6650b57cec5SDimitry Andric (void)fde; 6660b57cec5SDimitry Andric return false; 6670b57cec5SDimitry Andric #endif 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, 6710b57cec5SDimitry Andric size_t bufLen, 6720b57cec5SDimitry Andric unw_word_t *offset) { 6730b57cec5SDimitry Andric #if _LIBUNWIND_USE_DLADDR 6740b57cec5SDimitry Andric Dl_info dyldInfo; 6750b57cec5SDimitry Andric if (dladdr((void *)addr, &dyldInfo)) { 6760b57cec5SDimitry Andric if (dyldInfo.dli_sname != NULL) { 6770b57cec5SDimitry Andric snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); 6780b57cec5SDimitry Andric *offset = (addr - (pint_t) dyldInfo.dli_saddr); 6790b57cec5SDimitry Andric return true; 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric #else 6830b57cec5SDimitry Andric (void)addr; 6840b57cec5SDimitry Andric (void)buf; 6850b57cec5SDimitry Andric (void)bufLen; 6860b57cec5SDimitry Andric (void)offset; 6870b57cec5SDimitry Andric #endif 6880b57cec5SDimitry Andric return false; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric } // namespace libunwind 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric #endif // __ADDRESSSPACE_HPP__ 694