hrev45055 adds 2 changesets to branch 'master' old head: 268177055e889e53b8fdf80ed7a33f484662f8c7 new head: 96a4619b92d32c9a068d32e60aba9d02f230fac7 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=96a4619+%5E2681770 ---------------------------------------------------------------------------- 54531e9: Allow CfaContext to be initialized lazily. 96a4619: Make use of augmentation if available. - Pull out a _ParseCIEAugmentation() from _ParseCIE(). - If .eh_frame is being used, do a quick parse of the CIE up front in order to determine the augmentation (if any), and use it to retrieve addresses in the appropriate format. This fixes stack unwinding on x86-64, and possibly other cases where the address encoding didn't correspond to architectural target size in absolute address format. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 96 insertions(+), 32 deletions(-) src/apps/debugger/dwarf/CfaContext.cpp | 16 +++-- src/apps/debugger/dwarf/CfaContext.h | 6 +- src/apps/debugger/dwarf/DwarfFile.cpp | 96 ++++++++++++++++++++++-------- src/apps/debugger/dwarf/DwarfFile.h | 10 ++++ ############################################################################ Commit: 54531e9f97d78a52610ec486828543a9abb2ab69 URL: http://cgit.haiku-os.org/haiku/commit/?id=54531e9 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Sat Dec 22 04:24:51 2012 UTC Allow CfaContext to be initialized lazily. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/dwarf/CfaContext.cpp b/src/apps/debugger/dwarf/CfaContext.cpp index 6205ad0..d4d13a1 100644 --- a/src/apps/debugger/dwarf/CfaContext.cpp +++ b/src/apps/debugger/dwarf/CfaContext.cpp @@ -9,11 +9,10 @@ #include "CfaContext.h" -CfaContext::CfaContext(target_addr_t targetLocation, - target_addr_t initialLocation) +CfaContext::CfaContext() : - fTargetLocation(targetLocation), - fLocation(initialLocation), + fTargetLocation(0), + fLocation(0), fCodeAlignment(0), fDataAlignment(0), fReturnAddressRegister(0), @@ -31,6 +30,15 @@ CfaContext::~CfaContext() } +void +CfaContext::SetLocation(target_addr_t targetLocation, + target_addr_t initialLocation) +{ + fTargetLocation = targetLocation; + fLocation = initialLocation; +} + + status_t CfaContext::Init(uint32 registerCount) { diff --git a/src/apps/debugger/dwarf/CfaContext.h b/src/apps/debugger/dwarf/CfaContext.h index b652e01..78d224c 100644 --- a/src/apps/debugger/dwarf/CfaContext.h +++ b/src/apps/debugger/dwarf/CfaContext.h @@ -14,10 +14,12 @@ class CfaContext { public: - CfaContext(target_addr_t targetLocation, - target_addr_t initialLocation); + CfaContext(); ~CfaContext(); + void SetLocation(target_addr_t targetLocation, + target_addr_t initialLocation); + status_t Init(uint32 registerCount); status_t SaveInitialRuleSet(); ############################################################################ Revision: hrev45055 Commit: 96a4619b92d32c9a068d32e60aba9d02f230fac7 URL: http://cgit.haiku-os.org/haiku/commit/?id=96a4619 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Sat Dec 22 04:26:34 2012 UTC Make use of augmentation if available. - Pull out a _ParseCIEAugmentation() from _ParseCIE(). - If .eh_frame is being used, do a quick parse of the CIE up front in order to determine the augmentation (if any), and use it to retrieve addresses in the appropriate format. This fixes stack unwinding on x86-64, and possibly other cases where the address encoding didn't correspond to architectural target size in absolute address format. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index e858ceb..69187c5 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -335,17 +335,15 @@ struct DwarfFile::CIEAugmentation { return (fFlags & CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT) != 0; } - target_addr_t FDEAddressOffset(CompilationUnit* unit, - ElfFile* file) const + target_addr_t FDEAddressOffset(ElfFile* file) const { switch (FDEAddressType()) { // function relative is currently equivalent to absolute // in all the cases in which it gets generated case CFI_ADDRESS_FORMAT_ABSOLUTE: + case CFI_ADDRESS_TYPE_PC_RELATIVE: case CFI_ADDRESS_TYPE_FUNCTION_RELATIVE: return 0; - case CFI_ADDRESS_TYPE_PC_RELATIVE: - return unit->AddressRangeBase(); case CFI_ADDRESS_TYPE_TEXT_RELATIVE: return file->TextSegment()->LoadAddress(); case CFI_ADDRESS_TYPE_DATA_RELATIVE: @@ -384,9 +382,9 @@ struct DwarfFile::CIEAugmentation { } target_addr_t ReadEncodedAddress(DataReader &reader, - CompilationUnit* unit, ElfFile* file) const + ElfFile* file) const { - target_addr_t address = FDEAddressOffset(unit, file); + target_addr_t address = FDEAddressOffset(file); switch (fAddressEncoding & 0x0f) { case CFI_ADDRESS_FORMAT_ABSOLUTE: address += reader.ReadAddress(0); @@ -1512,8 +1510,44 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit, } else { // this is a FDE uint64 initialLocationOffset = dataReader.Offset(); - target_addr_t initialLocation = dataReader.ReadAddress(0); - target_size_t addressRange = dataReader.ReadAddress(0); + // In .eh_frame the CIE offset is a relative back offset. + if (usingEHFrameSection) { + if (cieID > (uint64)lengthOffset) { + TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max " + "possible: %" B_PRIu64 "\n", cieID, lengthOffset); + break; + } + // convert to a section relative offset + cieID = lengthOffset - cieID; + } + + + CfaContext context; + CIEAugmentation cieAugmentation; + // when using .eh_frame format, we need to parse the CIE's + // augmentation up front in order to know how the FDE's addresses + // will be represented + if (usingEHFrameSection) { + // TODO: this isn't so ideal since it means we parse + // the CIE twice, once here in order to get the augmentation + // data for address parsing, and again later when we perform + // the full CIE parse to get its initial Cfa ruleset. In the + // long term, we should probably + // shift to parsing the CIEs as we hit them and caching + // their information so it can simply be retrieved directly + // later. + DataReader cieReader; + status_t error = _ParseCIEAugmentation(currentFrameSection, + usingEHFrameSection, unit, addressSize, context, cieID, + cieAugmentation, cieReader); + if (error != B_OK) + return error; + } + + target_addr_t initialLocation = cieAugmentation.ReadEncodedAddress( + dataReader, fElfFile); + target_size_t addressRange = cieAugmentation.ReadEncodedAddress( + dataReader, fElfFile); if (dataReader.HasOverflow()) return B_BAD_DATA; @@ -1552,23 +1586,12 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit, if (remaining < 0) return B_BAD_DATA; - // In .eh_frame the CIE offset is a relative back offset. - if (usingEHFrameSection) { - if (cieID > (uint64)lengthOffset) { - TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max " - "possible: %" B_PRIu64 "\n", cieID, lengthOffset); - break; - } - // convert to a section relative offset - cieID = lengthOffset - cieID; - } - TRACE_CFI(" found fde: length: %" B_PRIu64 " (%" B_PRIdOFF "), CIE offset: %#" B_PRIx64 ", location: %#" B_PRIx64 ", " "range: %#" B_PRIx64 "\n", length, remaining, cieID, initialLocation, addressRange); - CfaContext context(location, initialLocation); + context.SetLocation(location, initialLocation); uint32 registerCount = outputInterface->CountRegisters(); status_t error = context.Init(registerCount); if (error != B_OK) @@ -1579,7 +1602,6 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit, return error; // process the CIE - CIEAugmentation cieAugmentation; error = _ParseCIE(currentFrameSection, usingEHFrameSection, unit, addressSize, context, cieID, cieAugmentation); if (error != B_OK) @@ -1750,14 +1772,15 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit, status_t -DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection, - CompilationUnit* unit, uint8 addressSize, CfaContext& context, - off_t cieOffset, CIEAugmentation& cieAugmentation) +DwarfFile::_ParseCIEAugmentation(ElfSection* debugFrameSection, + bool usingEHFrameSection, CompilationUnit* unit, uint8 addressSize, + CfaContext& context, off_t cieOffset, CIEAugmentation& cieAugmentation, + DataReader& dataReader, off_t* _length, off_t* _lengthOffset) { if (cieOffset < 0 || cieOffset >= debugFrameSection->Size()) return B_BAD_DATA; - DataReader dataReader((uint8*)debugFrameSection->Data() + cieOffset, + dataReader.SetTo((uint8*)debugFrameSection->Data() + cieOffset, debugFrameSection->Size() - cieOffset, unit != NULL ? unit->AddressSize() : addressSize); @@ -1767,7 +1790,11 @@ DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection, if (length > (uint64)dataReader.BytesRemaining()) return B_BAD_DATA; - off_t lengthOffset = dataReader.Offset(); + if (_length != NULL) + *_length = length; + + if (_lengthOffset != NULL) + *_lengthOffset = dataReader.Offset(); // CIE ID/CIE pointer uint64 cieID = dwarf64 @@ -1815,6 +1842,23 @@ DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection, return error; } + return B_OK; +} + + +status_t +DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection, + CompilationUnit* unit, uint8 addressSize, CfaContext& context, + off_t cieOffset, CIEAugmentation& cieAugmentation) +{ + DataReader dataReader; + off_t length; + off_t lengthOffset; + status_t result = _ParseCIEAugmentation(debugFrameSection, + usingEHFrameSection, unit, addressSize, context, cieOffset, + cieAugmentation, dataReader, &length, &lengthOffset); + if (result != B_OK) + return result; if (dataReader.HasOverflow()) return B_BAD_DATA; off_t remaining = (off_t)length diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index 429e98d..35159c9 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -123,6 +123,16 @@ private: DwarfTargetInterface* outputInterface, target_addr_t& _framePointer); + status_t _ParseCIEAugmentation( + ElfSection* debugFrameSection, + bool usingEHFrameSection, + CompilationUnit* unit, + uint8 addressSize, + CfaContext& context, off_t cieOffset, + CIEAugmentation& cieAugmentation, + DataReader& reader, + off_t* length = NULL, + off_t* lengthOffset = NULL); status_t _ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection, CompilationUnit* unit,