DWARF location lists: Add section index dumping
authorPavel Labath <pavel@labath.sk>
Thu, 14 Nov 2019 10:22:00 +0000 (11:22 +0100)
committerPavel Labath <pavel@labath.sk>
Mon, 18 Nov 2019 09:50:22 +0000 (10:50 +0100)
Summary:
As discussed in D70081, this adds the ability to dump section
names/indices to the location list dumper. It does this by moving the
range specific logic from DWARFDie.cpp:dumpRanges into the
DWARFAddressRange class.

The trickiest part of this patch is the backflip in the meanings of the
two dump flags for the location list sections.

The dumping of "raw" location list data is now controlled by
"DisplayRawContents" flag. This frees up the "Verbose" flag to be used
to control whether we print the section index. Additionally, the
DisplayRawContents flag is set for section-based dumps whenever the
--verbose option is passed, but this is not done for the "inline" dumps.

Also note that the index dumping currently does not work for the DWARF
v5 location lists, as the parser does not fill out the appropriate
fields. This will be done in a separate patch.

Reviewers: dblaikie, probinson, JDevlieghere, SouraVX

Subscribers: sdardis, hiraditya, jrtc27, atanasyan, arphaman, aprantl, llvm-commits

Tags: #llvm

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

13 files changed:
llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp
llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
llvm/test/CodeGen/X86/debug-loclists.ll
llvm/test/DebugInfo/ARM/PR26163.ll
llvm/test/DebugInfo/Mips/dsr-fixed-objects.ll
llvm/test/DebugInfo/X86/DW_AT_location-reference.ll
llvm/test/DebugInfo/X86/dbg-value-frame-index.ll
llvm/test/DebugInfo/X86/dbg-value-regmask-clobber.ll
llvm/test/DebugInfo/X86/debug-loc-frame.ll
llvm/test/DebugInfo/X86/debug-loc-offset.mir

index 2d5f9f3..e171477 100644 (file)
@@ -17,6 +17,7 @@
 namespace llvm {
 
 class raw_ostream;
+class DWARFObject;
 
 struct DWARFAddressRange {
   uint64_t LowPC;
@@ -26,7 +27,9 @@ struct DWARFAddressRange {
   DWARFAddressRange() = default;
 
   /// Used for unit testing.
-  DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
+  DWARFAddressRange(
+      uint64_t LowPC, uint64_t HighPC,
+      uint64_t SectionIndex = object::SectionedAddress::UndefSection)
       : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
 
   /// Returns true if LowPC is smaller or equal to HighPC. This accounts for
@@ -42,8 +45,8 @@ struct DWARFAddressRange {
     return LowPC < RHS.HighPC && RHS.LowPC < HighPC;
   }
 
-  void dump(raw_ostream &OS, uint32_t AddressSize,
-            DIDumpOptions DumpOpts = {}) const;
+  void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts = {},
+            const DWARFObject *Obj = nullptr) const;
 };
 
 static inline bool operator<(const DWARFAddressRange &LHS,
index ef6da08..ddf307d 100644 (file)
@@ -7,19 +7,23 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
-
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 
 void DWARFAddressRange::dump(raw_ostream &OS, uint32_t AddressSize,
-                             DIDumpOptions DumpOpts) const {
+                             DIDumpOptions DumpOpts,
+                             const DWARFObject *Obj) const {
 
   OS << (DumpOpts.DisplayRawContents ? " " : "[");
   OS << format("0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, LowPC)
      << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2, HighPC);
   OS << (DumpOpts.DisplayRawContents ? "" : ")");
+
+  if (Obj)
+    DWARFFormValue::dumpAddressSection(*Obj, OS, DumpOpts, SectionIndex);
 }
 
 raw_ostream &llvm::operator<<(raw_ostream &OS, const DWARFAddressRange &R) {
index 3fad575..3071f63 100644 (file)
@@ -388,16 +388,20 @@ void DWARFContext::dump(
       dumpDebugType(".debug_types.dwo", dwo_types_section_units());
   }
 
+  DIDumpOptions LLDumpOpts = DumpOpts;
+  if (LLDumpOpts.Verbose)
+    LLDumpOpts.DisplayRawContents = true;
+
   if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
                                    DObj->getLocSection().Data)) {
-    getDebugLoc()->dump(OS, getRegisterInfo(), DumpOpts, *Off);
+    getDebugLoc()->dump(OS, getRegisterInfo(), LLDumpOpts, *Off);
   }
   if (const auto *Off =
           shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
                      DObj->getLoclistsSection().Data)) {
     DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
                             0);
-    dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off);
+    dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *Off);
   }
   if (const auto *Off =
           shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
@@ -409,10 +413,11 @@ void DWARFContext::dump(
       uint64_t Offset = **Off;
       Loc.dumpLocationList(&Offset, OS,
                            /*BaseAddr=*/None, getRegisterInfo(), nullptr,
-                           DumpOpts, /*Indent=*/0);
+                           LLDumpOpts, /*Indent=*/0);
       OS << "\n";
     } else {
-      Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(), DumpOpts);
+      Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(),
+                    LLDumpOpts);
     }
   }
 
index 218bf38..1af51a8 100644 (file)
@@ -115,14 +115,20 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
   OS << format("0x%8.8" PRIx64 ": ", *Offset);
   Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) {
     Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
-    if (!Loc || DumpOpts.Verbose)
+    if (!Loc || DumpOpts.DisplayRawContents)
       dumpRawEntry(E, OS, Indent);
     if (Loc && *Loc) {
       OS << "\n";
       OS.indent(Indent);
-      if (DumpOpts.Verbose)
+      if (DumpOpts.DisplayRawContents)
         OS << "          => ";
-      Loc.get()->Range->dump(OS, Data.getAddressSize(), DumpOpts);
+
+      DIDumpOptions RangeDumpOpts(DumpOpts);
+      RangeDumpOpts.DisplayRawContents = false;
+      const DWARFObject *Obj = nullptr;
+      if (U)
+        Obj = &U->getContext().getDWARFObj();
+      Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, Obj);
     }
     if (!Loc)
       consumeError(Loc.takeError());
index 7fa72b1..a11865e 100644 (file)
@@ -62,16 +62,10 @@ static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS,
   if (!DumpOpts.ShowAddresses)
     return;
 
-  ArrayRef<SectionName> SectionNames;
-  if (DumpOpts.Verbose)
-    SectionNames = Obj.getSectionNames();
-
   for (const DWARFAddressRange &R : Ranges) {
     OS << '\n';
     OS.indent(Indent);
-    R.dump(OS, AddressSize);
-
-    DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, R.SectionIndex);
+    R.dump(OS, AddressSize, DumpOpts, &Obj);
   }
 }
 
@@ -91,9 +85,6 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
   }
 
   if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
-    auto LLDumpOpts = DumpOpts;
-    LLDumpOpts.Verbose = false;
-
     uint64_t Offset = *FormValue.getAsSectionOffset();
 
     if (FormValue.getForm() == DW_FORM_loclistx) {
@@ -104,7 +95,7 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
         return;
     }
     U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(),
-                                           MRI, U, LLDumpOpts, Indent);
+                                           MRI, U, DumpOpts, Indent);
     return;
   }
 
index f22e9e1..a4dd7ed 100644 (file)
@@ -3,19 +3,18 @@
 
 ; CHECK:      DW_TAG_variable
 ; CHECK-NEXT:   DW_AT_location [DW_FORM_loclistx]   (indexed (0x0) loclist = 0x00000018:
-; CHECK-NEXT:     [0x0000000000000000, 0x0000000000000003): DW_OP_consts +3, DW_OP_stack_value
-; CHECK-NEXT:     [0x0000000000000003, 0x0000000000000004): DW_OP_consts +4, DW_OP_stack_value)
+; CHECK-NEXT:     [0x0000000000000000, 0x0000000000000003) ".text._Z2f1ii": DW_OP_consts +3, DW_OP_stack_value
+; CHECK-NEXT:     [0x0000000000000003, 0x0000000000000004) ".text._Z2f1ii": DW_OP_consts +4, DW_OP_stack_value)
 ; CHECK-NEXT:   DW_AT_name {{.*}} "y"
 
 ; CHECK:      DW_TAG_variable
 ; CHECK-NEXT:   DW_AT_location [DW_FORM_loclistx]   (indexed (0x1) loclist = 0x00000029:
-; CHECK-NEXT:     [0x0000000000000000, 0x0000000000000003): DW_OP_consts +5, DW_OP_stack_value)
+; CHECK-NEXT:     [0x0000000000000000, 0x0000000000000003) ".text._Z2f1ii": DW_OP_consts +5, DW_OP_stack_value)
 ; CHECK-NEXT:   DW_AT_name {{.*}} "x"
 
 ; CHECK:      DW_TAG_variable
-; FIXME: Use DW_FORM_loclistx to reduce relocations
 ; CHECK-NEXT:   DW_AT_location [DW_FORM_loclistx]   (indexed (0x2) loclist = 0x00000031:
-; CHECK-NEXT:     [0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX)
+; CHECK-NEXT:     [0x0000000000000003, 0x0000000000000004) ".text._Z2f1ii": DW_OP_reg0 RAX)
 ; CHECK-NEXT:   DW_AT_name {{.*}} "r"
 
 ; CHECK:      .debug_loclists contents:
index 5dac6ad..0beb942 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc -filetype=obj -o - < %s | llvm-dwarfdump -v -debug-info - | FileCheck %s
+; RUN: llc -filetype=obj -o - < %s | llvm-dwarfdump -debug-info - | FileCheck %s
 ;
 ; Checks that we're omitting the first range, as it is empty, and that we're
 ; emitting one that spans the rest of the function. In this case, the first
@@ -10,7 +10,7 @@
 ;
 ; CHECK: DW_TAG_inlined_subroutine
 ; CHECK: DW_TAG_variable
-; CHECK:   DW_AT_location [DW_FORM_sec_offset] ({{.*}}
+; CHECK:   DW_AT_location ({{.*}}
 ; CHECK-NEXT: [0x00000004, 0x00000014): DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4)
 
 ; Created form the following test case (PR26163) with
index ebbe64a..e931bbf 100644 (file)
@@ -24,8 +24,8 @@ declare void @foo(i32*)
 ; CHECK: DW_AT_name {{.*}}"e"
 ; CHECK: DW_TAG_variable
 ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (
-; CHECK-NEXT:   [0x00000028, 0x0000002c): DW_OP_reg1 AT_64
-; CHECK-NEXT:   [0x0000002c, 0x00000048): DW_OP_breg29 SP_64+16)
+; CHECK-NEXT:   [0x00000028, 0x0000002c) ".text": DW_OP_reg1 AT_64
+; CHECK-NEXT:   [0x0000002c, 0x00000048) ".text": DW_OP_breg29 SP_64+16)
 ; CHECK-NEXT: DW_AT_name [DW_FORM_strp]     ( .debug_str[0x0000006b] = "x")
 
 define i32 @f0(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e) !dbg !4 {
@@ -55,8 +55,8 @@ entry:
 
 ; CHECK: DW_TAG_variable
 ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset]  (
-; CHECK-NEXT:   [0x00000080, 0x00000084): DW_OP_reg1 AT_64
-; CHECK-NEXT:   [0x00000084, 0x00000098): DW_OP_breg29 SP_64+16)
+; CHECK-NEXT:   [0x00000080, 0x00000084) ".text": DW_OP_reg1 AT_64
+; CHECK-NEXT:   [0x00000084, 0x00000098) ".text": DW_OP_breg29 SP_64+16)
 ; CHECK-NEXT: DW_AT_name [DW_FORM_strp]     ( .debug_str[0x0000006b] = "x")
 
 define i32 @f1(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e) !dbg !15 {
index dbcae5d..43fde0b 100644 (file)
@@ -33,8 +33,8 @@
 ; CHECK:      DW_TAG_variable
 ; CHECK-NEXT:   DW_AT_location [DW_FORM_sec_offset] (0x00000000
 ; Check that the location contains only 2 ranges.
-; CHECK-NEXT:   [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}):
-; CHECK-NEXT:   [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}){{.*}})
+; CHECK-NEXT:   [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}})
+; CHECK-NEXT:   [0x{{[0-9a-f]*}}, 0x{{[0-9a-f]*}}){{.*}})
 ; CHECK-NEXT:   DW_AT_name {{.*}} "x"
 ; CHECK-NEXT:   DW_AT_decl_file
 ; CHECK-NEXT:   DW_AT_decl_line
index a2cf2cc..d6fdada 100644 (file)
@@ -1,6 +1,6 @@
 ; RUN: llc -mtriple=x86_64-unknown-unknown -o - %s | FileCheck %s
 ; RUN: llc -mtriple=x86_64-unknown-unknown -filetype=obj < %s \
-; RUN:   | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF
+; RUN:   | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF
 
 define i1 @test() !dbg !4 {
 entry:
@@ -22,7 +22,7 @@ while.end:
 ; CHECK-LABEL: test
 ; To get the value of the variable, we need to do [$rsp+8], i.e:
 ; CHECK:       #DEBUG_VALUE: test:w <- [DW_OP_plus_uconst 8, DW_OP_deref] $rsp
-; DWARF:  DW_AT_location [DW_FORM_sec_offset] (
+; DWARF:  DW_AT_location (
 ; DWARF-NEXT:   [{{.*}}, {{.*}}): DW_OP_breg7 RSP+8)
 
 ; Note: A previous version of this test checked for `[DW_OP_plus_uconst 8] [$rsp+0]`,
index 22d0a70..440498a 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: llc < %s | FileCheck %s --check-prefix=ASM
-; RUN: llc < %s -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF
+; RUN: llc < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF
 
 ; Values in registers should be clobbered by calls, which use a regmask instead
 ; of individual register def operands.
@@ -22,9 +22,9 @@
 ; argc is the first formal parameter.
 ; DWARF: .debug_info contents:
 ; DWARF:  DW_TAG_formal_parameter
-; DWARF-NEXT:    DW_AT_location [DW_FORM_sec_offset]   ({{0x.*}}
+; DWARF-NEXT:    DW_AT_location ({{0x.*}}
 ; DWARF-NEXT:      [0x0000000000000000, 0x0000000000000013): DW_OP_reg2 RCX)
-; DWARF-NEXT:    DW_AT_name [DW_FORM_strp]     {{.*}} "argc"
+; DWARF-NEXT:    DW_AT_name ("argc")
 
 ; ModuleID = 't.cpp'
 source_filename = "test/DebugInfo/X86/dbg-value-regmask-clobber.ll"
index f3bcfcb..90a38f1 100644 (file)
@@ -4,7 +4,7 @@
 ; for the stack location directly instead of generating a register+offset indirection.
 
 ; RUN: llc -O2 -filetype=obj -disable-post-ra -mtriple=x86_64-unknown-linux-gnu < %s \
-; RUN: | llvm-dwarfdump -v - | FileCheck %s
+; RUN: | llvm-dwarfdump - | FileCheck %s
 ;
 ; int data = 17;
 ; int sum  = 0;
@@ -26,7 +26,7 @@
 ; CHECK:      DW_TAG_subprogram
 ; CHECK-NOT:  NULL
 ; CHECK:      DW_TAG_variable
-; CHECK:      DW_AT_location [DW_FORM_sec_offset] ({{.*}}
+; CHECK:      DW_AT_location ({{.*}}
 ; CHECK-NEXT:   [{{0x.*}}, {{0x.*}}): DW_OP_reg0 RAX
 ;
 ; Note: This is a location, so we don't want an extra DW_OP_deref at the end.
@@ -36,7 +36,7 @@
 ;     ... [rsp+4] DW_OP_deref
 ;
 ; CHECK-NEXT:   [{{0x.*}}, {{0x.*}}): DW_OP_breg7 RSP+4)
-; CHECK-NEXT: DW_AT_name {{.*}}"val"
+; CHECK-NEXT: DW_AT_name ("val")
 
 ; ModuleID = 'frame.c'
 source_filename = "frame.c"
index 4968419..41c04ae 100644 (file)
@@ -42,8 +42,8 @@
 # CHECK: DW_TAG_formal_parameter
 # CHECK-NOT: DW_TAG
 # CHECK:       DW_AT_location [DW_FORM_sec_offset]   ({{.*}}
-# CHECK-NEXT:    [0x00000029, 0x00000037): DW_OP_breg0 EAX+0, DW_OP_deref
-# CHECK-NEXT:    [0x00000037, 0x00000063): DW_OP_breg5 EBP-8, DW_OP_deref, DW_OP_deref
+# CHECK-NEXT:    [0x00000029, 0x00000037) ".text": DW_OP_breg0 EAX+0, DW_OP_deref
+# CHECK-NEXT:    [0x00000037, 0x00000063) ".text": DW_OP_breg5 EBP-8, DW_OP_deref, DW_OP_deref
 # CHECK-NEXT:  DW_AT_name [DW_FORM_strp]{{.*}}"a"
 #
 # CHECK: DW_TAG_variable
@@ -61,8 +61,8 @@
 # CHECK: DW_TAG_formal_parameter
 # CHECK-NOT: DW_TAG
 # CHECK:       DW_AT_location [DW_FORM_sec_offset]   ({{.*}}
-# CHECK-NEXT:    [0x00000000, 0x0000000a): DW_OP_consts +0, DW_OP_stack_value
-# CHECK-NEXT:    [0x0000000a, 0x00000017): DW_OP_consts +1, DW_OP_stack_value)
+# CHECK-NEXT:    [0x00000000, 0x0000000a) ".text": DW_OP_consts +0, DW_OP_stack_value
+# CHECK-NEXT:    [0x0000000a, 0x00000017) ".text": DW_OP_consts +1, DW_OP_stack_value)
 # CHECK-NEXT:  DW_AT_name [DW_FORM_strp]{{.*}}"b"
 #
 # CHECK: .debug_loc contents: