Fix DWARFBlockInputFormat failing on DWARF 5 unit address ranges

This commit is contained in:
Michael Kolupaev 2023-12-23 21:43:32 +00:00
parent a30980c930
commit 172687f53a
2 changed files with 35 additions and 7 deletions

View File

@ -390,6 +390,40 @@ Chunk DWARFBlockInputFormat::parseEntries(UnitState & unit)
if (need[COL_TAG])
col_tag->insertValue(tag);
if (tag == llvm::dwarf::DW_TAG_compile_unit)
{
/// Pre-parse DW_AT_addr_base and DW_AT_rnglists_base because other attributes may
/// rely on them. (Why couldn't DWARF just promise that these attributes must appear
/// before any attributes that depend on them?)
uint64_t offset = unit.offset;
for (auto attr : abbrev->attributes())
{
if (attr.Attr == llvm::dwarf::DW_AT_addr_base ||
attr.Attr == llvm::dwarf::DW_AT_rnglists_base)
{
auto val = llvm::DWARFFormValue::createFromSValue(
attr.Form, attr.isImplicitConst() ? attr.getImplicitConstValue() : 0);
if (!val.extractValue(*extractor, &offset, form_params, unit.dwarf_unit))
throw Exception(ErrorCodes::CANNOT_PARSE_DWARF,
"Failed to parse attribute {} of form {} at offset {}",
llvm::dwarf::AttributeString(attr.Attr), attr.Form, unit.offset);
uint64_t v = val.getRawUValue();
if (attr.Attr == llvm::dwarf::DW_AT_addr_base)
unit.addr_base = v;
else
unit.rnglists_base = v;
}
else
{
if (!llvm::DWARFFormValue::skipValue(
attr.Form, *extractor, &offset, form_params))
throw Exception(ErrorCodes::CANNOT_PARSE_DWARF,
"Failed to skip attribute {} of form {} at offset {}",
llvm::dwarf::AttributeString(attr.Attr), attr.Form, offset);
}
}
}
bool need_name = need[COL_NAME];
bool need_linkage_name = need[COL_LINKAGE_NAME];
bool need_decl_file = need[COL_DECL_FILE];
@ -452,13 +486,6 @@ Chunk DWARFBlockInputFormat::parseEntries(UnitState & unit)
if (attr.Attr == llvm::dwarf::DW_AT_decl_line && std::exchange(need_decl_line, false))
col_decl_line->insertValue(static_cast<UInt32>(val.getRawUValue()));
/// Starting offset of this unit's data in .debug_addr section.
if (attr.Attr == llvm::dwarf::DW_AT_addr_base)
unit.addr_base = val.getRawUValue();
/// Same for .debug_rnglists section.
if (attr.Attr == llvm::dwarf::DW_AT_rnglists_base)
unit.rnglists_base = val.getRawUValue();
if (attr.Attr == llvm::dwarf::DW_AT_high_pc)
{
high_pc = val.getRawUValue();

View File

@ -53,6 +53,7 @@ private:
std::string unit_name;
ColumnPtr filename_table; // from .debug_line
size_t filename_table_size = 0;
/// Starting offset of this unit's data in .debug_addr and .debug_rnglists sections.
uint64_t addr_base = UINT64_MAX;
uint64_t rnglists_base = UINT64_MAX;