]> granicus.if.org Git - llvm/commitdiff
[DWARF v5] Refactor range lists dumping by using a more generic way of handling table...
authorWolfgang Pieb <Wolfgang.Pieb@sony.com>
Mon, 23 Jul 2018 22:37:17 +0000 (22:37 +0000)
committerWolfgang Pieb <Wolfgang.Pieb@sony.com>
Mon, 23 Jul 2018 22:37:17 +0000 (22:37 +0000)
The intent is to use it for location list tables as well. Change is almost NFC with the exception
of the spelling of some strings used during dumping (all lowercase now).

Reviewer: JDevlieghere

Differential Revision: https://reviews.llvm.org/D49500

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337763 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
include/llvm/DebugInfo/DWARF/DWARFListTable.h [new file with mode: 0644]
lib/DebugInfo/DWARF/CMakeLists.txt
lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
lib/DebugInfo/DWARF/DWARFListTable.cpp [new file with mode: 0644]
lib/DebugInfo/DWARF/DWARFUnit.cpp
test/DebugInfo/X86/fission-ranges.ll
test/tools/llvm-dwarfdump/X86/debug_rnglists.s
test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s

index 5dd1cca3ce4074a6bb9060a1efe2214aa309b357..e2e8ab5ed2193bb50d1c43511b26cee861888524 100644 (file)
@@ -14,6 +14,7 @@
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
 #include <cstdint>
 #include <map>
 #include <vector>
@@ -23,108 +24,35 @@ namespace llvm {
 class Error;
 class raw_ostream;
 
-/// A class representing a single rangelist.
-class DWARFDebugRnglist {
-public:
-  struct RangeListEntry {
-    /// The offset at which the entry is located in the section.
-    uint32_t Offset;
-    /// The DWARF encoding (DW_RLE_*).
-    uint8_t EntryKind;
-    /// The index of the section this range belongs to.
-    uint64_t SectionIndex;
-    /// The values making up the range list entry. Most represent a range with
-    /// a start and end address or a start address and a length. Others are
-    /// single value base addresses or end-of-list with no values. The unneeded
-    /// values are semantically undefined, but initialized to 0.
-    uint64_t Value0;
-    uint64_t Value1;
-
-    Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
-  };
-
-  using RngListEntries = std::vector<RangeListEntry>;
-
-private:
-  RngListEntries Entries;
+/// A class representing a single range list entry.
+struct RangeListEntry : public DWARFListEntryBase {
+  /// The values making up the range list entry. Most represent a range with
+  /// a start and end address or a start address and a length. Others are
+  /// single value base addresses or end-of-list with no values. The unneeded
+  /// values are semantically undefined, but initialized to 0.
+  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; }
+};
 
+/// A class representing a single rangelist.
+class DWARFDebugRnglist : public DWARFListType<RangeListEntry> {
 public:
-  const RngListEntries &getEntries() const { return Entries; }
-  bool empty() const { return Entries.empty(); }
-  void clear() { Entries.clear(); }
-  Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
-                uint32_t *OffsetPtr);
   /// Build a DWARFAddressRangesVector from a rangelist.
   DWARFAddressRangesVector
   getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
 };
 
-/// A class representing a table of range lists as specified in DWARF v5.
-/// The table consists of a header followed by an array of offsets into the
-/// .debug_rnglists section, followed by one or more rangelists. The rangelists
-/// are kept in a map where the keys are the lists' section offsets.
-class DWARFDebugRnglistTable {
+class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> {
 public:
-  struct Header {
-    /// 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 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;
-    /// The number of offsets that follow the header before the range lists.
-    uint32_t OffsetEntryCount;
-  };
-
-private:
-  dwarf::DwarfFormat Format;
-  uint32_t HeaderOffset;
-  Header HeaderData;
-  std::vector<uint32_t> Offsets;
-  std::map<uint32_t, DWARFDebugRnglist> Ranges;
-
-public:
-  void clear();
-  /// Extract the table header and the array of offsets.
-  Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr);
-  /// Extract an entire table, including all rangelists.
-  Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
-  /// Look up a rangelist based on a given offset. Extract it and enter it into
-  /// the ranges map if necessary.
-  Expected<DWARFDebugRnglist> findRangeList(DWARFDataExtractor Data,
-                                            uint32_t Offset);
-  uint32_t getHeaderOffset() const { return HeaderOffset; }
-  uint8_t getAddrSize() const { return HeaderData.AddrSize; }
-  void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const;
-  /// Return the contents of the offset entry designated by a given index.
-  Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
-    if (Index < Offsets.size())
-      return Offsets[Index];
-    return None;
-  }
-  /// Return the size of the table header including the length but not including
-  /// the offsets. This is dependent on the table format, which is unambiguously
-  /// derived from parsing the table.
-  uint8_t getHeaderSize() const {
-    switch (Format) {
-    case dwarf::DwarfFormat::DWARF32:
-      return 12;
-    case dwarf::DwarfFormat::DWARF64:
-      return 20;
-    }
-    llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
-  }
-
-  /// Returns the length of this 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).
-  uint32_t length() const;
+  DWARFDebugRnglistTable()
+      : DWARFListTableBase(/* SectionName    = */ ".debug_rnglists",
+                           /* HeaderString   = */ "ranges:",
+                           /* ListTypeString = */ "range") {}
 };
 
 } // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/include/llvm/DebugInfo/DWARF/DWARFListTable.h
new file mode 100644 (file)
index 0000000..ab12f3b
--- /dev/null
@@ -0,0 +1,278 @@
+//===- DWARFListTable.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_DWARFLISTTABLE_H
+#define LLVM_DEBUGINFO_DWARFLISTTABLE_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+/// A base class for DWARF list entries, such as range or location list
+/// entries.
+struct DWARFListEntryBase {
+  /// The offset at which the entry is located in the section.
+  uint32_t Offset;
+  /// The DWARF encoding (DW_RLE_* or DW_LLE_*).
+  uint8_t EntryKind;
+  /// The index of the section this entry belongs to.
+  uint64_t SectionIndex;
+};
+
+/// 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 {
+  using EntryType = ListEntryType;
+  using ListEntries = std::vector<EntryType>;
+
+protected:
+  ListEntries Entries;
+
+public:
+  // FIXME: We need to consolidate the various verions of "createError"
+  // that are used in the DWARF consumer. Until then, this is a workaround.
+  Error createError(const char *, const char *, uint32_t);
+
+  const ListEntries &getEntries() const { return Entries; }
+  bool empty() const { return Entries.empty(); }
+  void clear() { Entries.clear(); }
+  Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
+                uint32_t *OffsetPtr, StringRef SectionName,
+                StringRef ListStringName);
+};
+
+/// A class representing the header of a list table such as the range list
+/// table in the .debug_rnglists section.
+class DWARFListTableHeader {
+  struct Header {
+    /// 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 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;
+    /// The number of offsets that follow the header before the range lists.
+    uint32_t OffsetEntryCount;
+  };
+
+  Header HeaderData;
+  /// The offset table, which contains offsets to the individual list entries.
+  /// It is used by forms such as DW_FORM_rnglistx.
+  /// 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;
+  /// The offset at which the header (and hence the table) is located within
+  /// its section.
+  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
+  /// "location".
+  StringRef ListTypeString;
+
+public:
+  DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString)
+      : SectionName(SectionName), ListTypeString(ListTypeString) {}
+
+  void clear() {
+    HeaderData = {};
+    Offsets.clear();
+  }
+  uint32_t getHeaderOffset() const { return HeaderOffset; }
+  uint8_t getAddrSize() const { return HeaderData.AddrSize; }
+  uint32_t getLength() const { return HeaderData.Length; }
+  StringRef getSectionName() const { return SectionName; }
+  StringRef getListTypeString() const { return ListTypeString; }
+  dwarf::DwarfFormat getFormat() const { return Format; }
+
+  void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+  Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
+    if (Index < Offsets.size())
+      return Offsets[Index];
+    return None;
+  }
+
+  /// Extract the table header and the array of offsets.
+  Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+
+  /// 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).
+  uint32_t length() const;
+};
+
+/// A class representing a table of lists as specified in the DWARF v5
+/// standard for location lists and range lists. The table consists of a header
+/// followed by an array of offsets into a DWARF section, followed by zero or
+/// more list entries. The list entries are kept in a map where the keys are
+/// the lists' section offsets.
+template <typename DWARFListType> class DWARFListTableBase {
+  DWARFListTableHeader Header;
+  /// 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;
+  /// This string is displayed as a heading before the list is dumped
+  /// (e.g. "ranges:").
+  StringRef HeaderString;
+
+protected:
+  DWARFListTableBase(StringRef SectionName, StringRef HeaderString,
+                     StringRef ListTypeString)
+      : Header(SectionName, ListTypeString), HeaderString(HeaderString) {}
+
+public:
+  void clear() {
+    Header.clear();
+    ListMap.clear();
+  }
+  /// Extract the table header and the array of offsets.
+  Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
+    return Header.extract(Data, OffsetPtr);
+  }
+  /// Extract an entire table, including all list entries.
+  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(); }
+
+  void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
+
+  /// Return the contents of the offset entry designated by a given index.
+  Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
+    return Header.getOffsetEntry(Index);
+  }
+  /// Return the size of the table header including the length but not including
+  /// the offsets. This is dependent on the table format, which is unambiguously
+  /// derived from parsing the table.
+  uint8_t getHeaderSize() const {
+    switch (Header.getFormat()) {
+    case dwarf::DwarfFormat::DWARF32:
+      return 12;
+    case dwarf::DwarfFormat::DWARF64:
+      return 20;
+    }
+    llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
+  }
+
+  uint32_t length() { return Header.length(); }
+};
+
+template <typename DWARFListType>
+Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
+                                                 uint32_t *OffsetPtr) {
+  clear();
+  if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
+    return E;
+
+  Data.setAddressSize(Header.getAddrSize());
+  uint32_t End = getHeaderOffset() + Header.length();
+  while (*OffsetPtr < End) {
+    DWARFListType CurrentList;
+    uint32_t Off = *OffsetPtr;
+    if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
+                                      Header.getSectionName(),
+                                      Header.getListTypeString()))
+      return E;
+    ListMap[Off] = CurrentList;
+  }
+
+  assert(*OffsetPtr == End &&
+         "mismatch between expected length of table and length "
+         "of extracted data");
+  return Error::success();
+}
+
+template <typename ListEntryType>
+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 createError("invalid %s list offset 0x%" PRIx32,
+                       ListTypeString.data(), *OffsetPtr);
+  Entries.clear();
+  while (*OffsetPtr < End) {
+    ListEntryType Entry;
+    if (Error E = Entry.extract(Data, End, OffsetPtr))
+      return E;
+    Entries.push_back(Entry);
+    if (Entry.isSentinel())
+      return Error::success();
+  }
+  return createError("no end of list marker detected at end of %s table "
+                     "starting at offset 0x%" PRIx32,
+                     SectionName.data(), HeaderOffset);
+}
+
+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;
+  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)
+    for (const auto &Entry : List.second.getEntries())
+      Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
+                 DumpOpts);
+}
+
+template <typename DWARFListType>
+Expected<DWARFListType>
+DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
+                                            uint32_t Offset) {
+  auto Entry = ListMap.find(Offset);
+  if (Entry != ListMap.end())
+    return Entry->second;
+
+  // Extract the list from the section and enter it into the list map.
+  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()))
+    return std::move(E);
+  ListMap[StartingOffset] = List;
+  return List;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H
index 8dd4edcb800900ff015d4a40a17ce21aae8a95eb..d88a02721700853762768b4044a6434585a0c43f 100644 (file)
@@ -20,6 +20,7 @@ add_llvm_library(LLVMDebugInfoDWARF
   DWARFExpression.cpp
   DWARFFormValue.cpp
   DWARFGdbIndex.cpp
+  DWARFListTable.cpp
   DWARFTypeUnit.cpp
   DWARFUnitIndex.cpp
   DWARFUnit.cpp
index 533b0922c1d126bc6e75505e2963034c4956fe23..fac075ba5369f3f8b8076c17bf5a035228a5a66a 100644 (file)
 
 using namespace llvm;
 
-void DWARFDebugRnglistTable::clear() {
-  HeaderData = {};
-  Offsets.clear();
-  Ranges.clear();
-}
-
 template <typename... Ts>
 static Error createError(char const *Fmt, const Ts &... Vals) {
   std::string Buffer;
@@ -30,66 +24,14 @@ static Error createError(char const *Fmt, const Ts &... Vals) {
   return make_error<StringError>(Stream.str(), inconvertibleErrorCode());
 }
 
-Error DWARFDebugRnglistTable::extractHeaderAndOffsets(DWARFDataExtractor Data,
-                                                      uint32_t *OffsetPtr) {
-  HeaderOffset = *OffsetPtr;
-  // Read and verify the length field.
-  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
-    return createError("section is not large enough to contain a "
-                       ".debug_rnglists table length at offset 0x%" PRIx32,
-                       *OffsetPtr);
-  // TODO: Add support for DWARF64.
-  HeaderData.Length = Data.getU32(OffsetPtr);
-  if (HeaderData.Length == 0xffffffffu)
-    return createError(
-        "DWARF64 is not supported in .debug_rnglists at offset 0x%" PRIx32,
-        HeaderOffset);
-  Format = dwarf::DwarfFormat::DWARF32;
-  if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
-    return createError(".debug_rnglists table at offset 0x%" PRIx32
-                       " has too small length (0x%" PRIx32
-                       ") to contain a complete header",
-                       HeaderOffset, length());
-  uint32_t End = HeaderOffset + length();
-  if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
-    return createError(
-        "section is not large enough to contain a .debug_rnglists table "
-        "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
-        length(), HeaderOffset);
-
-  HeaderData.Version = Data.getU16(OffsetPtr);
-  HeaderData.AddrSize = Data.getU8(OffsetPtr);
-  HeaderData.SegSize = Data.getU8(OffsetPtr);
-  HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);
-
-  // Perform basic validation of the remaining header fields.
-  if (HeaderData.Version != 5)
-    return createError("unrecognised .debug_rnglists table version %" PRIu16
-                       " in table at offset 0x%" PRIx32,
-                       HeaderData.Version, HeaderOffset);
-  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
-    return createError(".debug_rnglists table at offset 0x%" PRIx32
-                       " has unsupported address size %hhu",
-                       HeaderOffset, HeaderData.AddrSize);
-  if (HeaderData.SegSize != 0)
-    return createError(".debug_rnglists table at offset 0x%" PRIx32
-                       " has unsupported segment selector size %" PRIu8,
-                       HeaderOffset, HeaderData.SegSize);
-  if (End < HeaderOffset + sizeof(HeaderData) +
-                HeaderData.OffsetEntryCount * sizeof(uint32_t))
-    return createError(".debug_rnglists table at offset 0x%" PRIx32
-                       " has more offset entries (%" PRIu32
-                       ") than there is space for",
-                       HeaderOffset, HeaderData.OffsetEntryCount);
-  Data.setAddressSize(HeaderData.AddrSize);
-  for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
-    Offsets.push_back(Data.getU32(OffsetPtr));
-  return Error::success();
+template <>
+Error DWARFListType<RangeListEntry>::createError(const char *Fmt, const char *s,
+                                                 uint32_t Val) {
+  return ::createError(Fmt, s, Val);
 }
 
-Error DWARFDebugRnglist::RangeListEntry::extract(DWARFDataExtractor Data,
-                                                 uint32_t End,
-                                                 uint32_t *OffsetPtr) {
+Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
+                              uint32_t *OffsetPtr) {
   Offset = *OffsetPtr;
   SectionIndex = -1ULL;
   // The caller should guarantee that we have at least 1 byte available, so
@@ -206,53 +148,10 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
   return Res;
 }
 
-Error DWARFDebugRnglist::extract(DWARFDataExtractor Data, uint32_t HeaderOffset,
-                                 uint32_t End, uint32_t *OffsetPtr) {
-  if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
-    return createError("invalid range list offset 0x%" PRIx32, *OffsetPtr);
-  Entries.clear();
-  while (*OffsetPtr < End) {
-    RangeListEntry Entry{0, 0, 0, 0, 0};
-    if (Error E = Entry.extract(Data, End, OffsetPtr))
-      return E;
-    Entries.push_back(Entry);
-    if (Entry.EntryKind == dwarf::DW_RLE_end_of_list)
-      return Error::success();
-  }
-  return createError(
-      "no end of list marker detected at end of .debug_rnglists table "
-      "starting at offset 0x%" PRIx32,
-      HeaderOffset);
-}
-
-Error DWARFDebugRnglistTable::extract(DWARFDataExtractor Data,
-                                      uint32_t *OffsetPtr) {
-  clear();
-  if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
-    return E;
-
-  Data.setAddressSize(HeaderData.AddrSize);
-  uint32_t End = HeaderOffset + length();
-  while (*OffsetPtr < End) {
-    DWARFDebugRnglist CurrentRangeList;
-    uint32_t Off = *OffsetPtr;
-    if (Error E = CurrentRangeList.extract(Data, HeaderOffset, End, OffsetPtr))
-      return E;
-    Ranges[Off] = CurrentRangeList;
-  }
-
-  assert(*OffsetPtr == End &&
-         "mismatch between expected length of .debug_rnglists table and length "
-         "of extracted data");
-  return Error::success();
-}
-
-static void dumpRangeEntry(raw_ostream &OS,
-                           DWARFDebugRnglist::RangeListEntry Entry,
-                           uint8_t AddrSize, uint8_t MaxEncodingStringLength,
-                           uint64_t &CurrentBase, DIDumpOptions DumpOpts) {
-  auto PrintRawEntry = [](raw_ostream &OS,
-                          DWARFDebugRnglist::RangeListEntry Entry,
+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) {
       DumpOpts.DisplayRawContents = true;
@@ -264,108 +163,41 @@ static void dumpRangeEntry(raw_ostream &OS,
 
   if (DumpOpts.Verbose) {
     // Print the section offset in verbose mode.
-    OS << format("0x%8.8" PRIx32 ":", Entry.Offset);
-    auto EncodingString = dwarf::RangeListEncodingString(Entry.EntryKind);
+    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 (Entry.EntryKind != dwarf::DW_RLE_end_of_list)
+    if (EntryKind != dwarf::DW_RLE_end_of_list)
       OS << ": ";
   }
 
-  switch (Entry.EntryKind) {
+  switch (EntryKind) {
   case dwarf::DW_RLE_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.
-    CurrentBase = Entry.Value0;
+    CurrentBase = Value0;
     if (!DumpOpts.Verbose)
       return;
-    OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Entry.Value0);
+    OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
     break;
   case dwarf::DW_RLE_start_length:
-    PrintRawEntry(OS, Entry, AddrSize, DumpOpts);
-    DWARFAddressRange(Entry.Value0, Entry.Value0 + Entry.Value1)
-        .dump(OS, AddrSize, DumpOpts);
+    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
+    DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
     break;
   case dwarf::DW_RLE_offset_pair:
-    PrintRawEntry(OS, Entry, AddrSize, DumpOpts);
-    DWARFAddressRange(Entry.Value0 + CurrentBase, Entry.Value1 + CurrentBase)
+    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
+    DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
         .dump(OS, AddrSize, DumpOpts);
     break;
   case dwarf::DW_RLE_start_end:
-    DWARFAddressRange(Entry.Value0, Entry.Value1).dump(OS, AddrSize, DumpOpts);
+    DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
     break;
   default:
     llvm_unreachable("Unsupported range list encoding");
   }
   OS << "\n";
 }
-
-void DWARFDebugRnglistTable::dump(raw_ostream &OS,
-                                  DIDumpOptions DumpOpts) const {
-  if (DumpOpts.Verbose)
-    OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
-  OS << format("Range List Header: length = 0x%8.8" PRIx32
-               ", version = 0x%4.4" PRIx16 ", "
-               "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8
-               ", offset_entry_count = "
-               "0x%8.8" PRIx32 "\n",
-               HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
-               HeaderData.SegSize, HeaderData.OffsetEntryCount);
-
-  if (HeaderData.OffsetEntryCount > 0) {
-    OS << "Offsets: [";
-    for (const auto &Off : Offsets) {
-      OS << format("\n0x%8.8" PRIx32, Off);
-      if (DumpOpts.Verbose)
-        OS << format(" => 0x%8.8" PRIx32,
-                     Off + HeaderOffset + sizeof(HeaderData));
-    }
-    OS << "\n]\n";
-  }
-  OS << "Ranges:\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 : Ranges)
-      for (const auto &Entry : List.second.getEntries())
-        MaxEncodingStringLength =
-            std::max(MaxEncodingStringLength,
-                     dwarf::RangeListEncodingString(Entry.EntryKind).size());
-  }
-
-  uint64_t CurrentBase = 0;
-  for (const auto &List : Ranges)
-    for (const auto &Entry : List.second.getEntries())
-      dumpRangeEntry(OS, Entry, HeaderData.AddrSize, MaxEncodingStringLength,
-                     CurrentBase, DumpOpts);
-}
-
-uint32_t DWARFDebugRnglistTable::length() const {
-  if (HeaderData.Length == 0)
-    return 0;
-  // TODO: DWARF64 support.
-  return HeaderData.Length + sizeof(uint32_t);
-}
-
-Expected<DWARFDebugRnglist>
-DWARFDebugRnglistTable::findRangeList(DWARFDataExtractor Data,
-                                      uint32_t Offset) {
-  auto Entry = Ranges.find(Offset);
-  if (Entry != Ranges.end())
-    return Entry->second;
-
-  // Extract the rangelist from the section and enter it into the ranges map.
-  DWARFDebugRnglist RngList;
-  uint32_t End = HeaderOffset + length();
-  uint32_t StartingOffset = Offset;
-  if (Error E = RngList.extract(Data, HeaderOffset, End, &Offset))
-    return std::move(E);
-  Ranges[StartingOffset] = RngList;
-  return RngList;
-}
diff --git a/lib/DebugInfo/DWARF/DWARFListTable.cpp b/lib/DebugInfo/DWARF/DWARFListTable.cpp
new file mode 100644 (file)
index 0000000..559afc7
--- /dev/null
@@ -0,0 +1,109 @@
+//===- DWARFListTable.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/DWARFListTable.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+template <typename... Ts>
+static Error createError(char const *Fmt, const Ts &... Vals) {
+  std::string Buffer;
+  raw_string_ostream Stream(Buffer);
+  Stream << format(Fmt, Vals...);
+  return make_error<StringError>(Stream.str(), inconvertibleErrorCode());
+}
+
+Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
+                                    uint32_t *OffsetPtr) {
+  HeaderOffset = *OffsetPtr;
+  // Read and verify the length field.
+  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
+    return createError("section is not large enough to contain a "
+                       "%s table length at offset 0x%" PRIx32,
+                       SectionName.data(), *OffsetPtr);
+  // TODO: Add support for DWARF64.
+  HeaderData.Length = Data.getU32(OffsetPtr);
+  if (HeaderData.Length == 0xffffffffu)
+    return createError("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))
+    return createError("%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 createError("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);
+  HeaderData.SegSize = Data.getU8(OffsetPtr);
+  HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);
+
+  // Perform basic validation of the remaining header fields.
+  if (HeaderData.Version != 5)
+    return createError("unrecognised %s table version %" PRIu16
+                       " in table at offset 0x%" PRIx32,
+                       SectionName.data(), HeaderData.Version, HeaderOffset);
+  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
+    return createError("%s table at offset 0x%" PRIx32
+                       " has unsupported address size %hhu",
+                       SectionName.data(), HeaderOffset, HeaderData.AddrSize);
+  if (HeaderData.SegSize != 0)
+    return createError("%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))
+    return createError(
+        "%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));
+  return Error::success();
+}
+
+void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
+  if (DumpOpts.Verbose)
+    OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
+  OS << format(
+      "%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", "
+      "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8
+      ", offset_entry_count = "
+      "0x%8.8" PRIx32 "\n",
+      ListTypeString.data(), HeaderData.Length, HeaderData.Version,
+      HeaderData.AddrSize, HeaderData.SegSize, HeaderData.OffsetEntryCount);
+
+  if (HeaderData.OffsetEntryCount > 0) {
+    OS << "offsets: [";
+    for (const auto &Off : Offsets) {
+      OS << format("\n0x%8.8" PRIx32, Off);
+      if (DumpOpts.Verbose)
+        OS << format(" => 0x%8.8" PRIx32,
+                     Off + HeaderOffset + sizeof(HeaderData));
+    }
+    OS << "\n]\n";
+  }
+}
+
+uint32_t DWARFListTableHeader::length() const {
+  if (HeaderData.Length == 0)
+    return 0;
+  // TODO: DWARF64 support.
+  return HeaderData.Length + sizeof(uint32_t);
+}
index 2e965e0b94d55786d6812276a4fbc074ebc4a1ae..51d086597efffcc9462f159555291d346702d8ce 100644 (file)
@@ -408,7 +408,7 @@ DWARFUnit::findRnglistFromOffset(uint32_t Offset) {
   if (RngListTable) {
     DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
                                   isLittleEndian, RngListTable->getAddrSize());
-    auto RangeListOrError = RngListTable->findRangeList(RangesData, Offset);
+    auto RangeListOrError = RngListTable->findList(RangesData, Offset);
     if (RangeListOrError)
       return RangeListOrError.get().getAbsoluteRanges(getBaseAddress());
     return RangeListOrError.takeError();
index 29ed97ffa5578074f4018b3a07b6c7360e2a8095..51234c336ed9d59025379f8b14642954f5ae02b9 100644 (file)
@@ -55,9 +55,9 @@
 ; V5RNGLISTS-NOT:  DW_TAG
 ; V5RNGLISTS:      DW_AT_rnglists_base [DW_FORM_sec_offset]  (0x0000000c)
 ; V5RNGLISTS:      .debug_rnglists contents:
-; V5RNGLISTS-NEXT: 0x00000000: Range List Header: length = 0x00000014, version = 0x0005,
+; V5RNGLISTS-NEXT: 0x00000000: range list header: length = 0x00000014, version = 0x0005,
 ; V5RNGLISTS-SAME: addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
-; V5RNGLISTS-NEXT: Ranges:
+; V5RNGLISTS-NEXT: ranges:
 ; V5RNGLISTS-NEXT: 0x0000000c: [DW_RLE_offset_pair]:
 ; V5RNGLISTS-NEXT: 0x0000000f: [DW_RLE_offset_pair]:
 ; V5RNGLISTS:      0x{{[0-9a-f]+}}: [DW_RLE_end_of_list]
index b65d8bba0c5f5028ed23c1d7837e9860b3ef6823..8f718b699f55e4d0c860a3b8278913b5bbb4b2ff 100644 (file)
@@ -4,12 +4,12 @@
 # RUN: llvm-dwarfdump -v --debug-rnglists %t.o 2> %t.err | FileCheck %s --check-prefixes=VERBOSE,BOTH
 
 # BOTH:         .debug_rnglists contents:
-# TERSE-NEXT:     Range List Header: length = 0x00000037, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# TERSE-NEXT:     range list header: length = 0x00000037, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
 # VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
-# VERBOSE-SAME: Range List Header: length = 0x00000037, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# VERBOSE-SAME: range list header: length = 0x00000037, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
-# BOTH-NEXT:    Ranges:
+# BOTH-NEXT:    ranges:
 # TERSE-NEXT:   [0x0000000000000010, 0x0000000000000020)
 # TERSE-NEXT:   [0x0000000000000025, 0x00000000000000a5)
 # TERSE-NEXT:   <End of list>
 # VERBOSE-NEXT: 0x00000029: [DW_RLE_start_end   ]: [0x0000000000000100, 0x0000000000000200)
 # VERBOSE-NEXT: 0x0000003a: [DW_RLE_end_of_list ]
 
-# TERSE-NEXT:   Range List Header: length = 0x0000002b, version = 0x0005, addr_size = 0x04, seg_size = 0x00, offset_entry_count = 0x00000002
+# TERSE-NEXT:   range list header: length = 0x0000002b, version = 0x0005, addr_size = 0x04, seg_size = 0x00, offset_entry_count = 0x00000002
 
 # VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
-# VERBOSE-SAME: Range List Header: length = 0x0000002b, version = 0x0005, addr_size = 0x04, seg_size = 0x00, offset_entry_count = 0x00000002
+# VERBOSE-SAME: range list header: length = 0x0000002b, version = 0x0005, addr_size = 0x04, seg_size = 0x00, offset_entry_count = 0x00000002
 
-# BOTH-NEXT:    Offsets: [
+# BOTH-NEXT:    offsets: [
 # BOTH-NEXT:      0x00000008
 # VERBOSE-SAME:   => 0x0000004f
 # BOTH-NEXT:      0x0000001b
 # VERBOSE-SAME:   => 0x00000062
 # BOTH-NEXT:    ]
-# BOTH-NEXT:    Ranges:
+# BOTH-NEXT:    ranges:
 
 # TERSE-NEXT:   [0x00000000, 0x00000000)
 # TERSE-NEXT:   [0x00000002, 0x00000006)
 # VERBOSE-NEXT: 0x00000062: [DW_RLE_start_length]:  0x00000036, 0x00000100 => [0x00000036, 0x00000136)
 # VERBOSE-NEXT: 0x00000069: [DW_RLE_end_of_list ]
 
-# TERSE-NEXT:   Range List Header: length = 0x00000008, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# TERSE-NEXT:   range list header: length = 0x00000008, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
 # VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
-# VERBOSE-SAME: Range List Header: length = 0x00000008, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# VERBOSE-SAME: range list header: length = 0x00000008, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
-# BOTH-NOT:     Offsets:
-# BOTH:         Ranges:
+# BOTH-NOT:     offsets:
+# BOTH:         ranges:
 # BOTH-NOT:     [
 
-# TERSE-NEXT:   Range List Header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# TERSE-NEXT:   range list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
 # VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
-# VERBOSE-SAME: Range List Header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# VERBOSE-SAME: range list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
-# BOTH-NEXT:    Ranges:
+# BOTH-NEXT:    ranges:
 # TERSE-NEXT:   [0x0000000000000800, 0x0000000000001000)
 # TERSE-NEXT:   <End of list>
 
 # VERBOSE-SAME:                                   [0x0000000000000800, 0x0000000000001000)
 # VERBOSE-NEXT: 0x000000b6: [DW_RLE_end_of_list]
 
-# TERSE-NEXT:   Range List Header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# TERSE-NEXT:   range list header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
 # VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
-# VERBOSE-SAME: Range List Header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# VERBOSE-SAME: range list header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 
-# BOTH-NEXT:    Ranges:
+# BOTH-NEXT:    ranges:
 # TERSE-NEXT:   [0x0000000000001800, 0x0000000000002000)
 # TERSE-NEXT:   <End of list>
 
@@ -84,7 +84,7 @@
 # VERBOSE-SAME:                                    [0x0000000000001800, 0x0000000000002000)
 # VERBOSE-NEXT: 0x000000d1: [DW_RLE_end_of_list ]
 
-# BOTH-NOT:     Range List Header:
+# BOTH-NOT:     range list header:
 
 # ERR-NOT:  error:
 # ERR:      error: unsupported rnglists encoding DW_RLE_base_addressx at offset 0x82
index d67f546e8d0c51330747baa382bcd174360eec8e..48890c433aa57b180b216c8139adbdf884972f25 100644 (file)
@@ -1,9 +1,9 @@
 # RUN: llvm-mc %S/Inputs/debug_rnglists_short_section.s -filetype obj -triple x86_64-pc-linux -o - | \
 # RUN: llvm-dwarfdump --debug-rnglists - 2>&1 | FileCheck %s --check-prefix=SHORT
 # SHORT-NOT: error:
-# SHORT-NOT: Range List Header
+# SHORT-NOT: range list header
 # SHORT: error: section is not large enough to contain a .debug_rnglists table length at offset 0
-# SHORT-NOT: Range List Header
+# SHORT-NOT: range list header
 # SHORT-NOT: error:
 
 # RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o - | \
 # RUN: FileCheck %s --input-file %t.err
 
 # GOOD: .debug_rnglists contents:
-# GOOD-NEXT: Range List Header: length = 0x0000001e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000001
-# GOOD-NEXT: Offsets: [
+# GOOD-NEXT: range list header: length = 0x0000001e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000001
+# GOOD-NEXT: offsets: [
 # GOOD-NEXT:    0x00000004
 # GOOD-NEXT: ]
-# GOOD-NEXT: Ranges:
+# GOOD-NEXT: ranges:
 # GOOD-NEXT: [0x0000000000000010, 0x0000000000000020)
 # GOOD-NEXT: <End of list>
-# GOOD-NEXT: Range List Header: length = 0x0000001a, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
-# GOOD-NEXT: Ranges:
+# GOOD-NEXT: range list header: length = 0x0000001a, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+# GOOD-NEXT: ranges:
 # GOOD-NEXT: [0x0000000000000030, 0x0000000000000040)
 # GOOD-NEXT: <End of list>
-# GOOD-NOT:  Range List Header
+# GOOD-NOT:  range list header
 
 # CHECK-NOT: error:
 # CHECK: error: .debug_rnglists table at offset 0x22 has too small length (0xb) to contain a complete header