[llvm] r371016 - [DWARF] Fix referencing Range List Tables from CUs for DWARF64.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 5 00:02:29 PDT 2019


Author: ikudrin
Date: Thu Sep  5 00:02:28 2019
New Revision: 371016

URL: http://llvm.org/viewvc/llvm-project?rev=371016&view=rev
Log:
[DWARF] Fix referencing Range List Tables from CUs for DWARF64.

As DW_AT_rnglists_base points after the header and headers have
different sizes for DWARF32 and DWARF64, we have to use the format
of the CU to adjust the offset correctly in order to extract
the referenced range list table.

The patch also changes the type of RangeSectionBase because in DWARF64
it is 8-bytes long.

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

Added:
    llvm/trunk/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s
Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h?rev=371016&r1=371015&r2=371016&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h Thu Sep  5 00:02:28 2019
@@ -198,7 +198,7 @@ class DWARFUnit {
   DWARFUnitHeader Header;
   const DWARFDebugAbbrev *Abbrev;
   const DWARFSection *RangeSection;
-  uint32_t RangeSectionBase;
+  uint64_t RangeSectionBase;
   /// We either keep track of the location list section or its data, depending
   /// on whether we are handling a split DWARF section or not.
   union {
@@ -304,7 +304,7 @@ public:
   /// Recursively update address to Die map.
   void updateAddressDieMap(DWARFDie Die);
 
-  void setRangesSection(const DWARFSection *RS, uint32_t Base) {
+  void setRangesSection(const DWARFSection *RS, uint64_t Base) {
     RangeSection = RS;
     RangeSectionBase = Base;
   }

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp?rev=371016&r1=371015&r2=371016&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp Thu Sep  5 00:02:28 2019
@@ -306,16 +306,18 @@ bool DWARFUnitHeader::extract(DWARFConte
 // Parse the rangelist table header, including the optional array of offsets
 // following it (DWARF v5 and later).
 static Expected<DWARFDebugRnglistTable>
-parseRngListTableHeader(DWARFDataExtractor &DA, uint64_t Offset) {
-  // TODO: Support DWARF64
+parseRngListTableHeader(DWARFDataExtractor &DA, uint64_t Offset,
+                        DwarfFormat Format) {
   // We are expected to be called with Offset 0 or pointing just past the table
-  // header, which is 12 bytes long for DWARF32.
+  // header. Correct Offset in the latter case so that it points to the start
+  // of the header.
   if (Offset > 0) {
-    if (Offset < 12U)
+    uint64_t HeaderSize = DWARFListTableHeader::getHeaderSize(Format);
+    if (Offset < HeaderSize)
       return createStringError(errc::invalid_argument, "Did not detect a valid"
-                               " range list table with base = 0x%" PRIx64,
+                               " range list table with base = 0x%" PRIx64 "\n",
                                Offset);
-    Offset -= 12U;
+    Offset -= HeaderSize;
   }
   llvm::DWARFDebugRnglistTable Table;
   if (Error E = Table.extractHeaderAndOffsets(DA, &Offset))
@@ -469,8 +471,8 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(
       // extracted lazily.
       DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
                                   isLittleEndian, 0);
-      auto TableOrError =
-              parseRngListTableHeader(RangesDA, RangeSectionBase);
+      auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase,
+                                                  Header.getFormat());
       if (!TableOrError)
         return createStringError(errc::invalid_argument,
                                  "parsing a range list table: " +
@@ -525,7 +527,8 @@ bool DWARFUnit::parseDWO() {
     DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
     DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
                                 isLittleEndian, 0);
-    if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase))
+    if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase,
+                                                    Header.getFormat()))
       DWO->RngListTable = TableOrError.get();
     else
       WithColor::error() << "parsing a range list table: "

Added: llvm/trunk/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s?rev=371016&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s (added)
+++ llvm/trunk/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s Thu Sep  5 00:02:28 2019
@@ -0,0 +1,211 @@
+# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o
+# RUN: llvm-dwarfdump -v -debug-info %t.o 2> %t.err | FileCheck %s
+# RUN: FileCheck %s --input-file %t.err --check-prefix=ERR
+# RUN: llvm-dwarfdump -lookup 10 %t.o 2> %t2.err
+# RUN: FileCheck %s --input-file %t2.err --check-prefix=ERR
+
+# Test object to verify dwarfdump handles v5 range lists in 64-bit DWARF format.
+# This is similar to 'dwarfdump-rnglists.s', which uses 32-bit DWARF format.
+# We use very simplified compile unit dies.
+# There are 2 full CUs with DW_AT_rnglists_base, one with a DW_AT_ranges
+# attribute using DW_FORM_sec_offset, the other with DW_AT_ranges using
+# DW_FORM_rnglistx.
+
+        .section .debug_abbrev,"", at progbits
+        .byte 0x01  # Abbrev code
+        .byte 0x11  # DW_TAG_compile_unit
+        .byte 0x00  # DW_CHILDREN_no
+        .byte 0x74  # DW_AT_rnglists_base
+        .byte 0x17  # DW_FORM_sec_offset
+        .byte 0x55  # DW_AT_ranges
+        .byte 0x17  # DW_FORM_sec_offset
+        .byte 0x00  # EOM(1)
+        .byte 0x00  # EOM(2)
+        .byte 0x02  # Abbrev code
+        .byte 0x11  # DW_TAG_compile_unit
+        .byte 0x00  # DW_CHILDREN_no
+        .byte 0x74  # DW_AT_rnglists_base
+        .byte 0x17  # DW_FORM_sec_offset
+        .byte 0x55  # DW_AT_ranges
+        .byte 0x23  # DW_FORM_rnglistx
+        .byte 0x00  # EOM(1)
+        .byte 0x00  # EOM(2)
+        .byte 0x00  # EOM(3)
+
+# The split CU uses DW_FORM_rnglistx (the only correct option).
+# There is no DW_AT_rnglists_base in split units.
+        .section .debug_abbrev.dwo,"", at progbits
+        .byte 0x01  # Abbrev code
+        .byte 0x11  # DW_TAG_compile_unit
+        .byte 0x00  # DW_CHILDREN_no
+        .byte 0x55  # DW_AT_ranges
+        .byte 0x23  # DW_FORM_rnglistx
+        .byte 0x00  # EOM(1)
+        .byte 0x00  # EOM(2)
+        .byte 0x00  # EOM(3)
+        
+        .section .debug_info,"", at progbits
+        .long 0xffffffff       # DWARF64 mark
+        .quad  CU1_5_64_end - CU1_5_64_version  # Length of Unit
+CU1_5_64_version:
+        .short 5               # DWARF version number
+        .byte 1                # DWARF Unit Type
+        .byte 4                # Address Size (in bytes)
+        .quad .debug_abbrev    # Offset Into Abbrev. Section
+# The compile-unit DIE, which has DW_AT_rnglists_base and DW_AT_ranges.
+        .byte 1                # Abbreviation code
+        .quad Rnglist_Table0_base     # DW_AT_rnglists_base
+        .quad Rnglist_Table0_Rnglist0 # DW_AT_ranges
+CU1_5_64_end:
+
+        .long 0xffffffff       # DWARF64 mark
+        .quad  CU2_5_64_end - CU2_5_64_version  # Length of Unit
+CU2_5_64_version:
+        .short 5               # DWARF version number
+        .byte 1                # DWARF Unit Type
+        .byte 4                # Address Size (in bytes)
+        .quad .debug_abbrev    # Offset Into Abbrev. Section
+# The compile-unit DIE, which has DW_AT_rnglists_base and DW_AT_ranges.
+        .byte 2                # Abbreviation code
+        .quad Rnglist_Table0_base   # DW_AT_rnglists_base
+        .uleb128 1             # DW_AT_ranges
+CU2_5_64_end:
+
+# A CU with an invalid DW_AT_rnglists_base attribute
+        .long 0xffffffff       # DWARF64 mark
+        .quad  CU3_5_64_end - CU3_5_64_version  # Length of Unit
+CU3_5_64_version:
+        .short 5               # DWARF version number
+        .byte 1                # DWARF Unit Type
+        .byte 4                # Address Size (in bytes)
+        .quad .debug_abbrev    # Offset Into Abbrev. Section
+# The compile-unit DIE, which has DW_AT_rnglists_base and DW_AT_ranges.
+        .byte 2                # Abbreviation code
+        .quad 0x8              # DW_AT_rnglists_base
+        .uleb128 0             # DW_AT_ranges
+CU3_5_64_end:
+
+# A CU DIE with an incorrect DW_AT_ranges attribute
+        .long 0xffffffff       # DWARF64 mark
+        .quad  CU4_5_64_end - CU4_5_64_version  # Length of Unit
+CU4_5_64_version:
+        .short 5               # DWARF version number
+        .byte 1                # DWARF Unit Type
+        .byte 4                # Address Size (in bytes)
+        .quad .debug_abbrev    # Offset Into Abbrev. Section
+# The compile-unit DIE, which has DW_AT_rnglists_base and DW_AT_ranges.
+        .byte 1                # Abbreviation code
+        .quad Rnglist_Table0_base   # DW_AT_rnglists_base
+        .quad 4000             # DW_AT_ranges
+CU4_5_64_end:
+
+        .section .debug_info.dwo,"", at progbits
+
+# DWARF v5 split CU header.
+        .long 0xffffffff       # DWARF64 mark
+        .quad  CU_split_5_64_end-CU_split_5_64_version  # Length of Unit
+CU_split_5_64_version:
+        .short 5               # DWARF version number
+        .byte 5                # DWARF Unit Type
+        .byte 4                # Address Size (in bytes)
+        .quad 0                # Offset Into Abbrev Section
+# The compile-unit DIE, which has DW_AT_rnglists_base and DW_AT_ranges.
+        .byte 1                # Abbreviation code
+        .uleb128 1             # DW_AT_ranges
+CU_split_5_64_end:
+
+        .section .debug_rnglists,"", at progbits
+# A rnglist table with 2 range lists. The first one uses DW_RLE_start_end
+# and DW_RLE_start_length. The second one uses DW_RLE_base_address and
+# DW_RLE_offset_pair. The range lists have entries in the offset table.
+        .long 0xffffffff                            # DWARF64 mark
+        .quad Rnglist_Table0_end - Rnglist_Table0   # table length
+Rnglist_Table0:
+        .short 5                                    # version
+        .byte 4                                     # address size
+        .byte 0                                     # segment selector size
+        .long 2                                     # offset entry count
+Rnglist_Table0_base:
+# 2 offset entries which can be used by DW_FORM_rnglistx.
+        .quad Rnglist_Table0_Rnglist0 - Rnglist_Table0_base
+        .quad Rnglist_Table0_Rnglist1 - Rnglist_Table0_base
+Rnglist_Table0_Rnglist0:
+        .byte 6                                     # DW_RLE_start_end
+        .long Range0_start
+        .long Range0_end
+        .byte 7                                     # DW_RLE_start_length
+        .long Range1_start
+        .uleb128 Range1_end - Range1_start 
+        .byte 0                                     # DW_RLE_end_of_list
+Rnglist_Table0_Rnglist1:
+        .byte 5                                     # DW_RLE_base_address
+        .long Range0_start
+        .byte 4                                     # DW_RLE_offset_pair
+        .uleb128 Range1_start - Range0_start
+        .uleb128 Range1_end - Range0_start
+        .byte 0                                     # DW_RLE_end_of_list
+Rnglist_Table0_end:
+
+# A rnglist table for the split unit with an empty rangelist and one that
+# uses DW_RLE_base_address and DW_RLE_offset_pair. The ranges have entries
+# in the offset table. We use the empty range list so we can test 
+# DW_FORM_rnglistx with an index other than 0.
+        .section .debug_rnglists.dwo,"", at progbits
+        .long 0xffffffff                            # DWARF64 mark
+        .quad Rnglist_Table0_dwo_end - Rnglist_Table0_dwo   # table length
+Rnglist_Table0_dwo:
+        .short 5                                    # version
+        .byte 4                                     # address size
+        .byte 0                                     # segment selector size
+        .long 2                                     # offset entry count
+Rnglist_Table0_base_dwo:
+# 2 offset entries which can be used by DW_FORM_rnglistx.
+        .quad Rnglist_Table0_Rnglist0_dwo - Rnglist_Table0_base_dwo
+        .quad Rnglist_Table0_Rnglist1_dwo - Rnglist_Table0_base_dwo
+Rnglist_Table0_Rnglist0_dwo:
+        .byte 0                                     # DW_RLE_start_end
+Rnglist_Table0_Rnglist1_dwo:
+        .byte 5                                     # DW_RLE_base_address
+        .long Range0_start - .text
+        .byte 4                                     # DW_RLE_offset_pair
+        .uleb128 Range1_start - Range0_start
+        .uleb128 Range1_end - Range0_start
+        .byte 0                                     # DW_RLE_end_of_list
+Rnglist_Table0_dwo_end:
+
+.text
+        .space 20
+Range0_start:               # Range0: 0x14 - 0x1c
+        .space 10
+Range0_end:
+        .space 12
+Range1_start:               # Range1: 0x2a - 0x34
+        .space 10
+Range1_end:
+
+# CHECK:      .debug_info contents:
+# CHECK:      Compile Unit: 
+# CHECK-NOT:  Compile Unit:
+# CHECK:      DW_TAG_compile_unit
+# CHECK-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset]  (0x00000014)
+# CHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000024
+# CHECK-NEXT: [0x00000014, 0x0000001e) ".text"
+# CHECK-NEXT: [0x0000002a, 0x00000034) ".text")
+
+# CHECK:      Compile Unit:
+# CHECK-NOT:  Compile Unit:
+# CHECK:      DW_TAG_compile_unit
+# CHECK-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset]  (0x00000014)
+# CHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000020
+# CHECK-NEXT: [0x0000002a, 0x00000034) ".text")
+
+# CHECK:      .debug_info.dwo contents:
+# CHECK:      Compile Unit:
+# CHECK-NOT:  contents:
+# CHECK:      DW_TAG_compile_unit
+# CHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000011
+# CHECK-NEXT: [0x0000002a, 0x00000034))
+
+#ERR: error: parsing a range list table: Did not detect a valid range list table with base = 0x8
+#ERR: error: decoding address ranges: missing or invalid range list table
+#ERR: error: decoding address ranges: invalid range list offset 0xfa0




More information about the llvm-commits mailing list