From 3fcc74500a3802efed7bc6fa2a998321d32f189c Mon Sep 17 00:00:00 2001 From: James Henderson Date: Fri, 2 Feb 2018 12:35:52 +0000 Subject: [PATCH] [DWARF v5] Add limited support for dumping .debug_rnglists This change adds support to llvm-dwarfdump for dumping DWARF5 .debug_rnglists sections in regular ELF files. It is not complete, in that several DW_RLE_* encodings are currently not supported, but does dump the headert and the basic ranges for DW_RLE_start_length and DW_RLE_start_end encodings. Obvious next steps are to add verbose dumping that dumps the raw encodings, rather than the interpreted contents, to add -verify support of the section (e.g. to show that the correct number of offsets are specified), add dumping of .debug_rnglists.dwo, and to add support for other encodings. Reviewed by: dblaikie, JDevlieghere Differential Revision: https://reviews.llvm.org/D42481 llvm-svn: 324077 --- llvm/include/llvm/BinaryFormat/Dwarf.def | 3 +- .../DebugInfo/DWARF/DWARFDebugRangeList.h | 45 +------------------ llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 2 +- .../llvm/DebugInfo/DWARF/DWARFObject.h | 1 + .../llvm/DebugInfo/DWARF/DWARFVerifier.h | 2 +- llvm/lib/DebugInfo/DWARF/CMakeLists.txt | 2 + llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 27 +++++++++++ .../DebugInfo/DWARF/DWARFDebugRangeList.cpp | 12 ----- 8 files changed, 35 insertions(+), 59 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index a6dac774ef8d..11b81a467936 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -845,11 +845,12 @@ HANDLE_DWARF_SECTION(DebugLoc, ".debug_loc", "debug-loc") HANDLE_DWARF_SECTION(DebugFrame, ".debug_frame", "debug-frame") HANDLE_DWARF_SECTION(DebugMacro, ".debug_macro", "debug-macro") HANDLE_DWARF_SECTION(DebugNames, ".debug_names", "debug-names") -HANDLE_DWARF_SECTION(DebugRanges, ".debug_ranges", "debug-ranges") HANDLE_DWARF_SECTION(DebugPubnames, ".debug_pubnames", "debug-pubnames") HANDLE_DWARF_SECTION(DebugPubtypes, ".debug_pubtypes", "debug-pubtypes") HANDLE_DWARF_SECTION(DebugGnuPubnames, ".debug_gnu_pubnames", "debug-gnu-pubnames") HANDLE_DWARF_SECTION(DebugGnuPubtypes, ".debug_gnu_pubtypes", "debug-gnu-pubtypes") +HANDLE_DWARF_SECTION(DebugRanges, ".debug_ranges", "debug-ranges") +HANDLE_DWARF_SECTION(DebugRnglists, ".debug_rnglists", "debug-rnglists") HANDLE_DWARF_SECTION(DebugStr, ".debug_str", "debug-str") HANDLE_DWARF_SECTION(DebugStrOffsets, ".debug_str_offsets", "debug-str-offsets") HANDLE_DWARF_SECTION(DebugCUIndex, ".debug_cu_index", "debug-cu-index") diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index 8c0011793ff1..38b7f225e772 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -10,8 +10,8 @@ #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include #include #include @@ -21,49 +21,6 @@ namespace llvm { struct BaseAddress; class raw_ostream; -struct DWARFAddressRange { - uint64_t LowPC; - uint64_t HighPC; - uint64_t SectionIndex; - - DWARFAddressRange() = default; - - /// Used for unit testing. - DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0) - : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {} - - /// Returns true if LowPC is smaller or equal to HighPC. This accounts for - /// dead-stripped ranges. - bool valid() const { return LowPC <= HighPC; } - - /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC). - bool intersects(const DWARFAddressRange &RHS) const { - // Empty ranges can't intersect. - if (LowPC == HighPC || RHS.LowPC == RHS.HighPC) - return false; - return (LowPC < RHS.HighPC) && (HighPC > RHS.LowPC); - } - - /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC). - bool contains(const DWARFAddressRange &RHS) const { - if (LowPC <= RHS.LowPC && RHS.LowPC <= HighPC) - return LowPC <= RHS.HighPC && RHS.HighPC <= HighPC; - return false; - } - - void dump(raw_ostream &OS, uint32_t AddressSize) const; -}; - -static inline bool operator<(const DWARFAddressRange &LHS, - const DWARFAddressRange &RHS) { - return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC); -} - -raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R); - -/// DWARFAddressRangesVector - represents a set of absolute address ranges. -using DWARFAddressRangesVector = std::vector; - class DWARFDebugRangeList { public: struct RangeListEntry { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index 75fc5995c5b2..39a3dd32c0f7 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -16,9 +16,9 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFAttribute.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include #include #include diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h index 7575cf9a9c51..795eddd1c5db 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -45,6 +45,7 @@ public: virtual StringRef getLineStringSection() const { return ""; } virtual StringRef getStringSection() const { return ""; } virtual const DWARFSection &getRangeSection() const { return Dummy; } + virtual const DWARFSection &getRnglistsSection() const { return Dummy; } virtual StringRef getMacinfoSection() const { return ""; } virtual StringRef getPubNamesSection() const { return ""; } virtual StringRef getPubTypesSection() const { return ""; } diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index eaaf9341de32..589a5ebd9863 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -11,7 +11,7 @@ #define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt index 620016d76fb6..28632b6c5ea1 100644 --- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -1,5 +1,6 @@ add_llvm_library(LLVMDebugInfoDWARF DWARFAbbreviationDeclaration.cpp + DWARFAddressRange.cpp DWARFAcceleratorTable.cpp DWARFCompileUnit.cpp DWARFContext.cpp @@ -14,6 +15,7 @@ add_llvm_library(LLVMDebugInfoDWARF DWARFDebugMacro.cpp DWARFDebugPubTable.cpp DWARFDebugRangeList.cpp + DWARFDebugRnglists.cpp DWARFDie.cpp DWARFExpression.cpp DWARFFormValue.cpp diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index e159303ab207..761f2b5d8002 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -25,6 +25,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" @@ -490,6 +491,27 @@ void DWARFContext::dump( rangeList.dump(OS); } + if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, + DObj->getRnglistsSection().Data)) { + DWARFDataExtractor rnglistData(*DObj, DObj->getRnglistsSection(), + isLittleEndian(), 0); + uint32_t Offset = 0; + while (rnglistData.isValidOffset(Offset)) { + DWARFDebugRnglists Rnglists; + uint32_t TableOffset = Offset; + if (Error Err = Rnglists.extract(rnglistData, &Offset)) { + errs() << "error: " + toString(std::move(Err)) << '\n'; + uint64_t Length = Rnglists.length(); + // Keep going after an error, if we can, assuming that the length field + // could be read. If it couldn't, stop reading the section. + if (Length == 0) + break; + Offset = TableOffset + Length; + } else + Rnglists.dump(OS); + } + } + if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, DObj->getPubNamesSection())) DWARFDebugPubTable(DObj->getPubNamesSection(), isLittleEndian(), false) @@ -1164,6 +1186,7 @@ class DWARFObjInMemory final : public DWARFObject { DWARFSectionMap LocSection; DWARFSectionMap LineSection; DWARFSectionMap RangeSection; + DWARFSectionMap RnglistsSection; DWARFSectionMap StringOffsetSection; DWARFSectionMap InfoDWOSection; DWARFSectionMap LineDWOSection; @@ -1184,6 +1207,7 @@ class DWARFObjInMemory final : public DWARFObject { .Case("debug_line", &LineSection) .Case("debug_str_offsets", &StringOffsetSection) .Case("debug_ranges", &RangeSection) + .Case("debug_rnglists", &RnglistsSection) .Case("debug_info.dwo", &InfoDWOSection) .Case("debug_loc.dwo", &LocDWOSection) .Case("debug_line.dwo", &LineDWOSection) @@ -1475,6 +1499,9 @@ public: const DWARFSection &getLineSection() const override { return LineSection; } StringRef getStringSection() const override { return StringSection; } const DWARFSection &getRangeSection() const override { return RangeSection; } + const DWARFSection &getRnglistsSection() const override { + return RnglistsSection; + } StringRef getMacinfoSection() const override { return MacinfoSection; } StringRef getPubNamesSection() const override { return PubNamesSection; } StringRef getPubTypesSection() const override { return PubTypesSection; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index 943a740c7ae4..87a0fd366af8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -13,21 +13,9 @@ #include "llvm/Support/raw_ostream.h" #include #include -#include using namespace llvm; -void DWARFAddressRange::dump(raw_ostream &OS, uint32_t AddressSize) const { - - OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, LowPC) - << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, HighPC); -} - -raw_ostream &llvm::operator<<(raw_ostream &OS, const DWARFAddressRange &R) { - R.dump(OS, /* AddressSize */ 8); - return OS; -} - void DWARFDebugRangeList::clear() { Offset = -1U; AddressSize = 0;