[DWARF] Support DWARF64 in DWARFListTableHeader.

This enables 64-bit DWARF support for parsing range and location list tables.

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

llvm-svn: 371014
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
index ccd5739..269ea9f 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
@@ -24,25 +24,34 @@
                        "section is not large enough to contain a "
                        "%s table length at offset 0x%" PRIx64,
                        SectionName.data(), *OffsetPtr);
-  // TODO: Add support for DWARF64.
-  HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr);
-  if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64)
-    return createStringError(errc::not_supported,
-                       "DWARF64 is not supported in %s at offset 0x%" PRIx64,
-                       SectionName.data(), HeaderOffset);
   Format = dwarf::DwarfFormat::DWARF32;
-  if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
+  uint8_t OffsetByteSize = 4;
+  HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr);
+  if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) {
+    Format = dwarf::DwarfFormat::DWARF64;
+    OffsetByteSize = 8;
+    HeaderData.Length = Data.getU64(OffsetPtr);
+  } else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) {
+    return createStringError(errc::invalid_argument,
+        "%s table at offset 0x%" PRIx64
+        " has unsupported reserved unit length of value 0x%8.8" PRIx64,
+        SectionName.data(), HeaderOffset, HeaderData.Length);
+  }
+  uint64_t FullLength =
+      HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format);
+  assert(FullLength == length());
+  if (FullLength < getHeaderSize(Format))
     return createStringError(errc::invalid_argument,
                        "%s table at offset 0x%" PRIx64
-                       " has too small length (0x%" PRIx32
+                       " has too small length (0x%" PRIx64
                        ") to contain a complete header",
-                       SectionName.data(), HeaderOffset, length());
-  uint64_t End = HeaderOffset + length();
-  if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
+                       SectionName.data(), HeaderOffset, FullLength);
+  uint64_t End = HeaderOffset + FullLength;
+  if (!Data.isValidOffsetForDataOfSize(HeaderOffset, FullLength))
     return createStringError(errc::invalid_argument,
                        "section is not large enough to contain a %s table "
-                       "of length 0x%" PRIx32 " at offset 0x%" PRIx64,
-                       SectionName.data(), length(), HeaderOffset);
+                       "of length 0x%" PRIx64 " at offset 0x%" PRIx64,
+                       SectionName.data(), FullLength, HeaderOffset);
 
   HeaderData.Version = Data.getU16(OffsetPtr);
   HeaderData.AddrSize = Data.getU8(OffsetPtr);
@@ -65,15 +74,15 @@
                        "%s table at offset 0x%" PRIx64
                        " has unsupported segment selector size %" PRIu8,
                        SectionName.data(), HeaderOffset, HeaderData.SegSize);
-  if (End < HeaderOffset + sizeof(HeaderData) +
-                HeaderData.OffsetEntryCount * sizeof(uint32_t))
+  if (End < HeaderOffset + getHeaderSize(Format) +
+                HeaderData.OffsetEntryCount * OffsetByteSize)
     return createStringError(errc::invalid_argument,
         "%s table at offset 0x%" PRIx64 " 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.getRelocatedValue(4, OffsetPtr));
+    Offsets.push_back(Data.getRelocatedValue(OffsetByteSize, OffsetPtr));
   return Error::success();
 }
 
@@ -81,7 +90,7 @@
   if (DumpOpts.Verbose)
     OS << format("0x%8.8" PRIx64 ": ", HeaderOffset);
   OS << format(
-      "%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", "
+      "%s list header: length = 0x%8.8" PRIx64 ", 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",
@@ -91,18 +100,17 @@
   if (HeaderData.OffsetEntryCount > 0) {
     OS << "offsets: [";
     for (const auto &Off : Offsets) {
-      OS << format("\n0x%8.8" PRIx32, Off);
+      OS << format("\n0x%8.8" PRIx64, Off);
       if (DumpOpts.Verbose)
         OS << format(" => 0x%8.8" PRIx64,
-                     Off + HeaderOffset + sizeof(HeaderData));
+                     Off + HeaderOffset + getHeaderSize(Format));
     }
     OS << "\n]\n";
   }
 }
 
-uint32_t DWARFListTableHeader::length() const {
+uint64_t DWARFListTableHeader::length() const {
   if (HeaderData.Length == 0)
     return 0;
-  // TODO: DWARF64 support.
-  return HeaderData.Length + sizeof(uint32_t);
+  return HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format);
 }