DwarfFile: Implement handling of .debug_types section.

- Refactor ExpressionEvaluationContext::GetCallTarget() and
DwarfFile::_ResolveReference() to use an enum value for the type of
reference being passed in, as we now need to support signature
references in addition to local/global. Adjust callers.
- Factor out an _ParseDebugInfoSection() and add a corresponding
_ParseTypesSection() for the top level loops that handle .debug_info and
.debug_types respectively.
- Refactor _ParseDebugInfoEntry(), _ParseEntryAttributes() and
_ResolveReference to take a pointer to the relevant BaseUnit in order
to allow sharing between parsing of the types and info sections.
- Implement support for DW_FORM_ref_sig8. In order to handle this, we
use a hash table that maps from the corresponding 64-bit DW_AT_signature
values to their respective type units.
- Adjust debug output to more closely match offsets and values used by
objdump for ease of troubleshooting parsing issues.

Combined, these changes allow us to load DWARF 4 binaries sufficiently
to get source information and unwind call frame, though support is still
incomplete. In particular, global references aren't yet implemented,
and neither are location expression attributes, which are now used
quite heavily, and consequently we can't yet resolve variable values
and a few other things properly.
This commit is contained in:
Rene Gollent 2013-07-16 22:47:30 -04:00
parent 4bf8368675
commit 71fec49e67
5 changed files with 362 additions and 127 deletions

View File

@ -507,4 +507,11 @@ enum {
};
enum dwarf_reference_type {
dwarf_reference_type_local = 0,
dwarf_reference_type_global,
dwarf_reference_type_signature
};
#endif // DWARF_H

View File

@ -600,18 +600,21 @@ DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
case DW_OP_call2:
TRACE_EXPR(" DW_OP_call2\n");
_Call(fDataReader.Read<uint16>(0), true);
_Call(fDataReader.Read<uint16>(0), dwarf_reference_type_local);
break;
case DW_OP_call4:
TRACE_EXPR(" DW_OP_call4\n");
_Call(fDataReader.Read<uint32>(0), true);
_Call(fDataReader.Read<uint32>(0), dwarf_reference_type_local);
break;
case DW_OP_call_ref:
TRACE_EXPR(" DW_OP_call_ref\n");
if (fContext->AddressSize() == 4)
_Call(fDataReader.Read<uint32>(0), false);
else
_Call(fDataReader.Read<uint64>(0), false);
if (fContext->AddressSize() == 4) {
_Call(fDataReader.Read<uint32>(0),
dwarf_reference_type_global);
} else {
_Call(fDataReader.Read<uint64>(0),
dwarf_reference_type_global);
}
break;
case DW_OP_piece:
@ -746,7 +749,7 @@ DwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset)
void
DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
DwarfExpressionEvaluator::_Call(uint64 offset, uint8 refType)
{
if (fDataReader.HasOverflow())
throw EvaluationException("unexpected end of expression");
@ -754,7 +757,7 @@ DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
// get the expression to "call"
const void* block;
off_t size;
if (fContext->GetCallTarget(offset, local, block, size) != B_OK)
if (fContext->GetCallTarget(offset, refType, block, size) != B_OK)
throw EvaluationException("failed to get call target");
// no expression is OK, then this is just a no-op

View File

@ -37,8 +37,9 @@ public:
virtual bool GetTLSAddress(target_addr_t localAddress,
target_addr_t& _address) = 0;
virtual status_t GetCallTarget(uint64 offset, bool local,
const void*& _block, off_t& _size) = 0;
virtual status_t GetCallTarget(uint64 offset,
uint8 refType, const void*& _block,
off_t& _size) = 0;
// returns error, when an error resolving
// the entry occurs; returns B_OK and a NULL
// block, when the entry doesn't have a
@ -81,7 +82,7 @@ private:
void _DereferenceAddressSpaceAddress(
uint8 addressSize);
void _PushRegister(uint32 reg, target_addr_t offset);
void _Call(uint64 offset, bool local);
void _Call(uint64 offset, uint8 refType);
private:
DwarfExpressionEvaluationContext* fContext;

View File

@ -147,11 +147,11 @@ public:
return false;
}
virtual status_t GetCallTarget(uint64 offset, bool local,
virtual status_t GetCallTarget(uint64 offset, uint8 refType,
const void*& _block, off_t& _size)
{
// resolve the entry
DebugInfoEntry* entry = fFile->_ResolveReference(fUnit, offset, local);
DebugInfoEntry* entry = fFile->_ResolveReference(fUnit, offset, refType);
if (entry == NULL)
return B_ENTRY_NOT_FOUND;
@ -459,8 +459,9 @@ DwarfFile::DwarfFile()
fEHFrameSection(NULL),
fDebugLocationSection(NULL),
fDebugPublicTypesSection(NULL),
fDebugTypesSection(NULL),
fCompilationUnits(20, true),
fCurrentCompilationUnit(NULL),
fTypesSectionRequired(false),
fFinished(false),
fFinishError(B_OK)
{
@ -501,12 +502,16 @@ DwarfFile::Load(const char* fileName)
if (fName == NULL)
return B_NO_MEMORY;
status_t error = fTypeUnits.Init();
if (error != B_OK)
return error;
// load the ELF file
fElfFile = new(std::nothrow) ElfFile;
if (fElfFile == NULL)
return B_NO_MEMORY;
status_t error = fElfFile->Init(fileName);
error = fElfFile->Init(fileName);
if (error != B_OK)
return error;
@ -535,72 +540,19 @@ DwarfFile::Load(const char* fileName)
return B_OK;
}
// iterate through the debug info section
DataReader dataReader(fDebugInfoSection->Data(),
fDebugInfoSection->Size(), 4);
// address size doesn't matter here
while (dataReader.HasData()) {
off_t unitHeaderOffset = dataReader.Offset();
bool dwarf64;
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
error = _ParseDebugInfoSection();
if (error != B_OK)
return error;
off_t unitLengthOffset = dataReader.Offset();
// the unitLength starts here
if (unitLengthOffset + unitLength
> (uint64)fDebugInfoSection->Size()) {
WARNING("\"%s\": Invalid compilation unit length.\n", fileName);
break;
if (fTypesSectionRequired) {
fDebugTypesSection = debugInfoFile->GetSection(".debug_types");
if (fDebugTypesSection == NULL) {
WARNING(".debug_types section required but missing.\n");
return B_BAD_DATA;
}
int version = dataReader.Read<uint16>(0);
off_t abbrevOffset = dwarf64
? dataReader.Read<uint64>(0)
: dataReader.Read<uint32>(0);
uint8 addressSize = dataReader.Read<uint8>(0);
if (dataReader.HasOverflow()) {
WARNING("\"%s\": Unexpected end of data in compilation unit "
"header.\n", fileName);
break;
}
TRACE_DIE("DWARF%d compilation unit: version %d, length: %" B_PRIu64
", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
if (version != 2 && version != 3) {
WARNING("\"%s\": Unsupported compilation unit version: %d\n",
fileName, version);
break;
}
if (addressSize != 4 && addressSize != 8) {
WARNING("\"%s\": Unsupported address size: %d\n", fileName,
addressSize);
break;
}
dataReader.SetAddressSize(addressSize);
off_t unitContentOffset = dataReader.Offset();
// create a compilation unit object
CompilationUnit* unit = new(std::nothrow) CompilationUnit(
unitHeaderOffset, unitContentOffset,
unitLength + (unitLengthOffset - unitHeaderOffset),
abbrevOffset, addressSize, dwarf64);
if (unit == NULL || !fCompilationUnits.AddItem(unit)) {
delete unit;
return B_NO_MEMORY;
}
// parse the debug info for the unit
fCurrentCompilationUnit = unit;
error = _ParseCompilationUnit(unit);
error = _ParseTypesSection();
if (error != B_OK)
return error;
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
}
return B_OK;
@ -615,10 +567,17 @@ DwarfFile::FinishLoading()
if (fFinishError != B_OK)
return fFinishError;
status_t error;
for (int32 i = 0; CompilationUnit* unit = fCompilationUnits.ItemAt(i);
i++) {
fCurrentCompilationUnit = unit;
status_t error = _FinishCompilationUnit(unit);
error = _FinishUnit(unit);
if (error != B_OK)
return fFinishError = error;
}
for (TypeUnitTable::Iterator it = fTypeUnits.GetIterator();
TypeUnitTableEntry* entry = it.Next();) {
error = _FinishUnit(entry->unit);
if (error != B_OK)
return fFinishError = error;
}
@ -935,6 +894,171 @@ DwarfFile::EvaluateDynamicValue(CompilationUnit* unit, uint8 addressSize,
}
status_t
DwarfFile::_ParseDebugInfoSection()
{
// iterate through the debug info section
DataReader dataReader(fDebugInfoSection->Data(),
fDebugInfoSection->Size(), 4);
// address size doesn't matter here
while (dataReader.HasData()) {
off_t unitHeaderOffset = dataReader.Offset();
bool dwarf64;
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
off_t unitLengthOffset = dataReader.Offset();
// the unitLength starts here
if (unitLengthOffset + unitLength
> (uint64)fDebugInfoSection->Size()) {
WARNING("\"%s\": Invalid compilation unit length.\n", fName);
break;
}
int version = dataReader.Read<uint16>(0);
off_t abbrevOffset = dwarf64
? dataReader.Read<uint64>(0)
: dataReader.Read<uint32>(0);
uint8 addressSize = dataReader.Read<uint8>(0);
if (dataReader.HasOverflow()) {
WARNING("\"%s\": Unexpected end of data in compilation unit "
"header.\n", fName);
break;
}
TRACE_DIE("DWARF%d compilation unit: version %d, length: %" B_PRIu64
", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
if (version < 2 || version > 4) {
WARNING("\"%s\": Unsupported compilation unit version: %d\n",
fName, version);
break;
}
if (addressSize != 4 && addressSize != 8) {
WARNING("\"%s\": Unsupported address size: %d\n", fName,
addressSize);
break;
}
dataReader.SetAddressSize(addressSize);
off_t unitContentOffset = dataReader.Offset();
// create a compilation unit object
CompilationUnit* unit = new(std::nothrow) CompilationUnit(
unitHeaderOffset, unitContentOffset,
unitLength + (unitLengthOffset - unitHeaderOffset),
abbrevOffset, addressSize, dwarf64);
if (unit == NULL || !fCompilationUnits.AddItem(unit)) {
delete unit;
return B_NO_MEMORY;
}
// parse the debug info for the unit
status_t error = _ParseCompilationUnit(unit);
if (error != B_OK)
return error;
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
}
return B_OK;
}
status_t
DwarfFile::_ParseTypesSection()
{
DataReader dataReader(fDebugTypesSection->Data(),
fDebugTypesSection->Size(), 4);
while (dataReader.HasData()) {
off_t unitHeaderOffset = dataReader.Offset();
bool dwarf64;
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
off_t unitLengthOffset = dataReader.Offset();
// the unitLength starts here
if (unitLengthOffset + unitLength
> (uint64)fDebugTypesSection->Size()) {
WARNING("Invalid type unit length, offset %#" B_PRIx64 ".\n",
unitHeaderOffset);
break;
}
int version = dataReader.Read<uint16>(0);
off_t abbrevOffset = dwarf64
? dataReader.Read<uint64>(0)
: dataReader.Read<uint32>(0);
uint8 addressSize = dataReader.Read<uint8>(0);
if (dataReader.HasOverflow()) {
WARNING("Unexpected end of data in type unit header at %#"
B_PRIx64 ".\n", unitHeaderOffset);
break;
}
TRACE_DIE("DWARF%d type unit: version %d, length: %" B_PRIu64
", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
if (version > 4) {
WARNING("\"%s\": Unsupported type unit version: %d\n",
fName, version);
break;
}
if (addressSize != 4 && addressSize != 8) {
WARNING("\"%s\": Unsupported address size: %d\n", fName,
addressSize);
break;
}
dataReader.SetAddressSize(addressSize);
uint64 signature = dataReader.Read<uint64>(0);
off_t typeOffset = dwarf64
? dataReader.Read<uint64>(0)
: dataReader.Read<uint32>(0);
off_t unitContentOffset = dataReader.Offset();
// create a type unit object
TypeUnit* unit = new(std::nothrow) TypeUnit(
unitHeaderOffset, unitContentOffset,
unitLength + (unitLengthOffset - unitHeaderOffset),
abbrevOffset, typeOffset, addressSize, signature, dwarf64);
if (unit == NULL) {
delete unit;
return B_NO_MEMORY;
}
// parse the debug info for the unit
status_t error = _ParseTypeUnit(unit);
if (error != B_OK)
return error;
// TODO: it should theoretically never happen that we get a duplicate,
// but it wouldn't hurt to check since that situation would potentially
// be problematic.
if (fTypeUnits.Lookup(signature) == NULL) {
TypeUnitTableEntry* entry = new(std::nothrow)
TypeUnitTableEntry(signature, unit);
if (entry == NULL)
return B_NO_MEMORY;
fTypeUnits.Insert(entry);
}
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
}
return B_OK;
}
status_t
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
{
@ -952,7 +1076,7 @@ DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
DebugInfoEntry* entry;
bool endOfEntryList;
error = _ParseDebugInfoEntry(dataReader, abbreviationTable, entry,
error = _ParseDebugInfoEntry(dataReader, unit, abbreviationTable, entry,
endOfEntryList);
if (error != B_OK)
return error;
@ -979,13 +1103,57 @@ DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
}
status_t
DwarfFile::_ParseTypeUnit(TypeUnit* unit)
{
AbbreviationTable* abbreviationTable;
status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(),
abbreviationTable);
if (error != B_OK)
return error;
unit->SetAbbreviationTable(abbreviationTable);
DataReader dataReader(
(const uint8*)fDebugTypesSection->Data() + unit->ContentOffset(),
unit->ContentSize(), unit->AddressSize());
DebugInfoEntry* entry;
bool endOfEntryList;
error = _ParseDebugInfoEntry(dataReader, unit, abbreviationTable, entry,
endOfEntryList);
if (error != B_OK)
return error;
DIETypeUnit* unitEntry = dynamic_cast<DIETypeUnit*>(entry);
if (unitEntry == NULL) {
WARNING("No type unit entry in .debug_types section.\n");
return B_BAD_DATA;
}
unit->SetUnitEntry(unitEntry);
TRACE_DIE_ONLY(
TRACE_DIE("remaining bytes in unit: %" B_PRIdOFF "\n",
dataReader.BytesRemaining());
if (dataReader.HasData()) {
TRACE_DIE(" ");
while (dataReader.HasData())
TRACE_DIE("%02x", dataReader.Read<uint8>(0));
TRACE_DIE("\n");
}
)
return B_OK;
}
status_t
DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
AbbreviationTable* abbreviationTable, DebugInfoEntry*& _entry,
bool& _endOfEntryList, int level)
BaseUnit* unit, AbbreviationTable* abbreviationTable,
DebugInfoEntry*& _entry, bool& _endOfEntryList, int level)
{
off_t entryOffset = dataReader.Offset()
+ fCurrentCompilationUnit->RelativeContentOffset();
+ unit->RelativeContentOffset();
uint32 code = dataReader.ReadUnsignedLEB128(0);
if (code == 0) {
@ -1001,7 +1169,7 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
// get the corresponding abbreviation entry
AbbreviationEntry abbreviationEntry;
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
WARNING("No abbreviation entry for code %" B_PRIu32 "\n", code);
WARNING("No abbreviation entry for code %" B_PRIx32 "\n", code);
return B_BAD_DATA;
}
@ -1021,12 +1189,13 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset);
error = unit->AddDebugInfoEntry(entry, entryOffset);
if (error != B_OK)
return error;
// parse the attributes (supply NULL entry to avoid adding them yet)
error = _ParseEntryAttributes(dataReader, NULL, abbreviationEntry);
error = _ParseEntryAttributes(dataReader, unit, NULL, abbreviationEntry);
if (error != B_OK)
return error;
@ -1036,7 +1205,7 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
DebugInfoEntry* childEntry;
bool endOfEntryList;
status_t error = _ParseDebugInfoEntry(dataReader,
abbreviationTable, childEntry, endOfEntryList, level + 1);
unit, abbreviationTable, childEntry, endOfEntryList, level + 1);
if (error != B_OK)
return error;
@ -1072,14 +1241,20 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
status_t
DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
DwarfFile::_FinishUnit(BaseUnit* unit)
{
TRACE_DIE("\nfinishing compilation unit %p\n", unit);
CompilationUnit* compilationUnit = dynamic_cast<CompilationUnit*>(unit);
bool isTypeUnit = compilationUnit == NULL;
TRACE_DIE("\nfinishing %s unit %p\n",
isTypeUnit ? "type" : "compilation", unit);
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
ElfSection* section = isTypeUnit
? fDebugTypesSection : fDebugInfoSection;
DataReader dataReader(
(const uint8*)fDebugInfoSection->Data() + unit->HeaderOffset(),
(const uint8*)section->Data() + unit->HeaderOffset(),
unit->TotalSize(), unit->AddressSize());
DebugInfoEntryInitInfo entryInitInfo;
@ -1112,7 +1287,8 @@ DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
// parse the attributes -- this time pass the entry, so that the
// attribute get set on it
error = _ParseEntryAttributes(dataReader, entry, abbreviationEntry);
error = _ParseEntryAttributes(dataReader, unit, entry,
abbreviationEntry);
if (error != B_OK)
return error;
@ -1127,21 +1303,27 @@ DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
// set the compilation unit's source language
unit->SetSourceLanguage(entryInitInfo.languageInfo);
if (isTypeUnit)
return B_OK;
// resolve the compilation unit's address range list
if (TargetAddressRangeList* ranges = ResolveRangeList(unit,
unit->UnitEntry()->AddressRangesOffset())) {
unit->SetAddressRanges(ranges);
if (TargetAddressRangeList* ranges = ResolveRangeList(compilationUnit,
compilationUnit->UnitEntry()->AddressRangesOffset())) {
compilationUnit->SetAddressRanges(ranges);
ranges->ReleaseReference();
}
// add compilation dir to directory list
const char* compilationDir = unit->UnitEntry()->CompilationDir();
if (!unit->AddDirectory(compilationDir != NULL ? compilationDir : "."))
const char* compilationDir = compilationUnit->UnitEntry()
->CompilationDir();
if (!compilationUnit->AddDirectory(compilationDir != NULL
? compilationDir : ".")) {
return B_NO_MEMORY;
}
// parse line info header
if (fDebugLineSection != NULL)
_ParseLineInfo(unit);
_ParseLineInfo(compilationUnit);
return B_OK;
}
@ -1149,7 +1331,7 @@ DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
status_t
DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
BaseUnit* unit, DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
{
uint32 attributeName;
uint32 attributeForm;
@ -1170,7 +1352,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
// first.
uint64 value = 0;
off_t blockLength = 0;
bool localReference = true;
off_t valueOffset = dataReader.Offset() + unit->ContentOffset();
uint8 refType = dwarf_reference_type_local;
switch (attributeForm) {
case DW_FORM_addr:
@ -1213,7 +1396,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
case DW_FORM_strp:
{
if (fDebugStringSection != NULL) {
off_t offset = fCurrentCompilationUnit->IsDwarf64()
off_t offset = unit->IsDwarf64()
? (off_t)dataReader.Read<uint64>(0)
: (off_t)dataReader.Read<uint32>(0);
if (offset >= fDebugStringSection->Size()) {
@ -1233,10 +1416,10 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
value = dataReader.ReadUnsignedLEB128(0);
break;
case DW_FORM_ref_addr:
value = fCurrentCompilationUnit->IsDwarf64()
value = unit->IsDwarf64()
? dataReader.Read<uint64>(0)
: (uint64)dataReader.Read<uint32>(0);
localReference = false;
refType = dwarf_reference_type_global;
break;
case DW_FORM_ref1:
value = dataReader.Read<uint8>(0);
@ -1260,10 +1443,12 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
attributeValue.SetToFlag(true);
break;
case DW_FORM_ref_sig8:
fTypesSectionRequired = true;
value = dataReader.Read<uint64>(0);
refType = dwarf_reference_type_signature;
break;
case DW_FORM_sec_offset:
value = fCurrentCompilationUnit->IsDwarf64()
value = unit->IsDwarf64()
? dataReader.Read<uint64>(0)
: (uint64)dataReader.Read<uint32>(0);
break;
@ -1278,14 +1463,13 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
// it
uint8 attributeClass = get_attribute_class(attributeName,
attributeForm);
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
TRACE_DIE("skipping attribute with unrecognized class: %s (%#"
B_PRIx32 ") %s (%#" B_PRIx32 ")\n",
get_attribute_name_name(attributeName), attributeName,
get_attribute_form_name(attributeForm), attributeForm);
continue;
}
// attributeValue.attributeClass = attributeClass;
// set the attribute value according to the attribute's class
switch (attributeClass) {
@ -1314,7 +1498,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
case ATTRIBUTE_CLASS_REFERENCE:
if (entry != NULL) {
attributeValue.SetToReference(_ResolveReference(
fCurrentCompilationUnit, value, localReference));
unit, value, refType));
if (attributeValue.reference == NULL) {
// gcc 2 apparently somtimes produces DW_AT_sibling
// attributes pointing to the end of the sibling list.
@ -1322,8 +1506,11 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
if (attributeName == DW_AT_sibling)
continue;
WARNING("Failed to resolve reference: %s (%#" B_PRIx32
") %s (%#" B_PRIx32 "): value: %" B_PRIu64 "\n",
WARNING("Failed to resolve reference on entry %p: "
"(%#" B_PRIx64 ") %s (%#" B_PRIx32 ") %s "
"(%#" B_PRIx32 "): value: %#" B_PRIx64 "\n",
entry,
valueOffset,
get_attribute_name_name(attributeName),
attributeName,
get_attribute_form_name(attributeForm),
@ -1337,6 +1524,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
// already set
break;
case ATTRIBUTE_CLASS_EXPRESSION:
WARNING("Skipping unhandled attribute class expression.\n");
// TODO: implement
dataReader.Skip(value);
break;
@ -1347,16 +1535,17 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
return B_BAD_DATA;
}
TRACE_DIE_ONLY(
char buffer[1024];
TRACE_DIE(" attr (%#" B_PRIx64 ") %s %s (%d): %s\n",
valueOffset,
get_attribute_name_name(attributeName),
get_attribute_form_name(attributeForm), attributeClass,
attributeValue.ToString(buffer, sizeof(buffer)));
)
// add the attribute
if (entry != NULL) {
TRACE_DIE_ONLY(
char buffer[1024];
TRACE_DIE(" attr %s %s (%d): %s\n",
get_attribute_name_name(attributeName),
get_attribute_form_name(attributeForm), attributeClass,
attributeValue.ToString(buffer, sizeof(buffer)));
)
DebugInfoEntrySetter attributeSetter
= get_attribute_name_setter(attributeName);
if (attributeSetter != 0) {
@ -2378,13 +2567,27 @@ DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
DebugInfoEntry*
DwarfFile::_ResolveReference(CompilationUnit* unit, uint64 offset,
bool localReference) const
DwarfFile::_ResolveReference(BaseUnit* unit, uint64 offset,
uint8 refType) const
{
if (localReference)
return unit->EntryForOffset(offset);
switch (refType) {
case dwarf_reference_type_local:
return unit->EntryForOffset(offset);
break;
case dwarf_reference_type_global:
{
WARNING("DwarfFile: Unhandled global reference\n");
break;
}
case dwarf_reference_type_signature:
{
TypeUnitTableEntry* entry = fTypeUnits.Lookup(offset);
if (entry != NULL && entry->unit != NULL)
return entry->unit->TypeEntry();
break;
}
}
// TODO: Implement program-global references!
return NULL;
}
@ -2524,7 +2727,8 @@ DwarfFile::_LocateDebugInfo()
status_t
DwarfFile::_GetDebugInfoPath(const char* debugFileName, BString& _infoPath)
DwarfFile::_GetDebugInfoPath(const char* debugFileName,
BString& _infoPath) const
{
const directory_which dirLocations[] = { B_USER_CONFIG_DIRECTORY,
B_COMMON_DIRECTORY, B_SYSTEM_DIRECTORY };
@ -2571,3 +2775,10 @@ DwarfFile::_GetDebugInfoPath(const char* debugFileName, BString& _infoPath)
return B_ENTRY_NOT_FOUND;
}
TypeUnitTableEntry*
DwarfFile::_GetTypeUnit(uint64 signature) const
{
return fTypeUnits.Lookup(signature);
}

View File

@ -10,8 +10,10 @@
#include <ObjectList.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h>
#include "DebugInfoEntries.h"
#include "TypeUnit.h"
class AbbreviationEntry;
@ -107,15 +109,21 @@ private:
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
typedef BObjectList<CompilationUnit> CompilationUnitList;
typedef BOpenHashTable<TypeUnitTableHashDefinition> TypeUnitTable;
private:
status_t _ParseDebugInfoSection();
status_t _ParseTypesSection();
status_t _ParseCompilationUnit(CompilationUnit* unit);
status_t _ParseTypeUnit(TypeUnit* unit);
status_t _ParseDebugInfoEntry(DataReader& dataReader,
BaseUnit* unit,
AbbreviationTable* abbreviationTable,
DebugInfoEntry*& _entry,
bool& _endOfEntryList, int level = 0);
status_t _FinishCompilationUnit(CompilationUnit* unit);
status_t _FinishUnit(BaseUnit* unit);
status_t _ParseEntryAttributes(DataReader& dataReader,
BaseUnit* unit,
DebugInfoEntry* entry,
AbbreviationEntry& abbreviationEntry);
@ -150,8 +158,9 @@ private:
status_t _GetAbbreviationTable(off_t offset,
AbbreviationTable*& _table);
DebugInfoEntry* _ResolveReference(CompilationUnit* unit,
uint64 offset, bool localReference) const;
DebugInfoEntry* _ResolveReference(BaseUnit* unit,
uint64 offset,
uint8 refType) const;
status_t _GetLocationExpression(CompilationUnit* unit,
const LocationDescription* location,
@ -165,7 +174,9 @@ private:
status_t _LocateDebugInfo();
status_t _GetDebugInfoPath(const char* fileName,
BString& _infoPath);
BString& _infoPath) const;
TypeUnitTableEntry* _GetTypeUnit(uint64 signature) const;
private:
friend class DwarfFile::ExpressionEvaluationContext;
@ -184,10 +195,12 @@ private:
ElfSection* fEHFrameSection;
ElfSection* fDebugLocationSection;
ElfSection* fDebugPublicTypesSection;
ElfSection* fDebugTypesSection;
AbbreviationTableList fAbbreviationTables;
DebugInfoEntryFactory fDebugInfoFactory;
CompilationUnitList fCompilationUnits;
CompilationUnit* fCurrentCompilationUnit;
TypeUnitTable fTypeUnits;
bool fTypesSectionRequired;
bool fFinished;
status_t fFinishError;
};