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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits