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
= getHostTripleForAddrSize(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(Obj
, Obj
.getLineSection(),
54 sys::IsLittleEndianHost
, 8);
57 std::unique_ptr
<DWARFContext
> createContext() {
60 StringRef FileBytes
= Gen
->generate();
61 MemoryBufferRef
FileBuffer(FileBytes
, "dwarf");
62 auto Obj
= object::ObjectFile::createObjectFile(FileBuffer
);
64 return DWARFContext::create(**Obj
);
68 DWARFDebugLine::SectionParser
setupParser() {
69 LineTable
<
= Gen
->addLineTable(DWARF32
);
70 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
71 LT
.addStandardOpcode(DW_LNS_copy
, {});
73 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
75 LineTable
<2
= Gen
->addLineTable(DWARF64
);
76 LT2
.addExtendedOpcode(9, DW_LNE_set_address
,
77 {{0x11223344, LineTable::Quad
}});
78 LT2
.addStandardOpcode(DW_LNS_copy
, {});
80 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
84 return DWARFDebugLine::SectionParser(LineData
, *Context
, CUs
, TUs
);
87 void recordRecoverable(Error Err
) {
88 Recoverable
= joinErrors(std::move(Recoverable
), std::move(Err
));
90 void recordUnrecoverable(Error Err
) {
91 Unrecoverable
= joinErrors(std::move(Unrecoverable
), std::move(Err
));
94 void checkError(ArrayRef
<StringRef
> ExpectedMsgs
, Error Err
) {
95 ASSERT_TRUE(Err
.operator bool());
98 handleErrors(std::move(Err
), [&](const ErrorInfoBase
&Actual
) {
99 ASSERT_LT(WhichMsg
, ExpectedMsgs
.size());
100 // Use .str(), because googletest doesn't visualise a StringRef
102 EXPECT_EQ(Actual
.message(), ExpectedMsgs
[WhichMsg
++].str());
104 EXPECT_EQ(WhichMsg
, ExpectedMsgs
.size());
105 EXPECT_FALSE(Remaining
);
108 void checkError(StringRef ExpectedMsg
, Error Err
) {
109 checkError(ArrayRef
<StringRef
>{ExpectedMsg
}, std::move(Err
));
112 void checkGetOrParseLineTableEmitsError(StringRef ExpectedMsg
,
113 uint64_t Offset
= 0) {
114 auto ExpectedLineTable
= Line
.getOrParseLineTable(
115 LineData
, Offset
, *Context
, nullptr, RecordRecoverable
);
116 EXPECT_FALSE(ExpectedLineTable
);
117 EXPECT_FALSE(Recoverable
);
119 checkError(ExpectedMsg
, ExpectedLineTable
.takeError());
122 std::unique_ptr
<Generator
> Gen
;
123 std::unique_ptr
<DWARFContext
> Context
;
124 DWARFDataExtractor LineData
;
127 std::function
<void(Error
)> RecordRecoverable
;
129 std::function
<void(Error
)> RecordUnrecoverable
;
131 SmallVector
<std::unique_ptr
<DWARFUnit
>, 2> CUs
;
132 SmallVector
<std::unique_ptr
<DWARFUnit
>, 2> TUs
;
135 // Fixtures must derive from "Test", but parameterised fixtures from
136 // "TestWithParam". It does not seem possible to inherit from both, so we share
137 // the common state in a separate class, inherited by the two fixture classes.
138 struct DebugLineBasicFixture
: public Test
, public CommonFixture
{};
140 struct DebugLineParameterisedFixture
141 : public TestWithParam
<std::pair
<uint16_t, DwarfFormat
>>,
142 public CommonFixture
{
143 void SetUp() { std::tie(Version
, Format
) = GetParam(); }
149 void checkDefaultPrologue(uint16_t Version
, DwarfFormat Format
,
150 DWARFDebugLine::Prologue Prologue
,
151 uint64_t BodyLength
) {
152 // Check version specific fields and values.
154 uint64_t PrologueLength
;
158 UnitLength
= PrologueLength
+ 2;
159 EXPECT_EQ(Prologue
.MaxOpsPerInst
, 1u);
164 UnitLength
= PrologueLength
+ 2;
168 UnitLength
= PrologueLength
+ 4;
169 EXPECT_EQ(Prologue
.getAddressSize(), 8u);
170 EXPECT_EQ(Prologue
.SegSelectorSize
, 0u);
173 llvm_unreachable("unsupported DWARF version");
175 UnitLength
+= BodyLength
+ (Format
== DWARF32
? 4 : 8);
177 EXPECT_EQ(Prologue
.TotalLength
, UnitLength
);
178 EXPECT_EQ(Prologue
.PrologueLength
, PrologueLength
);
179 EXPECT_EQ(Prologue
.MinInstLength
, 1u);
180 EXPECT_EQ(Prologue
.DefaultIsStmt
, 1u);
181 EXPECT_EQ(Prologue
.LineBase
, -5);
182 EXPECT_EQ(Prologue
.LineRange
, 14u);
183 EXPECT_EQ(Prologue
.OpcodeBase
, 13u);
184 std::vector
<uint8_t> ExpectedLengths
= {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
185 EXPECT_EQ(Prologue
.StandardOpcodeLengths
, ExpectedLengths
);
186 ASSERT_EQ(Prologue
.IncludeDirectories
.size(), 1u);
187 ASSERT_EQ(Prologue
.IncludeDirectories
[0].getForm(), DW_FORM_string
);
188 EXPECT_STREQ(*Prologue
.IncludeDirectories
[0].getAsCString(), "a dir");
189 ASSERT_EQ(Prologue
.FileNames
.size(), 1u);
190 ASSERT_EQ(Prologue
.FileNames
[0].Name
.getForm(), DW_FORM_string
);
191 EXPECT_STREQ(*Prologue
.FileNames
[0].Name
.getAsCString(), "a file");
194 TEST_F(DebugLineBasicFixture
, GetOrParseLineTableAtInvalidOffset
) {
195 if (!setupGenerator())
199 checkGetOrParseLineTableEmitsError(
200 "offset 0x00000000 is not a valid debug line section offset", 0);
201 // Repeat to show that an error is reported each time.
202 checkGetOrParseLineTableEmitsError(
203 "offset 0x00000000 is not a valid debug line section offset", 0);
204 // Show that an error is reported for later offsets too.
205 checkGetOrParseLineTableEmitsError(
206 "offset 0x00000001 is not a valid debug line section offset", 1);
209 TEST_F(DebugLineBasicFixture
, GetOrParseLineTableAtInvalidOffsetAfterData
) {
210 if (!setupGenerator())
213 LineTable
<
= Gen
->addLineTable();
214 LT
.setCustomPrologue({{0, LineTable::Byte
}});
218 checkGetOrParseLineTableEmitsError(
219 "offset 0x00000001 is not a valid debug line section offset", 1);
222 TEST_P(DebugLineParameterisedFixture
, GetOrParseLineTableValidTable
) {
223 if (!setupGenerator(Version
))
226 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
227 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
229 LineTable
<
= Gen
->addLineTable(Format
);
230 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
231 LT
.addStandardOpcode(DW_LNS_copy
, {});
233 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
235 LineTable
<2
= Gen
->addLineTable(Format
);
236 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x11223344, LineTable::Quad
}});
237 LT2
.addStandardOpcode(DW_LNS_copy
, {});
239 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
240 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x55667788, LineTable::Quad
}});
241 LT2
.addStandardOpcode(DW_LNS_copy
, {});
243 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
247 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
248 nullptr, RecordRecoverable
);
249 ASSERT_TRUE(ExpectedLineTable
.operator bool());
250 EXPECT_FALSE(Recoverable
);
251 const DWARFDebugLine::LineTable
*Expected
= *ExpectedLineTable
;
252 checkDefaultPrologue(Version
, Format
, Expected
->Prologue
, 16);
253 EXPECT_EQ(Expected
->Sequences
.size(), 1u);
255 uint64_t SecondOffset
=
256 Expected
->Prologue
.sizeofTotalLength() + Expected
->Prologue
.TotalLength
;
257 Recoverable
= Error::success();
258 auto ExpectedLineTable2
= Line
.getOrParseLineTable(
259 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
260 ASSERT_TRUE(ExpectedLineTable2
.operator bool());
261 EXPECT_FALSE(Recoverable
);
262 const DWARFDebugLine::LineTable
*Expected2
= *ExpectedLineTable2
;
263 checkDefaultPrologue(Version
, Format
, Expected2
->Prologue
, 32);
264 EXPECT_EQ(Expected2
->Sequences
.size(), 2u);
266 EXPECT_NE(Expected
, Expected2
);
268 // Check that if the same offset is requested, the exact same pointer is
270 Recoverable
= Error::success();
271 auto ExpectedLineTable3
= Line
.getOrParseLineTable(
272 LineData
, 0, *Context
, nullptr, RecordRecoverable
);
273 ASSERT_TRUE(ExpectedLineTable3
.operator bool());
274 EXPECT_FALSE(Recoverable
);
275 EXPECT_EQ(Expected
, *ExpectedLineTable3
);
277 Recoverable
= Error::success();
278 auto ExpectedLineTable4
= Line
.getOrParseLineTable(
279 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
280 ASSERT_TRUE(ExpectedLineTable4
.operator bool());
281 EXPECT_FALSE(Recoverable
);
282 EXPECT_EQ(Expected2
, *ExpectedLineTable4
);
284 // TODO: Add tests that show that the body of the programs have been read
288 TEST_F(DebugLineBasicFixture
, ErrorForReservedLength
) {
289 if (!setupGenerator())
292 LineTable
<
= Gen
->addLineTable();
293 LT
.setCustomPrologue({{0xffffff00, LineTable::Long
}});
297 checkGetOrParseLineTableEmitsError(
298 "parsing line table prologue at offset 0x00000000 unsupported reserved "
299 "unit length found of value 0xffffff00");
302 TEST_F(DebugLineBasicFixture
, ErrorForLowVersion
) {
303 if (!setupGenerator())
306 LineTable
<
= Gen
->addLineTable();
307 LT
.setCustomPrologue(
308 {{LineTable::Half
, LineTable::Long
}, {1, LineTable::Half
}});
312 checkGetOrParseLineTableEmitsError("parsing line table prologue at offset "
313 "0x00000000 found unsupported version "
317 TEST_F(DebugLineBasicFixture
, ErrorForInvalidV5IncludeDirTable
) {
318 if (!setupGenerator(5))
321 LineTable
<
= Gen
->addLineTable();
322 LT
.setCustomPrologue({
323 {19, LineTable::Long
}, // unit length
324 {5, LineTable::Half
}, // version
325 {8, LineTable::Byte
}, // addr size
326 {0, LineTable::Byte
}, // segment selector size
327 {11, LineTable::Long
}, // prologue length
328 {1, LineTable::Byte
}, // min instruction length
329 {1, LineTable::Byte
}, // max ops per instruction
330 {1, LineTable::Byte
}, // default is_stmt
331 {0, LineTable::Byte
}, // line base
332 {14, LineTable::Byte
}, // line range
333 {2, LineTable::Byte
}, // opcode base (small to reduce the amount of
335 {0, LineTable::Byte
}, // standard opcode lengths
336 {0, LineTable::Byte
}, // directory entry format count (should not be
338 {0, LineTable::ULEB
}, // directories count
339 {0, LineTable::Byte
}, // file name entry format count
340 {0, LineTable::ULEB
} // file name entry count
345 checkGetOrParseLineTableEmitsError(
346 "parsing line table prologue at 0x00000000 found an invalid directory or "
347 "file table description at 0x00000014");
350 TEST_P(DebugLineParameterisedFixture
, ErrorForTooLargePrologueLength
) {
351 if (!setupGenerator(Version
))
354 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
355 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
357 LineTable
<
= Gen
->addLineTable(Format
);
358 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
359 ++Prologue
.PrologueLength
;
360 LT
.setPrologue(Prologue
);
364 uint64_t ExpectedEnd
=
365 Prologue
.TotalLength
+ 1 + Prologue
.sizeofTotalLength();
366 checkGetOrParseLineTableEmitsError(
367 (Twine("parsing line table prologue at 0x00000000 should have ended at "
369 Twine::utohexstr(ExpectedEnd
) + " but it ended at 0x000000" +
370 Twine::utohexstr(ExpectedEnd
- 1))
374 TEST_P(DebugLineParameterisedFixture
, ErrorForTooShortPrologueLength
) {
375 if (!setupGenerator(Version
))
378 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
379 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
381 LineTable
<
= Gen
->addLineTable(Format
);
382 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
383 // FIXME: Ideally, we'd test for 1 less than expected, but the code does not
384 // currently fail if missing only the terminator of a v2-4 file table.
386 Prologue
.PrologueLength
-= 2;
388 Prologue
.PrologueLength
-= 1;
389 LT
.setPrologue(Prologue
);
393 uint64_t ExpectedEnd
=
394 Prologue
.TotalLength
- 1 + Prologue
.sizeofTotalLength();
397 checkGetOrParseLineTableEmitsError(
398 (Twine("parsing line table prologue at 0x00000000 should have ended at "
400 Twine::utohexstr(ExpectedEnd
) + " but it ended at 0x000000" +
401 Twine::utohexstr(ExpectedEnd
+ 1))
405 INSTANTIATE_TEST_CASE_P(
406 LineTableTestParams
, DebugLineParameterisedFixture
,
407 Values(std::make_pair(
408 2, DWARF32
), // Test lower-bound of v2-3 fields and DWARF32.
409 std::make_pair(3, DWARF32
), // Test upper-bound of v2-3 fields.
410 std::make_pair(4, DWARF64
), // Test v4 fields and DWARF64.
411 std::make_pair(5, DWARF32
), std::make_pair(5, DWARF64
)), );
413 TEST_F(DebugLineBasicFixture
, ErrorForInvalidExtendedOpcodeLength
) {
414 if (!setupGenerator())
417 LineTable
<
= Gen
->addLineTable();
418 // The Length should be 1 for an end sequence opcode.
419 LT
.addExtendedOpcode(2, DW_LNE_end_sequence
, {});
423 checkGetOrParseLineTableEmitsError("unexpected line op length at offset "
424 "0x00000030 expected 0x02 found 0x01");
427 TEST_F(DebugLineBasicFixture
, ErrorForMismatchedAddressSize
) {
428 if (!setupGenerator())
431 LineTable
<
= Gen
->addLineTable();
432 // The line data extractor expects size 8 (Quad) addresses.
433 LT
.addExtendedOpcode(5, DW_LNE_set_address
, {{0x11223344, LineTable::Long
}});
434 LT
.addStandardOpcode(DW_LNS_copy
, {});
436 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
440 checkGetOrParseLineTableEmitsError(
441 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04");
444 TEST_F(DebugLineBasicFixture
, CallbackUsedForUnterminatedSequence
) {
445 if (!setupGenerator())
448 LineTable
<
= Gen
->addLineTable();
449 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
450 {{0x1122334455667788, LineTable::Quad
}});
451 LT
.addStandardOpcode(DW_LNS_copy
, {});
453 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
454 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
455 {{0x99aabbccddeeff00, LineTable::Quad
}});
456 LT
.addStandardOpcode(DW_LNS_copy
, {});
462 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
463 nullptr, RecordRecoverable
);
464 checkError("last sequence in debug line table is not terminated!",
465 std::move(Recoverable
));
466 ASSERT_TRUE(ExpectedLineTable
.operator bool());
467 EXPECT_EQ((*ExpectedLineTable
)->Rows
.size(), 6u);
468 // The unterminated sequence is not added to the sequence list.
469 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
472 TEST_F(DebugLineBasicFixture
, ParserParsesCorrectly
) {
473 if (!setupGenerator())
476 DWARFDebugLine::SectionParser Parser
= setupParser();
478 EXPECT_EQ(Parser
.getOffset(), 0u);
479 ASSERT_FALSE(Parser
.done());
481 DWARFDebugLine::LineTable Parsed
=
482 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
483 checkDefaultPrologue(4, DWARF32
, Parsed
.Prologue
, 16);
484 EXPECT_EQ(Parsed
.Sequences
.size(), 1u);
485 EXPECT_EQ(Parser
.getOffset(), 62u);
486 ASSERT_FALSE(Parser
.done());
488 DWARFDebugLine::LineTable Parsed2
=
489 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
490 checkDefaultPrologue(4, DWARF64
, Parsed2
.Prologue
, 16);
491 EXPECT_EQ(Parsed2
.Sequences
.size(), 1u);
492 EXPECT_EQ(Parser
.getOffset(), 136u);
493 EXPECT_TRUE(Parser
.done());
495 EXPECT_FALSE(Recoverable
);
496 EXPECT_FALSE(Unrecoverable
);
499 TEST_F(DebugLineBasicFixture
, ParserSkipsCorrectly
) {
500 if (!setupGenerator())
503 DWARFDebugLine::SectionParser Parser
= setupParser();
505 EXPECT_EQ(Parser
.getOffset(), 0u);
506 ASSERT_FALSE(Parser
.done());
508 Parser
.skip(RecordUnrecoverable
);
509 EXPECT_EQ(Parser
.getOffset(), 62u);
510 ASSERT_FALSE(Parser
.done());
512 Parser
.skip(RecordUnrecoverable
);
513 EXPECT_EQ(Parser
.getOffset(), 136u);
514 EXPECT_TRUE(Parser
.done());
516 EXPECT_FALSE(Unrecoverable
);
519 TEST_F(DebugLineBasicFixture
, ParserAlwaysDoneForEmptySection
) {
520 if (!setupGenerator())
524 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
526 EXPECT_TRUE(Parser
.done());
529 TEST_F(DebugLineBasicFixture
, ParserMovesToEndForBadLengthWhenParsing
) {
530 if (!setupGenerator())
533 LineTable
<
= Gen
->addLineTable();
534 LT
.setCustomPrologue({{0xffffff00, LineTable::Long
}});
538 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
539 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
541 EXPECT_EQ(Parser
.getOffset(), 4u);
542 EXPECT_TRUE(Parser
.done());
543 EXPECT_FALSE(Recoverable
);
545 checkError("parsing line table prologue at offset 0x00000000 unsupported "
546 "reserved unit length found of value 0xffffff00",
547 std::move(Unrecoverable
));
550 TEST_F(DebugLineBasicFixture
, ParserMovesToEndForBadLengthWhenSkipping
) {
551 if (!setupGenerator())
554 LineTable
<
= Gen
->addLineTable();
555 LT
.setCustomPrologue({{0xffffff00, LineTable::Long
}});
559 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
560 Parser
.skip(RecordUnrecoverable
);
562 EXPECT_EQ(Parser
.getOffset(), 4u);
563 EXPECT_TRUE(Parser
.done());
565 checkError("parsing line table prologue at offset 0x00000000 unsupported "
566 "reserved unit length found of value 0xffffff00",
567 std::move(Unrecoverable
));
570 TEST_F(DebugLineBasicFixture
, ParserReportsFirstErrorInEachTableWhenParsing
) {
571 if (!setupGenerator())
574 LineTable
<
= Gen
->addLineTable(DWARF32
);
575 LT
.setCustomPrologue({{2, LineTable::Long
}, {0, LineTable::Half
}});
576 LineTable
<2
= Gen
->addLineTable(DWARF32
);
577 LT2
.setCustomPrologue({{2, LineTable::Long
}, {1, LineTable::Half
}});
580 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
581 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
582 ASSERT_FALSE(Parser
.done());
583 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
585 EXPECT_TRUE(Parser
.done());
586 EXPECT_FALSE(Recoverable
);
588 checkError({"parsing line table prologue at offset 0x00000000 found "
589 "unsupported version 0x00",
590 "parsing line table prologue at offset 0x00000006 found "
591 "unsupported version 0x01"},
592 std::move(Unrecoverable
));
595 TEST_F(DebugLineBasicFixture
, ParserReportsNonPrologueProblemsWhenParsing
) {
596 if (!setupGenerator())
599 LineTable
<
= Gen
->addLineTable(DWARF32
);
600 LT
.addExtendedOpcode(0x42, DW_LNE_end_sequence
, {});
601 LineTable
<2
= Gen
->addLineTable(DWARF32
);
602 LT2
.addExtendedOpcode(9, DW_LNE_set_address
,
603 {{0x1234567890abcdef, LineTable::Quad
}});
604 LT2
.addStandardOpcode(DW_LNS_copy
, {});
608 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
609 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
610 EXPECT_FALSE(Recoverable
);
611 ASSERT_FALSE(Parser
.done());
613 "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01",
614 std::move(Unrecoverable
));
616 // Reset the error state so that it does not confuse the next set of checks.
617 Unrecoverable
= Error::success();
618 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
620 EXPECT_TRUE(Parser
.done());
621 checkError("last sequence in debug line table is not terminated!",
622 std::move(Recoverable
));
623 EXPECT_FALSE(Unrecoverable
);
626 TEST_F(DebugLineBasicFixture
,
627 ParserReportsPrologueErrorsInEachTableWhenSkipping
) {
628 if (!setupGenerator())
631 LineTable
<
= Gen
->addLineTable(DWARF32
);
632 LT
.setCustomPrologue({{2, LineTable::Long
}, {0, LineTable::Half
}});
633 LineTable
<2
= Gen
->addLineTable(DWARF32
);
634 LT2
.setCustomPrologue({{2, LineTable::Long
}, {1, LineTable::Half
}});
637 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
638 Parser
.skip(RecordUnrecoverable
);
639 ASSERT_FALSE(Parser
.done());
640 Parser
.skip(RecordUnrecoverable
);
642 EXPECT_TRUE(Parser
.done());
644 checkError({"parsing line table prologue at offset 0x00000000 found "
645 "unsupported version 0x00",
646 "parsing line table prologue at offset 0x00000006 found "
647 "unsupported version 0x01"},
648 std::move(Unrecoverable
));
651 TEST_F(DebugLineBasicFixture
, ParserIgnoresNonPrologueErrorsWhenSkipping
) {
652 if (!setupGenerator())
655 LineTable
<
= Gen
->addLineTable(DWARF32
);
656 LT
.addExtendedOpcode(42, DW_LNE_end_sequence
, {});
659 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, CUs
, TUs
);
660 Parser
.skip(RecordUnrecoverable
);
662 EXPECT_TRUE(Parser
.done());
663 EXPECT_FALSE(Unrecoverable
);
666 } // end anonymous namespace