diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -923,6 +923,9 @@
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+ 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() {
@@ -1472,6 +1475,32 @@
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+template
+bool UnwindCursor::getInfoFromFdeCie(
+ const typename CFI_Parser::FDE_Info &fdeInfo,
+ const typename CFI_Parser::CIE_Info &cieInfo, pint_t pc,
+ uintptr_t dso_base) {
+ typename CFI_Parser::PrologInfo prolog;
+ if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
+ R::getArch(), &prolog)) {
+ // Save off parsed FDE info
+ _info.start_ip = fdeInfo.pcStart;
+ _info.end_ip = fdeInfo.pcEnd;
+ _info.lsda = fdeInfo.lsda;
+ _info.handler = cieInfo.personality;
+ // Some frameless functions need SP altered when resuming in function, so
+ // propagate spExtraArgSize.
+ _info.gp = prolog.spExtraArgSize;
+ _info.flags = 0;
+ _info.format = dwarfEncoding();
+ _info.unwind_info = fdeInfo.fdeStart;
+ _info.unwind_info_size = static_cast(fdeInfo.fdeLength);
+ _info.extra = static_cast(dso_base);
+ return true;
+ }
+ return false;
+}
+
template
bool UnwindCursor::getInfoFromDwarfSection(pint_t pc,
const UnwindInfoSections §s,
@@ -1512,21 +1541,7 @@
&fdeInfo, &cieInfo);
}
if (foundFDE) {
- typename CFI_Parser::PrologInfo prolog;
- if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
- R::getArch(), &prolog)) {
- // Save off parsed FDE info
- _info.start_ip = fdeInfo.pcStart;
- _info.end_ip = fdeInfo.pcEnd;
- _info.lsda = fdeInfo.lsda;
- _info.handler = cieInfo.personality;
- _info.gp = prolog.spExtraArgSize;
- _info.flags = 0;
- _info.format = dwarfEncoding();
- _info.unwind_info = fdeInfo.fdeStart;
- _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
- _info.extra = (unw_word_t) sects.dso_base;
-
+ 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)) {
@@ -1928,58 +1943,24 @@
// dynamically registered for it.
pint_t cachedFDE = DwarfFDECache::findFDE(0, pc);
if (cachedFDE != 0) {
- CFI_Parser::FDE_Info fdeInfo;
- CFI_Parser::CIE_Info cieInfo;
- const char *msg = CFI_Parser::decodeFDE(_addressSpace,
- cachedFDE, &fdeInfo, &cieInfo);
- if (msg == NULL) {
- typename CFI_Parser::PrologInfo prolog;
- if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
- pc, R::getArch(), &prolog)) {
- // save off parsed FDE info
- _info.start_ip = fdeInfo.pcStart;
- _info.end_ip = fdeInfo.pcEnd;
- _info.lsda = fdeInfo.lsda;
- _info.handler = cieInfo.personality;
- _info.gp = prolog.spExtraArgSize;
- // Some frameless functions need SP
- // altered when resuming in function.
- _info.flags = 0;
- _info.format = dwarfEncoding();
- _info.unwind_info = fdeInfo.fdeStart;
- _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
- _info.extra = 0;
+ typename CFI_Parser::FDE_Info fdeInfo;
+ typename CFI_Parser::CIE_Info cieInfo;
+ if (!CFI_Parser::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo))
+ if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))
return;
- }
- }
}
// Lastly, ask AddressSpace object about platform specific ways to locate
// other FDEs.
pint_t fde;
if (_addressSpace.findOtherFDE(pc, fde)) {
- CFI_Parser::FDE_Info fdeInfo;
- CFI_Parser::CIE_Info cieInfo;
+ typename CFI_Parser::FDE_Info fdeInfo;
+ typename CFI_Parser::CIE_Info cieInfo;
if (!CFI_Parser::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
// Double check this FDE is for a function that includes the pc.
- if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
- typename CFI_Parser::PrologInfo prolog;
- if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
- pc, R::getArch(), &prolog)) {
- // save off parsed FDE info
- _info.start_ip = fdeInfo.pcStart;
- _info.end_ip = fdeInfo.pcEnd;
- _info.lsda = fdeInfo.lsda;
- _info.handler = cieInfo.personality;
- _info.gp = prolog.spExtraArgSize;
- _info.flags = 0;
- _info.format = dwarfEncoding();
- _info.unwind_info = fdeInfo.fdeStart;
- _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
- _info.extra = 0;
+ if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd))
+ if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))
return;
- }
- }
}
}
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)