diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -59,74 +59,67 @@ // In 10.7.0 or later, libSystem.dylib implements this function. extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) - -// When statically linked on bare-metal, the symbols for the EH table are looked -// up without going through the dynamic loader. - -// The following linker script may be used to produce the necessary sections and symbols. -// Unless the --eh-frame-hdr linker option is provided, the section is not generated -// and does not take space in the output file. -// -// .eh_frame : -// { -// __eh_frame_start = .; -// KEEP(*(.eh_frame)) -// __eh_frame_end = .; -// } -// -// .eh_frame_hdr : -// { -// KEEP(*(.eh_frame_hdr)) -// } -// -// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; -// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; - -extern char __eh_frame_start; -extern char __eh_frame_end; - -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) -extern char __eh_frame_hdr_start; -extern char __eh_frame_hdr_end; -#endif - -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) - -// When statically linked on bare-metal, the symbols for the EH table are looked -// up without going through the dynamic loader. -extern char __exidx_start; -extern char __exidx_end; - -#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - -// ELF-based systems may use dl_iterate_phdr() to access sections -// containing unwinding information. The ElfW() macro for pointer-size -// independent ELF header traversal is not provided by on some -// systems (e.g., FreeBSD). On these systems the data structures are -// just called Elf_XXX. Define ElfW() locally. -#ifndef _WIN32 -#include -#else -#include -#include -#endif -#if !defined(ElfW) -#define ElfW(type) Elf_##type -#endif +#elif defined(_LIBUNWIND_IS_BAREMETAL) + + // When statically linked on bare-metal, the symbols for the EH table are looked + // up without going through the dynamic loader. + + // The following linker script may be used to produce the necessary sections and symbols. + // Unless the --eh-frame-hdr linker option is provided, the section is not generated + // and does not take space in the output file. + // + // .eh_frame : + // { + // __eh_frame_start = .; + // KEEP(*(.eh_frame)) + // __eh_frame_end = .; + // } + // + // .eh_frame_hdr : + // { + // KEEP(*(.eh_frame_hdr)) + // } + // + // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; + // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + + #if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) + extern char __eh_frame_start; + extern char __eh_frame_end; + #endif + #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + extern char __eh_frame_hdr_start; + extern char __eh_frame_hdr_end; + #endif + #if defined(_LIBUNWIND_ARM_EHABI) + // When statically linked on bare-metal, the symbols for the EH table are looked + // up without going through the dynamic loader. + extern char __exidx_start; + extern char __exidx_end; + #endif +#elif defined(_WIN32) + #include + #include +#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \ + defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) + #include #endif namespace libunwind { /// Used by findUnwindSections() to return info about needed sections. struct UnwindInfoSections { -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || \ defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) // No dso_base for SEH or ARM EHABI. uintptr_t dso_base; #endif -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) && \ + defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + uintptr_t dso_length; +#endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) uintptr_t dwarf_section; uintptr_t dwarf_section_length; #endif @@ -351,23 +344,14 @@ return result; } -#ifdef __APPLE__ -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) -#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) -// Code inside findUnwindSections handles all these cases. -// -// Although the above ifdef chain is ugly, there doesn't seem to be a cleaner -// way to handle it. The generalized boolean expression is: -// -// A OR (B AND C) OR (D AND C) OR (B AND E) OR (F AND E) OR (D AND G) -// -// Running it through various boolean expression simplifiers gives expressions -// that don't help at all. -#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) +// The ElfW() macro for pointer-size independent ELF header traversal is not +// provided by on some systems (e.g., FreeBSD). On these systems the +// data structures are just called Elf_XXX. Define ElfW() locally. +#if !defined(ElfW) + #define ElfW(type) Elf_##type +#endif #if !defined(Elf_Half) typedef ElfW(Half) Elf_Half; #endif @@ -406,9 +390,14 @@ uintptr_t targetAddr; }; -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + #if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) + // dl_iterate_phdr finds PT_GNU_EH_FRAME (.eh_frame_hdr section), which + // provides the start of the .eh_frame section, but not its length. The + // .eh_frame length isn't strictly necessary if we assume the section ends + // with a terminator, but sometimes it doesn't, and if we have the index, + // then scanning .eh_frame shouldn't be necessary anyway. + #error _LIBUNWIND_SUPPORT_DWARF_SECTION is unsupported with dl_iterate_phdr. #endif #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) @@ -426,7 +415,7 @@ uintptr_t end = begin + phdr->p_memsz; if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { cbdata->sects->dso_base = begin; - cbdata->sects->dwarf_section_length = phdr->p_memsz; + cbdata->sects->dso_length = phdr->p_memsz; return true; } } @@ -456,15 +445,10 @@ for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) { - EHHeaderParser::EHHeaderInfo hdrInfo; + found_hdr = true; uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section_length = phdr->p_memsz; - found_hdr = EHHeaderParser::decodeEHHdr( - *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, - hdrInfo); - if (found_hdr) - cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; } else if (!found_obj) { found_obj = checkAddrInSegment(phdr, image_base, cbdata); } @@ -475,13 +459,10 @@ return 1; } } - cbdata->sects->dwarf_section_length = 0; return 0; } -#else // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) -// Given all the #ifdef's above, the code here is for -// defined(LIBUNWIND_ARM_EHABI) +#elif defined(_LIBUNWIND_ARM_EHABI) static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) { @@ -513,8 +494,9 @@ } return found_obj && found_hdr; } -#endif // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) -#endif // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +#endif +#endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, @@ -523,7 +505,7 @@ dyld_unwind_sections dyldInfo; if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { info.dso_base = (uintptr_t)dyldInfo.mh; - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + #if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; info.dwarf_section_length = dyldInfo.dwarf_section_length; #endif @@ -531,29 +513,35 @@ info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; return true; } -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) +#elif defined(_LIBUNWIND_IS_BAREMETAL) + bool result = false; + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + info.dso_base = 0; + #endif + #if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) // Bare metal is statically linked, so no need to ask the dynamic loader info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); info.dwarf_section = (uintptr_t)(&__eh_frame_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", (void *)info.dwarf_section, (void *)info.dwarf_section_length); -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + result = result || info.dwarf_section_length; + #endif + #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); -#endif - if (info.dwarf_section_length) - return true; -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) - // Bare metal is statically linked, so no need to ask the dynamic loader + result = result || info.dwarf_index_section_length; + #endif + #if defined(_LIBUNWIND_ARM_EHABI) info.arm_section = (uintptr_t)(&__exidx_start); info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", (void *)info.arm_section, (void *)info.arm_section_length); - if (info.arm_section && info.arm_section_length) - return true; -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) + result = result || (info.arm_section && info.arm_section_length); + #endif + return result; +#elif defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) && defined(_WIN32) HMODULE mods[1024]; HANDLE process = GetCurrentProcess(); DWORD needed; @@ -598,16 +586,14 @@ (void)targetAddr; (void)info; return true; -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) - // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After - // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. +#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) int length = 0; info.arm_section = (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); if (info.arm_section && info.arm_section_length) return true; -#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) dl_iterate_cb_data cb_data = {this, &info, targetAddr}; int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); return static_cast(found); diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -135,8 +135,8 @@ }; static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, - CIE_Info *cieInfo); + uint32_t sectionLength, pint_t scanStart, + FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, FDE_Info *fdeInfo, CIE_Info *cieInfo); static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, @@ -211,11 +211,11 @@ /// Scan an eh_frame section to find an FDE for a pc template bool CFI_Parser::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uint32_t sectionLength, pint_t fdeHint, + uint32_t sectionLength, pint_t scanStart, FDE_Info *fdeInfo, CIE_Info *cieInfo) { //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); - pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; - const pint_t ehSectionEnd = p + sectionLength; + pint_t p = scanStart; + const pint_t ehSectionEnd = ehSectionStart + sectionLength; while (p < ehSectionEnd) { pint_t currentCFI = p; //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); diff --git a/libunwind/src/FrameHeaderCache.hpp b/libunwind/src/FrameHeaderCache.hpp --- a/libunwind/src/FrameHeaderCache.hpp +++ b/libunwind/src/FrameHeaderCache.hpp @@ -32,7 +32,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache { struct CacheEntry { uintptr_t LowPC() { return Info.dso_base; }; - uintptr_t HighPC() { return Info.dso_base + Info.dwarf_section_length; }; + uintptr_t HighPC() { return Info.dso_base + Info.dso_length; }; UnwindInfoSections Info; CacheEntry *Next; }; diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -926,8 +926,6 @@ bool getInfoFromFdeCie(const typename CFI_Parser::FDE_Info &fdeInfo, const typename CFI_Parser::CIE_Info &cieInfo, pint_t pc, uintptr_t dso_base); - bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, - uint32_t fdeSectionOffsetHint=0); int stepWithDwarfFDE() { return DwarfInstructions::stepWithDwarf(_addressSpace, (pint_t)this->getReg(UNW_REG_IP), @@ -936,6 +934,11 @@ } #endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) + bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, + uint32_t fdeSectionOffsetHint = 0); +#endif + #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) bool getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s); @@ -1500,65 +1503,50 @@ } return false; } +#endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) template -bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, - const UnwindInfoSections §s, - uint32_t fdeSectionOffsetHint) { +bool UnwindCursor::getInfoFromDwarfSection( + pint_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; - bool foundFDE = false; - bool foundInCache = false; - // If compact encoding table gave offset into dwarf section, go directly there - if (fdeSectionOffsetHint != 0) { - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - (uint32_t)sects.dwarf_section_length, - sects.dwarf_section + fdeSectionOffsetHint, - &fdeInfo, &cieInfo); - } -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - if (!foundFDE && (sects.dwarf_index_section != 0)) { - foundFDE = EHHeaderParser::findFDE( - _addressSpace, pc, sects.dwarf_index_section, - (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); - } -#endif - if (!foundFDE) { - // otherwise, search cache of previously found FDEs. + + // If there is a compact encoding hint, then we start the scan at the hint, + // and we neither search nor add to the cache. + const bool useCache = (fdeSectionOffsetHint == 0); + + if (useCache) { + // For some configs (e.g. bare-metal), the dso_base will be zero, so this + // cache search will also find dynamically-registered FDEs. pint_t cachedFDE = DwarfFDECache::findFDE(sects.dso_base, pc); if (cachedFDE != 0) { - foundFDE = - CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - (uint32_t)sects.dwarf_section_length, - cachedFDE, &fdeInfo, &cieInfo); - foundInCache = foundFDE; + if (CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, + static_cast(sects.dwarf_section_length), + cachedFDE, &fdeInfo, &cieInfo)) { + if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) + return true; + } } } - if (!foundFDE) { - // Still not found, do full scan of __eh_frame section. - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - (uint32_t)sects.dwarf_section_length, 0, - &fdeInfo, &cieInfo); - } - if (foundFDE) { + + if (CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, + static_cast(sects.dwarf_section_length), + sects.dwarf_section + fdeSectionOffsetHint, + &fdeInfo, &cieInfo)) { if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { - // Add to cache (to make next lookup faster) if we had no hint - // and there was no index. - if (!foundInCache && (fdeSectionOffsetHint == 0)) { - #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - if (sects.dwarf_index_section == 0) - #endif + if (useCache) { DwarfFDECache::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart); } return true; } } + //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); return false; } -#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template @@ -1896,14 +1884,15 @@ // If there is a compact unwind encoding table, look there first. if (sects.compact_unwind_section != 0) { if (this->getInfoFromCompactEncodingSection(pc, sects)) { - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - // Found info in table, done unless encoding says to use dwarf. + #if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) + // Found info in table, done unless encoding says to use dwarf. Scan + // __eh_frame if we have a non-zero hint. Otherwise, we'll scan the + // entire __eh_frame below. uint32_t dwarfOffset; - if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { - if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { - // found info in dwarf, done + if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset) && + (dwarfOffset != 0)) { + if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) return; - } } #endif // If unwind table has entry, but entry says there is no unwind info, @@ -1921,15 +1910,31 @@ return; #endif -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - // If there is dwarf unwind info, look there next. - if (sects.dwarf_section != 0) { - if (this->getInfoFromDwarfSection(pc, sects)) { - // found info in dwarf, done - return; + bool hasDwarfIndex = false; +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + if (sects.dwarf_index_section != 0) { + hasDwarfIndex = true; + typename CFI_Parser::FDE_Info fdeInfo; + typename CFI_Parser::CIE_Info cieInfo; + if (EHHeaderParser::findFDE( + _addressSpace, pc, sects.dwarf_index_section, + static_cast(sects.dwarf_index_section_length), &fdeInfo, + &cieInfo)) { + if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) + return; } } #endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) + // If we have both eh_frame and its index (e.g. for a bare-metal target), + // and the index doesn't have the FDE, there is no need to scan the + // eh_frame. + if ((sects.dwarf_section != 0) && !hasDwarfIndex) { + if (this->getInfoFromDwarfSection(pc, sects)) + return; + } +#endif + (void)hasDwarfIndex; #if defined(_LIBUNWIND_ARM_EHABI) // If there is ARM EHABI unwind info, look there next. diff --git a/libunwind/src/config.h b/libunwind/src/config.h --- a/libunwind/src/config.h +++ b/libunwind/src/config.h @@ -18,6 +18,8 @@ #include #include +#include <__libunwind_config.h> + // Define static_assert() unless already defined by compiler. #ifndef __has_feature #define __has_feature(__x) 0 @@ -34,20 +36,35 @@ #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 #else #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #define _LIBUNWIND_SUPPORT_DWARF_SECTION 1 #endif #elif defined(_WIN32) #ifdef __SEH__ #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 #else - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #define _LIBUNWIND_SUPPORT_DWARF_SECTION 1 + #endif +#elif defined(_LIBUNWIND_IS_BAREMETAL) + #if !defined(_LIBUNWIND_ARM_EHABI) + // Prefer to use the index, but if that's empty, we'll fall back to scanning + // .eh_frame. + #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 + #define _LIBUNWIND_SUPPORT_DWARF_SECTION 1 #endif +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) + // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After + // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. + #define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 1 #else - #if defined(__ARM_DWARF_EH__) || !defined(__arm__) - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 + #if !defined(_LIBUNWIND_ARM_EHABI) #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 #endif #endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ + defined(_LIBUNWIND_SUPPORT_DWARF_SECTION) + #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 +#endif #if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) #define _LIBUNWIND_EXPORT diff --git a/libunwind/test/frameheadercache_test.pass.cpp b/libunwind/test/frameheadercache_test.pass.cpp --- a/libunwind/test/frameheadercache_test.pass.cpp +++ b/libunwind/test/frameheadercache_test.pass.cpp @@ -3,27 +3,10 @@ #include "../src/config.h" // Only run this test under supported configurations. -// The frame header cache should work fine for other architectures, -// but the #ifdefs end up being even more complicated than this. -#if defined(__x86_64__) && defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) - -// This #if chain is ugly, but see the comments in AddressSpace.hpp for -// the reasoning. - -#ifdef __APPLE__ -int main() { return 0; } -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) -int main() { return 0; } -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) -int main() { return 0; } -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) -int main() { return 0; } -#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) -int main() { return 0; } -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) -int main() { return 0; } -#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) && \ + defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) && \ + defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) #include #include @@ -33,7 +16,7 @@ #include "../src/AddressSpace.hpp" #define kBaseAddr 0xFFF000 -#define kDwarfSectionLength 0xFF +#define kDsoLength 0xFF using namespace libunwind; @@ -49,7 +32,7 @@ UnwindInfoSections UIS; UIS.dso_base = kBaseAddr; - UIS.dwarf_section_length = kDwarfSectionLength; + UIS.dso_length = kDsoLength; dl_iterate_cb_data CBData; // Unused by the cache. CBData.addressSpace = nullptr; @@ -75,7 +58,7 @@ abort(); // Add enough things to the cache that the entry is evicted. for (int i = 0; i < 9; i++) { - UIS.dso_base = kBaseAddr + (kDwarfSectionLength * i); + UIS.dso_base = kBaseAddr + (kDsoLength * i); FHC.add(&UIS); } CBData.targetAddr = kBaseAddr; @@ -84,9 +67,7 @@ abort(); return 0; } -#else -int main() { return 0; } -#endif + #else int main() { return 0;} #endif