hrev45053 adds 1 changeset to branch 'master' old head: e5f2a41917df873d947b2c819e4063f370cd2806 new head: b510524436d85a3970e610ca7ed68638652f1830 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=b510524+%5Ee5f2a41 ---------------------------------------------------------------------------- b510524: Resolve TODO. - We now handle augmentation 'zR', which in the case of gcc's .eh_frame format specifies how the addresses in the FDEs are encoded. Not actually used yet though since that will require some refactoring of _UnwindCallFrame(), since we currently parse the CIE too late to apply the above address size rules to the initial offset + range. This is also the reason x86-64 stack unwind currently fails, since the addresses there are, for most current tests actually being encoded in 32-bit format rather than architecture address size as should be the case for a standard DWARF debug_frame. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev45053 Commit: b510524436d85a3970e610ca7ed68638652f1830 URL: http://cgit.haiku-os.org/haiku/commit/?id=b510524 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Sat Dec 22 03:38:11 2012 UTC ---------------------------------------------------------------------------- 1 file changed, 132 insertions(+), 6 deletions(-) src/apps/debugger/dwarf/DwarfFile.cpp | 138 ++++++++++++++++++++++++++++-- ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index 1ca733e..e858ceb 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -200,11 +200,41 @@ enum { }; +// encodings for CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT +enum { + CFI_ADDRESS_FORMAT_ABSOLUTE = 0x00, + CFI_ADDRESS_FORMAT_UNSIGNED_LEB128 = 0x01, + CFI_ADDRESS_FORMAT_UNSIGNED_16 = 0x02, + CFI_ADDRESS_FORMAT_UNSIGNED_32 = 0x03, + CFI_ADDRESS_FORMAT_UNSIGNED_64 = 0x04, + CFI_ADDRESS_FORMAT_SIGNED = 0x08, + CFI_ADDRESS_FORMAT_SIGNED_LEB128 = + CFI_ADDRESS_FORMAT_UNSIGNED_LEB128 | CFI_ADDRESS_FORMAT_SIGNED, + CFI_ADDRESS_FORMAT_SIGNED_16 = + CFI_ADDRESS_FORMAT_UNSIGNED_16 | CFI_ADDRESS_FORMAT_SIGNED, + CFI_ADDRESS_FORMAT_SIGNED_32 = + CFI_ADDRESS_FORMAT_UNSIGNED_32 | CFI_ADDRESS_FORMAT_SIGNED, + CFI_ADDRESS_FORMAT_SIGNED_64 = + CFI_ADDRESS_FORMAT_UNSIGNED_64 | CFI_ADDRESS_FORMAT_SIGNED +}; + + +enum { + CFI_ADDRESS_TYPE_PC_RELATIVE = 0x10, + CFI_ADDRESS_TYPE_TEXT_RELATIVE = 0x20, + CFI_ADDRESS_TYPE_DATA_RELATIVE = 0x30, + CFI_ADDRESS_TYPE_FUNCTION_RELATIVE = 0x40, + CFI_ADDRESS_TYPE_ALIGNED = 0x50, + CFI_ADDRESS_TYPE_INDIRECT = 0x80 +}; + + struct DwarfFile::CIEAugmentation { CIEAugmentation() : fString(NULL), - fFlags(0) + fFlags(0), + fAddressEncoding(0) { } @@ -224,17 +254,25 @@ struct DwarfFile::CIEAugmentation { fFlags |= CFI_AUGMENTATION_DATA; const char* string = fString + 1; + uint64 length = dataReader.ReadUnsignedLEB128(0); + uint64 remaining = length; // let's see what data we have to expect while (*string != '\0') { switch (*string) { case 'L': fFlags |= CFI_AUGMENTATION_LANGUAGE_SPECIFIC_DATA; + dataReader.Read<char>(0); + --remaining; break; case 'P': fFlags |= CFI_AUGMENTATION_PERSONALITY; + dataReader.Read<char>(0); + --remaining; break; case 'R': fFlags |= CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT; + fAddressEncoding = dataReader.Read<char>(0); + --remaining; break; default: return B_UNSUPPORTED; @@ -244,11 +282,7 @@ struct DwarfFile::CIEAugmentation { // read the augmentation data block -- it is preceeded by an // LEB128 indicating the length of the data block - uint64 length = dataReader.ReadUnsignedLEB128(0); - dataReader.Skip(length); - // TODO: Actually read what is interesting for us! The - // CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT might be. The - // specs are not saying much about it. + dataReader.Skip(remaining); TRACE_CFI(" %" B_PRIu64 " bytes of augmentation data\n", length); @@ -296,9 +330,101 @@ struct DwarfFile::CIEAugmentation { return (fFlags & CFI_AUGMENTATION_DATA) != 0; } + bool HasFDEAddressFormat() const + { + return (fFlags & CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT) != 0; + } + + target_addr_t FDEAddressOffset(CompilationUnit* unit, + 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_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: + return file->DataSegment()->LoadAddress(); + case CFI_ADDRESS_TYPE_ALIGNED: + case CFI_ADDRESS_TYPE_INDIRECT: + // TODO: implement + // -- note: type indirect is currently not generated + return 0; + } + + return 0; + } + + int8 FDEAddressSize(CompilationUnit* unit) const + { + switch (fAddressEncoding & 0x07) { + case CFI_ADDRESS_FORMAT_ABSOLUTE: + return unit->AddressSize(); + case CFI_ADDRESS_FORMAT_UNSIGNED_16: + return 2; + case CFI_ADDRESS_FORMAT_UNSIGNED_32: + return 4; + case CFI_ADDRESS_FORMAT_UNSIGNED_64: + return 8; + } + + // TODO: gcc doesn't (currently) actually generate LEB128-formatted + // addresses. If that changes, we'll need to handle them accordingly + return 0; + } + + uint8 FDEAddressType() const + { + return fAddressEncoding & 0x70; + } + + target_addr_t ReadEncodedAddress(DataReader &reader, + CompilationUnit* unit, ElfFile* file) const + { + target_addr_t address = FDEAddressOffset(unit, file); + switch (fAddressEncoding & 0x0f) { + case CFI_ADDRESS_FORMAT_ABSOLUTE: + address += reader.ReadAddress(0); + break; + case CFI_ADDRESS_FORMAT_UNSIGNED_LEB128: + address += reader.ReadUnsignedLEB128(0); + break; + case CFI_ADDRESS_FORMAT_SIGNED_LEB128: + address += reader.ReadSignedLEB128(0); + break; + case CFI_ADDRESS_FORMAT_UNSIGNED_16: + address += reader.Read<uint16>(0); + break; + case CFI_ADDRESS_FORMAT_SIGNED_16: + address += reader.Read<int16>(0); + break; + case CFI_ADDRESS_FORMAT_UNSIGNED_32: + address += reader.Read<uint32>(0); + break; + case CFI_ADDRESS_FORMAT_SIGNED_32: + address += reader.Read<int32>(0); + break; + case CFI_ADDRESS_FORMAT_UNSIGNED_64: + address += reader.Read<uint64>(0); + break; + case CFI_ADDRESS_FORMAT_SIGNED_64: + address += reader.Read<int64>(0); + break; + } + + return address; + } + + private: const char* fString; uint32 fFlags; + int8 fAddressEncoding; };