Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / unittests / DebugInfo / DWARF / DWARFDebugLineTest.cpp
blobd016a946b1af9edd9431b7be509415af38a5e35a
1 //===- DWARFDebugLineTest.cpp ---------------------------------------------===//
2 //
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
6 //
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"
17 using namespace llvm;
18 using namespace dwarf;
19 using namespace dwarfgen;
20 using namespace object;
21 using namespace utils;
22 using namespace testing;
24 namespace {
25 struct CommonFixture {
26 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)){};
34 ~CommonFixture() {
35 EXPECT_FALSE(Recoverable);
36 EXPECT_FALSE(Unrecoverable);
39 bool setupGenerator(uint16_t Version = 4) {
40 Triple T = getHostTripleForAddrSize(8);
41 if (!isConfigurationSupported(T))
42 return false;
43 auto ExpectedGenerator = Generator::create(T, Version);
44 if (ExpectedGenerator)
45 Gen.reset(ExpectedGenerator->release());
46 return true;
49 void generate() {
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() {
58 if (!Gen)
59 return nullptr;
60 StringRef FileBytes = Gen->generate();
61 MemoryBufferRef FileBuffer(FileBytes, "dwarf");
62 auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
63 if (Obj)
64 return DWARFContext::create(**Obj);
65 return nullptr;
68 DWARFDebugLine::SectionParser setupParser() {
69 LineTable &LT = Gen->addLineTable(DWARF32);
70 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
71 LT.addStandardOpcode(DW_LNS_copy, {});
72 LT.addByte(0xaa);
73 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
75 LineTable &LT2 = Gen->addLineTable(DWARF64);
76 LT2.addExtendedOpcode(9, DW_LNE_set_address,
77 {{0x11223344, LineTable::Quad}});
78 LT2.addStandardOpcode(DW_LNS_copy, {});
79 LT2.addByte(0xbb);
80 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
82 generate();
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());
96 size_t WhichMsg = 0;
97 Error Remaining =
98 handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
99 ASSERT_LT(WhichMsg, ExpectedMsgs.size());
100 // Use .str(), because googletest doesn't visualise a StringRef
101 // properly.
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;
125 DWARFDebugLine Line;
126 Error Recoverable;
127 std::function<void(Error)> RecordRecoverable;
128 Error Unrecoverable;
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(); }
145 uint16_t Version;
146 DwarfFormat Format;
149 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format,
150 DWARFDebugLine::Prologue Prologue,
151 uint64_t BodyLength) {
152 // Check version specific fields and values.
153 uint64_t UnitLength;
154 uint64_t PrologueLength;
155 switch (Version) {
156 case 4:
157 PrologueLength = 36;
158 UnitLength = PrologueLength + 2;
159 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u);
160 break;
161 case 2:
162 case 3:
163 PrologueLength = 35;
164 UnitLength = PrologueLength + 2;
165 break;
166 case 5:
167 PrologueLength = 39;
168 UnitLength = PrologueLength + 4;
169 EXPECT_EQ(Prologue.getAddressSize(), 8u);
170 EXPECT_EQ(Prologue.SegSelectorSize, 0u);
171 break;
172 default:
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())
196 return;
197 generate();
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())
211 return;
213 LineTable &LT = Gen->addLineTable();
214 LT.setCustomPrologue({{0, LineTable::Byte}});
216 generate();
218 checkGetOrParseLineTableEmitsError(
219 "offset 0x00000001 is not a valid debug line section offset", 1);
222 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {
223 if (!setupGenerator(Version))
224 return;
226 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
227 (Format == DWARF64 ? "DWARF64" : "DWARF32"));
229 LineTable &LT = Gen->addLineTable(Format);
230 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
231 LT.addStandardOpcode(DW_LNS_copy, {});
232 LT.addByte(0xaa);
233 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
235 LineTable &LT2 = Gen->addLineTable(Format);
236 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}});
237 LT2.addStandardOpcode(DW_LNS_copy, {});
238 LT2.addByte(0xbb);
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, {});
242 LT2.addByte(0xcc);
243 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
245 generate();
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
269 // returned.
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
285 // correctly.
288 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {
289 if (!setupGenerator())
290 return;
292 LineTable &LT = Gen->addLineTable();
293 LT.setCustomPrologue({{0xffffff00, LineTable::Long}});
295 generate();
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())
304 return;
306 LineTable &LT = Gen->addLineTable();
307 LT.setCustomPrologue(
308 {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}});
310 generate();
312 checkGetOrParseLineTableEmitsError("parsing line table prologue at offset "
313 "0x00000000 found unsupported version "
314 "0x01");
317 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
318 if (!setupGenerator(5))
319 return;
321 LineTable &LT = 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
334 // setup required).
335 {0, LineTable::Byte}, // standard opcode lengths
336 {0, LineTable::Byte}, // directory entry format count (should not be
337 // zero).
338 {0, LineTable::ULEB}, // directories count
339 {0, LineTable::Byte}, // file name entry format count
340 {0, LineTable::ULEB} // file name entry count
343 generate();
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))
352 return;
354 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
355 (Format == DWARF64 ? "DWARF64" : "DWARF32"));
357 LineTable &LT = Gen->addLineTable(Format);
358 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
359 ++Prologue.PrologueLength;
360 LT.setPrologue(Prologue);
362 generate();
364 uint64_t ExpectedEnd =
365 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
366 checkGetOrParseLineTableEmitsError(
367 (Twine("parsing line table prologue at 0x00000000 should have ended at "
368 "0x000000") +
369 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
370 Twine::utohexstr(ExpectedEnd - 1))
371 .str());
374 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
375 if (!setupGenerator(Version))
376 return;
378 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
379 (Format == DWARF64 ? "DWARF64" : "DWARF32"));
381 LineTable &LT = 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.
385 if (Version < 5)
386 Prologue.PrologueLength -= 2;
387 else
388 Prologue.PrologueLength -= 1;
389 LT.setPrologue(Prologue);
391 generate();
393 uint64_t ExpectedEnd =
394 Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();
395 if (Version < 5)
396 --ExpectedEnd;
397 checkGetOrParseLineTableEmitsError(
398 (Twine("parsing line table prologue at 0x00000000 should have ended at "
399 "0x000000") +
400 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
401 Twine::utohexstr(ExpectedEnd + 1))
402 .str());
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())
415 return;
417 LineTable &LT = Gen->addLineTable();
418 // The Length should be 1 for an end sequence opcode.
419 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});
421 generate();
423 checkGetOrParseLineTableEmitsError("unexpected line op length at offset "
424 "0x00000030 expected 0x02 found 0x01");
427 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
428 if (!setupGenerator())
429 return;
431 LineTable &LT = 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, {});
435 LT.addByte(0xaa);
436 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
438 generate();
440 checkGetOrParseLineTableEmitsError(
441 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04");
444 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {
445 if (!setupGenerator())
446 return;
448 LineTable &LT = Gen->addLineTable();
449 LT.addExtendedOpcode(9, DW_LNE_set_address,
450 {{0x1122334455667788, LineTable::Quad}});
451 LT.addStandardOpcode(DW_LNS_copy, {});
452 LT.addByte(0xaa);
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, {});
457 LT.addByte(0xbb);
458 LT.addByte(0xcc);
460 generate();
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())
474 return;
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())
501 return;
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())
521 return;
523 generate();
524 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
526 EXPECT_TRUE(Parser.done());
529 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) {
530 if (!setupGenerator())
531 return;
533 LineTable &LT = Gen->addLineTable();
534 LT.setCustomPrologue({{0xffffff00, LineTable::Long}});
535 Gen->addLineTable();
536 generate();
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())
552 return;
554 LineTable &LT = Gen->addLineTable();
555 LT.setCustomPrologue({{0xffffff00, LineTable::Long}});
556 Gen->addLineTable();
557 generate();
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())
572 return;
574 LineTable &LT = Gen->addLineTable(DWARF32);
575 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
576 LineTable &LT2 = Gen->addLineTable(DWARF32);
577 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
578 generate();
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())
597 return;
599 LineTable &LT = Gen->addLineTable(DWARF32);
600 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});
601 LineTable &LT2 = Gen->addLineTable(DWARF32);
602 LT2.addExtendedOpcode(9, DW_LNE_set_address,
603 {{0x1234567890abcdef, LineTable::Quad}});
604 LT2.addStandardOpcode(DW_LNS_copy, {});
605 LT2.addByte(0xbb);
606 generate();
608 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
609 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
610 EXPECT_FALSE(Recoverable);
611 ASSERT_FALSE(Parser.done());
612 checkError(
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())
629 return;
631 LineTable &LT = Gen->addLineTable(DWARF32);
632 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
633 LineTable &LT2 = Gen->addLineTable(DWARF32);
634 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
635 generate();
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())
653 return;
655 LineTable &LT = Gen->addLineTable(DWARF32);
656 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});
657 generate();
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