diff options
author | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2018-09-12 14:40:04 +0000 |
---|---|---|
committer | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2018-09-12 14:40:04 +0000 |
commit | 233bc73047f45ace46f080c5e08f14d35c09c137 (patch) | |
tree | 88d9269e2e0fa3200b203af5df0e763db500edf8 | |
parent | 54d56f274cc93815e83a1dfd0b98c1f958f9706f (diff) | |
download | bcm5719-llvm-233bc73047f45ace46f080c5e08f14d35c09c137.tar.gz bcm5719-llvm-233bc73047f45ace46f080c5e08f14d35c09c137.zip |
Reverting r342048, which caused UBSan failures in dsymutil.
llvm-svn: 342056
21 files changed, 417 insertions, 438 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index a4efbfc43c9..9218e4bd2da 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -231,9 +231,7 @@ public: /// Get a DIE given an exact offset. DWARFDie getDIEForOffset(uint32_t Offset); - unsigned getMaxVersion(uint16_t DefaultVersion = 0) const { - return MaxVersion ? MaxVersion : DefaultVersion; - } + unsigned getMaxVersion() const { return MaxVersion; } void setMaxVersionIfGreater(unsigned Version) { if (Version > MaxVersion) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h new file mode 100644 index 00000000000..ce7436d9faa --- /dev/null +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -0,0 +1,86 @@ +//===- DWARFDebugRangeList.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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 <cassert> +#include <cstdint> +#include <vector> + +namespace llvm { + +struct BaseAddress; +class raw_ostream; + +class DWARFDebugRangeList { +public: + struct RangeListEntry { + /// A beginning address offset. This address offset has the size of an + /// address and is relative to the applicable base address of the + /// compilation unit referencing this range list. It marks the beginning + /// of an address range. + uint64_t StartAddress; + /// An ending address offset. This address offset again has the size of + /// an address and is relative to the applicable base address of the + /// compilation unit referencing this range list. It marks the first + /// address past the end of the address range. The ending address must + /// be greater than or equal to the beginning address. + uint64_t EndAddress; + /// A section index this range belongs to. + uint64_t SectionIndex; + + /// The end of any given range list is marked by an end of list entry, + /// which consists of a 0 for the beginning address offset + /// and a 0 for the ending address offset. + bool isEndOfListEntry() const { + return (StartAddress == 0) && (EndAddress == 0); + } + + /// A base address selection entry consists of: + /// 1. The value of the largest representable address offset + /// (for example, 0xffffffff when the size of an address is 32 bits). + /// 2. An address, which defines the appropriate base address for + /// use in interpreting the beginning and ending address offsets of + /// subsequent entries of the location list. + bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { + assert(AddressSize == 4 || AddressSize == 8); + if (AddressSize == 4) + return StartAddress == -1U; + else + return StartAddress == -1ULL; + } + }; + +private: + /// Offset in .debug_ranges section. + uint32_t Offset; + uint8_t AddressSize; + std::vector<RangeListEntry> Entries; + +public: + DWARFDebugRangeList() { clear(); } + + void clear(); + void dump(raw_ostream &OS) const; + Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr); + const std::vector<RangeListEntry> &getEntries() { return Entries; } + + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector + getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h index 6499764b930..e2e8ab5ed21 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -12,8 +12,8 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFListTable.h" #include <cstdint> #include <map> @@ -21,8 +21,6 @@ namespace llvm { -struct BaseAddress; -class DWARFContext; class Error; class raw_ostream; @@ -35,29 +33,10 @@ struct RangeListEntry : public DWARFListEntryBase { uint64_t Value0; uint64_t Value1; - Error extract(DWARFDataExtractor Data, uint32_t End, uint16_t Version, - StringRef SectionName, uint32_t *OffsetPtr, bool isDWO = false); - bool isEndOfList() const { return EntryKind == dwarf::DW_RLE_end_of_list; } - bool isBaseAddressSelectionEntry() const { - return EntryKind == dwarf::DW_RLE_base_address; - } - uint64_t getStartAddress() const { - assert((EntryKind == dwarf::DW_RLE_start_end || - EntryKind == dwarf::DW_RLE_offset_pair || - EntryKind == dwarf::DW_RLE_startx_length) && - "Unexpected range list entry kind"); - return Value0; - } - uint64_t getEndAddress() const { - assert((EntryKind == dwarf::DW_RLE_start_end || - EntryKind == dwarf::DW_RLE_offset_pair) && - "Unexpected range list entry kind"); - return Value1; - } - void dump(raw_ostream &OS, DWARFContext *C, uint8_t AddrSize, - uint64_t &CurrentBase, unsigned Indent, uint16_t Version, - uint8_t MaxEncodingStringLength = 0, - DIDumpOptions DumpOpts = {}) const; + Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); + void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, + uint64_t &CurrentBase, DIDumpOptions DumpOpts) const; + bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } }; /// A class representing a single rangelist. @@ -70,12 +49,10 @@ public: class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> { public: - DWARFDebugRnglistTable(DWARFContext *C, StringRef SectionName, - bool isDWO = false) - : DWARFListTableBase(C, SectionName, isDWO, + DWARFDebugRnglistTable() + : DWARFListTableBase(/* SectionName = */ ".debug_rnglists", /* HeaderString = */ "ranges:", - /* ListTypeString = */ "range", - dwarf::RangeListEncodingString) {} + /* ListTypeString = */ "range") {} }; } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h index a55f994dca8..8cf9e400892 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -23,8 +23,6 @@ namespace llvm { -class DWARFContext; - /// A base class for DWARF list entries, such as range or location list /// entries. struct DWARFListEntryBase { @@ -39,7 +37,6 @@ struct DWARFListEntryBase { /// A base class for lists of entries that are extracted from a particular /// section, such as range lists or location lists. template <typename ListEntryType> class DWARFListType { -public: using EntryType = ListEntryType; using ListEntries = std::vector<EntryType>; @@ -48,26 +45,11 @@ protected: public: const ListEntries &getEntries() const { return Entries; } - bool empty() const { - return Entries.empty() || Entries.begin()->isEndOfList(); - } + bool empty() const { return Entries.empty(); } void clear() { Entries.clear(); } - uint32_t getOffset() const { - if (Entries.empty()) - return 0; - return Entries.begin()->Offset; - } - - /// Extract a list. The caller must pass the correct DWARF version. - /// The end-of-list entry is retained as the last element of the vector of - /// entries. Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, - uint16_t Version, uint32_t *OffsetPtr, StringRef SectionName, - StringRef ListStringName, bool isDWO = false); - void dump(raw_ostream &OS, DWARFContext *C, uint8_t AddressSize, - uint64_t BaseAddress, unsigned Indent, uint16_t Version, - size_t MaxEncodingStringLength = 0, - DIDumpOptions DumpOpts = {}) const; + uint32_t *OffsetPtr, StringRef SectionName, + StringRef ListStringName); }; /// A class representing the header of a list table such as the range list @@ -85,9 +67,9 @@ class DWARFListTableHeader { uint8_t AddrSize; /// The size in bytes of a segment selector on the target architecture. /// If the target system uses a flat address space, this value is 0. - uint8_t SegSize = 0; + uint8_t SegSize; /// The number of offsets that follow the header before the range lists. - uint32_t OffsetEntryCount = 0; + uint32_t OffsetEntryCount; }; Header HeaderData; @@ -96,10 +78,10 @@ class DWARFListTableHeader { /// FIXME: Generate the table and use the appropriate forms. std::vector<uint32_t> Offsets; /// The table's format, either DWARF32 or DWARF64. - dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32; + dwarf::DwarfFormat Format; /// The offset at which the header (and hence the table) is located within /// its section. - uint32_t HeaderOffset = 0; + uint32_t HeaderOffset; /// The name of the section the list is located in. StringRef SectionName; /// A characterization of the list for dumping purposes, e.g. "range" or @@ -115,19 +97,8 @@ public: Offsets.clear(); } uint32_t getHeaderOffset() const { return HeaderOffset; } - uint8_t getAddrSize() const { return HeaderData.AddrSize; } - void setAddrSize(uint8_t AddrSize) { HeaderData.AddrSize = AddrSize; } - uint32_t getLength() const { return HeaderData.Length; } - void setLength(uint32_t Length) { HeaderData.Length = Length; } - - uint16_t getVersion() const { return HeaderData.Version; } - void setVersion(uint16_t Version) { HeaderData.Version = Version; } - - uint8_t getSegSize() const { return HeaderData.SegSize; } - uint32_t getOffsetEntryCount() const { return HeaderData.OffsetEntryCount; } - StringRef getSectionName() const { return SectionName; } StringRef getListTypeString() const { return ListTypeString; } dwarf::DwarfFormat getFormat() const { return Format; } @@ -144,10 +115,8 @@ public: /// Returns the length of the table, including the length field, or 0 if the /// length has not been determined (e.g. because the table has not yet been - /// parsed, or there was a problem in parsing). In fake tables, such as for - /// DWARF v4 and earlier, there is no header, so the length simply reflects - /// the size of the section. - uint32_t getTableLength() const; + /// parsed, or there was a problem in parsing). + uint32_t length() const; }; /// A class representing a table of lists as specified in the DWARF v5 @@ -160,22 +129,14 @@ template <typename DWARFListType> class DWARFListTableBase { /// A mapping between file offsets and lists. It is used to find a particular /// list based on an offset (obtained from DW_AT_ranges, for example). std::map<uint32_t, DWARFListType> ListMap; - DWARFContext *C; - /// True if this list is located in a split-DWARF (dwo or dwp) file. - bool isDWO; /// This string is displayed as a heading before the list is dumped /// (e.g. "ranges:"). StringRef HeaderString; - /// A function returning the encoding string for a given list entry encoding, - /// e.g. "DW_RLE_start_end". - std::function<StringRef(unsigned)> EncodingString; protected: - DWARFListTableBase(DWARFContext *C, StringRef SectionName, bool isDWO, - StringRef HeaderString, StringRef ListTypeString, - std::function<StringRef(unsigned)> EncodingString) - : Header(SectionName, ListTypeString), C(C), isDWO(isDWO), - HeaderString(HeaderString), EncodingString(EncodingString) {} + DWARFListTableBase(StringRef SectionName, StringRef HeaderString, + StringRef ListTypeString) + : Header(SectionName, ListTypeString), HeaderString(HeaderString) {} public: void clear() { @@ -186,28 +147,14 @@ public: Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) { return Header.extract(Data, OffsetPtr); } - - /// Initialize the table header to explicit values. This is used for DWARF v4 - /// and earlier since there is no header that can be extracted from a section. - void setHeaderData(uint32_t Length, uint16_t Version, uint8_t AddrSize) { - assert(Header.getSegSize() == 0 && - "Unexpected segsize in list table header."); - assert(Header.getOffsetEntryCount() == 0 && - "Unexpected offset entry count in list table header."); - Header.setLength(Length); - Header.setVersion(Version); - Header.setAddrSize(AddrSize); - } - /// Extract an entire table, including all list entries. - Error extract(DWARFDataExtractor Data, uint16_t Version, uint32_t *OffsetPtr); + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); /// Look up a list based on a given offset. Extract it and enter it into the /// list map if necessary. Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset); uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); } uint8_t getAddrSize() const { return Header.getAddrSize(); } - StringRef getListTypeString() const { return Header.getListTypeString(); } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; @@ -228,35 +175,25 @@ public: llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); } - uint16_t getVersion() const { return Header.getVersion(); } - uint32_t getLength() const { return Header.getTableLength(); } + uint32_t length() { return Header.length(); } }; template <typename DWARFListType> Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data, - uint16_t Version, uint32_t *OffsetPtr) { - assert(Version > 0 && "DWARF version required and not given."); clear(); - // For DWARF v4 and earlier, we cannot extract a table header, so we - // initialize it explicitly. - if (Version < 5) - setHeaderData(Data.size(), Version, Data.getAddressSize()); - else if (Error E = extractHeaderAndOffsets(Data, OffsetPtr)) + if (Error E = extractHeaderAndOffsets(Data, OffsetPtr)) return E; Data.setAddressSize(Header.getAddrSize()); - uint32_t End = getHeaderOffset() + getLength(); - // Extract all lists. + uint32_t End = getHeaderOffset() + Header.length(); while (*OffsetPtr < End) { DWARFListType CurrentList; uint32_t Off = *OffsetPtr; - if (Error E = CurrentList.extract( - Data, getHeaderOffset(), End, Header.getVersion(), OffsetPtr, - Header.getSectionName(), Header.getListTypeString(), isDWO)) { - *OffsetPtr = End; + if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr, + Header.getSectionName(), + Header.getListTypeString())) return E; - } ListMap[Off] = CurrentList; } @@ -267,10 +204,11 @@ Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data, } template <typename ListEntryType> -Error DWARFListType<ListEntryType>::extract( - DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, - uint16_t Version, uint32_t *OffsetPtr, StringRef SectionName, - StringRef ListTypeString, bool isDWO) { +Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, + uint32_t HeaderOffset, uint32_t End, + uint32_t *OffsetPtr, + StringRef SectionName, + StringRef ListTypeString) { if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) return createStringError(errc::invalid_argument, "invalid %s list offset 0x%" PRIx32, @@ -278,11 +216,10 @@ Error DWARFListType<ListEntryType>::extract( Entries.clear(); while (*OffsetPtr < End) { ListEntryType Entry; - if (Error E = - Entry.extract(Data, End, Version, SectionName, OffsetPtr, isDWO)) + if (Error E = Entry.extract(Data, End, OffsetPtr)) return E; Entries.push_back(Entry); - if (Entry.isEndOfList()) + if (Entry.isSentinel()) return Error::success(); } return createStringError(errc::illegal_byte_sequence, @@ -291,41 +228,28 @@ Error DWARFListType<ListEntryType>::extract( SectionName.data(), HeaderOffset); } -template <typename ListEntryType> -void DWARFListType<ListEntryType>::dump(raw_ostream &OS, DWARFContext *C, - uint8_t AddressSize, - uint64_t BaseAddress, unsigned Indent, - uint16_t Version, - size_t MaxEncodingStringLength, - DIDumpOptions DumpOpts) const { - uint64_t CurrentBase = BaseAddress; - for (const auto &Entry : Entries) - Entry.dump(OS, C, AddressSize, CurrentBase, Indent, Version, - MaxEncodingStringLength, DumpOpts); -} - template <typename DWARFListType> void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { + Header.dump(OS, DumpOpts); + OS << HeaderString << "\n"; + + // Determine the length of the longest encoding string we have in the table, + // so we can align the output properly. We only need this in verbose mode. size_t MaxEncodingStringLength = 0; - // Don't dump the fake table header we create for DWARF v4 and earlier. - if (Header.getVersion() > 4) { - Header.dump(OS, DumpOpts); - OS << HeaderString << '\n'; - // Determine the length of the longest encoding string we have in the table, - // so we can align the output properly. We only need this in verbose mode. - if (DumpOpts.Verbose) - for (const auto &List : ListMap) - for (const auto &Entry : List.second.getEntries()) - MaxEncodingStringLength = std::max( - MaxEncodingStringLength, EncodingString(Entry.EntryKind).size()); + if (DumpOpts.Verbose) { + for (const auto &List : ListMap) + for (const auto &Entry : List.second.getEntries()) + MaxEncodingStringLength = + std::max(MaxEncodingStringLength, + dwarf::RangeListEncodingString(Entry.EntryKind).size()); } uint64_t CurrentBase = 0; - for (const auto &List : ListMap) { - List.second.dump(OS, C, getAddrSize(), CurrentBase, 0, Header.getVersion(), - MaxEncodingStringLength, DumpOpts); - } + for (const auto &List : ListMap) + for (const auto &Entry : List.second.getEntries()) + Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase, + DumpOpts); } template <typename DWARFListType> @@ -338,11 +262,11 @@ DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data, // Extract the list from the section and enter it into the list map. DWARFListType List; - uint32_t End = getHeaderOffset() + getLength(); + uint32_t End = getHeaderOffset() + Header.length(); uint32_t StartingOffset = Offset; - if (Error E = List.extract(Data, getHeaderOffset(), End, Header.getVersion(), - &Offset, Header.getSectionName(), - Header.getListTypeString(), isDWO)) + if (Error E = + List.extract(Data, getHeaderOffset(), End, &Offset, + Header.getSectionName(), Header.getListTypeString())) return std::move(E); ListMap[StartingOffset] = List; return List; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 2aa19c1a71c..d3be52d8018 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -17,6 +17,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.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" @@ -305,6 +306,12 @@ public: return DataExtractor(StringSection, false, 0); } + /// Extract the range list referenced by this compile unit from the + /// .debug_ranges section. If the extraction is unsuccessful, an error + /// is returned. Successful extraction requires that the compile unit + /// has already been extracted. + Error extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; void clear(); const Optional<StrOffsetsContributionDescriptor> & diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt index 437c845718d..b4770e561f7 100644 --- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -15,6 +15,7 @@ add_llvm_library(LLVMDebugInfoDWARF DWARFDebugLoc.cpp DWARFDebugMacro.cpp DWARFDebugPubTable.cpp + DWARFDebugRangeList.cpp DWARFDebugRnglists.cpp DWARFDie.cpp DWARFExpression.cpp diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index be0192cdeda..a5c31a56fad 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -25,6 +25,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #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" @@ -266,29 +267,24 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, } } -// Dump a section that contains a sequence of tables of lists, such as range -// or location list tables. In DWARF v5 we expect to find properly formatted -// tables with headers. In DWARF v4 and earlier we simply expect a sequence of -// lists, which we treat, mutatis mutandis, like DWARF v5 tables. -template <typename ListTable> -static void dumpListSection(raw_ostream &OS, DWARFContext *C, - StringRef SectionName, uint16_t MaxVersion, - DWARFDataExtractor &ListData, - DIDumpOptions DumpOpts, bool isDWO = false) { +// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). +static void dumpRnglistsSection(raw_ostream &OS, + DWARFDataExtractor &rnglistData, + DIDumpOptions DumpOpts) { uint32_t Offset = 0; - while (ListData.isValidOffset(Offset)) { - ListTable Table(C, SectionName, isDWO); - if (Error Err = Table.extract(ListData, MaxVersion, &Offset)) { + while (rnglistData.isValidOffset(Offset)) { + llvm::DWARFDebugRnglistTable Rnglists; + uint32_t TableOffset = Offset; + if (Error Err = Rnglists.extract(rnglistData, &Offset)) { WithColor::error() << toString(std::move(Err)) << '\n'; - // If table extraction set Offset to 0, it indicates that we cannot - // continue to read the section. - if (Offset == 0) + 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; - // In DWARF v4 and earlier, dump as much of the lists as we can. - if (MaxVersion < 5) - Table.dump(OS, DumpOpts); + Offset = TableOffset + Length; } else { - Table.dump(OS, DumpOpts); + Rnglists.dump(OS, DumpOpts); } } } @@ -488,25 +484,29 @@ void DWARFContext::dump( uint8_t savedAddressByteSize = getCUAddrSize(); DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(), isLittleEndian(), savedAddressByteSize); - dumpListSection<DWARFDebugRnglistTable>( - OS, this, ".debug_ranges", /* MaxVersion = */ 4, rangesData, DumpOpts); + uint32_t offset = 0; + DWARFDebugRangeList rangeList; + while (rangesData.isValidOffset(offset)) { + if (Error E = rangeList.extract(rangesData, &offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + break; + } + rangeList.dump(OS); + } } if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, DObj->getRnglistsSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), - isLittleEndian(), getCUAddrSize()); - dumpListSection<DWARFDebugRnglistTable>( - OS, this, ".debug_rnglists", getMaxVersion(5), RnglistData, DumpOpts); + isLittleEndian(), 0); + dumpRnglistsSection(OS, RnglistData, DumpOpts); } if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, DObj->getRnglistsDWOSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), - isLittleEndian(), getCUAddrSize()); - dumpListSection<DWARFDebugRnglistTable>(OS, this, ".debug_rnglists.dwo", - getMaxVersion(5), RnglistData, - DumpOpts); + isLittleEndian(), 0); + dumpRnglistsSection(OS, RnglistData, DumpOpts); } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp new file mode 100644 index 00000000000..84e3c634f54 --- /dev/null +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -0,0 +1,96 @@ +//===- DWARFDebugRangesList.cpp -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <cinttypes> +#include <cstdint> + +using namespace llvm; + +void DWARFDebugRangeList::clear() { + Offset = -1U; + AddressSize = 0; + Entries.clear(); +} + +Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, + uint32_t *offset_ptr) { + clear(); + if (!data.isValidOffset(*offset_ptr)) + return createStringError(errc::invalid_argument, + "invalid range list offset 0x%" PRIx32, *offset_ptr); + + AddressSize = data.getAddressSize(); + if (AddressSize != 4 && AddressSize != 8) + return createStringError(errc::invalid_argument, + "invalid address size: %" PRIu8, AddressSize); + Offset = *offset_ptr; + while (true) { + RangeListEntry Entry; + Entry.SectionIndex = -1ULL; + + uint32_t prev_offset = *offset_ptr; + Entry.StartAddress = data.getRelocatedAddress(offset_ptr); + Entry.EndAddress = + data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex); + + // Check that both values were extracted correctly. + if (*offset_ptr != prev_offset + 2 * AddressSize) { + clear(); + return createStringError(errc::invalid_argument, + "invalid range list entry at offset 0x%" PRIx32, + prev_offset); + } + if (Entry.isEndOfListEntry()) + break; + Entries.push_back(Entry); + } + return Error::success(); +} + +void DWARFDebugRangeList::dump(raw_ostream &OS) const { + for (const RangeListEntry &RLE : Entries) { + const char *format_str = (AddressSize == 4 + ? "%08x %08" PRIx64 " %08" PRIx64 "\n" + : "%08x %016" PRIx64 " %016" PRIx64 "\n"); + OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress); + } + OS << format("%08x <End of list>\n", Offset); +} + +DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( + llvm::Optional<BaseAddress> BaseAddr) const { + DWARFAddressRangesVector Res; + for (const RangeListEntry &RLE : Entries) { + if (RLE.isBaseAddressSelectionEntry(AddressSize)) { + BaseAddr = {RLE.EndAddress, RLE.SectionIndex}; + continue; + } + + DWARFAddressRange E; + E.LowPC = RLE.StartAddress; + E.HighPC = RLE.EndAddress; + E.SectionIndex = RLE.SectionIndex; + // Base address of a range list entry is determined by the closest preceding + // base address selection entry in the same range list. It defaults to the + // base address of the compilation unit if there is no such entry. + if (BaseAddr) { + E.LowPC += BaseAddr->Address; + E.HighPC += BaseAddr->Address; + if (E.SectionIndex == -1ULL) + E.SectionIndex = BaseAddr->SectionIndex; + } + Res.push_back(E); + } + return Res; +} diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index 0b0133304c3..eeb85edf5b2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -13,30 +13,19 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, - uint16_t Version, StringRef /* SectionName */, - uint32_t *OffsetPtr, bool /* isDWO */) { + uint32_t *OffsetPtr) { Offset = *OffsetPtr; SectionIndex = -1ULL; - - assert((Data.getAddressSize() == 4 || Data.getAddressSize() == 8) && - "Unsupported address size"); - - // We model a DWARF v4 range list entry like DWARF v5 DW_RLE_offset_pair, - // since it is subject to base adjustment. - uint8_t Encoding = dwarf::DW_RLE_offset_pair; - if (Version > 4) { - // The caller should guarantee that we have at least 1 byte available, so - // we just assert instead of revalidate. - assert(*OffsetPtr < End && - "not enough space to extract a rangelist encoding"); - Encoding = Data.getU8(OffsetPtr); - } + // The caller should guarantee that we have at least 1 byte available, so + // we just assert instead of revalidate. + assert(*OffsetPtr < End && + "not enough space to extract a rangelist encoding"); + uint8_t Encoding = Data.getU8(OffsetPtr); switch (Encoding) { case dwarf::DW_RLE_end_of_list: @@ -59,23 +48,6 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, "at offset 0x%" PRIx32, *OffsetPtr - 1); case dwarf::DW_RLE_offset_pair: { - if (Version < 5) { - if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) - return createStringError( - errc::illegal_byte_sequence, - "invalid range list entry at offset 0x%" PRIx32, *OffsetPtr); - Value0 = Data.getRelocatedAddress(OffsetPtr); - Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); - // Adjust the EntryKind for end-of-list and base_address based on the - // contents. - if (Value0 == maxUIntN(Data.getAddressSize() * 8)) { - Encoding = dwarf::DW_RLE_base_address; - Value0 = Value1; - Value1 = 0; - } else if (Value0 == 0 && Value1 == 0) - Encoding = dwarf::DW_RLE_end_of_list; - break; - } uint32_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getULEB128(OffsetPtr); Value1 = Data.getULEB128(OffsetPtr); @@ -86,7 +58,7 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, PreviousOffset); break; } - case dwarf::DW_RLE_base_address: + case dwarf::DW_RLE_base_address: { if ((End - *OffsetPtr) < Data.getAddressSize()) return createStringError(errc::invalid_argument, "insufficient space remaining in table for " @@ -94,16 +66,18 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, *OffsetPtr - 1); Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); break; - case dwarf::DW_RLE_start_end: + } + case dwarf::DW_RLE_start_end: { if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) return createStringError(errc::invalid_argument, "insufficient space remaining in table for " "DW_RLE_start_end encoding " "at offset 0x%" PRIx32, *OffsetPtr - 1); - Value0 = Data.getRelocatedAddress(OffsetPtr); - Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); + Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); + Value1 = Data.getRelocatedAddress(OffsetPtr); break; + } case dwarf::DW_RLE_start_length: { uint32_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); @@ -169,10 +143,9 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( return Res; } -void RangeListEntry::dump(raw_ostream &OS, DWARFContext *, uint8_t AddrSize, - uint64_t &CurrentBase, unsigned Indent, - uint16_t Version, uint8_t MaxEncodingStringLength, - DIDumpOptions DumpOpts) const { +void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, + uint8_t MaxEncodingStringLength, + uint64_t &CurrentBase, DIDumpOptions DumpOpts) const { auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, uint8_t AddrSize, DIDumpOptions DumpOpts) { if (DumpOpts.Verbose) { @@ -183,49 +156,27 @@ void RangeListEntry::dump(raw_ostream &OS, DWARFContext *, uint8_t AddrSize, } }; - // Output indentations before we print the actual entry. We only print - // anything for DW_RLE_base_address when we are in verbose mode. - if (DumpOpts.Verbose || !isBaseAddressSelectionEntry()) - OS.indent(Indent); - if (DumpOpts.Verbose) { // Print the section offset in verbose mode. OS << format("0x%8.8" PRIx32 ":", Offset); - if (Version > 4) { - auto EncodingString = dwarf::RangeListEncodingString(EntryKind); - // Unsupported encodings should have been reported during parsing. - assert(!EncodingString.empty() && "Unknown range entry encoding"); - OS << format(" [%s%*c", EncodingString.data(), - MaxEncodingStringLength - EncodingString.size() + 1, ']'); - if (!isEndOfList()) - OS << ": "; - } + auto EncodingString = dwarf::RangeListEncodingString(EntryKind); + // Unsupported encodings should have been reported during parsing. + assert(!EncodingString.empty() && "Unknown range entry encoding"); + OS << format(" [%s%*c", EncodingString.data(), + MaxEncodingStringLength - EncodingString.size() + 1, ']'); + if (EntryKind != dwarf::DW_RLE_end_of_list) + OS << ": "; } switch (EntryKind) { case dwarf::DW_RLE_end_of_list: - if (DumpOpts.Verbose) { - // For DWARF v4 and earlier, we print the raw entry, i.e. 2 zeros. - if (Version < 5) { - OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); - OS << format(", 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value1); - } - break; - } - OS << "<End of list>"; + OS << (DumpOpts.Verbose ? "" : "<End of list>"); break; case dwarf::DW_RLE_base_address: - // In non-verbose mode, we do not print anything for this entry. + // In non-verbose mode we do not print anything for this entry. CurrentBase = Value0; if (!DumpOpts.Verbose) return; - if (Version < 5) { - // Dump the entry in pre-DWARF v5 format, i.e. with a -1 as Value0. - uint64_t allOnes = maxUIntN(AddrSize * 8); - OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, allOnes); - OS << format(", 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); - break; - } OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); break; case dwarf::DW_RLE_start_length: diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 25457781e8c..35567d0f67a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -15,6 +15,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp index 835f7279e26..462c036d73a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -20,43 +20,30 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, uint32_t *OffsetPtr) { HeaderOffset = *OffsetPtr; // Read and verify the length field. - if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) { - // By setting *OffsetPtr to 0, we indicate to the caller that - // we could not detemine the length of the table. - *OffsetPtr = 0; + if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) return createStringError(errc::invalid_argument, "section is not large enough to contain a " "%s table length at offset 0x%" PRIx32, - SectionName.data(), HeaderOffset); - } + SectionName.data(), *OffsetPtr); // TODO: Add support for DWARF64. HeaderData.Length = Data.getU32(OffsetPtr); - if (HeaderData.Length == 0xffffffffu) { - *OffsetPtr = 0; + if (HeaderData.Length == 0xffffffffu) return createStringError(errc::not_supported, "DWARF64 is not supported in %s at offset 0x%" PRIx32, SectionName.data(), HeaderOffset); - } - - uint32_t TableLength = HeaderData.Length + sizeof(uint32_t); - uint32_t End = HeaderOffset + TableLength; Format = dwarf::DwarfFormat::DWARF32; - if (TableLength < sizeof(Header)) { - *OffsetPtr = End; - return createStringError( - errc::invalid_argument, - "%s table at offset 0x%" PRIx32 " has too small length (0x%" PRIx32 - ") to contain a complete header", - SectionName.data(), HeaderOffset, TableLength); - } - if (!Data.isValidOffsetForDataOfSize(HeaderOffset, TableLength)) { - *OffsetPtr = 0; // No recovery if the length exceeds the section size. - return createStringError( - errc::invalid_argument, - "section is not large enough to contain a %s table " - "of length 0x%" PRIx32 " at offset 0x%" PRIx32, - SectionName.data(), TableLength, HeaderOffset); - } + if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) + return createStringError(errc::invalid_argument, + "%s table at offset 0x%" PRIx32 + " has too small length (0x%" PRIx32 + ") to contain a complete header", + SectionName.data(), HeaderOffset, length()); + uint32_t End = HeaderOffset + length(); + if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) + return createStringError(errc::invalid_argument, + "section is not large enough to contain a %s table " + "of length 0x%" PRIx32 " at offset 0x%" PRIx32, + SectionName.data(), length(), HeaderOffset); HeaderData.Version = Data.getU16(OffsetPtr); HeaderData.AddrSize = Data.getU8(OffsetPtr); @@ -64,36 +51,27 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr); // Perform basic validation of the remaining header fields. - if (HeaderData.Version != 5) { - *OffsetPtr = End; + if (HeaderData.Version != 5) return createStringError(errc::invalid_argument, - "unrecognised %s table version %" PRIu16 - " in table at offset 0x%" PRIx32, - SectionName.data(), HeaderData.Version, - HeaderOffset); - } - if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) { - *OffsetPtr = End; + "unrecognised %s table version %" PRIu16 + " in table at offset 0x%" PRIx32, + SectionName.data(), HeaderData.Version, HeaderOffset); + if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) return createStringError(errc::not_supported, "%s table at offset 0x%" PRIx32 " has unsupported address size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.AddrSize); - } - if (HeaderData.SegSize != 0) { - *OffsetPtr = End; + if (HeaderData.SegSize != 0) return createStringError(errc::not_supported, "%s table at offset 0x%" PRIx32 " has unsupported segment selector size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.SegSize); - } if (End < HeaderOffset + sizeof(HeaderData) + - HeaderData.OffsetEntryCount * sizeof(uint32_t)) { - *OffsetPtr = End; + HeaderData.OffsetEntryCount * sizeof(uint32_t)) return createStringError(errc::invalid_argument, "%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32 ") than there is space for", SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); - } Data.setAddressSize(HeaderData.AddrSize); for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I) Offsets.push_back(Data.getU32(OffsetPtr)); @@ -123,11 +101,9 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { } } -uint32_t DWARFListTableHeader::getTableLength() const { +uint32_t DWARFListTableHeader::length() const { if (HeaderData.Length == 0) return 0; - assert(HeaderData.Version > 0 && - "No DWARF version in header when using getTableLength()"); // TODO: DWARF64 support. - return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t); + return HeaderData.Length + sizeof(uint32_t); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 38dfe67f299..b2bc2c8fa32 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -264,16 +264,13 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, return true; } -// Parse a list table header, including the optional array of offsets +// Parse the rangelist table header, including the optional array of offsets // following it (DWARF v5 and later). -template <typename DWARFListTable> -static Expected<DWARFListTable> -parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C, - StringRef SectionName, uint32_t Offset, bool isDWO) { +static Expected<DWARFDebugRnglistTable> +parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { // TODO: Support DWARF64 // We are expected to be called with Offset 0 or pointing just past the table // header, which is 12 bytes long for DWARF32. - DWARFListTable Table(C, SectionName, isDWO); if (Offset > 0) { if (Offset < 12U) return createStringError(errc::invalid_argument, "Did not detect a valid" @@ -281,46 +278,20 @@ parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C, Offset); Offset -= 12U; } + llvm::DWARFDebugRnglistTable Table; if (Error E = Table.extractHeaderAndOffsets(DA, &Offset)) return std::move(E); return Table; } -// Parse a DWARF v5 list table (e.g. either a rangelist table or a location -// list table). For DWARF units with version 4 or earlier, we instead create -// the table artifically by giving it a size that equals the section size. -template <typename DWARFListTable> -static Optional<DWARFListTable> -setupListTable(DWARFUnit *U, const DWARFSection *Section, StringRef SectionName, - uint32_t &Base, bool isDWO, bool isLittleEndian) { - if (!Section->Data.size()) - return None; - DWARFContext &Ctx = U->getContext(); - DWARFListTable Table(&Ctx, SectionName, isDWO); - // Parse the list table header. Individual lists are extracted lazily. - DWARFDataExtractor DA(Ctx.getDWARFObj(), *Section, isLittleEndian, - U->getAddressByteSize()); - if (U->getVersion() < 5) { - Base = 0; - Table.setHeaderData(Section->Data.size(), U->getVersion(), - DA.getAddressSize()); - return Table; - } - if (auto TableOrError = parseListTableHeader<DWARFListTable>( - DA, &Ctx, SectionName, Base, isDWO)) - Table = TableOrError.get(); - else { - WithColor::error() << "parsing a " << Table.getListTypeString().data() - << " list table: " << toString(TableOrError.takeError()) - << '\n'; - return None; - } - // In a split dwarf unit, there are no attributes like DW_AT_rnglists_base or - // DW_AT_loclists_base that describe the table base. Adjust Base to point past - // the table header which is expected to start at offset 0. - if (isDWO) - Base = Table.getHeaderSize(); - return Table; +Error DWARFUnit::extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const { + // Require that compile unit is extracted. + assert(!DieArray.empty()); + DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, + isLittleEndian, getAddressByteSize()); + uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; + return RangeList.extract(RangesData, &ActualRangeListOffset); } void DWARFUnit::clear() { @@ -440,20 +411,31 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to // describe address ranges. - StringRef RangeSectionName = ".debug_ranges"; if (getVersion() >= 5) { - if (isDWO) { - RangeSectionName = ".debug_rnglists.dwo"; + if (isDWO) setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - } else { - RangeSectionName = ".debug_rnglists"; + else setRangesSection(&Context.getDWARFObj().getRnglistsSection(), toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0)); + if (RangeSection->Data.size()) { + // Parse the range list table header. Individual range lists are + // extracted lazily. + DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, + isLittleEndian, 0); + if (auto TableOrError = + parseRngListTableHeader(RangesDA, RangeSectionBase)) + RngListTable = TableOrError.get(); + else + WithColor::error() << "parsing a range list table: " + << toString(TableOrError.takeError()) + << '\n'; + + // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. + // Adjust RangeSectionBase to point past the table header. + if (isDWO && RngListTable) + RangeSectionBase = RngListTable->getHeaderSize(); } } - RngListTable = setupListTable<DWARFDebugRnglistTable>( - this, RangeSection, RangeSectionName, RangeSectionBase, isDWO, - isLittleEndian); // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for // skeleton CU DIE, so that DWARF users not aware of it are not broken. @@ -495,9 +477,16 @@ bool DWARFUnit::parseDWO() { DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); if (getVersion() >= 5) { DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - DWO->RngListTable = setupListTable<DWARFDebugRnglistTable>( - DWOCU, DWO->RangeSection, ".debug_rnglists.dwo", DWO->RangeSectionBase, - /* isDWO =*/true, isLittleEndian); + DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, + isLittleEndian, 0); + if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase)) + DWO->RngListTable = TableOrError.get(); + else + WithColor::error() << "parsing a range list table: " + << toString(TableOrError.takeError()) + << '\n'; + if (DWO->RngListTable) + DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); @@ -515,6 +504,12 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { Expected<DWARFAddressRangesVector> DWARFUnit::findRnglistFromOffset(uint32_t Offset) { + if (getVersion() <= 4) { + DWARFDebugRangeList RangeList; + if (Error E = extractRangeList(Offset, RangeList)) + return std::move(E); + return RangeList.getAbsoluteRanges(getBaseAddress()); + } if (RngListTable) { DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, isLittleEndian, RngListTable->getAddrSize()); diff --git a/llvm/test/DebugInfo/Generic/cu-ranges.ll b/llvm/test/DebugInfo/Generic/cu-ranges.ll index 5ca6e8a9afd..cb9066fce3a 100644 --- a/llvm/test/DebugInfo/Generic/cu-ranges.ll +++ b/llvm/test/DebugInfo/Generic/cu-ranges.ll @@ -4,18 +4,18 @@ ; Check that we emit ranges for this which has a non-traditional section and a normal section. -; CHECK: .debug_info contents: -; CHECK: DW_TAG_compile_unit -; CHECK-NOT: DW_TAG -; CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x -; CHECK-NEXT: "__TEXT,__foo" -; CHECK-NEXT: ".text") -; CHECK: DW_TAG_subprogram -; CHECK: DW_AT_low_pc -; CHECK: DW_AT_high_pc -; CHECK: DW_TAG_subprogram -; CHECK: DW_AT_low_pc -; CHECK: DW_AT_high_pc +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_ranges +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_low_pc +; CHECK: DW_AT_high_pc +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_low_pc +; CHECK: DW_AT_high_pc + +; CHECK: .debug_ranges contents: +; FIXME: When we get better dumping facilities we'll want to elaborate here. +; CHECK: 00000000 <End of list> ; Function Attrs: nounwind uwtable define i32 @foo(i32 %a) #0 section "__TEXT,__foo" !dbg !4 { diff --git a/llvm/test/DebugInfo/Inputs/gmlt.ll b/llvm/test/DebugInfo/Inputs/gmlt.ll index caff35d7fd8..b6050e2ba6f 100644 --- a/llvm/test/DebugInfo/Inputs/gmlt.ll +++ b/llvm/test/DebugInfo/Inputs/gmlt.ll @@ -83,7 +83,7 @@ ; written in relocation places (dumper needs to be fixed to read the ; relocations rather than interpret that as the end of a range list)) -; CHECK: 0x00000030: 0x0000000000000000, 0x0000000000000000 +; CHECK: 00000000 <End of list> ; Check that we don't emit any pubnames or pubtypes under -gmlt diff --git a/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s b/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s index a0f5ba577df..25ea30d737c 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s @@ -1,6 +1,5 @@ # RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t # RUN: llvm-dwarfdump -v %t 2>%t.err | FileCheck %s -# RUN: llvm-dwarfdump --debug-ranges %t | FileCheck --check-prefix=TERSE %s # RUN: FileCheck %s <%t.err -check-prefix=ERR # CHECK: .debug_info contents: @@ -11,24 +10,6 @@ # CHECK-NEXT: [0x0000000000000003, 0x0000000000000006) ".text" # CHECK-NEXT: [0x0000000000000001, 0x0000000000000002) ".text.foo1") -# CHECK: .debug_ranges contents: -# CHECK-NEXT: 0x00000000: 0x0000000000000000, 0x0000000000000001 => -# CHECK-SAME: [0x0000000000000000, 0x0000000000000001) -# CHECK-NEXT: 0x00000010: 0x0000000000000003, 0x0000000000000006 => -# CHECK-SAME: [0x0000000000000003, 0x0000000000000006) -# CHECK-NEXT: 0x00000020: 0xffffffffffffffff, 0x0000000000000000 -# CHECK-NEXT: 0x00000030: 0x0000000000000001, 0x0000000000000002 => -# CHECK-SAME: [0x0000000000000001, 0x0000000000000002) -# CHECK-NEXT: 0x00000040: 0x0000000000000000, 0x0000000000000000 - -# TERSE: .debug_ranges contents: -# TERSE-NEXT: [0x0000000000000000, 0x0000000000000001) -# TERSE-NEXT: [0x0000000000000003, 0x0000000000000006) -# TERSE-NEXT: [0x0000000000000001, 0x0000000000000002) -# TERSE-NEXT: <End of list> - - - .text .globl foo .type foo,@function diff --git a/llvm/test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s b/llvm/test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s index 4c5f563429c..2bb46707cc8 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s @@ -9,13 +9,10 @@ # CHECK-NEXT: [0x0000000000000000, 0x0000000000000003) ".text.foo2" [5]) # CHECK: .debug_ranges contents: -# CHECK-NEXT: 0x00000000: 0x0000000000000000, 0x0000000000000001 => -# CHECK-SAME: [0x0000000000000000, 0x0000000000000001) -# CHECK-NEXT: 0x00000010: 0x0000000000000000, 0x0000000000000002 => -# CHECK-SAME: [0x0000000000000000, 0x0000000000000002) -# CHECK-NEXT: 0x00000020: 0x0000000000000000, 0x0000000000000003 => -# CHECK-SAME: [0x0000000000000000, 0x0000000000000003) -# CHCKK-NEXT: 0x00000030: 0x0000000000000000, 0x0000000000000000 +# CHECK: 00000000 0000000000000000 0000000000000001 +# CHECK: 00000000 0000000000000000 0000000000000002 +# CHECK: 00000000 0000000000000000 0000000000000003 +# CHECK: 00000000 <End of list> # RUN: llvm-dwarfdump %t | FileCheck %s --check-prefix=BRIEF # BRIEF: DW_TAG_compile_unit diff --git a/llvm/test/DebugInfo/dwarfdump-ranges.test b/llvm/test/DebugInfo/dwarfdump-ranges.test index 6a98af46d76..54417931f93 100644 --- a/llvm/test/DebugInfo/dwarfdump-ranges.test +++ b/llvm/test/DebugInfo/dwarfdump-ranges.test @@ -1,5 +1,4 @@ RUN: llvm-dwarfdump -v %p/Inputs/dwarfdump-test4.elf-x86-64 | FileCheck %s -RUN: llvm-dwarfdump --debug-ranges %p/Inputs/dwarfdump-test4.elf-x86-64 | FileCheck -check-prefix=TERSE %s CHECK: .debug_info contents: CHECK: DW_TAG_compile_unit @@ -16,21 +15,10 @@ CHECK-NEXT: [0x0000000000000637, 0x000000000000063d)) CHECK: .debug_ranges contents: -CHECK-NEXT: 0x00000000: 0x000000000000062c, 0x0000000000000637 => -CHECK-SAME: [0x000000000000062c, 0x0000000000000637) -CHECK-NEXT: 0x00000010: 0x0000000000000637, 0x000000000000063d => -CHECK-SAME: [0x0000000000000637, 0x000000000000063d) -CHECK-NEXT: 0x00000020: 0x0000000000000000, 0x0000000000000000 -CHECK-NEXT: 0x00000030: 0x0000000000000640, 0x000000000000064b => -CHECK-SAME: [0x0000000000000640, 0x000000000000064b) -CHECK-NEXT: 0x00000040: 0x0000000000000637, 0x000000000000063d => -CHECK-SAME: [0x0000000000000637, 0x000000000000063d) -CHECK-NEXT: 0x00000050: 0x0000000000000000, 0x0000000000000000 +CHECK-NEXT: 00000000 000000000000062c 0000000000000637 +CHECK-NEXT: 00000000 0000000000000637 000000000000063d +CHECK-NEXT: 00000000 <End of list> +CHECK-NEXT: 00000030 0000000000000640 000000000000064b +CHECK-NEXT: 00000030 0000000000000637 000000000000063d +CHECK-NEXT: 00000030 <End of list> -TERSE: .debug_ranges contents: -TERSE-NEXT: [0x000000000000062c, 0x0000000000000637) -TERSE-NEXT: [0x0000000000000637, 0x000000000000063d) -TERSE-NEXT: <End of list> -TERSE-NEXT: [0x0000000000000640, 0x000000000000064b) -TERSE-NEXT: [0x0000000000000637, 0x000000000000063d) -TERSE-NEXT: <End of list> diff --git a/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s b/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s index 09c781bf991..cff8f000731 100644 --- a/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s +++ b/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s @@ -64,11 +64,12 @@ b: // DWARF: .debug_ranges contents: -// DWARF-NEXT: 0x00000000: 0xffffffff, 0x00000000 -// DWARF-NEXT: 0x00000008: 0x00000000, 0x00000004 => [0x00000000, 0x00000004) -// DWARF-NEXT: 0x00000010: 0xffffffff, 0x00000000 -// DWARF-NEXT: 0x00000018: 0x00000000, 0x00000004 => [0x00000000, 0x00000004) -// DWARF-NEXT: 0x00000020: 0x00000000, 0x00000000 +// DWARF: 00000000 ffffffff 00000000 +// DWARF: 00000000 00000000 00000004 +// DWARF: 00000000 ffffffff 00000000 +// DWARF: 00000000 00000000 00000004 +// DWARF: 00000000 <End of list> + // Offsets are different in DWARF v5 due to different header layout. diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp index 6411b6fd89b..cc4a1419420 100644 --- a/llvm/tools/dsymutil/DwarfLinker.cpp +++ b/llvm/tools/dsymutil/DwarfLinker.cpp @@ -43,6 +43,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" @@ -1575,7 +1576,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, DWARFContext &OrigDwarf, const DebugMapObject &DMO) const { - DWARFDebugRnglist RangeList; + DWARFDebugRangeList RangeList; const auto &FunctionRanges = Unit.getFunctionRanges(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), @@ -1595,23 +1596,21 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, for (const auto &RangeAttribute : Unit.getRangesAttributes()) { uint32_t Offset = RangeAttribute.get(); RangeAttribute.set(Streamer->getRangesSectionSize()); - if (Error E = RangeList.extract(RangeExtractor, /* HeaderOffset = */0, - RangeExtractor.size(), - Unit.getOrigUnit().getVersion(), &Offset, - ".debug_ranges", "range")) { + if (Error E = RangeList.extract(RangeExtractor, &Offset)) { llvm::consumeError(std::move(E)); reportWarning("invalid range list ignored.", DMO); RangeList.clear(); } const auto &Entries = RangeList.getEntries(); - if (!RangeList.empty()) { - const auto &First = Entries.front(); + if (!Entries.empty()) { + const DWARFDebugRangeList::RangeListEntry &First = Entries.front(); + if (CurrRange == InvalidRange || - First.getStartAddress() + OrigLowPc < CurrRange.start() || - First.getStartAddress() + OrigLowPc >= CurrRange.stop()) { - CurrRange = FunctionRanges.find(First.getStartAddress() + OrigLowPc); + First.StartAddress + OrigLowPc < CurrRange.start() || + First.StartAddress + OrigLowPc >= CurrRange.stop()) { + CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc); if (CurrRange == InvalidRange || - CurrRange.start() > First.getStartAddress() + OrigLowPc) { + CurrRange.start() > First.StartAddress + OrigLowPc) { reportWarning("no mapping for range.", DMO); continue; } diff --git a/llvm/tools/dsymutil/DwarfStreamer.cpp b/llvm/tools/dsymutil/DwarfStreamer.cpp index 0687c5740f2..6a0554bb729 100644 --- a/llvm/tools/dsymutil/DwarfStreamer.cpp +++ b/llvm/tools/dsymutil/DwarfStreamer.cpp @@ -269,27 +269,28 @@ void DwarfStreamer::emitSwiftAST(StringRef Buffer) { void DwarfStreamer::emitRangesEntries( int64_t UnitPcOffset, uint64_t OrigLowPc, const FunctionIntervals::const_iterator &FuncRange, - const DWARFDebugRnglist::ListEntries &Entries, unsigned AddressSize) { + const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries, + unsigned AddressSize) { MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); // Offset each range by the right amount. int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset; for (const auto &Range : Entries) { - if (Range.isBaseAddressSelectionEntry()) { + if (Range.isBaseAddressSelectionEntry(AddressSize)) { warn("unsupported base address selection operation", "emitting debug_ranges"); break; } // Do not emit empty ranges. - if (Range.isEndOfList() || Range.getStartAddress() == Range.getEndAddress()) + if (Range.StartAddress == Range.EndAddress) continue; // All range entries should lie in the function range. - if (!(Range.getStartAddress() + OrigLowPc >= FuncRange.start() && - Range.getEndAddress() + OrigLowPc <= FuncRange.stop())) + if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() && + Range.EndAddress + OrigLowPc <= FuncRange.stop())) warn("inconsistent range data.", "emitting debug_ranges"); - MS->EmitIntValue(Range.getStartAddress() + PcOffset, AddressSize); - MS->EmitIntValue(Range.getEndAddress() + PcOffset, AddressSize); + MS->EmitIntValue(Range.StartAddress + PcOffset, AddressSize); + MS->EmitIntValue(Range.EndAddress + PcOffset, AddressSize); RangesSectionSize += 2 * AddressSize; } diff --git a/llvm/tools/dsymutil/DwarfStreamer.h b/llvm/tools/dsymutil/DwarfStreamer.h index 524950d52b4..679d124f4cb 100644 --- a/llvm/tools/dsymutil/DwarfStreamer.h +++ b/llvm/tools/dsymutil/DwarfStreamer.h @@ -17,7 +17,7 @@ #include "llvm/CodeGen/AccelTable.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" @@ -83,7 +83,7 @@ public: void emitRangesEntries( int64_t UnitPcOffset, uint64_t OrigLowPc, const FunctionIntervals::const_iterator &FuncRange, - const DWARFDebugRnglist::ListEntries &Entries, + const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries, unsigned AddressSize); /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true, |