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 <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
David Karoly 2023-11-13 20:08:37 +01:00 committed by waddlesplash
parent 973f6d3320
commit 8497e56650
2 changed files with 133 additions and 0 deletions

View File

@ -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<uint64>(0)
: dataReader.Read<uint32>(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<uint64>(0);
@ -1672,6 +1773,32 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
? dataReader.Read<uint64>(0)
: (uint64)dataReader.Read<uint32>(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",

View File

@ -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;