Index: include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -1,86 +0,0 @@ -//===- 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 -#include -#include - -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 Entries; - -public: - DWARFDebugRangeList() { clear(); } - - void clear(); - void dump(raw_ostream &OS) const; - Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr); - const std::vector &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 BaseAddr) const; -}; - -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H Index: include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ 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 #include @@ -21,6 +21,8 @@ namespace llvm { +struct BaseAddress; +class DWARFContext; class Error; class raw_ostream; @@ -33,10 +35,27 @@ uint64_t Value0; uint64_t Value1; - 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; } + 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_startx_length) && + "Unexpected range list entry kind"); + return Value0; + } + uint64_t getEndAddress() const { + assert(EntryKind == dwarf::DW_RLE_start_end && + "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; }; /// A class representing a single rangelist. @@ -44,15 +63,18 @@ public: /// Build a DWARFAddressRangesVector from a rangelist. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional BaseAddr) const; + getAbsoluteRanges(llvm::Optional BaseAddr, + uint16_t Version) const; }; class DWARFDebugRnglistTable : public DWARFListTableBase { public: - DWARFDebugRnglistTable() - : DWARFListTableBase(/* SectionName = */ ".debug_rnglists", + DWARFDebugRnglistTable(DWARFContext *C, StringRef SectionName, + bool isDWO = false) + : DWARFListTableBase(C, SectionName, isDWO, /* HeaderString = */ "ranges:", - /* ListTypeString = */ "range") {} + /* ListTypeString = */ "range", + dwarf::RangeListEncodingString) {} }; } // end namespace llvm Index: include/llvm/DebugInfo/DWARF/DWARFListTable.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -23,6 +23,8 @@ namespace llvm { +class DWARFContext; + /// A base class for DWARF list entries, such as range or location list /// entries. struct DWARFListEntryBase { @@ -37,6 +39,7 @@ /// A base class for lists of entries that are extracted from a particular /// section, such as range lists or location lists. template class DWARFListType { +public: using EntryType = ListEntryType; using ListEntries = std::vector; @@ -45,11 +48,33 @@ public: const ListEntries &getEntries() const { return Entries; } - bool empty() const { return Entries.empty(); } + bool empty() const { + return Entries.empty() || Entries.begin()->isEndOfList(); + } 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, - uint32_t *OffsetPtr, StringRef SectionName, - StringRef ListStringName); + 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; + void addEntry(const ListEntryType &Entry) { Entries.push_back(Entry); } + /// Print a header for the list. Returns the indentation that is to be used + /// when subsequently dumping each list entry. + unsigned printListHeader(raw_ostream &OS, uint8_t AddrSize, + DIDumpOptions DIDumpOpts) const { + return 0; + } }; /// A class representing the header of a list table such as the range list @@ -59,17 +84,19 @@ /// The total length of the entries for this table, not including the length /// field itself. uint32_t Length = 0; - /// The DWARF version number. - uint16_t Version; + /// The DWARF version number. We assume version 5 until we either extract + /// the version from the section or explicitly set it (e.g. to fake a + /// table for DWARF v4 and earlier). + uint16_t Version = 5; /// The size in bytes of an address on the target architecture. For /// segmented addressing, this is the size of the offset portion of the /// address. 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; + uint8_t SegSize = 0; /// The number of offsets that follow the header before the range lists. - uint32_t OffsetEntryCount; + uint32_t OffsetEntryCount = 0; }; Header HeaderData; @@ -78,10 +105,10 @@ /// FIXME: Generate the table and use the appropriate forms. std::vector Offsets; /// The table's format, either DWARF32 or DWARF64. - dwarf::DwarfFormat Format; + dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32; /// The offset at which the header (and hence the table) is located within /// its section. - uint32_t HeaderOffset; + uint32_t HeaderOffset = 0; /// The name of the section the list is located in. StringRef SectionName; /// A characterization of the list for dumping purposes, e.g. "range" or @@ -97,8 +124,19 @@ 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; } @@ -115,7 +153,9 @@ /// 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). + /// 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 length() const; }; @@ -129,14 +169,21 @@ /// 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 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; + /// + std::function EncodingString; protected: - DWARFListTableBase(StringRef SectionName, StringRef HeaderString, - StringRef ListTypeString) - : Header(SectionName, ListTypeString), HeaderString(HeaderString) {} + DWARFListTableBase(DWARFContext *C, StringRef SectionName, bool isDWO, + StringRef HeaderString, StringRef ListTypeString, + std::function EncodingString) + : Header(SectionName, ListTypeString), C(C), isDWO(isDWO), + HeaderString(HeaderString), EncodingString(EncodingString) {} public: void clear() { @@ -147,14 +194,28 @@ 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, uint32_t *OffsetPtr); + Error extract(DWARFDataExtractor Data, uint16_t Version, uint32_t *OffsetPtr); /// Look up a list based on a given offset. Extract it and enter it into the /// list map if necessary. Expected 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; @@ -175,24 +236,32 @@ llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); } - uint32_t length() { return Header.length(); } + uint16_t getVersion() const { return Header.getVersion(); } + uint32_t length() const { return Header.length(); } }; template Error DWARFListTableBase::extract(DWARFDataExtractor Data, + uint16_t Version, uint32_t *OffsetPtr) { + assert(Version > 0 && "DWARF version required and not given."); clear(); - if (Error E = extractHeaderAndOffsets(Data, OffsetPtr)) + // 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)) return E; Data.setAddressSize(Header.getAddrSize()); - uint32_t End = getHeaderOffset() + Header.length(); + uint32_t End = getHeaderOffset() + length(); + // Extract all lists. while (*OffsetPtr < End) { DWARFListType CurrentList; uint32_t Off = *OffsetPtr; - if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr, - Header.getSectionName(), - Header.getListTypeString())) + if (Error E = CurrentList.extract( + Data, getHeaderOffset(), End, Header.getVersion(), OffsetPtr, + Header.getSectionName(), Header.getListTypeString(), isDWO)) return E; ListMap[Off] = CurrentList; } @@ -204,11 +273,10 @@ } template -Error DWARFListType::extract(DWARFDataExtractor Data, - uint32_t HeaderOffset, uint32_t End, - uint32_t *OffsetPtr, - StringRef SectionName, - StringRef ListTypeString) { +Error DWARFListType::extract( + DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, + uint16_t Version, uint32_t *OffsetPtr, StringRef SectionName, + StringRef ListTypeString, bool isDWO) { if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) return createStringError(errc::invalid_argument, "invalid %s list offset 0x%" PRIx32, @@ -216,10 +284,11 @@ Entries.clear(); while (*OffsetPtr < End) { ListEntryType Entry; - if (Error E = Entry.extract(Data, End, OffsetPtr)) + if (Error E = + Entry.extract(Data, End, Version, SectionName, OffsetPtr, isDWO)) return E; Entries.push_back(Entry); - if (Entry.isSentinel()) + if (Entry.isEndOfList()) return Error::success(); } return createStringError(errc::illegal_byte_sequence, @@ -228,28 +297,43 @@ SectionName.data(), HeaderOffset); } +template +void DWARFListType::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 void DWARFListTableBase::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; - if (DumpOpts.Verbose) { - for (const auto &List : ListMap) - for (const auto &Entry : List.second.getEntries()) - MaxEncodingStringLength = - std::max(MaxEncodingStringLength, - dwarf::RangeListEncodingString(Entry.EntryKind).size()); + // 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()); } uint64_t CurrentBase = 0; - for (const auto &List : ListMap) - for (const auto &Entry : List.second.getEntries()) - Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase, - DumpOpts); + for (const auto &List : ListMap) { + auto Indent = List.second.printListHeader(OS, getAddrSize(), DumpOpts); + List.second.dump(OS, C, getAddrSize(), CurrentBase, Indent, + Header.getVersion(), MaxEncodingStringLength, DumpOpts); + } } template @@ -264,9 +348,9 @@ DWARFListType List; uint32_t End = getHeaderOffset() + Header.length(); uint32_t StartingOffset = Offset; - if (Error E = - List.extract(Data, getHeaderOffset(), End, &Offset, - Header.getSectionName(), Header.getListTypeString())) + if (Error E = List.extract(Data, getHeaderOffset(), End, Header.getVersion(), + &Offset, Header.getSectionName(), + Header.getListTypeString(), isDWO)) return std::move(E); ListMap[StartingOffset] = List; return List; Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -17,7 +17,6 @@ #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" @@ -304,12 +303,6 @@ 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 & Index: lib/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- lib/DebugInfo/DWARF/CMakeLists.txt +++ lib/DebugInfo/DWARF/CMakeLists.txt @@ -15,7 +15,6 @@ DWARFDebugLoc.cpp DWARFDebugMacro.cpp DWARFDebugPubTable.cpp - DWARFDebugRangeList.cpp DWARFDebugRnglists.cpp DWARFDie.cpp DWARFExpression.cpp Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -25,7 +25,6 @@ #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" @@ -274,24 +273,32 @@ } } -// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). -static void dumpRnglistsSection(raw_ostream &OS, - DWARFDataExtractor &rnglistData, - DIDumpOptions DumpOpts) { +// 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 +static void dumpListSection(raw_ostream &OS, DWARFContext *C, + StringRef SectionName, uint16_t MaxVersion, + DWARFDataExtractor &ListData, + DIDumpOptions DumpOpts, bool isDWO = false) { uint32_t Offset = 0; - while (rnglistData.isValidOffset(Offset)) { - llvm::DWARFDebugRnglistTable Rnglists; + while (ListData.isValidOffset(Offset)) { + ListTable Table(C, SectionName, isDWO); uint32_t TableOffset = Offset; - if (Error Err = Rnglists.extract(rnglistData, &Offset)) { + if (Error Err = Table.extract(ListData, MaxVersion, &Offset)) { WithColor::error() << toString(std::move(Err)) << '\n'; - uint64_t Length = Rnglists.length(); + uint64_t Length = Table.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; + // In DWARF v4 and earlier, dump as much of the lists as we can. + if (MaxVersion < 5) + Table.dump(OS, DumpOpts); } else { - Rnglists.dump(OS, DumpOpts); + Table.dump(OS, DumpOpts); } } } @@ -326,6 +333,11 @@ return Should; }; + auto maxVersion = [this](uint16_t DefaultVersion) { + uint16_t MaxV = getMaxVersion(); + return MaxV ? MaxV : DefaultVersion; + }; + // Dump individual sections. if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev, DObj->getAbbrevSection())) @@ -490,29 +502,24 @@ uint8_t savedAddressByteSize = getCUAddrSize(); DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(), isLittleEndian(), savedAddressByteSize); - 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); - } + dumpListSection( + OS, this, ".debug_ranges", /* MaxVersion = */ 4, rangesData, DumpOpts); } if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, DObj->getRnglistsSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), - isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, DumpOpts); + isLittleEndian(), getCUAddrSize()); + dumpListSection( + OS, this, ".debug_rnglists", maxVersion(5), RnglistData, DumpOpts); } if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, DObj->getRnglistsDWOSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), - isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, DumpOpts); + isLittleEndian(), getCUAddrSize()); + dumpListSection( + OS, this, ".debug_rnglists.dwo", maxVersion(5), RnglistData, DumpOpts); } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, Index: lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -1,96 +0,0 @@ -//===- 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 -#include - -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 \n", Offset); -} - -DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( - llvm::Optional 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; -} Index: lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -13,19 +13,31 @@ #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, - uint32_t *OffsetPtr) { + uint16_t Version, StringRef /* SectionName */, + uint32_t *OffsetPtr, bool /* isDWO */) { Offset = *OffsetPtr; SectionIndex = -1ULL; - // 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); + + assert((Data.getAddressSize() == 4 || Data.getAddressSize() == 8) && + "Unsupported address size"); + + // In DWARF v4 and earlier, a range list entry corresponds to DWARF v5 + // entry kind DW_RLE_start_end, except that it is possibly subject to + // base adjustment, which is not relevant during extraction. + uint8_t Encoding = dwarf::DW_RLE_start_end; + 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); + } switch (Encoding) { case dwarf::DW_RLE_end_of_list: @@ -68,14 +80,19 @@ break; } case dwarf::DW_RLE_start_end: { - if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) + if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) { + if (Version < 5) + return createStringError( + errc::invalid_argument, + "invalid range list entry at offset 0x%" PRIx32, *OffsetPtr); 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, &SectionIndex); - Value1 = Data.getRelocatedAddress(OffsetPtr); + } + Value0 = Data.getRelocatedAddress(OffsetPtr); + Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); break; } case dwarf::DW_RLE_start_length: { @@ -97,11 +114,23 @@ } EntryKind = Encoding; + // For DWARF v4 and earlier, adjust the EntryKind for end-of-list and + // base_address based on the contents. + if (Version < 5) { + if (Value0 == maxUIntN(Data.getAddressSize() * 8)) { + EntryKind = dwarf::DW_RLE_base_address; + Value0 = Value1; + Value1 = 0; + } else if (Value0 == 0 && Value1 == 0) { + EntryKind = dwarf::DW_RLE_end_of_list; + } + } return Error::success(); } -DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( - llvm::Optional BaseAddr) const { +DWARFAddressRangesVector +DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional BaseAddr, + uint16_t Version) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) @@ -118,6 +147,7 @@ switch (RLE.EntryKind) { case dwarf::DW_RLE_offset_pair: + assert(Version > 4 && "Unexpected RLE entry kind"); E.LowPC = RLE.Value0; E.HighPC = RLE.Value1; if (BaseAddr) { @@ -128,8 +158,15 @@ case dwarf::DW_RLE_start_end: E.LowPC = RLE.Value0; E.HighPC = RLE.Value1; + // In DWARF v4 and earlier, this is the generic range list entry and is + // subject to base adjustment. + if (Version < 5 && BaseAddr) { + E.LowPC += BaseAddr->Address; + E.HighPC += BaseAddr->Address; + } break; case dwarf::DW_RLE_start_length: + assert(Version > 4 && "Unexpected RLE entry kind"); E.LowPC = RLE.Value0; E.HighPC = E.LowPC + RLE.Value1; break; @@ -143,9 +180,10 @@ return Res; } -void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, - uint8_t MaxEncodingStringLength, - uint64_t &CurrentBase, DIDumpOptions DumpOpts) const { +void RangeListEntry::dump(raw_ostream &OS, DWARFContext *, uint8_t AddrSize, + uint64_t &CurrentBase, unsigned Indent, + uint16_t Version, uint8_t MaxEncodingStringLength, + DIDumpOptions DumpOpts) const { auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, uint8_t AddrSize, DIDumpOptions DumpOpts) { if (DumpOpts.Verbose) { @@ -156,6 +194,17 @@ } }; + // Output indentations before we print the actual entry. For DWARF + // v5 and later we only print anything for DW_RLE_base_address when we + // are in verbose mode. + if (Version < 5 || DumpOpts.Verbose || !isBaseAddressSelectionEntry()) + OS.indent(Indent); + // Always print the section offset in DWARF v4 and earlier. + if (Version < 5) { + OS << format("%08x", Offset); + DumpOpts.Verbose = false; + } + if (DumpOpts.Verbose) { // Print the section offset in verbose mode. OS << format("0x%8.8" PRIx32 ":", Offset); @@ -164,17 +213,25 @@ 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) + if (!isEndOfList()) OS << ": "; } switch (EntryKind) { case dwarf::DW_RLE_end_of_list: - OS << (DumpOpts.Verbose ? "" : ""); + OS << (DumpOpts.Verbose ? "" : " "); break; case dwarf::DW_RLE_base_address: - // In non-verbose mode we do not print anything for this entry. + // In DWARF v5, in non-verbose mode, we do not print anything for this + // entry. CurrentBase = Value0; + 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(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, allOnes); + OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); + break; + } if (!DumpOpts.Verbose) return; OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); @@ -189,6 +246,11 @@ .dump(OS, AddrSize, DumpOpts); break; case dwarf::DW_RLE_start_end: + if (Version < 5) { + OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); + OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value1); + break; + } DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); break; default: Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -15,7 +15,6 @@ #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" Index: lib/DebugInfo/DWARF/DWARFListTable.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFListTable.cpp +++ lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -32,7 +32,7 @@ "DWARF64 is not supported in %s at offset 0x%" PRIx32, SectionName.data(), HeaderOffset); Format = dwarf::DwarfFormat::DWARF32; - if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) + if (length() < sizeof(Header)) return createStringError(errc::invalid_argument, "%s table at offset 0x%" PRIx32 " has too small length (0x%" PRIx32 @@ -51,11 +51,17 @@ HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr); // Perform basic validation of the remaining header fields. - if (HeaderData.Version != 5) + if (HeaderData.Version != 5) { + uint16_t ExtractedVersion = HeaderData.Version; + // Set the version field to something valid so we can use length() + // safely. + HeaderData.Version = 5; return createStringError(errc::invalid_argument, - "unrecognised %s table version %" PRIu16 - " in table at offset 0x%" PRIx32, - SectionName.data(), HeaderData.Version, HeaderOffset); + "unrecognised %s table version %" PRIu16 + " in table at offset 0x%" PRIx32, + SectionName.data(), ExtractedVersion, + HeaderOffset); + } if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) return createStringError(errc::not_supported, "%s table at offset 0x%" PRIx32 @@ -104,6 +110,8 @@ uint32_t DWARFListTableHeader::length() const { if (HeaderData.Length == 0) return 0; + assert(HeaderData.Version > 0 && + "No DWARF version in header when using length()"); // TODO: DWARF64 support. - return HeaderData.Length + sizeof(uint32_t); + return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t); } Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -261,13 +261,16 @@ return true; } -// Parse the rangelist table header, including the optional array of offsets +// Parse a list table header, including the optional array of offsets // following it (DWARF v5 and later). -static Expected -parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { +template +static Expected +parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C, + StringRef SectionName, uint32_t Offset, bool isDWO) { // 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" @@ -275,20 +278,46 @@ Offset); Offset -= 12U; } - llvm::DWARFDebugRnglistTable Table; if (Error E = Table.extractHeaderAndOffsets(DA, &Offset)) return std::move(E); 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); +// 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 +static Optional +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( + 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; } void DWARFUnit::clear() { @@ -402,37 +431,26 @@ StringOffsetsTableContribution = determineStringOffsetsTableContributionDWO( DA, StringOffsetsContributionBase); - else if (getVersion() >= 5) + else if (getVersion() > 4) StringOffsetsTableContribution = determineStringOffsetsTableContribution( DA, StringOffsetsContributionBase); // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to // describe address ranges. - if (getVersion() >= 5) { - if (isDWO) + StringRef RangeSectionName = ".debug_ranges"; + if (getVersion() > 4) { + if (isDWO) { + RangeSectionName = ".debug_rnglists.dwo"; setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - else + } else { + RangeSectionName = ".debug_rnglists"; 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( + 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. @@ -472,18 +490,11 @@ DWO = std::shared_ptr(std::move(DWOContext), DWOCU); // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); - if (getVersion() >= 5) { + if (getVersion() > 4) { DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - 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(); + DWO->RngListTable = setupListTable( + DWOCU, DWO->RangeSection, ".debug_rnglists.dwo", DWO->RangeSectionBase, + /* isDWO =*/true, isLittleEndian); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); @@ -501,18 +512,13 @@ Expected 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()); auto RangeListOrError = RngListTable->findList(RangesData, Offset); if (RangeListOrError) - return RangeListOrError.get().getAbsoluteRanges(getBaseAddress()); + return RangeListOrError.get().getAbsoluteRanges( + getBaseAddress(), RngListTable->getVersion()); return RangeListOrError.takeError(); } Index: test/DebugInfo/Generic/cu-ranges.ll =================================================================== --- test/DebugInfo/Generic/cu-ranges.ll +++ test/DebugInfo/Generic/cu-ranges.ll @@ -15,7 +15,7 @@ ; CHECK: .debug_ranges contents: ; FIXME: When we get better dumping facilities we'll want to elaborate here. -; CHECK: 00000000 +; CHECK: 00000020 ; Function Attrs: nounwind uwtable define i32 @foo(i32 %a) #0 section "__TEXT,__foo" !dbg !4 { Index: test/DebugInfo/Inputs/gmlt.ll =================================================================== --- test/DebugInfo/Inputs/gmlt.ll +++ 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: 00000000 +; CHECK: 00000030 ; Check that we don't emit any pubnames or pubtypes under -gmlt Index: test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s =================================================================== --- test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s +++ test/DebugInfo/X86/dwarfdump-ranges-unrelocated.s @@ -10,9 +10,9 @@ # CHECK: .debug_ranges contents: # CHECK: 00000000 0000000000000000 0000000000000001 -# CHECK: 00000000 0000000000000000 0000000000000002 -# CHECK: 00000000 0000000000000000 0000000000000003 -# CHECK: 00000000 +# CHECK: 00000010 0000000000000000 0000000000000002 +# CHECK: 00000020 0000000000000000 0000000000000003 +# CHECK: 00000030 # RUN: llvm-dwarfdump %t | FileCheck %s --check-prefix=BRIEF # BRIEF: DW_TAG_compile_unit Index: test/DebugInfo/dwarfdump-ranges.test =================================================================== --- test/DebugInfo/dwarfdump-ranges.test +++ test/DebugInfo/dwarfdump-ranges.test @@ -16,9 +16,9 @@ CHECK: .debug_ranges contents: CHECK-NEXT: 00000000 000000000000062c 0000000000000637 -CHECK-NEXT: 00000000 0000000000000637 000000000000063d -CHECK-NEXT: 00000000 +CHECK-NEXT: 00000010 0000000000000637 000000000000063d +CHECK-NEXT: 00000020 CHECK-NEXT: 00000030 0000000000000640 000000000000064b -CHECK-NEXT: 00000030 0000000000000637 000000000000063d -CHECK-NEXT: 00000030 +CHECK-NEXT: 00000040 0000000000000637 000000000000063d +CHECK-NEXT: 00000050 Index: test/MC/ARM/dwarf-asm-multiple-sections.s =================================================================== --- test/MC/ARM/dwarf-asm-multiple-sections.s +++ test/MC/ARM/dwarf-asm-multiple-sections.s @@ -65,10 +65,10 @@ // DWARF: .debug_ranges contents: // DWARF: 00000000 ffffffff 00000000 -// DWARF: 00000000 00000000 00000004 -// DWARF: 00000000 ffffffff 00000000 -// DWARF: 00000000 00000000 00000004 -// DWARF: 00000000 +// DWARF: 00000008 00000000 00000004 +// DWARF: 00000010 ffffffff 00000000 +// DWARF: 00000018 00000000 00000004 +// DWARF: 00000020 Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -43,7 +43,6 @@ #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" @@ -1568,7 +1567,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, DWARFContext &OrigDwarf, const DebugMapObject &DMO) const { - DWARFDebugRangeList RangeList; + DWARFDebugRnglist RangeList; const auto &FunctionRanges = Unit.getFunctionRanges(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), @@ -1588,21 +1587,23 @@ for (const auto &RangeAttribute : Unit.getRangesAttributes()) { uint32_t Offset = RangeAttribute.get(); RangeAttribute.set(Streamer->getRangesSectionSize()); - if (Error E = RangeList.extract(RangeExtractor, &Offset)) { + if (Error E = RangeList.extract(RangeExtractor, /* HeaderOffset = */0, + RangeExtractor.size(), + Unit.getOrigUnit().getVersion(), &Offset, + ".debug_ranges", "range")) { llvm::consumeError(std::move(E)); reportWarning("invalid range list ignored.", DMO); RangeList.clear(); } const auto &Entries = RangeList.getEntries(); - if (!Entries.empty()) { - const DWARFDebugRangeList::RangeListEntry &First = Entries.front(); - + if (!RangeList.empty()) { + const auto &First = Entries.front(); if (CurrRange == InvalidRange || - First.StartAddress + OrigLowPc < CurrRange.start() || - First.StartAddress + OrigLowPc >= CurrRange.stop()) { - CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc); + First.getStartAddress() + OrigLowPc < CurrRange.start() || + First.getStartAddress() + OrigLowPc >= CurrRange.stop()) { + CurrRange = FunctionRanges.find(First.getStartAddress() + OrigLowPc); if (CurrRange == InvalidRange || - CurrRange.start() > First.StartAddress + OrigLowPc) { + CurrRange.start() > First.getStartAddress() + OrigLowPc) { reportWarning("no mapping for range.", DMO); continue; } Index: tools/dsymutil/DwarfStreamer.h =================================================================== --- tools/dsymutil/DwarfStreamer.h +++ tools/dsymutil/DwarfStreamer.h @@ -14,7 +14,7 @@ #include "llvm/CodeGen/AccelTable.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" @@ -83,7 +83,7 @@ void emitRangesEntries( int64_t UnitPcOffset, uint64_t OrigLowPc, const FunctionIntervals::const_iterator &FuncRange, - const std::vector &Entries, + const DWARFDebugRnglist::ListEntries &Entries, unsigned AddressSize); /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true, Index: tools/dsymutil/DwarfStreamer.cpp =================================================================== --- tools/dsymutil/DwarfStreamer.cpp +++ tools/dsymutil/DwarfStreamer.cpp @@ -269,28 +269,27 @@ void DwarfStreamer::emitRangesEntries( int64_t UnitPcOffset, uint64_t OrigLowPc, const FunctionIntervals::const_iterator &FuncRange, - const std::vector &Entries, - unsigned AddressSize) { + const DWARFDebugRnglist::ListEntries &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(AddressSize)) { + if (Range.isBaseAddressSelectionEntry()) { warn("unsupported base address selection operation", "emitting debug_ranges"); break; } // Do not emit empty ranges. - if (Range.StartAddress == Range.EndAddress) + if (Range.isEndOfList() || Range.getStartAddress() == Range.getEndAddress()) continue; // All range entries should lie in the function range. - if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() && - Range.EndAddress + OrigLowPc <= FuncRange.stop())) + if (!(Range.getStartAddress() + OrigLowPc >= FuncRange.start() && + Range.getEndAddress() + OrigLowPc <= FuncRange.stop())) warn("inconsistent range data.", "emitting debug_ranges"); - MS->EmitIntValue(Range.StartAddress + PcOffset, AddressSize); - MS->EmitIntValue(Range.EndAddress + PcOffset, AddressSize); + MS->EmitIntValue(Range.getStartAddress() + PcOffset, AddressSize); + MS->EmitIntValue(Range.getEndAddress() + PcOffset, AddressSize); RangesSectionSize += 2 * AddressSize; }