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.
This commit is contained in:
Rene Gollent
2012-12-21 22:40:58 -05:00
parent e5f2a41917
commit b510524436
+132 -6
View File
@@ -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;
};