From 172687f53a09dbb27e2951db6747ace5cf7dec08 Mon Sep 17 00:00:00 2001 From: Michael Kolupaev Date: Sat, 23 Dec 2023 21:43:32 +0000 Subject: [PATCH] Fix DWARFBlockInputFormat failing on DWARF 5 unit address ranges --- .../Formats/Impl/DWARFBlockInputFormat.cpp | 41 +++++++++++++++---- .../Formats/Impl/DWARFBlockInputFormat.h | 1 + 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/Processors/Formats/Impl/DWARFBlockInputFormat.cpp b/src/Processors/Formats/Impl/DWARFBlockInputFormat.cpp index 22ccbe03f0f..b9f65dd49b0 100644 --- a/src/Processors/Formats/Impl/DWARFBlockInputFormat.cpp +++ b/src/Processors/Formats/Impl/DWARFBlockInputFormat.cpp @@ -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(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(); diff --git a/src/Processors/Formats/Impl/DWARFBlockInputFormat.h b/src/Processors/Formats/Impl/DWARFBlockInputFormat.h index 07c00656e4d..366671210bb 100644 --- a/src/Processors/Formats/Impl/DWARFBlockInputFormat.h +++ b/src/Processors/Formats/Impl/DWARFBlockInputFormat.h @@ -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;