[InstCombine] Signed saturation patterns
[llvm-complete.git] / unittests / DebugInfo / DWARF / DWARFDebugLineTest.cpp
blobbf2dee4ce2488f7806ce5efa9ec5d0910aa3b02d
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 = getDefaultTargetTripleForAddrSize(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(
54 Obj, Obj.getLineSection(),
55 getDefaultTargetTripleForAddrSize(8).isLittleEndian(), 8);
58 std::unique_ptr<DWARFContext> createContext() {
59 if (!Gen)
60 return nullptr;
61 StringRef FileBytes = Gen->generate();
62 MemoryBufferRef FileBuffer(FileBytes, "dwarf");
63 auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
64 if (Obj)
65 return DWARFContext::create(**Obj);
66 return nullptr;
69 DWARFDebugLine::SectionParser setupParser() {
70 LineTable &LT = Gen->addLineTable(DWARF32);
71 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
72 LT.addStandardOpcode(DW_LNS_copy, {});
73 LT.addByte(0xaa);
74 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
76 LineTable &LT2 = Gen->addLineTable(DWARF64);
77 LT2.addExtendedOpcode(9, DW_LNE_set_address,
78 {{0x11223344, LineTable::Quad}});
79 LT2.addStandardOpcode(DW_LNS_copy, {});
80 LT2.addByte(0xbb);
81 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
83 generate();
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());
97 size_t WhichMsg = 0;
98 Error Remaining =
99 handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
100 ASSERT_LT(WhichMsg, ExpectedMsgs.size());
101 // Use .str(), because googletest doesn't visualise a StringRef
102 // properly.
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;
136 DWARFDebugLine Line;
137 Error Recoverable;
138 std::function<void(Error)> RecordRecoverable;
139 Error Unrecoverable;
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(); }
156 uint16_t Version;
157 DwarfFormat Format;
160 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format,
161 DWARFDebugLine::Prologue Prologue,
162 uint64_t BodyLength) {
163 // Check version specific fields and values.
164 uint64_t UnitLength;
165 uint64_t PrologueLength;
166 switch (Version) {
167 case 4:
168 PrologueLength = 36;
169 UnitLength = PrologueLength + 2;
170 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u);
171 break;
172 case 2:
173 case 3:
174 PrologueLength = 35;
175 UnitLength = PrologueLength + 2;
176 break;
177 case 5:
178 PrologueLength = 39;
179 UnitLength = PrologueLength + 4;
180 EXPECT_EQ(Prologue.getAddressSize(), 8u);
181 EXPECT_EQ(Prologue.SegSelectorSize, 0u);
182 break;
183 default:
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())
207 return;
208 generate();
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())
222 return;
224 LineTable &LT = Gen->addLineTable();
225 LT.setCustomPrologue({{0, LineTable::Byte}});
227 generate();
229 checkGetOrParseLineTableEmitsError(
230 "offset 0x00000001 is not a valid debug line section offset", 1);
233 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {
234 if (!setupGenerator(Version))
235 return;
237 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
238 (Format == DWARF64 ? "DWARF64" : "DWARF32"));
240 LineTable &LT = Gen->addLineTable(Format);
241 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
242 LT.addStandardOpcode(DW_LNS_copy, {});
243 LT.addByte(0xaa);
244 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
246 LineTable &LT2 = Gen->addLineTable(Format);
247 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}});
248 LT2.addStandardOpcode(DW_LNS_copy, {});
249 LT2.addByte(0xbb);
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, {});
253 LT2.addByte(0xcc);
254 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
256 generate();
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
280 // returned.
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
296 // correctly.
299 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {
300 if (!setupGenerator())
301 return;
303 LineTable &LT = Gen->addLineTable();
304 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
306 generate();
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())
315 return;
317 LineTable &LT = Gen->addLineTable();
318 LT.setCustomPrologue(
319 {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}});
321 generate();
323 checkGetOrParseLineTableEmitsError("parsing line table prologue at offset "
324 "0x00000000 found unsupported version "
325 "0x01");
328 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
329 if (!setupGenerator(5))
330 return;
332 LineTable &LT = 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
345 // setup required).
346 {0, LineTable::Byte}, // standard opcode lengths
347 {0, LineTable::Byte}, // directory entry format count (should not be
348 // zero).
349 {0, LineTable::ULEB}, // directories count
350 {0, LineTable::Byte}, // file name entry format count
351 {0, LineTable::ULEB} // file name entry count
354 generate();
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))
364 return;
366 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
367 (Format == DWARF64 ? "DWARF64" : "DWARF32"));
369 LineTable &LT = Gen->addLineTable(Format);
370 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
371 ++Prologue.PrologueLength;
372 LT.setPrologue(Prologue);
374 generate();
376 uint64_t ExpectedEnd =
377 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
378 checkGetOrParseLineTableEmitsError(
379 (Twine("parsing line table prologue at 0x00000000 should have ended at "
380 "0x000000") +
381 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
382 Twine::utohexstr(ExpectedEnd - 1))
383 .str());
386 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
387 if (!setupGenerator(Version))
388 return;
390 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
391 (Format == DWARF64 ? "DWARF64" : "DWARF32"));
393 LineTable &LT = 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.
397 if (Version < 5)
398 Prologue.PrologueLength -= 2;
399 else
400 Prologue.PrologueLength -= 1;
401 LT.setPrologue(Prologue);
403 generate();
405 uint64_t ExpectedEnd =
406 Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();
407 if (Version < 5)
408 --ExpectedEnd;
409 checkGetOrParseLineTableEmitsError(
410 (Twine("parsing line table prologue at 0x00000000 should have ended at "
411 "0x000000") +
412 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
413 Twine::utohexstr(ExpectedEnd + 1))
414 .str());
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())
427 return;
429 LineTable &LT = Gen->addLineTable();
430 // The Length should be 1 for an end sequence opcode.
431 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});
433 generate();
435 checkGetOrParseLineTableEmitsError("unexpected line op length at offset "
436 "0x00000030 expected 0x02 found 0x01");
439 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
440 if (!setupGenerator())
441 return;
443 LineTable &LT = 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, {});
447 LT.addByte(0xaa);
448 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
450 generate();
452 checkGetOrParseLineTableEmitsError(
453 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04");
456 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {
457 if (!setupGenerator())
458 return;
460 LineTable &LT = Gen->addLineTable();
461 LT.addExtendedOpcode(9, DW_LNE_set_address,
462 {{0x1122334455667788, LineTable::Quad}});
463 LT.addStandardOpcode(DW_LNS_copy, {});
464 LT.addByte(0xaa);
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, {});
469 LT.addByte(0xbb);
470 LT.addByte(0xcc);
472 generate();
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())
486 return;
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())
513 return;
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())
533 return;
535 generate();
536 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
538 EXPECT_TRUE(Parser.done());
541 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) {
542 if (!setupGenerator())
543 return;
545 LineTable &LT = Gen->addLineTable();
546 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
547 Gen->addLineTable();
548 generate();
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())
564 return;
566 LineTable &LT = Gen->addLineTable();
567 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
568 Gen->addLineTable();
569 generate();
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())
584 return;
586 LineTable &LT = Gen->addLineTable(DWARF32);
587 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
588 LineTable &LT2 = Gen->addLineTable(DWARF32);
589 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
590 generate();
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())
609 return;
611 LineTable &LT = Gen->addLineTable(DWARF32);
612 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});
613 LineTable &LT2 = Gen->addLineTable(DWARF32);
614 LT2.addExtendedOpcode(9, DW_LNE_set_address,
615 {{0x1234567890abcdef, LineTable::Quad}});
616 LT2.addStandardOpcode(DW_LNS_copy, {});
617 LT2.addByte(0xbb);
618 generate();
620 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
621 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
622 EXPECT_FALSE(Recoverable);
623 ASSERT_FALSE(Parser.done());
624 checkError(
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())
641 return;
643 LineTable &LT = Gen->addLineTable(DWARF32);
644 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
645 LineTable &LT2 = Gen->addLineTable(DWARF32);
646 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
647 generate();
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())
665 return;
667 LineTable &LT = Gen->addLineTable(DWARF32);
668 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});
669 generate();
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