[llvm] r329345 - [DWARF v5][NFC]: Refactor DebugRnglists to prepare for the support of the DW_AT_ranges

Wolfgang Pieb via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 5 14:01:49 PDT 2018


Author: wolfgangp
Date: Thu Apr  5 14:01:49 2018
New Revision: 329345

URL: http://llvm.org/viewvc/llvm-project?rev=329345&view=rev
Log:
[DWARF v5][NFC]: Refactor DebugRnglists to prepare for the support of the DW_AT_ranges
 attribute in conjunction with .debug_rnglists.

Reviewers: JDevlieghere
 
Differential Revision: https://reviews.llvm.org/D45307

Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h?rev=329345&r1=329344&r2=329345&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h Thu Apr  5 14:01:49 2018
@@ -14,6 +14,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include <cstdint>
+#include <map>
 #include <vector>
 
 namespace llvm {
@@ -21,8 +22,43 @@ namespace llvm {
 class Error;
 class raw_ostream;
 
-class DWARFDebugRnglists {
+/// 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 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;
+
+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);
+};
+
+/// 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 {
+public:
   struct Header {
     /// The total length of the entries for this table, not including the length
     /// field itself.
@@ -40,32 +76,17 @@ private:
     uint32_t OffsetEntryCount;
   };
 
-public:
-  struct RangeListEntry {
-    /// The offset at which the entry is located in the section.
-    const uint32_t Offset;
-    /// The DWARF encoding (DW_RLE_*).
-    const uint8_t EntryKind;
-    /// 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.
-    const uint64_t Value0;
-    const uint64_t Value1;
-  };
-
-  using DWARFRangeList = std::vector<RangeListEntry>;
-
 private:
   uint32_t HeaderOffset;
   Header HeaderData;
   std::vector<uint32_t> Offsets;
-  std::vector<DWARFRangeList> Ranges;
-  // The length of the longest encoding string we encountered during parsing.
-  uint8_t MaxEncodingStringLength = 0;
+  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);
   uint32_t getHeaderOffset() const { return HeaderOffset; }
   void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const;

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=329345&r1=329344&r2=329345&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Thu Apr  5 14:01:49 2018
@@ -499,7 +499,7 @@ void DWARFContext::dump(
                                    isLittleEndian(), 0);
     uint32_t Offset = 0;
     while (rnglistData.isValidOffset(Offset)) {
-      DWARFDebugRnglists Rnglists;
+      DWARFDebugRnglistTable Rnglists;
       uint32_t TableOffset = Offset;
       if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
         errs() << "error: " + toString(std::move(Err)) << '\n';

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp?rev=329345&r1=329344&r2=329345&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp Thu Apr  5 14:01:49 2018
@@ -16,7 +16,7 @@
 
 using namespace llvm;
 
-void DWARFDebugRnglists::clear() {
+void DWARFDebugRnglistTable::clear() {
   HeaderData = {};
   Offsets.clear();
   Ranges.clear();
@@ -30,11 +30,9 @@ static Error createError(char const *Fmt
   return make_error<StringError>(Stream.str(), inconvertibleErrorCode());
 }
 
-Error DWARFDebugRnglists::extract(DWARFDataExtractor Data,
-                                  uint32_t *OffsetPtr) {
-  clear();
+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 "
@@ -82,113 +80,132 @@ Error DWARFDebugRnglists::extract(DWARFD
                        " 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();
+}
 
-  DWARFRangeList CurrentRanges;
-  while (*OffsetPtr < End) {
-    uint32_t EntryOffset = *OffsetPtr;
-    uint8_t Encoding = Data.getU8(OffsetPtr);
-    MaxEncodingStringLength =
-        std::max(MaxEncodingStringLength,
-                 (uint8_t)dwarf::RangeListEncodingString(Encoding).size());
-    switch (Encoding) {
-    case dwarf::DW_RLE_end_of_list:
-      CurrentRanges.push_back(RangeListEntry{ EntryOffset, Encoding, 0, 0 });
-      Ranges.insert(Ranges.end(), std::move(CurrentRanges));
-      CurrentRanges.clear();
-      break;
-    // TODO: Support other encodings.
-    case dwarf::DW_RLE_base_addressx:
-      return createError("unsupported rnglists encoding DW_RLE_base_addressx "
-                         "at offset 0x%" PRIx32,
-                         *OffsetPtr - 1);
-    case dwarf::DW_RLE_startx_endx:
-      return createError("unsupported rnglists encoding DW_RLE_startx_endx at "
-                         "offset 0x%" PRIx32,
+Error DWARFDebugRnglist::RangeListEntry::extract(DWARFDataExtractor Data,
+                                                 uint32_t End,
+                                                 uint32_t *OffsetPtr) {
+  Offset = *OffsetPtr;
+  // The caller should guarantee that we have at least 1 byte available, so
+  // we just assert instead of revalidate.
+  assert(*OffsetPtr < End &&
+         "not enough space to extract a rangelist encoding");
+  uint8_t Encoding = Data.getU8(OffsetPtr);
+
+  switch (Encoding) {
+  case dwarf::DW_RLE_end_of_list:
+    Value0 = Value1 = 0;
+    break;
+  // TODO: Support other encodings.
+  case dwarf::DW_RLE_base_addressx:
+    return createError("unsupported rnglists encoding DW_RLE_base_addressx "
+                       "at offset 0x%" PRIx32,
+                       *OffsetPtr - 1);
+  case dwarf::DW_RLE_startx_endx:
+    return createError("unsupported rnglists encoding DW_RLE_startx_endx at "
+                       "offset 0x%" PRIx32,
+                       *OffsetPtr - 1);
+  case dwarf::DW_RLE_startx_length:
+    return createError("unsupported rnglists encoding DW_RLE_startx_length "
+                       "at offset 0x%" PRIx32,
+                       *OffsetPtr - 1);
+  case dwarf::DW_RLE_offset_pair: {
+    uint32_t PreviousOffset = *OffsetPtr - 1;
+    Value0 = Data.getULEB128(OffsetPtr);
+    Value1 = Data.getULEB128(OffsetPtr);
+    if (End < *OffsetPtr)
+      return createError("read past end of table when reading "
+                         "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
+                         PreviousOffset);
+    break;
+  }
+  case dwarf::DW_RLE_base_address: {
+    if ((End - *OffsetPtr) < Data.getAddressSize())
+      return createError("insufficient space remaining in table for "
+                         "DW_RLE_base_address encoding at offset 0x%" PRIx32,
                          *OffsetPtr - 1);
-    case dwarf::DW_RLE_startx_length:
-      return createError("unsupported rnglists encoding DW_RLE_startx_length "
+    Value0 = Data.getAddress(OffsetPtr);
+    break;
+  }
+  case dwarf::DW_RLE_start_end: {
+    if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
+      return createError("insufficient space remaining in table for "
+                         "DW_RLE_start_end encoding "
                          "at offset 0x%" PRIx32,
                          *OffsetPtr - 1);
-    case dwarf::DW_RLE_offset_pair: {
-      uint32_t PreviousOffset = *OffsetPtr - 1;
-      uint64_t StartingOffset = Data.getULEB128(OffsetPtr);
-      uint64_t EndingOffset = Data.getULEB128(OffsetPtr);
-      if (End < *OffsetPtr)
-        return createError("read past end of table when reading "
-                           "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
-                           PreviousOffset);
-      CurrentRanges.push_back(
-          RangeListEntry{EntryOffset, Encoding, StartingOffset, EndingOffset});
-      break;
-    }
-    case dwarf::DW_RLE_base_address: {
-      if ((End - *OffsetPtr) < HeaderData.AddrSize)
-        return createError("insufficient space remaining in table for "
-                           "DW_RLE_base_address encoding at offset 0x%" PRIx32,
-                           *OffsetPtr - 1);
-      uint64_t Base = Data.getAddress(OffsetPtr);
-      CurrentRanges.push_back(RangeListEntry{EntryOffset, Encoding, Base, 0});
-      break;
-    }
-    case dwarf::DW_RLE_start_end: {
-      if ((End - *OffsetPtr) < unsigned(HeaderData.AddrSize * 2))
-        return createError("insufficient space remaining in table for "
-                           "DW_RLE_start_end encoding "
-                           "at offset 0x%" PRIx32,
-                           *OffsetPtr - 1);
-      uint64_t Start = Data.getAddress(OffsetPtr);
-      uint64_t End = Data.getAddress(OffsetPtr);
-      CurrentRanges.push_back(
-          RangeListEntry{EntryOffset, Encoding, Start, End});
-      break;
-    }
-    case dwarf::DW_RLE_start_length: {
-      uint32_t PreviousOffset = *OffsetPtr - 1;
-      uint64_t Start = Data.getAddress(OffsetPtr);
-      uint64_t Length = Data.getULEB128(OffsetPtr);
-      if (End < *OffsetPtr)
-        return createError("read past end of table when reading "
-                           "DW_RLE_start_length encoding at offset 0x%" PRIx32,
-                           PreviousOffset);
-      CurrentRanges.push_back(
-          RangeListEntry{EntryOffset, Encoding, Start, Length});
-      break;
-    }
-    default:
-      Ranges.insert(Ranges.end(), std::move(CurrentRanges));
-      return createError("unknown rnglists encoding 0x%" PRIx32
-                         " at offset 0x%" PRIx32,
-                         uint32_t(Encoding), *OffsetPtr - 1);
-    }
+    Value0 = Data.getAddress(OffsetPtr);
+    Value1 = Data.getAddress(OffsetPtr);
+    break;
+  }
+  case dwarf::DW_RLE_start_length: {
+    uint32_t PreviousOffset = *OffsetPtr - 1;
+    Value0 = Data.getAddress(OffsetPtr);
+    Value1 = Data.getULEB128(OffsetPtr);
+    if (End < *OffsetPtr)
+      return createError("read past end of table when reading "
+                         "DW_RLE_start_length encoding at offset 0x%" PRIx32,
+                         PreviousOffset);
+    break;
+  }
+  default:
+    return createError("unknown rnglists encoding 0x%" PRIx32
+                       " at offset 0x%" PRIx32,
+                       uint32_t(Encoding), *OffsetPtr - 1);
   }
 
-  // If OffsetPtr does not indicate the End offset, then either the above loop
-  // terminated prematurely, or we encountered a malformed encoding, but did not
-  // report an error when we should have done.
-  assert(*OffsetPtr == End &&
-         "did not detect malformed data or loop ended unexpectedly");
+  EntryKind = Encoding;
+  return Error::success();
+}
 
-  // If CurrentRanges is not empty, we have a malformed section, because we did
-  // not find a DW_RLE_end_of_list marker at the end of the last list.
-  if (!CurrentRanges.empty())
-    return createError(
-        "no end of list marker detected at end of .debug_rnglists table "
-        "starting at offset 0x%" PRIx32,
-        HeaderOffset);
+Error DWARFDebugRnglist::extract(DWARFDataExtractor Data, uint32_t HeaderOffset,
+                                 uint32_t End, uint32_t *OffsetPtr) {
+  Entries.clear();
+  while (*OffsetPtr < End) {
+    RangeListEntry Entry{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,
-                           DWARFDebugRnglists::RangeListEntry Entry,
+                           DWARFDebugRnglist::RangeListEntry Entry,
                            uint8_t AddrSize, uint8_t MaxEncodingStringLength,
                            uint64_t &CurrentBase, DIDumpOptions DumpOpts) {
   auto PrintRawEntry = [](raw_ostream &OS,
-                          DWARFDebugRnglists::RangeListEntry Entry,
+                          DWARFDebugRnglist::RangeListEntry Entry,
                           uint8_t AddrSize, DIDumpOptions DumpOpts) {
     if (DumpOpts.Verbose) {
       DumpOpts.DisplayRawContents = true;
@@ -240,7 +257,8 @@ static void dumpRangeEntry(raw_ostream &
   OS << "\n";
 }
 
-void DWARFDebugRnglists::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
+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
@@ -263,14 +281,25 @@ void DWARFDebugRnglists::dump(raw_ostrea
   }
   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)
+    for (const auto &Entry : List.second.getEntries())
       dumpRangeEntry(OS, Entry, HeaderData.AddrSize, MaxEncodingStringLength,
                      CurrentBase, DumpOpts);
 }
 
-uint32_t DWARFDebugRnglists::length() const {
+uint32_t DWARFDebugRnglistTable::length() const {
   if (HeaderData.Length == 0)
     return 0;
   // TODO: DWARF64 support.




More information about the llvm-commits mailing list