diff --git a/src/apps/debugger/dwarf/Dwarf.h b/src/apps/debugger/dwarf/Dwarf.h index 06dd514b7b..09d7eba9e1 100644 --- a/src/apps/debugger/dwarf/Dwarf.h +++ b/src/apps/debugger/dwarf/Dwarf.h @@ -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 diff --git a/src/apps/debugger/dwarf/DwarfExpressionEvaluator.cpp b/src/apps/debugger/dwarf/DwarfExpressionEvaluator.cpp index e1a431d08a..f47d5423b8 100644 --- a/src/apps/debugger/dwarf/DwarfExpressionEvaluator.cpp +++ b/src/apps/debugger/dwarf/DwarfExpressionEvaluator.cpp @@ -600,18 +600,21 @@ DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece) case DW_OP_call2: TRACE_EXPR(" DW_OP_call2\n"); - _Call(fDataReader.Read(0), true); + _Call(fDataReader.Read(0), dwarf_reference_type_local); break; case DW_OP_call4: TRACE_EXPR(" DW_OP_call4\n"); - _Call(fDataReader.Read(0), true); + _Call(fDataReader.Read(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(0), false); - else - _Call(fDataReader.Read(0), false); + if (fContext->AddressSize() == 4) { + _Call(fDataReader.Read(0), + dwarf_reference_type_global); + } else { + _Call(fDataReader.Read(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 diff --git a/src/apps/debugger/dwarf/DwarfExpressionEvaluator.h b/src/apps/debugger/dwarf/DwarfExpressionEvaluator.h index 71faec2057..49e95e180f 100644 --- a/src/apps/debugger/dwarf/DwarfExpressionEvaluator.h +++ b/src/apps/debugger/dwarf/DwarfExpressionEvaluator.h @@ -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; diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index 58fa3761e3..4386fc1cd1 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -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(0); - off_t abbrevOffset = dwarf64 - ? dataReader.Read(0) - : dataReader.Read(0); - uint8 addressSize = dataReader.Read(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(0); + off_t abbrevOffset = dwarf64 + ? dataReader.Read(0) + : dataReader.Read(0); + uint8 addressSize = dataReader.Read(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(0); + off_t abbrevOffset = dwarf64 + ? dataReader.Read(0) + : dataReader.Read(0); + uint8 addressSize = dataReader.Read(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(0); + + off_t typeOffset = dwarf64 + ? dataReader.Read(0) + : dataReader.Read(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(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(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(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(0) : (off_t)dataReader.Read(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(0) : (uint64)dataReader.Read(0); - localReference = false; + refType = dwarf_reference_type_global; break; case DW_FORM_ref1: value = dataReader.Read(0); @@ -1260,10 +1443,12 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, attributeValue.SetToFlag(true); break; case DW_FORM_ref_sig8: + fTypesSectionRequired = true; value = dataReader.Read(0); + refType = dwarf_reference_type_signature; break; case DW_FORM_sec_offset: - value = fCurrentCompilationUnit->IsDwarf64() + value = unit->IsDwarf64() ? dataReader.Read(0) : (uint64)dataReader.Read(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); +} + diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index 52575c3732..cf0d650474 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -10,8 +10,10 @@ #include #include #include +#include #include "DebugInfoEntries.h" +#include "TypeUnit.h" class AbbreviationEntry; @@ -107,15 +109,21 @@ private: typedef DoublyLinkedList AbbreviationTableList; typedef BObjectList CompilationUnitList; + typedef BOpenHashTable 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; };