Skip to content

Commit deb116e

Browse files
committed
[DWARFDebugLine] Avoid dumping prologue members we did not parse
Summary: This patch if motivated by D74560, specifically the subthread about what to print upon encountering reserved initial length values. If the debug_line prologue has an unsupported version, we skip parsing the rest of the data. If we encounter an reserved initial length field, we don't even parse the version. However, we still print out all members (with value 0) in the dump function. This patch introduces early exits in the Prologue::dump function so that we print only the fields that were parsed successfully. In case of an unsupported version, we skip printing all subsequent prologue fields -- because we don't even know if this version has those fields. In case of a reserved unit length, we don't print anything -- if the very first field of the prologue is invalid, it's hard to say if we even have a prologue to begin with. Note that the user will still be able to see the invalid/reserved initial length value in the error message. I've modified (reordered) debug_line_invalid.test to show that the error message comes straight after the debug_line offset. I've also added some flush() calls to the dumping code to ensure this is the case in all situations (without that, the warnings could get out of sync if the output was not a terminal -- I guess this is why std::iostreams have the tie() function). Reviewers: jhenderson, ikudrin, dblaikie Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D75043
1 parent ec1efe7 commit deb116e

File tree

3 files changed

+65
-60
lines changed

3 files changed

+65
-60
lines changed

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,15 @@ void DWARFContext::dump(
474474
}
475475
OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())
476476
<< "]\n";
477+
OS.flush();
477478
if (DumpOpts.Verbose) {
478479
Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS);
479480
} else {
480481
DWARFDebugLine::LineTable LineTable =
481482
Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler);
482483
LineTable.dump(OS, DumpOpts);
483484
}
485+
OS.flush();
484486
}
485487
};
486488

llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
4242

4343
} // end anonymous namespace
4444

45+
static bool versionIsSupported(uint16_t Version) {
46+
return Version >= 2 && Version <= 5;
47+
}
48+
4549
void DWARFDebugLine::ContentTypeTracker::trackContentType(
4650
dwarf::LineNumberEntryFormat ContentType) {
4751
switch (ContentType) {
@@ -100,9 +104,13 @@ void DWARFDebugLine::Prologue::clear() {
100104

101105
void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
102106
DIDumpOptions DumpOptions) const {
107+
if (!totalLengthIsValid())
108+
return;
103109
OS << "Line table prologue:\n"
104110
<< format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength)
105111
<< format(" version: %u\n", getVersion());
112+
if (!versionIsSupported(getVersion()))
113+
return;
106114
if (getVersion() >= 5)
107115
OS << format(" address_size: %u\n", getAddressSize())
108116
<< format(" seg_select_size: %u\n", SegSelectorSize);
@@ -345,7 +353,7 @@ Error DWARFDebugLine::Prologue::parse(
345353
PrologueOffset, TotalLength);
346354
}
347355
FormParams.Version = DebugLineData.getU16(OffsetPtr);
348-
if (getVersion() < 2 || getVersion() > 5)
356+
if (!versionIsSupported(getVersion()))
349357
// Treat this error as unrecoverable - we cannot be sure what any of
350358
// the data represents including the length field, so cannot skip it or make
351359
// any reasonable assumptions.

llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test

Lines changed: 54 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,34 @@
33

44
## Show that a bad length stops parsing of the section.
55
# RUN: llvm-mc -triple x86_64-pc-linux %S/Inputs/debug_line_reserved_length.s -filetype=obj -o %t-reserved.o
6-
# RUN: llvm-dwarfdump -debug-line %t-reserved.o 2> %t-reserved.err \
7-
# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL
8-
# RUN: FileCheck %s --input-file=%t-reserved.err --check-prefix=RESERVED
9-
# RUN: llvm-dwarfdump -debug-line %t-reserved.o -verbose 2> %t-reserved-verbose.err \
10-
# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL
11-
# RUN: FileCheck %s --input-file=%t-reserved-verbose.err --check-prefix=RESERVED
6+
# RUN: llvm-dwarfdump -debug-line %t-reserved.o 2>&1 \
7+
# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL,RESERVED
8+
# RUN: llvm-dwarfdump -debug-line %t-reserved.o -verbose 2>&1 \
9+
# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL,RESERVED
1210

1311
## We only produce warnings for malformed tables after the specified unit if
1412
## parsing can continue.
15-
# RUN: llvm-dwarfdump -debug-line=0 %t-reserved.o 2> %t-reserved-off-first.err \
16-
# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER
17-
# RUN: FileCheck %s --input-file=%t-reserved-off-first.err --check-prefix=RESERVED
13+
# RUN: llvm-dwarfdump -debug-line=0 %t-reserved.o 2>&1 \
14+
# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER,RESERVED
1815

1916
## Stop looking for the specified unit, if a fatally-bad prologue is detected.
20-
# RUN: llvm-dwarfdump -debug-line=0x4b %t-reserved.o 2> %t-reserved-off-last.err \
21-
# RUN: | FileCheck %s --check-prefixes=NOFIRST,NOLATER
22-
# RUN: FileCheck %s --input-file=%t-reserved-off-last.err --check-prefix=RESERVED
17+
# RUN: llvm-dwarfdump -debug-line=0x4b %t-reserved.o 2>&1 \
18+
# RUN: | FileCheck %s --check-prefixes=NOFIRST,NOLATER,RESERVED
2319

2420
## Show that non-fatal errors do not prevent parsing the rest of the section.
2521
# RUN: llvm-mc -triple x86_64-pc-linux %S/Inputs/debug_line_malformed.s -filetype=obj -o %t-malformed.o
26-
# RUN: llvm-dwarfdump -debug-line %t-malformed.o 2> %t-malformed.err \
27-
# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]'
28-
# RUN: FileCheck %s --input-file=%t-malformed.err --check-prefixes=ALL,OTHER
29-
# RUN: llvm-dwarfdump -debug-line %t-malformed.o -verbose 2> %t-malformed-verbose.err \
30-
# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]'
31-
# RUN: FileCheck %s --input-file=%t-malformed-verbose.err --check-prefixes=ALL,OTHER
22+
# RUN: llvm-dwarfdump -debug-line %t-malformed.o 2>&1 \
23+
# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST,ALL,OTHER --implicit-check-not='debug_line[{{.*}}]'
24+
# RUN: llvm-dwarfdump -debug-line %t-malformed.o -verbose 2>&1 \
25+
# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST,ALL,OTHER --implicit-check-not='debug_line[{{.*}}]'
3226

3327
## We should still produce warnings for malformed tables after the specified unit.
34-
# RUN: llvm-dwarfdump -debug-line=0 %t-malformed.o 2> %t-malformed-off-first.err \
35-
# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER
36-
# RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL
28+
# RUN: llvm-dwarfdump -debug-line=0 %t-malformed.o 2>&1 \
29+
# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER,ALL
3730

3831
## Don't stop looking for the later unit if non-fatal issues are found.
39-
# RUN: llvm-dwarfdump -debug-line=0x3c9 %t-malformed.o 2> %t-malformed-off-last.err \
40-
# RUN: | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]'
41-
# RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL
32+
# RUN: llvm-dwarfdump -debug-line=0x3c9 %t-malformed.o 2>&1 \
33+
# RUN: | FileCheck %s --check-prefixes=LAST,ALL --implicit-check-not='debug_line[{{.*}}]'
4234

4335
# FIRST: debug_line[0x00000000]
4436
# FIRST: 0x000000000badbeef {{.*}} end_sequence
@@ -49,31 +41,44 @@
4941

5042
## For fatal issues, the following table(s) should not be dumped:
5143
# FATAL: debug_line[0x00000048]
52-
# FATAL-NEXT: Line table prologue
53-
# FATAL-NEXT: total_length: 0xfffffffe
44+
# RESERVED-NOT: prologue
45+
# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe
46+
# RESERVED-NOT: prologue
5447
# FATAL-NOT: debug_line
5548

5649
## For non-fatal issues, the table data should be dumped:
5750

5851
## Version 0 table.
5952
# NONFATAL: debug_line[0x00000048]
53+
# ALL: warning: parsing line table prologue at offset 0x00000048 found unsupported version 0
6054
# NONFATAL-NEXT: Line table prologue
61-
# NONFATAL-NOT: Address
55+
# NONFATAL-NEXT: total_length: 0x00000002
56+
# NONFATAL-NEXT: version: 0
57+
# NONFATAL-NOT: prologue_length
6258

6359
## Version 1 table.
6460
# NONFATAL: debug_line[0x0000004e]
61+
# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 1
6562
# NONFATAL-NEXT: Line table prologue
66-
# NONFATAL-NOT: Address
63+
# NONFATAL-NEXT: total_length: 0x00000002
64+
# NONFATAL-NEXT: version: 1
65+
# NONFATAL-NOT: prologue_length
6766

6867
## Malformed directory format with no path component.
6968
# NONFATAL: debug_line[0x00000054]
69+
# ALL-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073
70+
# ALL-NEXT: warning: failed to parse entry content descriptions because no path was found
7071
# NONFATAL-NEXT: Line table prologue
72+
# NONFATAL: prologue_length: 0x00000013
7173
# NONFATAL-NOT: include_directories
7274
# NONFATAL-NOT: file_names
7375
# NONFATAL: 0x8877665544332211 {{.*}} end_sequence
7476

7577
## Prologue with length shorter than parsed.
7678
# NONFATAL: debug_line[0x00000081]
79+
# ALL-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000ba
80+
# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue
81+
# ALL-NEXT: warning: parsing line table prologue at 0x00000081 should have ended at 0x000000b9 but it ended at 0x000000ba
7782
# NONFATAL-NEXT: Line table prologue
7883
# NONFATAL: file_names[ 2]:
7984
# NONFATAL-NEXT: name: "file2"
@@ -84,6 +89,7 @@
8489

8590
## Prologue with length longer than parsed.
8691
# NONFATAL: debug_line[0x000000c8]
92+
# ALL-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102
8793
# NONFATAL-NEXT: Line table prologue
8894
# NONFATAL: file_names[ 2]:
8995
# NONFATAL-NEXT: name: "file2"
@@ -95,18 +101,24 @@
95101

96102
## Extended opcode with incorrect length versus expected.
97103
# NONFATAL: debug_line[0x00000111]
104+
# OTHER-NEXT: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01
105+
# OTHER-NEXT: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02
98106
# NONFATAL-NEXT: Line table prologue
107+
# NONFATAL: prologue_length: 0x00000030
99108
# NONFATAL: 0x00000000abbadaba {{.*}} end_sequence
100109
# NONFATAL: 0x00000000babb1e45 {{.*}} 10 is_stmt prologue_end end_sequence{{$}}
101110

102111
## No end of sequence.
103112
# NONFATAL: debug_line[0x0000016c]
113+
# OTHER-NEXT: warning: last sequence in debug line table at offset 0x0000016c is not terminated
104114
# NONFATAL-NEXT: Line table prologue
115+
# NONFATAL: prologue_length: 0x00000030
105116
# NONFATAL: 0x00000000deadfade {{.*}} is_stmt
106117
# NONFATAL-NOT: end_sequence
107118

108119
## Very short prologue length for V5 (ends during parameters).
109120
# NONFATAL: debug_line[0x000001b2]
121+
# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1
110122
# NONFATAL-NEXT: Line table prologue
111123
# NONFATAL: standard_opcode_lengths[DW_LNS_set_isa] = 1
112124
# NONFATAL-NEXT: include_directories[ 0] = "/tmp"
@@ -117,6 +129,7 @@
117129

118130
## V5 prologue ends during file table.
119131
# NONFATAL: debug_line[0x000001ee]
132+
# ALL-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220
120133
# NONFATAL-NEXT: Line table prologue
121134
# NONFATAL: include_directories[ 0] = "/tmp"
122135
# NONFATAL-NEXT: file_names[ 0]:
@@ -127,6 +140,7 @@
127140

128141
## V5 prologue ends during directory table.
129142
# NONFATAL: debug_line[0x0000022f]
143+
# ALL-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e
130144
# NONFATAL-NEXT: Line table prologue
131145
# NONFATAL: include_directories[ 0] = "/tmp"
132146
# NONFATAL-NEXT: file_names[ 0]:
@@ -136,6 +150,8 @@
136150

137151
## V5 invalid MD5 hash form when there is still data to be read.
138152
# NONFATAL: debug_line[0x0000026b]
153+
# ALL-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f
154+
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
139155
# NONFATAL-NEXT: Line table prologue
140156
# NONFATAL: include_directories[ 0] = "/tmp"
141157
# NONFATAL-NOT: file_names
@@ -145,6 +161,9 @@
145161
## V5 invalid MD5 hash form when data beyond the prologue length has
146162
## been read before the MD5 problem is identified.
147163
# NONFATAL: debug_line[0x000002ae]
164+
# ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0
165+
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
166+
# ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0
148167
# NONFATAL-NEXT: Line table prologue
149168
# NONFATAL: include_directories[ 0] = "/tmp"
150169
# NONFATAL-NOT: file_names
@@ -153,6 +172,8 @@
153172

154173
## V5 invalid directory content description has unsupported form.
155174
# NONFATAL: debug_line[0x000002ec]
175+
# ALL-NEXT: warning: parsing line table prologue at 0x000002ec found an invalid directory or file table description at 0x00000315
176+
# ALL-NEXT: warning: failed to parse directory entry because skipping the form value failed.
156177
# NONFATAL-NEXT: Line table prologue
157178
# NONFATAL: include_directories[ 0] = "/foo"
158179
# NONFATAL-NOT: include_directories
@@ -161,6 +182,7 @@
161182

162183
## Opcode base field of value zero.
163184
# NONFATAL: debug_line[0x00000332]
185+
# ALL-NEXT: warning: parsing line table prologue at offset 0x00000332 found opcode base of 0. Assuming no standard opcodes
164186
# NONFATAL-NEXT: Line table prologue
165187
# NONFATAL: include_directories[ 1] = "dir1"
166188
# NONFATAL-NEXT: file_names[ 1]:
@@ -173,13 +195,17 @@
173195

174196
## V4 table with unterminated include directory table.
175197
# NONFATAL: debug_line[0x00000361]
198+
# ALL-NEXT: warning: parsing line table prologue at 0x00000361 found an invalid directory or file table description at 0x00000382
199+
# ALL-NEXT: warning: include directories table was not null terminated before the end of the prologue
176200
# NONFATAL-NEXT: Line table prologue
177201
# NONFATAL: include_directories[ 1] = "dir1"
178202
# NONFATAL-NOT: file_names
179203
# NONFATAL: 0xabcdef0123456789 {{.*}} is_stmt end_sequence
180204

181205
## V4 table with unterminated file name table.
182206
# NONFATAL: debug_line[0x00000390]
207+
# ALL-NEXT: warning: parsing line table prologue at 0x00000390 found an invalid directory or file table description at 0x000003bb
208+
# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue
183209
# NONFATAL-NEXT: Line table prologue
184210
# NONFATAL: file_names[ 1]:
185211
# NONFATAL-NEXT: name: "foo.c"
@@ -191,34 +217,3 @@
191217

192218
# LAST: debug_line[0x000003c9]
193219
# LAST: 0x00000000cafebabe {{.*}} end_sequence
194-
195-
# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe
196-
197-
# ALL-NOT: warning:
198-
# ALL: warning: parsing line table prologue at offset 0x00000048 found unsupported version 0
199-
# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 1
200-
# ALL-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073
201-
# ALL-NEXT: warning: failed to parse entry content descriptions because no path was found
202-
# ALL-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000ba
203-
# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue
204-
# ALL-NEXT: warning: parsing line table prologue at 0x00000081 should have ended at 0x000000b9 but it ended at 0x000000ba
205-
# ALL-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102
206-
# OTHER-NEXT: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01
207-
# OTHER-NEXT: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02
208-
# OTHER-NEXT: warning: last sequence in debug line table at offset 0x0000016c is not terminated
209-
# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1
210-
# ALL-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220
211-
# ALL-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e
212-
# ALL-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f
213-
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
214-
# ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0
215-
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
216-
# ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0
217-
# ALL-NEXT: warning: parsing line table prologue at 0x000002ec found an invalid directory or file table description at 0x00000315
218-
# ALL-NEXT: warning: failed to parse directory entry because skipping the form value failed.
219-
# ALL-NEXT: warning: parsing line table prologue at offset 0x00000332 found opcode base of 0. Assuming no standard opcodes
220-
# ALL-NEXT: warning: parsing line table prologue at 0x00000361 found an invalid directory or file table description at 0x00000382
221-
# ALL-NEXT: warning: include directories table was not null terminated before the end of the prologue
222-
# ALL-NEXT: warning: parsing line table prologue at 0x00000390 found an invalid directory or file table description at 0x000003bb
223-
# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue
224-
# ALL-NOT: warning:

0 commit comments

Comments
 (0)