diff options
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 56 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp | 96 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp | 97 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp | 72 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 99 | 
7 files changed, 201 insertions, 221 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt index b4770e561f7..437c845718d 100644 --- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -15,7 +15,6 @@ 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 a5c31a56fad..be0192cdeda 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/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" @@ -267,24 +266,29 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,    }  } -// 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 <typename ListTable> +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; -    uint32_t TableOffset = Offset; -    if (Error Err = Rnglists.extract(rnglistData, &Offset)) { +  while (ListData.isValidOffset(Offset)) { +    ListTable Table(C, SectionName, isDWO); +    if (Error Err = Table.extract(ListData, MaxVersion, &Offset)) {        WithColor::error() << toString(std::move(Err)) << '\n'; -      uint64_t Length = Rnglists.length(); -      // Keep going after an error, if we can, assuming that the length field -      // could be read. If it couldn't, stop reading the section. -      if (Length == 0) +      // If table extraction set Offset to 0, it indicates that we cannot +      // continue to read the section. +      if (Offset == 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);      }    }  } @@ -484,29 +488,25 @@ void DWARFContext::dump(      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<DWARFDebugRnglistTable>( +        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<DWARFDebugRnglistTable>( +        OS, this, ".debug_rnglists", getMaxVersion(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<DWARFDebugRnglistTable>(OS, this, ".debug_rnglists.dwo", +                                            getMaxVersion(5), 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 deleted file mode 100644 index 84e3c634f54..00000000000 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ /dev/null @@ -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 <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 eeb85edf5b2..0b0133304c3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -13,19 +13,30 @@  #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"); + +  // 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); +  }    switch (Encoding) {    case dwarf::DW_RLE_end_of_list: @@ -48,6 +59,23 @@ 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); @@ -58,7 +86,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 " @@ -66,18 +94,16 @@ 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, &SectionIndex); -    Value1 = Data.getRelocatedAddress(OffsetPtr); +    Value0 = Data.getRelocatedAddress(OffsetPtr); +    Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);      break; -  }    case dwarf::DW_RLE_start_length: {      uint32_t PreviousOffset = *OffsetPtr - 1;      Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); @@ -143,9 +169,10 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(    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,27 +183,49 @@ void RangeListEntry::dump(raw_ostream &OS, 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); -    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 << ": "; +    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 << ": "; +    }    }    switch (EntryKind) {    case dwarf::DW_RLE_end_of_list: -    OS << (DumpOpts.Verbose ? "" : "<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>";      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 35567d0f67a..25457781e8c 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/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" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp index 462c036d73a..835f7279e26 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -20,30 +20,43 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,                                      uint32_t *OffsetPtr) {    HeaderOffset = *OffsetPtr;    // Read and verify the length field. -  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) +  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;      return createStringError(errc::invalid_argument,                         "section is not large enough to contain a "                         "%s table length at offset 0x%" PRIx32, -                       SectionName.data(), *OffsetPtr); +                       SectionName.data(), HeaderOffset); +  }    // TODO: Add support for DWARF64.    HeaderData.Length = Data.getU32(OffsetPtr); -  if (HeaderData.Length == 0xffffffffu) +  if (HeaderData.Length == 0xffffffffu) { +    *OffsetPtr = 0;      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 (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); +  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); +  }    HeaderData.Version = Data.getU16(OffsetPtr);    HeaderData.AddrSize = Data.getU8(OffsetPtr); @@ -51,27 +64,36 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,    HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);    // Perform basic validation of the remaining header fields. -  if (HeaderData.Version != 5) +  if (HeaderData.Version != 5) { +    *OffsetPtr = End;      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) +                             "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;      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) +  } +  if (HeaderData.SegSize != 0) { +    *OffsetPtr = End;      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)) +                HeaderData.OffsetEntryCount * sizeof(uint32_t)) { +    *OffsetPtr = End;      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)); @@ -101,9 +123,11 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {    }  } -uint32_t DWARFListTableHeader::length() const { +uint32_t DWARFListTableHeader::getTableLength() 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 + sizeof(uint32_t); +  return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t);  } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index b2bc2c8fa32..38dfe67f299 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -264,13 +264,16 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,    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<DWARFDebugRnglistTable> -parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { +template <typename DWARFListTable> +static Expected<DWARFListTable> +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" @@ -278,20 +281,46 @@ parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {                                 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 <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;  }  void DWARFUnit::clear() { @@ -411,31 +440,20 @@ 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) +      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<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. @@ -477,16 +495,9 @@ bool DWARFUnit::parseDWO() {    DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);    if (getVersion() >= 5) {      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<DWARFDebugRnglistTable>( +        DWOCU, DWO->RangeSection, ".debug_rnglists.dwo", DWO->RangeSectionBase, +        /* isDWO =*/true, isLittleEndian);    } else {      auto DWORangesBase = UnitDie.getRangesBaseAttribute();      DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); @@ -504,12 +515,6 @@ 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());  | 

