Skip to content

Commit 88b4e28

Browse files
committed
DWARF: Fix a regression in location list dumping
Summary: While fixing the handling of some error cases, r370363 introduced new problems -- assertion failures due to unchecked errors (my excuse is that a very early version of that patch used Optional<T> instead of Expected). This patch adds proper handling of parsing errors encountered when dumping location lists from inside DWARF DIEs, and adds a bunch of additional tests. I reorder the arguments of the location list dumping functions to make them consistent, and also be able to dump the two kinds of location lists generically. Reviewers: JDevlieghere, dblaikie, probinson Subscribers: aprantl, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67102 llvm-svn: 370868
1 parent aae9972 commit 88b4e28

File tree

5 files changed

+277
-28
lines changed

5 files changed

+277
-28
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class DWARFDebugLoc {
4040
/// All the locations in which the variable is stored.
4141
SmallVector<Entry, 2> Entries;
4242
/// Dump this list on OS.
43-
void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
44-
const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress,
43+
void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian,
44+
unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U,
4545
unsigned Indent) const;
4646
};
4747

llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data,
3535
DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
3636
}
3737

38-
void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
38+
void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress,
39+
bool IsLittleEndian,
3940
unsigned AddressSize,
40-
const MCRegisterInfo *MRI,
41-
DWARFUnit *U,
42-
uint64_t BaseAddress,
41+
const MCRegisterInfo *MRI, DWARFUnit *U,
4342
unsigned Indent) const {
4443
for (const Entry &E : Entries) {
4544
OS << '\n';
@@ -67,7 +66,7 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
6766
Optional<uint64_t> Offset) const {
6867
auto DumpLocationList = [&](const LocationList &L) {
6968
OS << format("0x%8.8" PRIx64 ": ", L.Offset);
70-
L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12);
69+
L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, 12);
7170
OS << "\n\n";
7271
};
7372

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

+18-21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/Object/ObjectFile.h"
2222
#include "llvm/Support/DataExtractor.h"
2323
#include "llvm/Support/Format.h"
24+
#include "llvm/Support/FormatAdapters.h"
2425
#include "llvm/Support/FormatVariadic.h"
2526
#include "llvm/Support/MathExtras.h"
2627
#include "llvm/Support/WithColor.h"
@@ -91,21 +92,27 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
9192
}
9293

9394
FormValue.dump(OS, DumpOpts);
95+
const auto &DumpLL = [&](auto ExpectedLL) {
96+
if (ExpectedLL) {
97+
uint64_t BaseAddr = 0;
98+
if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
99+
BaseAddr = BA->Address;
100+
ExpectedLL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(),
101+
MRI, U, Indent);
102+
} else {
103+
OS << '\n';
104+
OS.indent(Indent);
105+
OS << formatv("error extracting location list: {0}",
106+
fmt_consume(ExpectedLL.takeError()));
107+
}
108+
};
94109
if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
95110
uint64_t Offset = *FormValue.getAsSectionOffset();
96111
if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) {
97112
DWARFDebugLoc DebugLoc;
98113
DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(),
99114
Obj.getAddressSize());
100-
auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
101-
if (LL) {
102-
uint64_t BaseAddr = 0;
103-
if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
104-
BaseAddr = BA->Address;
105-
LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U,
106-
BaseAddr, Indent);
107-
} else
108-
OS << "error extracting location list.";
115+
DumpLL(DebugLoc.parseOneLocationList(Data, &Offset));
109116
return;
110117
}
111118

@@ -121,18 +128,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
121128
// Modern locations list (.debug_loclists) are used starting from v5.
122129
// Ideally we should take the version from the .debug_loclists section
123130
// header, but using CU's version for simplicity.
124-
auto LL = DWARFDebugLoclists::parseOneLocationList(
125-
Data, &Offset, UseLocLists ? U->getVersion() : 4);
126-
127-
uint64_t BaseAddr = 0;
128-
if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
129-
BaseAddr = BA->Address;
130-
131-
if (LL)
132-
LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI,
133-
U, Indent);
134-
else
135-
OS << "error extracting location list.";
131+
DumpLL(DWARFDebugLoclists::parseOneLocationList(
132+
Data, &Offset, UseLocLists ? U->getVersion() : 4));
136133
}
137134
}
138135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t
2+
# RUN: llvm-dwarfdump %t | FileCheck %s
3+
4+
# CHECK: DW_AT_name ("x0")
5+
# CHECK-NEXT: DW_AT_location (0x00000000
6+
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000002): DW_OP_reg5 RDI
7+
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg0 RAX)
8+
9+
# CHECK: DW_AT_name ("x1")
10+
# CHECK-NEXT: DW_AT_location (0xdeadbeef
11+
# CHECK-NEXT: error extracting location list: unexpected end of data)
12+
13+
# CHECK: DW_AT_name ("x2")
14+
# CHECK-NEXT: DW_AT_location (0x00000036
15+
# CHECK-NEXT: error extracting location list: unexpected end of data)
16+
17+
18+
.type f,@function
19+
f: # @f
20+
.Lfunc_begin0:
21+
movl %edi, %eax
22+
.Ltmp0:
23+
retq
24+
.Ltmp1:
25+
.Lfunc_end0:
26+
.size f, .Lfunc_end0-f
27+
28+
.section .debug_str,"MS",@progbits,1
29+
.Linfo_string0:
30+
.asciz "Hand-written DWARF"
31+
.Linfo_string3:
32+
.asciz "f"
33+
.Linfo_string4:
34+
.asciz "int"
35+
.Lx0:
36+
.asciz "x0"
37+
.Lx1:
38+
.asciz "x1"
39+
.Lx2:
40+
.asciz "x2"
41+
42+
.section .debug_loc,"",@progbits
43+
.Ldebug_loc0:
44+
.quad .Lfunc_begin0-.Lfunc_begin0
45+
.quad .Ltmp0-.Lfunc_begin0
46+
.short 1 # Loc expr size
47+
.byte 85 # super-register DW_OP_reg5
48+
.quad .Ltmp0-.Lfunc_begin0
49+
.quad .Lfunc_end0-.Lfunc_begin0
50+
.short 1 # Loc expr size
51+
.byte 80 # super-register DW_OP_reg0
52+
.quad 0
53+
.quad 0
54+
.Ldebug_loc2:
55+
.quad .Lfunc_begin0-.Lfunc_begin0
56+
.quad .Lfunc_end0-.Lfunc_begin0
57+
.short 0xdead # Loc expr size
58+
59+
.section .debug_abbrev,"",@progbits
60+
.byte 1 # Abbreviation Code
61+
.byte 17 # DW_TAG_compile_unit
62+
.byte 1 # DW_CHILDREN_yes
63+
.byte 37 # DW_AT_producer
64+
.byte 14 # DW_FORM_strp
65+
.byte 19 # DW_AT_language
66+
.byte 5 # DW_FORM_data2
67+
.byte 0 # EOM(1)
68+
.byte 0 # EOM(2)
69+
.byte 2 # Abbreviation Code
70+
.byte 46 # DW_TAG_subprogram
71+
.byte 1 # DW_CHILDREN_yes
72+
.byte 3 # DW_AT_name
73+
.byte 14 # DW_FORM_strp
74+
.byte 0 # EOM(1)
75+
.byte 0 # EOM(2)
76+
.byte 3 # Abbreviation Code
77+
.byte 5 # DW_TAG_formal_parameter
78+
.byte 0 # DW_CHILDREN_no
79+
.byte 3 # DW_AT_name
80+
.byte 14 # DW_FORM_strp
81+
.byte 2 # DW_AT_location
82+
.byte 23 # DW_FORM_sec_offset
83+
.byte 0 # EOM(1)
84+
.byte 0 # EOM(2)
85+
.byte 4 # Abbreviation Code
86+
.byte 36 # DW_TAG_base_type
87+
.byte 0 # DW_CHILDREN_no
88+
.byte 3 # DW_AT_name
89+
.byte 14 # DW_FORM_strp
90+
.byte 62 # DW_AT_encoding
91+
.byte 11 # DW_FORM_data1
92+
.byte 11 # DW_AT_byte_size
93+
.byte 11 # DW_FORM_data1
94+
.byte 0 # EOM(1)
95+
.byte 0 # EOM(2)
96+
.byte 0 # EOM(3)
97+
98+
.section .debug_info,"",@progbits
99+
.Lcu_begin0:
100+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
101+
.Ldebug_info_start0:
102+
.short 4 # DWARF version number
103+
.long .debug_abbrev # Offset Into Abbrev. Section
104+
.byte 8 # Address Size (in bytes)
105+
.byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit
106+
.long .Linfo_string0 # DW_AT_producer
107+
.short 12 # DW_AT_language
108+
.byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram
109+
.long .Linfo_string3 # DW_AT_name
110+
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
111+
.long .Lx0 # DW_AT_name
112+
.long .Ldebug_loc0 # DW_AT_location
113+
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
114+
.long .Lx1 # DW_AT_name
115+
.long 0xdeadbeef # DW_AT_location
116+
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
117+
.long .Lx2 # DW_AT_name
118+
.long .Ldebug_loc2 # DW_AT_location
119+
.byte 0 # End Of Children Mark
120+
.byte 0 # End Of Children Mark
121+
.Ldebug_info_end0:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t
2+
# RUN: llvm-dwarfdump %t | FileCheck %s
3+
4+
# CHECK: DW_AT_name ("x0")
5+
# CHECK-NEXT: DW_AT_location (0x0000000c
6+
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000002): DW_OP_reg5 RDI
7+
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg0 RAX)
8+
9+
# CHECK: DW_AT_name ("x1")
10+
# CHECK-NEXT: DW_AT_location (0xdeadbeef
11+
# CHECK-NEXT: error extracting location list: unexpected end of data)
12+
13+
# CHECK: DW_AT_name ("x2")
14+
# CHECK-NEXT: DW_AT_location (0x00000025
15+
# CHECK-NEXT: error extracting location list: unexpected end of data)
16+
17+
18+
.type f,@function
19+
f: # @f
20+
.Lfunc_begin0:
21+
movl %edi, %eax
22+
.Ltmp0:
23+
retq
24+
.Ltmp1:
25+
.Lfunc_end0:
26+
.size f, .Lfunc_end0-f
27+
28+
.section .debug_str,"MS",@progbits,1
29+
.Linfo_string0:
30+
.asciz "Hand-written DWARF"
31+
.Linfo_string3:
32+
.asciz "f"
33+
.Linfo_string4:
34+
.asciz "int"
35+
.Lx0:
36+
.asciz "x0"
37+
.Lx1:
38+
.asciz "x1"
39+
.Lx2:
40+
.asciz "x2"
41+
42+
.section .debug_loclists,"",@progbits
43+
.long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length
44+
.Ldebug_loclist_table_start0:
45+
.short 5 # Version
46+
.byte 8 # Address size
47+
.byte 0 # Segment selector size
48+
.long 0 # Offset entry count
49+
.Lloclists_table_base0:
50+
.Ldebug_loc0:
51+
.byte 8 # DW_LLE_start_length
52+
.quad .Lfunc_begin0-.Lfunc_begin0 # starting offset
53+
.uleb128 .Ltmp0-.Lfunc_begin0 # size
54+
.byte 1 # Loc expr size
55+
.byte 85 # super-register DW_OP_reg5
56+
.byte 8 # DW_LLE_start_length
57+
.quad .Ltmp0-.Lfunc_begin0 # starting offset
58+
.uleb128 .Lfunc_end0-.Ltmp0 # size
59+
.byte 1 # Loc expr size
60+
.byte 80 # super-register DW_OP_reg0
61+
.byte 0 # DW_LLE_end_of_list
62+
.Ldebug_loc2:
63+
.byte 8 # DW_LLE_start_length
64+
.quad .Lfunc_begin0-.Lfunc_begin0 # starting offset
65+
.uleb128 .Ltmp0-.Lfunc_begin0 # size
66+
.uleb128 0xdeadbeef # Loc expr size
67+
.Ldebug_loclist_table_end0:
68+
69+
.section .debug_abbrev,"",@progbits
70+
.byte 1 # Abbreviation Code
71+
.byte 17 # DW_TAG_compile_unit
72+
.byte 1 # DW_CHILDREN_yes
73+
.byte 37 # DW_AT_producer
74+
.byte 14 # DW_FORM_strp
75+
.byte 19 # DW_AT_language
76+
.byte 5 # DW_FORM_data2
77+
.byte 0 # EOM(1)
78+
.byte 0 # EOM(2)
79+
.byte 2 # Abbreviation Code
80+
.byte 46 # DW_TAG_subprogram
81+
.byte 1 # DW_CHILDREN_yes
82+
.byte 3 # DW_AT_name
83+
.byte 14 # DW_FORM_strp
84+
.byte 0 # EOM(1)
85+
.byte 0 # EOM(2)
86+
.byte 3 # Abbreviation Code
87+
.byte 5 # DW_TAG_formal_parameter
88+
.byte 0 # DW_CHILDREN_no
89+
.byte 3 # DW_AT_name
90+
.byte 14 # DW_FORM_strp
91+
.byte 2 # DW_AT_location
92+
.byte 23 # DW_FORM_sec_offset
93+
.byte 0 # EOM(1)
94+
.byte 0 # EOM(2)
95+
.byte 4 # Abbreviation Code
96+
.byte 36 # DW_TAG_base_type
97+
.byte 0 # DW_CHILDREN_no
98+
.byte 3 # DW_AT_name
99+
.byte 14 # DW_FORM_strp
100+
.byte 62 # DW_AT_encoding
101+
.byte 11 # DW_FORM_data1
102+
.byte 11 # DW_AT_byte_size
103+
.byte 11 # DW_FORM_data1
104+
.byte 0 # EOM(1)
105+
.byte 0 # EOM(2)
106+
.byte 0 # EOM(3)
107+
108+
.section .debug_info,"",@progbits
109+
.Lcu_begin0:
110+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
111+
.Ldebug_info_start0:
112+
.short 5 # DWARF version number
113+
.byte 1 # DWARF Unit Type
114+
.byte 8 # Address Size (in bytes)
115+
.long .debug_abbrev # Offset Into Abbrev. Section
116+
.byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit
117+
.long .Linfo_string0 # DW_AT_producer
118+
.short 12 # DW_AT_language
119+
.byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram
120+
.long .Linfo_string3 # DW_AT_name
121+
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
122+
.long .Lx0 # DW_AT_name
123+
.long .Ldebug_loc0 # DW_AT_location
124+
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
125+
.long .Lx1 # DW_AT_name
126+
.long 0xdeadbeef # DW_AT_location
127+
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
128+
.long .Lx2 # DW_AT_name
129+
.long .Ldebug_loc2 # DW_AT_location
130+
.byte 0 # End Of Children Mark
131+
.byte 0 # End Of Children Mark
132+
.Ldebug_info_end0:

0 commit comments

Comments
 (0)