From 8497e566502bda506c22558a67f007c6c2e46fa9 Mon Sep 17 00:00:00 2001 From: David Karoly Date: Mon, 13 Nov 2023 20:08:37 +0100 Subject: [PATCH] Debugger: implement DWARF5 indirect string and address forms Change-Id: Ie3ee6f4eb14606ee2d412d8e7122d59472619f81 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7059 Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- src/kits/debugger/dwarf/DwarfFile.cpp | 127 ++++++++++++++++++++++++++ src/kits/debugger/dwarf/DwarfFile.h | 6 ++ 2 files changed, 133 insertions(+) diff --git a/src/kits/debugger/dwarf/DwarfFile.cpp b/src/kits/debugger/dwarf/DwarfFile.cpp index 5d237e9048..90ea41a376 100644 --- a/src/kits/debugger/dwarf/DwarfFile.cpp +++ b/src/kits/debugger/dwarf/DwarfFile.cpp @@ -492,7 +492,9 @@ DwarfFile::DwarfFile() fAlternateElfFile(NULL), fDebugInfoSection(NULL), fDebugAbbrevSection(NULL), + fDebugAddressSection(NULL), fDebugStringSection(NULL), + fDebugStrOffsetsSection(NULL), fDebugRangesSection(NULL), fDebugLineSection(NULL), fDebugLineStrSection(NULL), @@ -524,7 +526,9 @@ DwarfFile::~DwarfFile() debugInfoFile->PutSection(fDebugInfoSection); debugInfoFile->PutSection(fDebugAbbrevSection); + debugInfoFile->PutSection(fDebugAddressSection); debugInfoFile->PutSection(fDebugStringSection); + debugInfoFile->PutSection(fDebugStrOffsetsSection); debugInfoFile->PutSection(fDebugRangesSection); debugInfoFile->PutSection(fDebugLineSection); debugInfoFile->PutSection(fDebugLineStrSection); @@ -588,7 +592,9 @@ DwarfFile::Load(uint8 addressSize, bool isBigEndian, const BString& externalInfo ? fAlternateElfFile : fElfFile; // non mandatory sections + fDebugAddressSection = debugInfoFile->GetSection(".debug_addr"); fDebugStringSection = debugInfoFile->GetSection(".debug_str"); + fDebugStrOffsetsSection = debugInfoFile->GetSection(".debug_str_offsets"); fDebugRangesSection = debugInfoFile->GetSection(".debug_ranges"); fDebugLineSection = debugInfoFile->GetSection(".debug_line"); fDebugLineStrSection = debugInfoFile->GetSection(".debug_line_str"); @@ -1547,6 +1553,64 @@ DwarfFile::_FinishUnit(BaseUnit* unit) } +status_t +DwarfFile::_ReadStringIndirect(BaseUnit* unit, uint64 index, const char*& value) const +{ + if (fDebugStrOffsetsSection == NULL) { + WARNING("Invalid DW_FORM_strx*: no debug_str_offsets section!\n"); + return B_BAD_DATA; + } + + uint64 strOffsetsBase = unit->IsDwarf64() ? 16 : 8; + uint64 offsetSize = unit->IsDwarf64() ? 8 : 4; + + if (strOffsetsBase + index * offsetSize >= fDebugStrOffsetsSection->Size()) { + WARNING("Invalid DW_FORM_strx* index: %" B_PRIu64 "\n", index); + return B_BAD_DATA; + } + + const char *strOffsets = (const char*)fDebugStrOffsetsSection->Data() + strOffsetsBase; + uint64 offset = unit->IsDwarf64() + ? ((uint64*)strOffsets)[index] + : ((uint32*)strOffsets)[index]; + + if (offset >= fDebugStringSection->Size()) { + WARNING("Invalid DW_FORM_strx* offset: %" B_PRIu64 "\n", offset); + return B_BAD_DATA; + } + + value = (const char*)fDebugStringSection->Data() + offset; + return B_OK; +} + + +status_t +DwarfFile::_ReadAddressIndirect(BaseUnit* unit, uint64 index, uint64& value) const +{ + if (fDebugAddressSection == NULL) { + WARNING("Invalid DW_FORM_addrx*: no debug_addr section!\n"); + return B_BAD_DATA; + } + + uint64 addrBase = unit->IsDwarf64() ? 16 : 8; + + if (addrBase + index * unit->AddressSize() >= fDebugAddressSection->Size()) { + WARNING("Invalid DW_FORM_addrx* index: %" B_PRIu64 "\n", index); + return B_BAD_DATA; + } + + const char *addrPtr = (const char*)fDebugAddressSection->Data() + + addrBase + index * unit->AddressSize(); + + if (unit->AddressSize() == 8) + value = *(uint64*)addrPtr; + else + value = *(uint32*)addrPtr; + + return B_OK; +} + + status_t DwarfFile::_ParseEntryAttributes(DataReader& dataReader, BaseUnit* unit, DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry) @@ -1659,6 +1723,43 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, case DW_FORM_flag_present: attributeValue.SetToFlag(true); break; + case DW_FORM_strx: + { + uint64 index = dataReader.ReadUnsignedLEB128(0); + const char* strValue; + status_t res = _ReadStringIndirect(unit, index, strValue); + if (res != B_OK) + return res; + attributeValue.SetToString(strValue); + break; + } + case DW_FORM_addrx: + { + uint64 index = dataReader.ReadUnsignedLEB128(0); + status_t res = _ReadAddressIndirect(unit, index, value); + if (res != B_OK) + return res; + break; + } + case DW_FORM_line_strp: + { + if (fDebugLineStrSection != NULL) { + uint64 offset = unit->IsDwarf64() + ? dataReader.Read(0) + : dataReader.Read(0); + if (offset >= fDebugLineStrSection->Size()) { + WARNING("Invalid DW_FORM_line_strp offset: %" B_PRIu64 "\n", + offset); + return B_BAD_DATA; + } + attributeValue.SetToString( + (const char*)fDebugLineStrSection->Data() + offset); + } else { + WARNING("Invalid DW_FORM_line_strp: no debug_line_str section!\n"); + return B_BAD_DATA; + } + break; + } case DW_FORM_ref_sig8: fTypesSectionRequired = true; value = dataReader.Read(0); @@ -1672,6 +1773,32 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, ? dataReader.Read(0) : (uint64)dataReader.Read(0); break; + case DW_FORM_strx1: + case DW_FORM_strx2: + case DW_FORM_strx3: + case DW_FORM_strx4: + { + size_t numBytes = attributeForm - DW_FORM_strx1 + 1; + uint64 index = dataReader.ReadUInt(numBytes, 0); + const char* strValue; + status_t res = _ReadStringIndirect(unit, index, strValue); + if (res != B_OK) + return res; + attributeValue.SetToString(strValue); + break; + } + case DW_FORM_addrx1: + case DW_FORM_addrx2: + case DW_FORM_addrx3: + case DW_FORM_addrx4: + { + size_t numBytes = attributeForm - DW_FORM_addrx1 + 1; + uint64 index = dataReader.ReadUInt(numBytes, 0); + status_t res = _ReadAddressIndirect(unit, index, value); + if (res != B_OK) + return res; + break; + } case DW_FORM_indirect: default: WARNING("Unsupported attribute form: %" B_PRIu32 "\n", diff --git a/src/kits/debugger/dwarf/DwarfFile.h b/src/kits/debugger/dwarf/DwarfFile.h index be3b1ccc8e..4c0b71cc65 100644 --- a/src/kits/debugger/dwarf/DwarfFile.h +++ b/src/kits/debugger/dwarf/DwarfFile.h @@ -131,6 +131,10 @@ private: DebugInfoEntry*& _entry, bool& _endOfEntryList, int level = 0); status_t _FinishUnit(BaseUnit* unit); + status_t _ReadStringIndirect(BaseUnit* unit, + uint64 index, const char*& value) const; + status_t _ReadAddressIndirect(BaseUnit* unit, + uint64 index, uint64& value) const; status_t _ParseEntryAttributes(DataReader& dataReader, BaseUnit* unit, DebugInfoEntry* entry, @@ -215,7 +219,9 @@ private: ElfFile* fAlternateElfFile; ElfSection* fDebugInfoSection; ElfSection* fDebugAbbrevSection; + ElfSection* fDebugAddressSection; ElfSection* fDebugStringSection; + ElfSection* fDebugStrOffsetsSection; ElfSection* fDebugRangesSection; ElfSection* fDebugLineSection; ElfSection* fDebugLineStrSection;