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:
@@ -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 {
|
struct DwarfFile::CIEAugmentation {
|
||||||
CIEAugmentation()
|
CIEAugmentation()
|
||||||
:
|
:
|
||||||
fString(NULL),
|
fString(NULL),
|
||||||
fFlags(0)
|
fFlags(0),
|
||||||
|
fAddressEncoding(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,17 +254,25 @@ struct DwarfFile::CIEAugmentation {
|
|||||||
fFlags |= CFI_AUGMENTATION_DATA;
|
fFlags |= CFI_AUGMENTATION_DATA;
|
||||||
const char* string = fString + 1;
|
const char* string = fString + 1;
|
||||||
|
|
||||||
|
uint64 length = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint64 remaining = length;
|
||||||
// let's see what data we have to expect
|
// let's see what data we have to expect
|
||||||
while (*string != '\0') {
|
while (*string != '\0') {
|
||||||
switch (*string) {
|
switch (*string) {
|
||||||
case 'L':
|
case 'L':
|
||||||
fFlags |= CFI_AUGMENTATION_LANGUAGE_SPECIFIC_DATA;
|
fFlags |= CFI_AUGMENTATION_LANGUAGE_SPECIFIC_DATA;
|
||||||
|
dataReader.Read<char>(0);
|
||||||
|
--remaining;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
fFlags |= CFI_AUGMENTATION_PERSONALITY;
|
fFlags |= CFI_AUGMENTATION_PERSONALITY;
|
||||||
|
dataReader.Read<char>(0);
|
||||||
|
--remaining;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
fFlags |= CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT;
|
fFlags |= CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT;
|
||||||
|
fAddressEncoding = dataReader.Read<char>(0);
|
||||||
|
--remaining;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
@@ -244,11 +282,7 @@ struct DwarfFile::CIEAugmentation {
|
|||||||
|
|
||||||
// read the augmentation data block -- it is preceeded by an
|
// read the augmentation data block -- it is preceeded by an
|
||||||
// LEB128 indicating the length of the data block
|
// LEB128 indicating the length of the data block
|
||||||
uint64 length = dataReader.ReadUnsignedLEB128(0);
|
dataReader.Skip(remaining);
|
||||||
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.
|
|
||||||
|
|
||||||
TRACE_CFI(" %" B_PRIu64 " bytes of augmentation data\n", length);
|
TRACE_CFI(" %" B_PRIu64 " bytes of augmentation data\n", length);
|
||||||
|
|
||||||
@@ -296,9 +330,101 @@ struct DwarfFile::CIEAugmentation {
|
|||||||
return (fFlags & CFI_AUGMENTATION_DATA) != 0;
|
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:
|
private:
|
||||||
const char* fString;
|
const char* fString;
|
||||||
uint32 fFlags;
|
uint32 fFlags;
|
||||||
|
int8 fAddressEncoding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user