1 //===- DWARFDebugLineTest.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "DwarfGenerator.h"
10 #include "DwarfUtils.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
13 #include "llvm/Object/ObjectFile.h"
14 #include "llvm/Testing/Support/Error.h"
15 #include "gtest/gtest.h"
18 using namespace dwarf
;
19 using namespace dwarfgen
;
20 using namespace object
;
21 using namespace utils
;
22 using namespace testing
;
25 struct CommonFixture
{
27 : LineData("", true, 0), Recoverable(Error::success()),
28 RecordRecoverable(std::bind(&CommonFixture::recordRecoverable
, this,
29 std::placeholders::_1
)),
30 Unrecoverable(Error::success()),
31 RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable
, this,
32 std::placeholders::_1
)){};
35 EXPECT_FALSE(Recoverable
);
36 EXPECT_FALSE(Unrecoverable
);
39 bool setupGenerator(uint16_t Version
= 4) {
40 Triple T
= getDefaultTargetTripleForAddrSize(8);
41 if (!isConfigurationSupported(T
))
43 auto ExpectedGenerator
= Generator::create(T
, Version
);
44 if (ExpectedGenerator
)
45 Gen
.reset(ExpectedGenerator
->release());
50 Context
= createContext();
51 assert(Context
!= nullptr && "test state is not valid");
52 const DWARFObject
&Obj
= Context
->getDWARFObj();
53 LineData
= DWARFDataExtractor(
54 Obj
, Obj
.getLineSection(),
55 getDefaultTargetTripleForAddrSize(8).isLittleEndian(), 8);
58 std::unique_ptr
<DWARFContext
> createContext() {
61 StringRef FileBytes
= Gen
->generate();
62 MemoryBufferRef
FileBuffer(FileBytes
, "dwarf");
63 auto Obj
= object::ObjectFile::createObjectFile(FileBuffer
);
65 return DWARFContext::create(**Obj
);
69 DWARFDebugLine::SectionParser
setupParser() {
70 LineTable
<
= Gen
->addLineTable(DWARF32
);
71 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
72 LT
.addStandardOpcode(DW_LNS_copy
, {});
74 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
76 LineTable
<2
= Gen
->addLineTable(DWARF64
);
77 LT2
.addExtendedOpcode(9, DW_LNE_set_address
,
78 {{0x11223344, LineTable::Quad
}});
79 LT2
.addStandardOpcode(DW_LNS_copy
, {});
81 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
85 return DWARFDebugLine::SectionParser(LineData
, *Context
, CUs
, TUs
);
88 void recordRecoverable(Error Err
) {
89 Recoverable
= joinErrors(std::move(Recoverable
), std::move(Err
));
91 void recordUnrecoverable(Error Err
) {
92 Unrecoverable
= joinErrors(std::move(Unrecoverable
), std::move(Err
));
95 void checkError(ArrayRef
<StringRef
> ExpectedMsgs
, Error Err
) {
96 ASSERT_TRUE(Err
.operator bool());
99 handleErrors(std::move(Err
), [&](const ErrorInfoBase
&Actual
) {
100 ASSERT_LT(WhichMsg
, ExpectedMsgs
.size());
101 // Use .str(), because googletest doesn't visualise a StringRef
103 EXPECT_EQ(Actual
.message(), ExpectedMsgs
[WhichMsg
++].str());
105 EXPECT_EQ(WhichMsg
, ExpectedMsgs
.size());
106 EXPECT_FALSE(Remaining
);
109 void checkError(StringRef ExpectedMsg
, Error Err
) {
110 checkError(ArrayRef
<StringRef
>{ExpectedMsg
}, std::move(Err
));
113 void checkGetOrParseLineTableEmitsError(StringRef ExpectedMsg
,
114 uint64_t Offset
= 0) {
115 auto ExpectedLineTable
= Line
.getOrParseLineTable(
116 LineData
, Offset
, *Context
, nullptr, RecordRecoverable
);
117 EXPECT_FALSE(ExpectedLineTable
);
118 EXPECT_FALSE(Recoverable
);
120 checkError(ExpectedMsg
, ExpectedLineTable
.takeError());
123 void checkGetOrParseLineTableEmitsError(ArrayRef
<StringRef
> ExpectedMsgs
,
124 uint64_t Offset
= 0) {
125 auto ExpectedLineTable
= Line
.getOrParseLineTable(
126 LineData
, Offset
, *Context
, nullptr, RecordRecoverable
);
127 EXPECT_FALSE(ExpectedLineTable
);
128 EXPECT_FALSE(Recoverable
);
130 checkError(ExpectedMsgs
, ExpectedLineTable
.takeError());
133 std::unique_ptr
<Generator
> Gen
;
134 std::unique_ptr
<DWARFContext
> Context
;
135 DWARFDataExtractor LineData
;
138 std::function
<void(Error
)> RecordRecoverable
;
140 std::function
<void(Error
)> RecordUnrecoverable
;
142 SmallVector
<std::unique_ptr
<DWARFUnit
>, 2> CUs
;
143 SmallVector
<std::unique_ptr
<DWARFUnit
>, 2> TUs
;
146 // Fixtures must derive from "Test", but parameterised fixtures from
147 // "TestWithParam". It does not seem possible to inherit from both, so we share
148 // the common state in a separate class, inherited by the two fixture classes.
149 struct DebugLineBasicFixture
: public Test
, public CommonFixture
{};
151 struct DebugLineParameterisedFixture
152 : public TestWithParam
<std::pair
<uint16_t, DwarfFormat
>>,
153 public CommonFixture
{
154 void SetUp() { std::tie(Version
, Format
) = GetParam(); }
160 void checkDefaultPrologue(uint16_t Version
, DwarfFormat Format
,
161 DWARFDebugLine::Prologue Prologue
,
162 uint64_t BodyLength
) {
163 // Check version specific fields and values.
165 uint64_t PrologueLength
;
169 UnitLength
= PrologueLength
+ 2;
170 EXPECT_EQ(Prologue
.MaxOpsPerInst
, 1u);
175 UnitLength
= PrologueLength
+ 2;
179 UnitLength
= PrologueLength
+ 4;
180 EXPECT_EQ(Prologue
.getAddressSize(), 8u);
181 EXPECT_EQ(Prologue
.SegSelectorSize
, 0u);
184 llvm_unreachable("unsupported DWARF version");
186 UnitLength
+= BodyLength
+ (Format
== DWARF32
? 4 : 8);
188 EXPECT_EQ(Prologue
.TotalLength
, UnitLength
);
189 EXPECT_EQ(Prologue
.PrologueLength
, PrologueLength
);
190 EXPECT_EQ(Prologue
.MinInstLength
, 1u);
191 EXPECT_EQ(Prologue
.DefaultIsStmt
, 1u);
192 EXPECT_EQ(Prologue
.LineBase
, -5);
193 EXPECT_EQ(Prologue
.LineRange
, 14u);
194 EXPECT_EQ(Prologue
.OpcodeBase
, 13u);
195 std::vector
<uint8_t> ExpectedLengths
= {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
196 EXPECT_EQ(Prologue
.StandardOpcodeLengths
, ExpectedLengths
);
197 ASSERT_EQ(Prologue
.IncludeDirectories
.size(), 1u);
198 ASSERT_EQ(Prologue
.IncludeDirectories
[0].getForm(), DW_FORM_string
);
199 EXPECT_STREQ(*Prologue
.IncludeDirectories
[0].getAsCString(), "a dir");
200 ASSERT_EQ(Prologue
.FileNames
.size(), 1u);
201 ASSERT_EQ(Prologue
.FileNames
[0].Name
.getForm(), DW_FORM_string
);
202 EXPECT_STREQ(*Prologue
.FileNames
[0].Name
.getAsCString(), "a file");
205 TEST_F(DebugLineBasicFixture
, GetOrParseLineTableAtInvalidOffset
) {
206 if (!setupGenerator())
210 checkGetOrParseLineTableEmitsError(
211 "offset 0x00000000 is not a valid debug line section offset", 0);
212 // Repeat to show that an error is reported each time.
213 checkGetOrParseLineTableEmitsError(
214 "offset 0x00000000 is not a valid debug line section offset", 0);
215 // Show that an error is reported for later offsets too.
216 checkGetOrParseLineTableEmitsError(
217 "offset 0x00000001 is not a valid debug line section offset", 1);
220 TEST_F(DebugLineBasicFixture
, GetOrParseLineTableAtInvalidOffsetAfterData
) {
221 if (!setupGenerator())
224 LineTable
<
= Gen
->addLineTable();
225 LT
.setCustomPrologue({{0, LineTable::Byte
}});
229 checkGetOrParseLineTableEmitsError(
230 "offset 0x00000001 is not a valid debug line section offset", 1);
233 TEST_P(DebugLineParameterisedFixture
, GetOrParseLineTableValidTable
) {
234 if (!setupGenerator(Version
))
237 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
238 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
240 LineTable
<
= Gen
->addLineTable(Format
);
241 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
242 LT
.addStandardOpcode(DW_LNS_copy
, {});
244 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
246 LineTable
<2
= Gen
->addLineTable(Format
);
247 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x11223344, LineTable::Quad
}});
248 LT2
.addStandardOpcode(DW_LNS_copy
, {});
250 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
251 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x55667788, LineTable::Quad
}});
252 LT2
.addStandardOpcode(DW_LNS_copy
, {});
254 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
258 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
259 nullptr, RecordRecoverable
);
260 ASSERT_TRUE(ExpectedLineTable
.operator bool());
261 EXPECT_FALSE(Recoverable
);
262 const DWARFDebugLine::LineTable
*Expected
= *ExpectedLineTable
;
263 checkDefaultPrologue(Version
, Format
, Expected
->Prologue
, 16);
264 EXPECT_EQ(Expected
->Sequences
.size(), 1u);
266 uint64_t SecondOffset
=
267 Expected
->Prologue
.sizeofTotalLength() + Expected
->Prologue
.TotalLength
;
268 Recoverable
= Error::success();
269 auto ExpectedLineTable2
= Line
.getOrParseLineTable(
270 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
271 ASSERT_TRUE(ExpectedLineTable2
.operator bool());
272 EXPECT_FALSE(Recoverable
);
273 const DWARFDebugLine::LineTable
*Expected2
= *ExpectedLineTable2
;
274 checkDefaultPrologue(Version
, Format
, Expected2
->Prologue
, 32);
275 EXPECT_EQ(Expected2
->Sequences
.size(), 2u);
277 EXPECT_NE(Expected
, Expected2
);
279 // Check that if the same offset is requested, the exact same pointer is
281 Recoverable
= Error::success();
282 auto ExpectedLineTable3
= Line
.getOrParseLineTable(
283 LineData
, 0, *Context
, nullptr, RecordRecoverable
);
284 ASSERT_TRUE(ExpectedLineTable3
.operator bool());
285 EXPECT_FALSE(Recoverable
);
286 EXPECT_EQ(Expected
, *ExpectedLineTable3
);
288 Recoverable
= Error::success();
289 auto ExpectedLineTable4
= Line
.getOrParseLineTable(
290 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
291 ASSERT_TRUE(ExpectedLineTable4
.operator bool());
292 EXPECT_FALSE(Recoverable
);
293 EXPECT_EQ(Expected2
, *ExpectedLineTable4
);
295 // TODO: Add tests that show that the body of the programs have been read
299 TEST_F(DebugLineBasicFixture
, ErrorForReservedLength
) {
300 if (!setupGenerator())
303 LineTable
<
= Gen
->addLineTable();
304 LT
.setCustomPrologue({{0xfffffff0, LineTable::Long
}});
308 checkGetOrParseLineTableEmitsError(
309 "parsing line table prologue at offset 0x00000000 unsupported reserved "
310 "unit length found of value 0xfffffff0");
313 TEST_F(DebugLineBasicFixture
, ErrorForLowVersion
) {
314 if (!setupGenerator())
317 LineTable
<
= Gen
->addLineTable();
318 LT
.setCustomPrologue(
319 {{LineTable::Half
, LineTable::Long
}, {1, LineTable::Half
}});
323 checkGetOrParseLineTableEmitsError("parsing line table prologue at offset "
324 "0x00000000 found unsupported version "
328 TEST_F(DebugLineBasicFixture
, ErrorForInvalidV5IncludeDirTable
) {
329 if (!setupGenerator(5))
332 LineTable
<
= Gen
->addLineTable();
333 LT
.setCustomPrologue({
334 {19, LineTable::Long
}, // unit length
335 {5, LineTable::Half
}, // version
336 {8, LineTable::Byte
}, // addr size
337 {0, LineTable::Byte
}, // segment selector size
338 {11, LineTable::Long
}, // prologue length
339 {1, LineTable::Byte
}, // min instruction length
340 {1, LineTable::Byte
}, // max ops per instruction
341 {1, LineTable::Byte
}, // default is_stmt
342 {0, LineTable::Byte
}, // line base
343 {14, LineTable::Byte
}, // line range
344 {2, LineTable::Byte
}, // opcode base (small to reduce the amount of
346 {0, LineTable::Byte
}, // standard opcode lengths
347 {0, LineTable::Byte
}, // directory entry format count (should not be
349 {0, LineTable::ULEB
}, // directories count
350 {0, LineTable::Byte
}, // file name entry format count
351 {0, LineTable::ULEB
} // file name entry count
356 checkGetOrParseLineTableEmitsError(
357 {"parsing line table prologue at 0x00000000 found an invalid directory "
358 "or file table description at 0x00000014",
359 "failed to parse entry content descriptions because no path was found"});
362 TEST_P(DebugLineParameterisedFixture
, ErrorForTooLargePrologueLength
) {
363 if (!setupGenerator(Version
))
366 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
367 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
369 LineTable
<
= Gen
->addLineTable(Format
);
370 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
371 ++Prologue
.PrologueLength
;
372 LT
.setPrologue(Prologue
);
376 uint64_t ExpectedEnd
=
377 Prologue
.TotalLength
+ 1 + Prologue
.sizeofTotalLength();
378 checkGetOrParseLineTableEmitsError(
379 (Twine("parsing line table prologue at 0x00000000 should have ended at "
381 Twine::utohexstr(ExpectedEnd
) + " but it ended at 0x000000" +
382 Twine::utohexstr(ExpectedEnd
- 1))
386 TEST_P(DebugLineParameterisedFixture
, ErrorForTooShortPrologueLength
) {
387 if (!setupGenerator(Version
))
390 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
391 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
393 LineTable
<
= Gen
->addLineTable(Format
);
394 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
395 // FIXME: Ideally, we'd test for 1 less than expected, but the code does not
396 // currently fail if missing only the terminator of a v2-4 file table.
398 Prologue
.PrologueLength
-= 2;
400 Prologue
.PrologueLength
-= 1;
401 LT
.setPrologue(Prologue
);
405 uint64_t ExpectedEnd
=
406 Prologue
.TotalLength
- 1 + Prologue
.sizeofTotalLength();
409 checkGetOrParseLineTableEmitsError(
410 (Twine("parsing line table prologue at 0x00000000 should have ended at "
412 Twine::utohexstr(ExpectedEnd
) + " but it ended at 0x000000" +
413 Twine::utohexstr(ExpectedEnd
+ 1))
417 INSTANTIATE_TEST_CASE_P(
418 LineTableTestParams
, DebugLineParameterisedFixture
,
419 Values(std::make_pair(
420 2, DWARF32
), // Test lower-bound of v2-3 fields and DWARF32.
421 std::make_pair(3, DWARF32
), // Test upper-bound of v2-3 fields.
422 std::make_pair(4, DWARF64
), // Test v4 fields and DWARF64.
423 std::make_pair(5, DWARF32
), std::make_pair(5, DWARF64
)), );
425 TEST_F(DebugLineBasicFixture
, ErrorForInvalidExtendedOpcodeLength
) {
426 if (!setupGenerator())
429 LineTable
<
= Gen
->addLineTable();
430 // The Length should be 1 for an end sequence opcode.
431 LT
.addExtendedOpcode(2, DW_LNE_end_sequence
, {});
435 checkGetOrParseLineTableEmitsError("unexpected line op length at offset "
436 "0x00000030 expected 0x02 found 0x01");
439 TEST_F(DebugLineBasicFixture
, ErrorForMismatchedAddressSize
) {
440 if (!setupGenerator())
443 LineTable
<
= Gen
->addLineTable();
444 // The line data extractor expects size 8 (Quad) addresses.
445 LT
.addExtendedOpcode(5, DW_LNE_set_address
, {{0x11223344, LineTable::Long
}});
446 LT
.addStandardOpcode(DW_LNS_copy
, {});
448 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
452 checkGetOrParseLineTableEmitsError(
453 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04");
456 TEST_F(DebugLineBasicFixture
, CallbackUsedForUnterminatedSequence
) {
457 if (!setupGenerator())
460 LineTable
<
= Gen
->addLineTable();
461 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
462 {{0x1122334455667788, LineTable::Quad
}});
463 LT
.addStandardOpcode(DW_LNS_copy
, {});
465 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
466 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
467 {{0x99aabbccddeeff00, LineTable::Quad
}});
468 LT
.addStandardOpcode(DW_LNS_copy
, {});
474 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
475 nullptr, RecordRecoverable
);
476 checkError("last sequence in debug line table is not terminated!",
477 std::move(Recoverable
));
478 ASSERT_TRUE(ExpectedLineTable
.operator bool());
479 EXPECT_EQ((*ExpectedLineTable
)->Rows
.size(), 6u);
480 // The unterminated sequence is not added to the sequence list.
481 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
484 TEST_F(DebugLineBasicFixture
, ParserParsesCorrectly
) {
485 if (!setupGenerator())
488 DWARFDebugLine::SectionParser Parser
= setupParser();
490 EXPECT_EQ(Parser
.getOffset(), 0u);
491 ASSERT_FALSE(Parser
.done());
493 DWARFDebugLine::LineTable Parsed
=
494 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
495 checkDefaultPrologue(4, DWARF32
, Parsed
.Prologue
, 16);
496 EXPECT_EQ(Parsed
.Sequences
.size(), 1u);
497 EXPECT_EQ(Parser
.getOffset(), 62u);
498 ASSERT_FALSE(Parser
.done());
500 DWARFDebugLine::LineTable Parsed2
=
501 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
502 checkDefaultPrologue(4, DWARF64
, Parsed2
.Prologue
, 16);
503 EXPECT_EQ(Parsed2
.Sequences
.size(), 1u);
504 EXPECT_EQ(Parser
.getOffset(), 136u);
505 EXPECT_TRUE(Parser
.done());
507 EXPECT_FALSE(Recoverable
);
508 EXPECT_FALSE(Unrecoverable
);
511 TEST_F(DebugLineBasicFixture
, ParserSkipsCorrectly
) {
512 if (!setupGenerator())
515 DWARFDebugLine::SectionParser Parser
= setupParser();
517 EXPECT_EQ(Parser
.getOffset(), 0u);
518 ASSERT_FALSE(Parser
.done());
520 Parser
.skip(RecordUnrecoverable
);
521 EXPECT_EQ(Parser
.getOffset(), 62u);
522 ASSERT_FALSE(Parser
.done());
524 Parser
.skip(RecordUnrecoverable
);
525 EXPECT_EQ(Parser
.getOffset(), 136u);
526 EXPECT_TRUE(Parser
.done());
528 EXPECT_FALSE(Unrecoverable
);
531 TEST_F(DebugLineBasicFixture
, ParserAlwaysDoneForEmptySection
) {
532 if (!setupGenerator())
536 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
538 EXPECT_TRUE(Parser
.done());
541 TEST_F(DebugLineBasicFixture
, ParserMovesToEndForBadLengthWhenParsing
) {
542 if (!setupGenerator())
545 LineTable
<
= Gen
->addLineTable();
546 LT
.setCustomPrologue({{0xfffffff0, LineTable::Long
}});
550 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
551 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
553 EXPECT_EQ(Parser
.getOffset(), 4u);
554 EXPECT_TRUE(Parser
.done());
555 EXPECT_FALSE(Recoverable
);
557 checkError("parsing line table prologue at offset 0x00000000 unsupported "
558 "reserved unit length found of value 0xfffffff0",
559 std::move(Unrecoverable
));
562 TEST_F(DebugLineBasicFixture
, ParserMovesToEndForBadLengthWhenSkipping
) {
563 if (!setupGenerator())
566 LineTable
<
= Gen
->addLineTable();
567 LT
.setCustomPrologue({{0xfffffff0, LineTable::Long
}});
571 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
572 Parser
.skip(RecordUnrecoverable
);
574 EXPECT_EQ(Parser
.getOffset(), 4u);
575 EXPECT_TRUE(Parser
.done());
577 checkError("parsing line table prologue at offset 0x00000000 unsupported "
578 "reserved unit length found of value 0xfffffff0",
579 std::move(Unrecoverable
));
582 TEST_F(DebugLineBasicFixture
, ParserReportsFirstErrorInEachTableWhenParsing
) {
583 if (!setupGenerator())
586 LineTable
<
= Gen
->addLineTable(DWARF32
);
587 LT
.setCustomPrologue({{2, LineTable::Long
}, {0, LineTable::Half
}});
588 LineTable
<2
= Gen
->addLineTable(DWARF32
);
589 LT2
.setCustomPrologue({{2, LineTable::Long
}, {1, LineTable::Half
}});
592 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
593 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
594 ASSERT_FALSE(Parser
.done());
595 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
597 EXPECT_TRUE(Parser
.done());
598 EXPECT_FALSE(Recoverable
);
600 checkError({"parsing line table prologue at offset 0x00000000 found "
601 "unsupported version 0x00",
602 "parsing line table prologue at offset 0x00000006 found "
603 "unsupported version 0x01"},
604 std::move(Unrecoverable
));
607 TEST_F(DebugLineBasicFixture
, ParserReportsNonPrologueProblemsWhenParsing
) {
608 if (!setupGenerator())
611 LineTable
<
= Gen
->addLineTable(DWARF32
);
612 LT
.addExtendedOpcode(0x42, DW_LNE_end_sequence
, {});
613 LineTable
<2
= Gen
->addLineTable(DWARF32
);
614 LT2
.addExtendedOpcode(9, DW_LNE_set_address
,
615 {{0x1234567890abcdef, LineTable::Quad
}});
616 LT2
.addStandardOpcode(DW_LNS_copy
, {});
620 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
621 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
622 EXPECT_FALSE(Recoverable
);
623 ASSERT_FALSE(Parser
.done());
625 "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01",
626 std::move(Unrecoverable
));
628 // Reset the error state so that it does not confuse the next set of checks.
629 Unrecoverable
= Error::success();
630 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
632 EXPECT_TRUE(Parser
.done());
633 checkError("last sequence in debug line table is not terminated!",
634 std::move(Recoverable
));
635 EXPECT_FALSE(Unrecoverable
);
638 TEST_F(DebugLineBasicFixture
,
639 ParserReportsPrologueErrorsInEachTableWhenSkipping
) {
640 if (!setupGenerator())
643 LineTable
<
= Gen
->addLineTable(DWARF32
);
644 LT
.setCustomPrologue({{2, LineTable::Long
}, {0, LineTable::Half
}});
645 LineTable
<2
= Gen
->addLineTable(DWARF32
);
646 LT2
.setCustomPrologue({{2, LineTable::Long
}, {1, LineTable::Half
}});
649 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
650 Parser
.skip(RecordUnrecoverable
);
651 ASSERT_FALSE(Parser
.done());
652 Parser
.skip(RecordUnrecoverable
);
654 EXPECT_TRUE(Parser
.done());
656 checkError({"parsing line table prologue at offset 0x00000000 found "
657 "unsupported version 0x00",
658 "parsing line table prologue at offset 0x00000006 found "
659 "unsupported version 0x01"},
660 std::move(Unrecoverable
));
663 TEST_F(DebugLineBasicFixture
, ParserIgnoresNonPrologueErrorsWhenSkipping
) {
664 if (!setupGenerator())
667 LineTable
<
= Gen
->addLineTable(DWARF32
);
668 LT
.addExtendedOpcode(42, DW_LNE_end_sequence
, {});
671 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
672 Parser
.skip(RecordUnrecoverable
);
674 EXPECT_TRUE(Parser
.done());
675 EXPECT_FALSE(Unrecoverable
);
678 } // end anonymous namespace