diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index d7348254af07b..e3cc1775686bc 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -1787,20 +1787,37 @@ bool UnwindCursor::getInfoFromDwarfSection( } if (!foundFDE) { // Still not found, do full scan of __eh_frame section. - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, 0, - &fdeInfo, &cieInfo); + // But only if __eh_frame_hdr is absent or empty. + // We assume that both sections have the same data, and don't want to waste + // time for long scan for absent addresses. + bool hasEHHeaderData = false; +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + if ((sects.dwarf_index_section != 0)) { + typename EHHeaderParser::EHHeaderInfo hdrInfo; + const pint_t ehHdrStart = sects.dwarf_index_section; + const pint_t ehHdrEnd = ehHdrStart + sects.dwarf_index_section_length; + if (EHHeaderParser::decodeEHHdr(_addressSpace, ehHdrStart, ehHdrEnd, + hdrInfo)) { + hasEHHeaderData = (hdrInfo.fde_count != 0); + } + } +#endif + if (!hasEHHeaderData) { + foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, + sects.dwarf_section_length, 0, &fdeInfo, + &cieInfo); + } } if (foundFDE) { 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 defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (sects.dwarf_index_section == 0) - #endif - DwarfFDECache::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, - fdeInfo.fdeStart); +#endif + DwarfFDECache::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, + fdeInfo.fdeStart); } return true; }