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 //===----------------------------------------------------------------------===//
8 
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"
16 
17 using namespace llvm;
18 using namespace dwarf;
19 using namespace dwarfgen;
20 using namespace object;
21 using namespace utils;
22 using namespace testing;
23 
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)){};
33 
34   ~CommonFixture() {
35     EXPECT_FALSE(Recoverable);
36     EXPECT_FALSE(Unrecoverable);
37   }
38 
39   bool setupGenerator(uint16_t Version = 4, uint8_t AddrSize = 8) {
40     AddressSize = AddrSize;
41     Triple T =
42         getDefaultTargetTripleForAddrSize(AddressSize == 0 ? 8 : AddressSize);
43     if (!isConfigurationSupported(T))
44       return false;
45     auto ExpectedGenerator = Generator::create(T, Version);
46     if (ExpectedGenerator)
47       Gen.reset(ExpectedGenerator->release());
48     return true;
49   }
50 
51   void generate() {
52     Context = createContext();
53     assert(Context != nullptr && "test state is not valid");
54     const DWARFObject &Obj = Context->getDWARFObj();
55     uint8_t TargetAddrSize = AddressSize == 0 ? 8 : AddressSize;
56     LineData = DWARFDataExtractor(
57         Obj, Obj.getLineSection(),
58         getDefaultTargetTripleForAddrSize(TargetAddrSize).isLittleEndian(),
59         AddressSize);
60   }
61 
62   std::unique_ptr<DWARFContext> createContext() {
63     if (!Gen)
64       return nullptr;
65     StringRef FileBytes = Gen->generate();
66     MemoryBufferRef FileBuffer(FileBytes, "dwarf");
67     auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
68     if (Obj)
69       return DWARFContext::create(**Obj);
70     return nullptr;
71   }
72 
73   DWARFDebugLine::SectionParser setupParser() {
74     LineTable &LT = Gen->addLineTable(DWARF32);
75     LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
76     LT.addStandardOpcode(DW_LNS_copy, {});
77     LT.addByte(0xaa);
78     LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
79 
80     LineTable &LT2 = Gen->addLineTable(DWARF64);
81     LT2.addExtendedOpcode(9, DW_LNE_set_address,
82                           {{0x11223344, LineTable::Quad}});
83     LT2.addStandardOpcode(DW_LNS_copy, {});
84     LT2.addByte(0xbb);
85     LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
86 
87     generate();
88 
89     return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs);
90   }
91 
92   void recordRecoverable(Error Err) {
93     Recoverable = joinErrors(std::move(Recoverable), std::move(Err));
94   }
95   void recordUnrecoverable(Error Err) {
96     Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err));
97   }
98 
99   void checkError(ArrayRef<StringRef> ExpectedMsgs, Error Err) {
100     ASSERT_TRUE(Err.operator bool());
101     size_t WhichMsg = 0;
102     Error Remaining =
103         handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
104           ASSERT_LT(WhichMsg, ExpectedMsgs.size());
105           // Use .str(), because googletest doesn't visualise a StringRef
106           // properly.
107           EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++].str());
108         });
109     EXPECT_EQ(WhichMsg, ExpectedMsgs.size());
110     EXPECT_FALSE(Remaining);
111   }
112 
113   void checkError(StringRef ExpectedMsg, Error Err) {
114     checkError(ArrayRef<StringRef>{ExpectedMsg}, std::move(Err));
115   }
116 
117   void checkGetOrParseLineTableEmitsFatalError(StringRef ExpectedMsg,
118                                                uint64_t Offset = 0) {
119     auto ExpectedLineTable = Line.getOrParseLineTable(
120         LineData, Offset, *Context, nullptr, RecordRecoverable);
121     EXPECT_FALSE(ExpectedLineTable);
122     EXPECT_FALSE(Recoverable);
123 
124     checkError(ExpectedMsg, ExpectedLineTable.takeError());
125   }
126 
127   void checkGetOrParseLineTableEmitsFatalError(ArrayRef<StringRef> ExpectedMsgs,
128                                                uint64_t Offset = 0) {
129     auto ExpectedLineTable = Line.getOrParseLineTable(
130         LineData, Offset, *Context, nullptr, RecordRecoverable);
131     EXPECT_FALSE(ExpectedLineTable);
132     EXPECT_FALSE(Recoverable);
133 
134     checkError(ExpectedMsgs, ExpectedLineTable.takeError());
135   }
136 
137   uint8_t AddressSize;
138   std::unique_ptr<Generator> Gen;
139   std::unique_ptr<DWARFContext> Context;
140   DWARFDataExtractor LineData;
141   DWARFDebugLine Line;
142   Error Recoverable;
143   std::function<void(Error)> RecordRecoverable;
144   Error Unrecoverable;
145   std::function<void(Error)> RecordUnrecoverable;
146 
147   SmallVector<std::unique_ptr<DWARFUnit>, 2> CUs;
148   SmallVector<std::unique_ptr<DWARFUnit>, 2> TUs;
149 };
150 
151 // Fixtures must derive from "Test", but parameterised fixtures from
152 // "TestWithParam". It does not seem possible to inherit from both, so we share
153 // the common state in a separate class, inherited by the two fixture classes.
154 struct DebugLineBasicFixture : public Test, public CommonFixture {};
155 
156 struct DebugLineParameterisedFixture
157     : public TestWithParam<std::pair<uint16_t, DwarfFormat>>,
158       public CommonFixture {
159   void SetUp() { std::tie(Version, Format) = GetParam(); }
160 
161   uint16_t Version;
162   DwarfFormat Format;
163 };
164 
165 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format,
166                           DWARFDebugLine::Prologue Prologue,
167                           uint64_t BodyLength) {
168   // Check version specific fields and values.
169   uint64_t UnitLength;
170   uint64_t PrologueLength;
171   switch (Version) {
172   case 4:
173     PrologueLength = 36;
174     UnitLength = PrologueLength + 2;
175     EXPECT_EQ(Prologue.MaxOpsPerInst, 1u);
176     break;
177   case 2:
178   case 3:
179     PrologueLength = 35;
180     UnitLength = PrologueLength + 2;
181     break;
182   case 5:
183     PrologueLength = 39;
184     UnitLength = PrologueLength + 4;
185     EXPECT_EQ(Prologue.getAddressSize(), 8u);
186     EXPECT_EQ(Prologue.SegSelectorSize, 0u);
187     break;
188   default:
189     llvm_unreachable("unsupported DWARF version");
190   }
191   UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8);
192 
193   EXPECT_EQ(Prologue.TotalLength, UnitLength);
194   EXPECT_EQ(Prologue.PrologueLength, PrologueLength);
195   EXPECT_EQ(Prologue.MinInstLength, 1u);
196   EXPECT_EQ(Prologue.DefaultIsStmt, 1u);
197   EXPECT_EQ(Prologue.LineBase, -5);
198   EXPECT_EQ(Prologue.LineRange, 14u);
199   EXPECT_EQ(Prologue.OpcodeBase, 13u);
200   std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
201   EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths);
202   ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u);
203   ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string);
204   EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir");
205   ASSERT_EQ(Prologue.FileNames.size(), 1u);
206   ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string);
207   EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file");
208 }
209 
210 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) {
211   if (!setupGenerator())
212     return;
213   generate();
214 
215   checkGetOrParseLineTableEmitsFatalError(
216       "offset 0x00000000 is not a valid debug line section offset", 0);
217   // Repeat to show that an error is reported each time.
218   checkGetOrParseLineTableEmitsFatalError(
219       "offset 0x00000000 is not a valid debug line section offset", 0);
220   // Show that an error is reported for later offsets too.
221   checkGetOrParseLineTableEmitsFatalError(
222       "offset 0x00000001 is not a valid debug line section offset", 1);
223 }
224 
225 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) {
226   if (!setupGenerator())
227     return;
228 
229   LineTable &LT = Gen->addLineTable();
230   LT.setCustomPrologue({{0, LineTable::Byte}});
231 
232   generate();
233 
234   checkGetOrParseLineTableEmitsFatalError(
235       "offset 0x00000001 is not a valid debug line section offset", 1);
236 }
237 
238 TEST_P(DebugLineParameterisedFixture, PrologueGetLength) {
239   if (!setupGenerator(Version))
240     return;
241   LineTable &LT = Gen->addLineTable(Format);
242   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
243   LT.setPrologue(Prologue);
244   generate();
245 
246   // + 10 for sizes of DWARF-32 unit length, version, prologue length.
247   uint64_t ExpectedLength = Prologue.PrologueLength + 10;
248   if (Version == 5)
249     // Add address and segment selector size fields.
250     ExpectedLength += 2;
251   if (Format == DWARF64)
252     // Unit length grows by 8, prologue length by 4.
253     ExpectedLength += 12;
254 
255   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
256                                                     nullptr, RecordRecoverable);
257   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
258   EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength);
259 }
260 
261 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {
262   if (!setupGenerator(Version))
263     return;
264 
265   SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
266                (Format == DWARF64 ? "DWARF64" : "DWARF32"));
267 
268   LineTable &LT = Gen->addLineTable(Format);
269   LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
270   LT.addStandardOpcode(DW_LNS_copy, {});
271   LT.addByte(0xaa);
272   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
273 
274   LineTable &LT2 = Gen->addLineTable(Format);
275   LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}});
276   LT2.addStandardOpcode(DW_LNS_copy, {});
277   LT2.addByte(0xbb);
278   LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
279   LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}});
280   LT2.addStandardOpcode(DW_LNS_copy, {});
281   LT2.addByte(0xcc);
282   LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
283 
284   generate();
285 
286   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
287                                                     nullptr, RecordRecoverable);
288   ASSERT_TRUE(ExpectedLineTable.operator bool());
289   EXPECT_FALSE(Recoverable);
290   const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable;
291   checkDefaultPrologue(Version, Format, Expected->Prologue, 16);
292   EXPECT_EQ(Expected->Sequences.size(), 1u);
293 
294   uint64_t SecondOffset =
295       Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength;
296   Recoverable = Error::success();
297   auto ExpectedLineTable2 = Line.getOrParseLineTable(
298       LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
299   ASSERT_TRUE(ExpectedLineTable2.operator bool());
300   EXPECT_FALSE(Recoverable);
301   const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2;
302   checkDefaultPrologue(Version, Format, Expected2->Prologue, 32);
303   EXPECT_EQ(Expected2->Sequences.size(), 2u);
304 
305   EXPECT_NE(Expected, Expected2);
306 
307   // Check that if the same offset is requested, the exact same pointer is
308   // returned.
309   Recoverable = Error::success();
310   auto ExpectedLineTable3 = Line.getOrParseLineTable(
311       LineData, 0, *Context, nullptr, RecordRecoverable);
312   ASSERT_TRUE(ExpectedLineTable3.operator bool());
313   EXPECT_FALSE(Recoverable);
314   EXPECT_EQ(Expected, *ExpectedLineTable3);
315 
316   Recoverable = Error::success();
317   auto ExpectedLineTable4 = Line.getOrParseLineTable(
318       LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
319   ASSERT_TRUE(ExpectedLineTable4.operator bool());
320   EXPECT_FALSE(Recoverable);
321   EXPECT_EQ(Expected2, *ExpectedLineTable4);
322 
323   // TODO: Add tests that show that the body of the programs have been read
324   // correctly.
325 }
326 
327 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {
328   if (!setupGenerator())
329     return;
330 
331   LineTable &LT = Gen->addLineTable();
332   LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
333 
334   generate();
335 
336   checkGetOrParseLineTableEmitsFatalError(
337       "parsing line table prologue at offset 0x00000000 unsupported reserved "
338       "unit length found of value 0xfffffff0");
339 }
340 
341 TEST_F(DebugLineBasicFixture, ErrorForLowVersion) {
342   if (!setupGenerator())
343     return;
344 
345   LineTable &LT = Gen->addLineTable();
346   LT.setCustomPrologue(
347       {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}});
348 
349   generate();
350 
351   checkGetOrParseLineTableEmitsFatalError(
352       "parsing line table prologue at offset "
353       "0x00000000 found unsupported version "
354       "0x01");
355 }
356 
357 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
358   if (!setupGenerator(5))
359     return;
360 
361   LineTable &LT = Gen->addLineTable();
362   LT.setCustomPrologue({
363       {19, LineTable::Long}, // unit length
364       {5, LineTable::Half},  // version
365       {8, LineTable::Byte},  // addr size
366       {0, LineTable::Byte},  // segment selector size
367       {11, LineTable::Long}, // prologue length
368       {1, LineTable::Byte},  // min instruction length
369       {1, LineTable::Byte},  // max ops per instruction
370       {1, LineTable::Byte},  // default is_stmt
371       {0, LineTable::Byte},  // line base
372       {14, LineTable::Byte}, // line range
373       {2, LineTable::Byte},  // opcode base (small to reduce the amount of
374                              // setup required).
375       {0, LineTable::Byte},  // standard opcode lengths
376       {0, LineTable::Byte},  // directory entry format count (should not be
377                              // zero).
378       {0, LineTable::ULEB},  // directories count
379       {0, LineTable::Byte},  // file name entry format count
380       {0, LineTable::ULEB}   // file name entry count
381   });
382 
383   generate();
384 
385   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
386                                                     nullptr, RecordRecoverable);
387   EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
388 
389   checkError(
390       {"parsing line table prologue at 0x00000000 found an invalid directory "
391        "or file table description at 0x00000014",
392        "failed to parse entry content descriptions because no path was found"},
393       std::move(Recoverable));
394 }
395 
396 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {
397   if (!setupGenerator(Version))
398     return;
399 
400   SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
401                (Format == DWARF64 ? "DWARF64" : "DWARF32"));
402 
403   LineTable &LT = Gen->addLineTable(Format);
404   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
405   ++Prologue.PrologueLength;
406   LT.setPrologue(Prologue);
407 
408   generate();
409 
410   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
411                                                     nullptr, RecordRecoverable);
412   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
413   DWARFDebugLine::LineTable Result(**ExpectedLineTable);
414   // Undo the earlier modification so that it can be compared against a
415   // "default" prologue.
416   --Result.Prologue.PrologueLength;
417   checkDefaultPrologue(Version, Format, Result.Prologue, 0);
418 
419   uint64_t ExpectedEnd =
420       Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
421   checkError(
422       (Twine("parsing line table prologue at 0x00000000 should have ended at "
423              "0x000000") +
424        Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
425        Twine::utohexstr(ExpectedEnd - 1))
426           .str(),
427       std::move(Recoverable));
428 }
429 
430 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
431   if (!setupGenerator(Version))
432     return;
433 
434   SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
435                (Format == DWARF64 ? "DWARF64" : "DWARF32"));
436 
437   LineTable &LT = Gen->addLineTable(Format);
438   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
439   // FIXME: Ideally, we'd test for 1 less than expected, but the code does not
440   // currently fail if missing only the terminator of a v2-4 file table.
441   if (Version < 5)
442     Prologue.PrologueLength -= 2;
443   else
444     Prologue.PrologueLength -= 1;
445   LT.setPrologue(Prologue);
446 
447   generate();
448 
449   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
450                                                     nullptr, RecordRecoverable);
451   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
452   DWARFDebugLine::LineTable Result(**ExpectedLineTable);
453   // Undo the earlier modification so that it can be compared against a
454   // "default" prologue.
455   if (Version < 5)
456     Result.Prologue.PrologueLength += 2;
457   else
458     Result.Prologue.PrologueLength += 1;
459   checkDefaultPrologue(Version, Format, Result.Prologue, 0);
460 
461   uint64_t ExpectedEnd =
462       Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();
463   if (Version < 5)
464     --ExpectedEnd;
465   checkError(
466       (Twine("parsing line table prologue at 0x00000000 should have ended at "
467              "0x000000") +
468        Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
469        Twine::utohexstr(ExpectedEnd + 1))
470           .str(),
471       std::move(Recoverable));
472 }
473 
474 INSTANTIATE_TEST_CASE_P(
475     LineTableTestParams, DebugLineParameterisedFixture,
476     Values(std::make_pair(
477                2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32.
478            std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields.
479            std::make_pair(4, DWARF64), // Test v4 fields and DWARF64.
480            std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), );
481 
482 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) {
483   if (!setupGenerator())
484     return;
485 
486   LineTable &LT = Gen->addLineTable();
487   LT.addByte(0xaa);
488   // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode.
489   // The operand will be read for both the discriminator opcode and then parsed
490   // again as DW_LNS_negate_stmt, to respect the claimed length.
491   LT.addExtendedOpcode(1, DW_LNE_set_discriminator,
492                        {{DW_LNS_negate_stmt, LineTable::ULEB}});
493   LT.addByte(0xbb);
494   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
495   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
496 
497   generate();
498 
499   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
500                                                     nullptr, RecordRecoverable);
501   checkError(
502       "unexpected line op length at offset 0x00000031 expected 0x01 found 0x02",
503       std::move(Recoverable));
504   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
505   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);
506   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
507   EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u);
508   EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt);
509 }
510 
511 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) {
512   if (!setupGenerator())
513     return;
514 
515   LineTable &LT = Gen->addLineTable();
516   LT.addByte(0xaa);
517   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
518   // The Length should be 1 for an end sequence opcode.
519   LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});
520   // The negate statement opcode will be skipped.
521   LT.addStandardOpcode(DW_LNS_negate_stmt, {});
522   LT.addByte(0xbb);
523   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
524   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
525 
526   generate();
527 
528   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
529                                                     nullptr, RecordRecoverable);
530   checkError(
531       "unexpected line op length at offset 0x00000032 expected 0x02 found 0x01",
532       std::move(Recoverable));
533   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
534   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u);
535   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u);
536   ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u);
537   EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u);
538 }
539 
540 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) {
541   if (!setupGenerator())
542     return;
543 
544   LineTable &Padding = Gen->addLineTable();
545   // Add some padding to show that a non-zero offset is handled correctly.
546   Padding.setCustomPrologue({{0, LineTable::Byte}});
547   LineTable &LT = Gen->addLineTable();
548   LT.addStandardOpcode(DW_LNS_copy, {});
549   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
550   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
551   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
552   // Set the total length to 1 higher than the actual length.
553   ++Prologue.TotalLength;
554   LT.setPrologue(Prologue);
555 
556   generate();
557 
558   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context,
559                                                     nullptr, RecordRecoverable);
560   checkError("line table program with offset 0x00000001 has length 0x00000034 "
561              "but only 0x00000033 bytes are available",
562              std::move(Recoverable));
563   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
564   EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
565   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
566 }
567 
568 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
569   if (!setupGenerator(4, 8))
570     return;
571 
572   LineTable &LT = Gen->addLineTable();
573   // The line data extractor expects size 8 (Quad) addresses.
574   uint64_t Addr1 = 0x11223344;
575   LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}});
576   LT.addStandardOpcode(DW_LNS_copy, {});
577   // Show that the expected address size is unchanged, so later valid lines
578   // don't cause a problem.
579   uint64_t Addr2 = 0x1122334455667788;
580   LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}});
581   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
582 
583   generate();
584 
585   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
586                                                     nullptr, RecordRecoverable);
587   checkError(
588       "mismatching address size at offset 0x00000030 expected 0x08 found 0x04",
589       std::move(Recoverable));
590   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
591   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
592   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
593   EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1);
594   EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2);
595 }
596 
597 TEST_F(DebugLineBasicFixture,
598        ErrorForMismatchedAddressSizeUnsetInitialAddress) {
599   if (!setupGenerator(4, 0))
600     return;
601 
602   LineTable &LT = Gen->addLineTable();
603   uint64_t Addr1 = 0x11223344;
604   LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}});
605   LT.addStandardOpcode(DW_LNS_copy, {});
606   uint64_t Addr2 = 0x1122334455667788;
607   LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}});
608   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
609 
610   generate();
611 
612   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
613                                                     nullptr, RecordRecoverable);
614   checkError(
615       "mismatching address size at offset 0x00000038 expected 0x04 found 0x08",
616       std::move(Recoverable));
617   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
618   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
619   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
620   EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1);
621   EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2);
622 }
623 
624 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {
625   if (!setupGenerator())
626     return;
627 
628   LineTable &LT = Gen->addLineTable();
629   LT.addExtendedOpcode(9, DW_LNE_set_address,
630                        {{0x1122334455667788, LineTable::Quad}});
631   LT.addStandardOpcode(DW_LNS_copy, {});
632   LT.addByte(0xaa);
633   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
634   LT.addExtendedOpcode(9, DW_LNE_set_address,
635                        {{0x99aabbccddeeff00, LineTable::Quad}});
636   LT.addStandardOpcode(DW_LNS_copy, {});
637   LT.addByte(0xbb);
638   LT.addByte(0xcc);
639 
640   generate();
641 
642   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
643                                                     nullptr, RecordRecoverable);
644   checkError("last sequence in debug line table at offset 0x00000000 is not "
645              "terminated",
646              std::move(Recoverable));
647   ASSERT_TRUE(ExpectedLineTable.operator bool());
648   EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u);
649   // The unterminated sequence is not added to the sequence list.
650   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
651 }
652 
653 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) {
654   if (!setupGenerator())
655     return;
656 
657   DWARFDebugLine::SectionParser Parser = setupParser();
658 
659   EXPECT_EQ(Parser.getOffset(), 0u);
660   ASSERT_FALSE(Parser.done());
661 
662   DWARFDebugLine::LineTable Parsed =
663       Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
664   checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16);
665   EXPECT_EQ(Parsed.Sequences.size(), 1u);
666   EXPECT_EQ(Parser.getOffset(), 62u);
667   ASSERT_FALSE(Parser.done());
668 
669   DWARFDebugLine::LineTable Parsed2 =
670       Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
671   checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16);
672   EXPECT_EQ(Parsed2.Sequences.size(), 1u);
673   EXPECT_EQ(Parser.getOffset(), 136u);
674   EXPECT_TRUE(Parser.done());
675 
676   EXPECT_FALSE(Recoverable);
677   EXPECT_FALSE(Unrecoverable);
678 }
679 
680 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) {
681   if (!setupGenerator())
682     return;
683 
684   DWARFDebugLine::SectionParser Parser = setupParser();
685 
686   EXPECT_EQ(Parser.getOffset(), 0u);
687   ASSERT_FALSE(Parser.done());
688 
689   Parser.skip(RecordRecoverable, RecordUnrecoverable);
690   EXPECT_EQ(Parser.getOffset(), 62u);
691   ASSERT_FALSE(Parser.done());
692 
693   Parser.skip(RecordRecoverable, RecordUnrecoverable);
694   EXPECT_EQ(Parser.getOffset(), 136u);
695   EXPECT_TRUE(Parser.done());
696 
697   EXPECT_FALSE(Recoverable);
698   EXPECT_FALSE(Unrecoverable);
699 }
700 
701 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) {
702   if (!setupGenerator())
703     return;
704 
705   generate();
706   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
707 
708   EXPECT_TRUE(Parser.done());
709 }
710 
711 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) {
712   if (!setupGenerator())
713     return;
714 
715   LineTable &LT = Gen->addLineTable();
716   LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
717   Gen->addLineTable();
718   generate();
719 
720   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
721   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
722 
723   EXPECT_EQ(Parser.getOffset(), 4u);
724   EXPECT_TRUE(Parser.done());
725   EXPECT_FALSE(Recoverable);
726 
727   checkError("parsing line table prologue at offset 0x00000000 unsupported "
728              "reserved unit length found of value 0xfffffff0",
729              std::move(Unrecoverable));
730 }
731 
732 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) {
733   if (!setupGenerator())
734     return;
735 
736   LineTable &LT = Gen->addLineTable();
737   LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
738   Gen->addLineTable();
739   generate();
740 
741   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
742   Parser.skip(RecordRecoverable, RecordUnrecoverable);
743 
744   EXPECT_EQ(Parser.getOffset(), 4u);
745   EXPECT_TRUE(Parser.done());
746   EXPECT_FALSE(Recoverable);
747 
748   checkError("parsing line table prologue at offset 0x00000000 unsupported "
749              "reserved unit length found of value 0xfffffff0",
750              std::move(Unrecoverable));
751 }
752 
753 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) {
754   if (!setupGenerator())
755     return;
756 
757   LineTable &LT = Gen->addLineTable(DWARF32);
758   LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
759   LineTable &LT2 = Gen->addLineTable(DWARF32);
760   LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
761   generate();
762 
763   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
764   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
765   ASSERT_FALSE(Parser.done());
766   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
767 
768   EXPECT_TRUE(Parser.done());
769   EXPECT_FALSE(Recoverable);
770 
771   checkError({"parsing line table prologue at offset 0x00000000 found "
772               "unsupported version 0x00",
773               "parsing line table prologue at offset 0x00000006 found "
774               "unsupported version 0x01"},
775              std::move(Unrecoverable));
776 }
777 
778 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) {
779   if (!setupGenerator())
780     return;
781 
782   LineTable &LT = Gen->addLineTable(DWARF32);
783   LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});
784   LineTable &LT2 = Gen->addLineTable(DWARF32);
785   LT2.addExtendedOpcode(9, DW_LNE_set_address,
786                         {{0x1234567890abcdef, LineTable::Quad}});
787   LT2.addStandardOpcode(DW_LNS_copy, {});
788   LT2.addByte(0xbb);
789   generate();
790 
791   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
792   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
793   EXPECT_FALSE(Unrecoverable);
794   ASSERT_FALSE(Parser.done());
795   checkError(
796       "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01",
797       std::move(Recoverable));
798 
799   // Reset the error state so that it does not confuse the next set of checks.
800   Unrecoverable = Error::success();
801   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
802 
803   EXPECT_TRUE(Parser.done());
804   checkError("last sequence in debug line table at offset 0x00000031 is not "
805              "terminated",
806              std::move(Recoverable));
807   EXPECT_FALSE(Unrecoverable);
808 }
809 
810 TEST_F(DebugLineBasicFixture,
811        ParserReportsPrologueErrorsInEachTableWhenSkipping) {
812   if (!setupGenerator())
813     return;
814 
815   LineTable &LT = Gen->addLineTable(DWARF32);
816   LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
817   LineTable &LT2 = Gen->addLineTable(DWARF32);
818   LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
819   generate();
820 
821   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
822   Parser.skip(RecordRecoverable, RecordUnrecoverable);
823   ASSERT_FALSE(Parser.done());
824   Parser.skip(RecordRecoverable, RecordUnrecoverable);
825 
826   EXPECT_TRUE(Parser.done());
827   EXPECT_FALSE(Recoverable);
828 
829   checkError({"parsing line table prologue at offset 0x00000000 found "
830               "unsupported version 0x00",
831               "parsing line table prologue at offset 0x00000006 found "
832               "unsupported version 0x01"},
833              std::move(Unrecoverable));
834 }
835 
836 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) {
837   if (!setupGenerator())
838     return;
839 
840   LineTable &LT = Gen->addLineTable(DWARF32);
841   LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});
842   generate();
843 
844   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
845   Parser.skip(RecordRecoverable, RecordUnrecoverable);
846 
847   EXPECT_TRUE(Parser.done());
848   EXPECT_FALSE(Recoverable);
849   EXPECT_FALSE(Unrecoverable);
850 }
851 
852 TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) {
853   if (!setupGenerator())
854     return;
855 
856   using ValLen = dwarfgen::LineTable::ValueAndLength;
857   LineTable &LT = Gen->addLineTable(DWARF32);
858   LT.addStandardOpcode(DW_LNS_copy, {});
859   LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}});
860   LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}});
861   LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}});
862   LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}});
863   LT.addStandardOpcode(DW_LNS_negate_stmt, {});
864   LT.addStandardOpcode(DW_LNS_set_basic_block, {});
865   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
866   LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}});
867   LT.addStandardOpcode(DW_LNS_set_prologue_end, {});
868   LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {});
869   LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}});
870   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
871   generate();
872 
873   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
874   std::string Output;
875   raw_string_ostream OS(Output);
876   Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS);
877   OS.flush();
878 
879   EXPECT_FALSE(Recoverable);
880   EXPECT_FALSE(Unrecoverable);
881   auto InOutput = [&Output](char const *Str) {
882     return Output.find(Str) != std::string::npos;
883   };
884   EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output;
885   EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output;
886   // FIXME: The value printed after DW_LNS_advance_line is currently the result
887   // of the advance, but it should be the value being advanced by. See
888   // https://bugs.llvm.org/show_bug.cgi?id=44261 for details.
889   EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output;
890   EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output;
891   EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output;
892   EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output;
893   EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output;
894   EXPECT_TRUE(
895       InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n"))
896       << Output;
897   EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n"))
898       << Output;
899   EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output;
900   EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output;
901   EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output;
902 }
903 
904 } // end anonymous namespace
905