labath updated this revision to Diff 223193.
labath added a comment.

Upload a new version of the patch.

This isn't fully ready for submission, but I am putting it up anyway, to get
some feedback on the direction I am taking this, and ask some questions.

First I tried to do a complete rewrite of the loclists class in a manner similar
to the rnglists parser, but then I ran into the problem called .debug_loc.dwo
(v4 extension vaguely similar to DWARF5 loclists). Right now, it is possible to
share the parsing code between this format and .debug_loclists. That would be
pretty tricky to do with the rnglists approach.

So, instead I went for a bottom-up approach and tried to rewrite/reuse/make
similar the lower level classes, which can be shared more easily with the
rnglists stuff. This patch creates a DWARFLocation class, which is based on the
existing DWARFAddressRange class. The next step would be (or maybe I'll land it
before this patch) a LocationListEntry class akin to the existing
RangeListEntry.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68270/new/

https://reviews.llvm.org/D68270

Files:
  include/llvm/BinaryFormat/Dwarf.h
  include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
  lib/BinaryFormat/Dwarf.cpp
  lib/DebugInfo/DWARF/DWARFContext.cpp
  lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
  lib/DebugInfo/DWARF/DWARFDie.cpp
  test/CodeGen/X86/debug-loclists.ll
  test/DebugInfo/X86/dwarfdump-debug-loclists-error-cases2.s
  test/DebugInfo/X86/dwarfdump-debug-loclists.test
  test/DebugInfo/X86/fission-ranges.ll
  test/DebugInfo/X86/loclists-dwp.ll
  test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
  test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s

Index: test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s
===================================================================
--- test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s
+++ test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s
@@ -8,7 +8,7 @@
 # CHECK:         .debug_loclists contents:
 # CHECK-NEXT:    0x00000000: locations list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 # CHECK-NEXT:    0x00000000:
-# CHECK-NEXT:    Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
+# CHECK-NEXT:    [DW_LLE_startx_length]: 0x0000000000000001, 0x0000000000000010[DW_LLE_startx_length]: 0x0000000000000001, 0x0000000000000010 => <Failed to read address offset 1> DW_OP_reg5 RDI
 
 .section .debug_loclists,"",@progbits
  .long  .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0
Index: test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
===================================================================
--- test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
+++ test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
@@ -6,7 +6,7 @@
 
 # CHECK:         .debug_loc.dwo contents:
 # CHECK-NEXT:    0x00000000:
-# CHECK-NEXT:    Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
+# CHECK-NEXT:    [DW_LLE_startx_length]: 0x00000001, 0x00000010 => <Failed to read address offset 1> DW_OP_reg5 RDI
 
 .section .debug_loc.dwo,"",@progbits
 # One location list. The pre-DWARF v5 implementation only recognizes
Index: test/DebugInfo/X86/loclists-dwp.ll
===================================================================
--- test/DebugInfo/X86/loclists-dwp.ll
+++ test/DebugInfo/X86/loclists-dwp.ll
@@ -19,10 +19,10 @@
 ; void b(int i) { asm("" : : : "rdi"); }
 
 ; CHECK:      DW_AT_location [DW_FORM_sec_offset]   (0x00000000
-; CHECK-NEXT: Addr idx 0 (w/ length 6): DW_OP_reg5 RDI)
+; CHECK-NEXT: [DW_LLE_startx_length]: 0x0000000000000000, 0x0000000000000006 => <Failed to read address offset 0> DW_OP_reg5 RDI)
 
 ; CHECK:      DW_AT_location [DW_FORM_sec_offset]   (0x00000000
-; CHECK-NEXT: Addr idx 0 (w/ length 0): DW_OP_reg5 RDI)
+; CHECK-NEXT: [DW_LLE_startx_length]: 0x0000000000000000, 0x0000000000000000 => <Failed to read address offset 0> DW_OP_reg5 RDI)
 
 target triple = "x86_64-unknown-linux-gnu"
 
Index: test/DebugInfo/X86/fission-ranges.ll
===================================================================
--- test/DebugInfo/X86/fission-ranges.ll
+++ test/DebugInfo/X86/fission-ranges.ll
@@ -45,18 +45,18 @@
 ; if they've changed due to a bugfix, change in register allocation, etc.
 
 ; CHECK:      [[A]]:
-; CHECK-NEXT:   Addr idx 2 (w/ length 15): DW_OP_consts +0, DW_OP_stack_value
-; CHECK-NEXT:   Addr idx 3 (w/ length 15): DW_OP_reg0 RAX
-; CHECK-NEXT:   Addr idx 4 (w/ length 18): DW_OP_breg7 RSP-8
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000002, 0x0000000f => <Failed to read address offset 2> DW_OP_consts +0, DW_OP_stack_value
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000003, 0x0000000f => <Failed to read address offset 3> DW_OP_reg0 RAX
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000004, 0x00000012 => <Failed to read address offset 4> DW_OP_breg7 RSP-8
 ; CHECK:      [[E]]:
-; CHECK-NEXT:   Addr idx 5 (w/ length 9): DW_OP_reg0 RAX
-; CHECK-NEXT:   Addr idx 6 (w/ length 98): DW_OP_breg7 RSP-44
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000005, 0x00000009 => <Failed to read address offset 5> DW_OP_reg0 RAX
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000006, 0x00000062 => <Failed to read address offset 6> DW_OP_breg7 RSP-44
 ; CHECK:      [[B]]:
-; CHECK-NEXT:   Addr idx 7 (w/ length 15): DW_OP_reg0 RAX
-; CHECK-NEXT:   Addr idx 8 (w/ length 66): DW_OP_breg7 RSP-32
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000007, 0x0000000f => <Failed to read address offset 7> DW_OP_reg0 RAX
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000008, 0x00000042 => <Failed to read address offset 8> DW_OP_breg7 RSP-32
 ; CHECK:      [[D]]:
-; CHECK-NEXT:   Addr idx 9 (w/ length 15): DW_OP_reg0 RAX
-; CHECK-NEXT:   Addr idx 10 (w/ length 42): DW_OP_breg7 RSP-20
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x00000009, 0x0000000f => <Failed to read address offset 9> DW_OP_reg0 RAX
+; CHECK-NEXT:   [DW_LLE_startx_length]: 0x0000000a, 0x0000002a => <Failed to read address offset 10> DW_OP_breg7 RSP-20
 
 ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo)
 ; HDR-NOT: .rela.{{.*}}.dwo
Index: test/DebugInfo/X86/dwarfdump-debug-loclists.test
===================================================================
--- test/DebugInfo/X86/dwarfdump-debug-loclists.test
+++ test/DebugInfo/X86/dwarfdump-debug-loclists.test
@@ -4,16 +4,19 @@
 # CHECK:      .debug_info
 # CHECK:       DW_AT_name{{.*}}"stub"
 # CHECK:       DW_AT_location [DW_FORM_sec_offset]   (0x0000000c
-# CHECK-NEXT:    [0x0000000000000010, 0x0000000000000020): DW_OP_breg5 RDI+0
-# CHECK-NEXT:    [0x0000000000000530, 0x0000000000000540): DW_OP_breg6 RBP-8, DW_OP_deref
-# CHECK-NEXT:    [0x0000000000000700, 0x0000000000000710): DW_OP_breg5 RDI+0
+# CHECK-NEXT:    [DW_LLE_offset_pair  ]: 0x0000000000000000, 0x0000000000000010 => [0x0000000000000010, 0x0000000000000020) DW_OP_breg5 RDI+0
+# CHECK-NEXT:    [DW_LLE_base_address ]: 0x0000000000000500
+# 
+# CHECK-NEXT:    [DW_LLE_offset_pair  ]: 0x0000000000000030, 0x0000000000000040 => [0x0000000000000530, 0x0000000000000540) DW_OP_breg6 RBP-8, DW_OP_deref
+# CHECK-NEXT:    [DW_LLE_start_length ]: 0x0000000000000700, 0x0000000000000010 => [0x0000000000000700, 0x0000000000000710) DW_OP_breg5 RDI+0
 
 # CHECK:      .debug_loclists contents:
 # CHECK-NEXT: 0x00000000: locations list header: length = 0x0000002c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 # CHECK-NEXT: 0x00000000:
-# CHECK-NEXT:   [0x0000000000000000, 0x0000000000000010): DW_OP_breg5 RDI+0
-# CHECK-NEXT:   [0x0000000000000530, 0x0000000000000540): DW_OP_breg6 RBP-8, DW_OP_deref
-# CHECK-NEXT:   [0x0000000000000700, 0x0000000000000710): DW_OP_breg5 RDI+0
+# CHECK-NEXT:   [DW_LLE_offset_pair ]: 0x0000000000000000, 0x0000000000000010 => [0x0000000000000000, 0x0000000000000010) DW_OP_breg5 RDI+0
+# CHECK-NEXT:   [DW_LLE_base_address ]: 0x0000000000000500
+# CHECK-NEXT:   [DW_LLE_offset_pair ]: 0x0000000000000030, 0x0000000000000040 => [0x0000000000000530, 0x0000000000000540) DW_OP_breg6 RBP-8, DW_OP_deref
+# CHECK-NEXT:   [DW_LLE_start_length ]: 0x0000000000000700, 0x0000000000000010 => [0x0000000000000700, 0x0000000000000710) DW_OP_breg5 RDI+0
 
 .section  .debug_str,"MS",@progbits,1
   .asciz  "stub"
Index: test/DebugInfo/X86/dwarfdump-debug-loclists-error-cases2.s
===================================================================
--- test/DebugInfo/X86/dwarfdump-debug-loclists-error-cases2.s
+++ test/DebugInfo/X86/dwarfdump-debug-loclists-error-cases2.s
@@ -3,8 +3,8 @@
 
 # CHECK:      DW_AT_name        ("x0")
 # CHECK-NEXT: DW_AT_location    (0x0000000c
-# CHECK-NEXT:    [0x0000000000000000,  0x0000000000000002): DW_OP_reg5 RDI
-# CHECK-NEXT:    [0x0000000000000002,  0x0000000000000003): DW_OP_reg0 RAX)
+# CHECK-NEXT:    [0x0000000000000000,  0x0000000000000002) DW_OP_reg5 RDI
+# CHECK-NEXT:    [0x0000000000000002,  0x0000000000000003) DW_OP_reg0 RAX)
 
 # CHECK:      DW_AT_name        ("x1")
 # CHECK-NEXT: DW_AT_location    (0xdeadbeef
Index: test/CodeGen/X86/debug-loclists.ll
===================================================================
--- test/CodeGen/X86/debug-loclists.ll
+++ test/CodeGen/X86/debug-loclists.ll
@@ -3,8 +3,8 @@
 
 ; CHECK:      0x00000033: DW_TAG_formal_parameter [3]
 ; CHECK-NEXT:               DW_AT_location [DW_FORM_sec_offset]   (0x0000000c
-; CHECK-NEXT:                  [0x0000000000000000, 0x0000000000000004): DW_OP_breg5 RDI+0
-; CHECK-NEXT:                  [0x0000000000000004, 0x0000000000000012): DW_OP_breg3 RBX+0)
+; CHECK-NEXT:                  [0x0000000000000000, 0x0000000000000004) DW_OP_breg5 RDI+0
+; CHECK-NEXT:                  [0x0000000000000004, 0x0000000000000012) DW_OP_breg3 RBX+0)
 ; CHECK-NEXT:               DW_AT_name [DW_FORM_strx1]    (indexed (0000000e) string = "a")
 ; CHECK-NEXT:               DW_AT_decl_file [DW_FORM_data1]       ("/home/folder{{\\|\/}}test.cc")
 ; CHECK-NEXT:               DW_AT_decl_line [DW_FORM_data1]       (6)
@@ -13,36 +13,8 @@
 ; CHECK:      .debug_loclists contents:
 ; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000015, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 ; CHECK-NEXT: 0x00000000:
-; CHECK-NEXT:  [0x0000000000000000, 0x0000000000000004): DW_OP_breg5 RDI+0
-; CHECK-NEXT:  [0x0000000000000004, 0x0000000000000012): DW_OP_breg3 RBX+0
-
-; There is no way to use llvm-dwarfdump atm (2018, october) to verify the DW_LLE_* codes emited,
-; because dumper is not yet implements that. Use asm code to do this check instead.
-;
-; RUN: llc -mtriple=x86_64-pc-linux -filetype=asm < %s -o - | FileCheck %s --check-prefix=ASM
-; ASM:      .section .debug_loclists,"",@progbits
-; ASM-NEXT: .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length
-; ASM-NEXT: .Ldebug_loclist_table_start0:
-; ASM-NEXT:  .short 5                              # Version
-; ASM-NEXT:  .byte 8                               # Address size
-; ASM-NEXT:  .byte 0                               # Segment selector size
-; ASM-NEXT:  .long 0                               # Offset entry count
-; ASM-NEXT: .Lloclists_table_base0:                
-; ASM-NEXT: .Ldebug_loc0:
-; ASM-NEXT:  .byte 4                               # DW_LLE_offset_pair
-; ASM-NEXT:  .uleb128 .Lfunc_begin0-.Lfunc_begin0  # starting offset
-; ASM-NEXT:  .uleb128 .Ltmp0-.Lfunc_begin0         # ending offset
-; ASM-NEXT:  .byte 2                               # Loc expr size
-; ASM-NEXT:  .byte 117                             # DW_OP_breg5
-; ASM-NEXT:  .byte 0                               # 0
-; ASM-NEXT:  .byte 4                               # DW_LLE_offset_pair
-; ASM-NEXT:  .uleb128 .Ltmp0-.Lfunc_begin0         # starting offset
-; ASM-NEXT:  .uleb128 .Ltmp1-.Lfunc_begin0         # ending offset
-; ASM-NEXT:  .byte 2                               # Loc expr size
-; ASM-NEXT:  .byte 115                             # DW_OP_breg3
-; ASM-NEXT:  .byte 0                               # 0
-; ASM-NEXT:  .byte 0                               # DW_LLE_end_of_list
-; ASM-NEXT: .Ldebug_loclist_table_end0:
+; CHECK-NEXT:    [DW_LLE_offset_pair ]: 0x0000000000000000, 0x0000000000000004 => [0x0000000000000000, 0x0000000000000004) DW_OP_breg5 RDI+0
+; CHECK-NEXT:    [DW_LLE_offset_pair ]: 0x0000000000000004, 0x0000000000000012 => [0x0000000000000004, 0x0000000000000012) DW_OP_breg3 RBX+0
 
 ; ModuleID = 'test.cc'
 source_filename = "test.cc"
Index: lib/DebugInfo/DWARF/DWARFDie.cpp
===================================================================
--- lib/DebugInfo/DWARF/DWARFDie.cpp
+++ lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -92,27 +92,28 @@
   }
 
   FormValue.dump(OS, DumpOpts);
-  const auto &DumpLL = [&](auto ExpectedLL) {
-    if (ExpectedLL) {
-      uint64_t BaseAddr = 0;
-      if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
-        BaseAddr = BA->Address;
-      ExpectedLL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(),
-                       MRI, U, Indent);
-    } else {
+  const auto &DumpError = [&](Error E) {
       OS << '\n';
       OS.indent(Indent);
       OS << formatv("error extracting location list: {0}",
-                    fmt_consume(ExpectedLL.takeError()));
-    }
+                    fmt_consume(std::move(E)));
   };
   if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
     uint64_t Offset = *FormValue.getAsSectionOffset();
+
+    uint64_t BaseAddr = 0;
+    if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
+      BaseAddr = BA->Address;
+
     if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) {
       DWARFDebugLoc DebugLoc;
       DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(),
                               Obj.getAddressSize());
-      DumpLL(DebugLoc.parseOneLocationList(Data, &Offset));
+      if (auto ExpectedLL = DebugLoc.parseOneLocationList(Data, &Offset))
+        ExpectedLL->dump(OS, BaseAddr, Ctx.isLittleEndian(),
+                         Obj.getAddressSize(), MRI, U, Indent);
+      else
+        DumpError(ExpectedLL.takeError());
       return;
     }
 
@@ -128,8 +129,16 @@
       // Modern locations list (.debug_loclists) are used starting from v5.
       // Ideally we should take the version from the .debug_loclists section
       // header, but using CU's version for simplicity.
-      DumpLL(DWARFDebugLoclists::parseOneLocationList(
-          Data, &Offset, UseLocLists ? U->getVersion() : 4));
+      if (auto ExpectedLL = DWARFDebugLoclists::parseOneLocationList(
+          Data, &Offset, UseLocLists ? U->getVersion() : 4))
+        ExpectedLL->dump(
+            OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI,
+            DumpOpts,
+            [U](uint32_t Index) { return U->getAddrOffsetSectionItem(Index); },
+            U, Indent);
+      else
+        DumpError(ExpectedLL.takeError());
+
     }
   }
 }
Index: lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
===================================================================
--- lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -15,6 +15,8 @@
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -22,6 +24,7 @@
 #include <cstdint>
 
 using namespace llvm;
+using object::SectionedAddress;
 
 // When directly dumping the .debug_loc without a compile unit, we have to guess
 // at the DWARF version. This only affects DW_OP_call_ref, which is a rare
@@ -135,6 +138,66 @@
   }
 }
 
+Expected<DWARFLocation> DWARFDebugLoclists::EntryIterator::operator*() const {
+  const Entry &E = Entries.front();
+  DWARFLocation Result;
+  switch (E.Kind) {
+  case dwarf::DW_LLE_startx_length: {
+    auto Start = AddrOffsetResolver(E.Value0);
+    if (!Start)
+      return createStringError(errc::invalid_argument,
+                               "Failed to read address offset %u",
+                               unsigned(E.Value0));
+    Result.Range.LowPC = Start->Address;
+    Result.Range.HighPC = Start->Address + E.Value1;
+    Result.Range.SectionIndex = Start->SectionIndex;
+    break;
+  }
+  case dwarf::DW_LLE_start_length:
+    Result.Range.LowPC = E.Value0;
+    Result.Range.HighPC = E.Value0 + E.Value1;
+    // TODO: Store the SectionedAddress in the Entry class
+    Result.Range.SectionIndex = SectionedAddress::UndefSection;
+    break;
+  case dwarf::DW_LLE_offset_pair:
+    if (!BaseAddr)
+      return createStringError(errc::invalid_argument,
+                               "Cannot interpret DW_LLE_offset_pair entry due "
+                               "to missing base address");
+
+    Result.Range.LowPC = BaseAddr->Address + E.Value0;
+    Result.Range.HighPC = BaseAddr->Address + E.Value1;
+    Result.Range.SectionIndex = BaseAddr->SectionIndex;
+    break;
+  case dwarf::DW_LLE_base_address:
+  case dwarf::DW_LLE_base_addressx:
+    llvm_unreachable("Base address selection entries handled elsewhere!");
+  default:
+    // Entries rejected by the parser.
+    llvm_unreachable("Unsupported location list kind!");
+  }
+  Result.Location = E.Loc;
+  return Result;
+}
+
+void DWARFDebugLoclists::EntryIterator::processBaseAddressEntries() {
+  for (; !Entries.empty(); Entries = Entries.drop_front()) {
+    const Entry &E = Entries.front();
+    switch (E.Kind) {
+    case dwarf::DW_LLE_base_address:
+      // TODO: Store the SectionedAddress in the Entry class
+      BaseAddr->Address = E.Value0;
+      BaseAddr->SectionIndex = SectionedAddress::UndefSection;
+      break;
+    case dwarf::DW_LLE_base_addressx:
+      // Entry rejected by the parser.
+      llvm_unreachable("Unsupported location list kind!");
+    default:
+      return;
+    }
+  }
+}
+
 Expected<DWARFDebugLoclists::LocationList>
 DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data,
                                          uint64_t *Offset, unsigned Version) {
@@ -211,50 +274,77 @@
   return nullptr;
 }
 
-void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr,
-                                            bool IsLittleEndian,
-                                            unsigned AddressSize,
-                                            const MCRegisterInfo *MRI,
-                                            DWARFUnit *U,
-                                            unsigned Indent) const {
+iterator_range<DWARFDebugLoclists::EntryIterator>
+DWARFDebugLoclists::LocationList::getAbsoluteLocations(
+    Optional<SectionedAddress> BaseAddr, DWARFUnit &U) const {
+  return getAbsoluteLocations(BaseAddr, [&U](uint32_t Index) {
+    return U.getAddrOffsetSectionItem(Index);
+  });
+}
+
+void DWARFDebugLoclists::LocationList::dump(
+    raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian,
+    unsigned AddressSize, const MCRegisterInfo *MRI, DIDumpOptions DumpOpts,
+    function_ref<Optional<SectionedAddress>(uint32_t)> LookupPooledAddress,
+    DWARFUnit *U, unsigned Indent) const {
+  uint8_t MaxEncodingStringLength = 20;
+  EntryIterator Absolute =
+      getAbsoluteLocations(
+          SectionedAddress{BaseAddr, SectionedAddress::UndefSection},
+          LookupPooledAddress)
+          .begin();
   for (const Entry &E : Entries) {
-    switch (E.Kind) {
-    case dwarf::DW_LLE_startx_length:
-      OS << '\n';
-      OS.indent(Indent);
-      OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): ";
-      break;
-    case dwarf::DW_LLE_start_length:
-      OS << '\n';
-      OS.indent(Indent);
-      OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
-                   AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2,
-                   E.Value0 + E.Value1);
-      break;
-    case dwarf::DW_LLE_offset_pair:
-      OS << '\n';
-      OS.indent(Indent);
-      OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
-                   AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2,
-                   AddressSize * 2, BaseAddr + E.Value1);
-      break;
-    case dwarf::DW_LLE_base_address:
-      BaseAddr = E.Value0;
-      break;
-    default:
-      llvm_unreachable("unreachable locations list kind");
+    // We dump the raw encoding if we're in verbose mode, *or* if we failed to
+    // produce the absolute address range.
+    const auto &DumpEncoding = [&] {
+      OS << format("[%-*s]", MaxEncodingStringLength,
+                   dwarf::LocationListEncodingString(E.Kind).data());
+      if (E.Kind != dwarf::DW_LLE_end_of_list)
+        OS << ": ";
+      switch (E.Kind) {
+      case dwarf::DW_LLE_end_of_list:
+        // TODO: Generate these entries.
+        llvm_unreachable("unreachable locations list kind");
+      case dwarf::DW_LLE_base_address:
+        OS << format_hex(E.Value0, 2 + AddressSize * 2);
+        break;
+      case dwarf::DW_LLE_startx_length:
+      case dwarf::DW_LLE_start_length:
+      case dwarf::DW_LLE_offset_pair:
+        OS << format_hex(E.Value0, 2 + AddressSize * 2) << ", "
+           << format_hex(E.Value1, 2 + AddressSize * 2);
+      }
+    };
+    OS << "\n";
+    OS.indent(Indent);
+    if (DumpOpts.Verbose)
+      DumpEncoding();
+    if (E.Kind == dwarf::DW_LLE_base_address)
+      continue;
+    assert(Absolute.position() == &E);
+    if (auto ExpectedLocation = *Absolute) {
+      if (DumpOpts.Verbose)
+        OS << " => ";
+      ExpectedLocation->Range.dump(OS, AddressSize);
+    } else {
+      DumpEncoding();
+      OS << " => ";
+      OS << formatv("<{0}>", fmt_consume(ExpectedLocation.takeError()));
     }
-
+    ++Absolute;
+    OS << " ";
     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U);
   }
 }
 
 void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr,
-                              const MCRegisterInfo *MRI,
+                              const MCRegisterInfo *MRI, DIDumpOptions DumpOpts,
                               Optional<uint64_t> Offset) const {
   auto DumpLocationList = [&](const LocationList &L) {
     OS << format("0x%8.8" PRIx64 ": ", L.Offset);
-    L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, /*Indent=*/12);
+    L.dump(
+        OS, BaseAddr, IsLittleEndian, AddressSize, MRI, DumpOpts,
+        [](uint32_t Index) { return llvm::None; }, nullptr, /*Indent=*/12);
     OS << "\n\n";
   };
 
Index: lib/DebugInfo/DWARF/DWARFContext.cpp
===================================================================
--- lib/DebugInfo/DWARF/DWARFContext.cpp
+++ lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -303,7 +303,7 @@
                         Data.isLittleEndian(), Header.getAddrSize());
 
   Loclists.parse(LocData, Header.getVersion());
-  Loclists.dump(OS, 0, MRI, DumpOffset);
+  Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset);
 }
 
 void DWARFContext::dump(
@@ -390,7 +390,7 @@
   if (const auto *Off =
           shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
                      DObj->getLocDWOSection().Data)) {
-    getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), *Off);
+    getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), DumpOpts, *Off);
   }
 
   if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
Index: lib/BinaryFormat/Dwarf.cpp
===================================================================
--- lib/BinaryFormat/Dwarf.cpp
+++ lib/BinaryFormat/Dwarf.cpp
@@ -472,6 +472,31 @@
   }
 }
 
+StringRef llvm::dwarf::LocationListEncodingString(unsigned Entry) {
+  switch(Entry) {
+  default:
+    return StringRef();
+  case DW_LLE_end_of_list:
+    return "DW_LLE_end_of_list";
+  case DW_LLE_base_addressx:
+    return "DW_LLE_base_addressx";
+  case DW_LLE_startx_endx:
+    return "DW_LLE_startx_endx";
+  case DW_LLE_startx_length:
+    return "DW_LLE_startx_length";
+  case DW_LLE_offset_pair:
+    return "DW_LLE_offset_pair";
+  case DW_LLE_default_location:
+    return "DW_LLE_default_location";
+  case DW_LLE_base_address:
+    return "DW_LLE_base_address";
+  case DW_LLE_start_end:
+    return "DW_LLE_start_end";
+  case DW_LLE_start_length:
+    return "DW_LLE_start_length";
+  }
+}
+
 StringRef llvm::dwarf::CallFrameString(unsigned Encoding,
     Triple::ArchType Arch) {
   assert(Arch != llvm::Triple::ArchType::UnknownArch);
Index: include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
===================================================================
--- include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -11,6 +11,8 @@
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
 #include <cstdint>
@@ -20,6 +22,11 @@
 class MCRegisterInfo;
 class raw_ostream;
 
+struct DWARFLocation {
+  DWARFAddressRange Range;
+  ArrayRef<uint8_t> Location;
+};
+
 class DWARFDebugLoc {
 public:
   /// A single location within a location list.
@@ -81,12 +88,80 @@
     SmallVector<uint8_t, 4> Loc;
   };
 
+  class EntryIterator {
+  public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type = Expected<DWARFLocation>;
+    using difference_type = std::ptrdiff_t;
+    using pointer = value_type *;
+    using reference = value_type;
+
+    EntryIterator(
+        ArrayRef<Entry> Entries,
+        llvm::Optional<object::SectionedAddress> BaseAddr,
+        std::function<llvm::Optional<object::SectionedAddress>(uint32_t)>
+            AddrOffsetResolver)
+        : Entries(Entries), BaseAddr(BaseAddr),
+          AddrOffsetResolver(AddrOffsetResolver) {
+      processBaseAddressEntries();
+    }
+
+    Expected<DWARFLocation> operator*() const;
+
+    EntryIterator &operator++() {
+      Entries = Entries.drop_front();
+      processBaseAddressEntries();
+      return *this;
+    }
+
+    EntryIterator operator++(int) {
+      EntryIterator Save = *this;
+      ++*this;
+      return Save;
+    }
+
+    friend bool operator==(const EntryIterator &L, const EntryIterator &R) {
+      return L.Entries.begin() == R.Entries.begin();
+    }
+
+    friend bool operator!=(const EntryIterator &L, const EntryIterator &R) {
+      return !(L == R);
+    }
+
+    const Entry *position() const { return Entries.begin(); }
+
+  private:
+    void processBaseAddressEntries();
+
+    ArrayRef<Entry> Entries;
+    llvm::Optional<object::SectionedAddress> BaseAddr;
+    std::function<Optional<object::SectionedAddress>(uint32_t)>
+        AddrOffsetResolver;
+  };
+
   struct LocationList {
     uint64_t Offset;
     SmallVector<Entry, 2> Entries;
     void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian,
               unsigned AddressSize, const MCRegisterInfo *RegInfo,
+              DIDumpOptions DumpOpts,
+              function_ref<Optional<object::SectionedAddress>(uint32_t)>
+                  LookupPooledAddress,
               DWARFUnit *U, unsigned Indent) const;
+
+    iterator_range<EntryIterator> getAbsoluteLocations(
+        Optional<object::SectionedAddress> BaseAddr,
+        std::function<Optional<object::SectionedAddress>(uint32_t)>
+            AddrOffsetResolver) const {
+      return make_range(
+          EntryIterator(Entries, BaseAddr, std::move(AddrOffsetResolver)),
+          EntryIterator(makeArrayRef(Entries.end(), Entries.end()), llvm::None,
+                        {}));
+    }
+
+    iterator_range<EntryIterator>
+    getAbsoluteLocations(Optional<object::SectionedAddress> BaseAddr,
+                         DWARFUnit &U) const;
   };
 
 private:
@@ -101,7 +176,7 @@
 public:
   void parse(DataExtractor data, unsigned Version);
   void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo,
-            Optional<uint64_t> Offset) const;
+            DIDumpOptions DumpOpts, Optional<uint64_t> Offset) const;
 
   /// Return the location list at the given offset or nullptr.
   LocationList const *getLocationListAtOffset(uint64_t Offset) const;
Index: include/llvm/BinaryFormat/Dwarf.h
===================================================================
--- include/llvm/BinaryFormat/Dwarf.h
+++ include/llvm/BinaryFormat/Dwarf.h
@@ -475,6 +475,7 @@
 StringRef LNExtendedString(unsigned Encoding);
 StringRef MacinfoString(unsigned Encoding);
 StringRef RangeListEncodingString(unsigned Encoding);
+StringRef LocationListEncodingString(unsigned Entry);
 StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch);
 StringRef ApplePropertyString(unsigned);
 StringRef UnitTypeString(unsigned);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to