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 = 42;
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   ASSERT_EQ(Prologue.FileNames[0].DirIdx, 0u);
208   EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file");
209 }
210 
211 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) {
212   if (!setupGenerator())
213     return;
214   generate();
215 
216   checkGetOrParseLineTableEmitsFatalError(
217       "offset 0x00000000 is not a valid debug line section offset", 0);
218   // Repeat to show that an error is reported each time.
219   checkGetOrParseLineTableEmitsFatalError(
220       "offset 0x00000000 is not a valid debug line section offset", 0);
221   // Show that an error is reported for later offsets too.
222   checkGetOrParseLineTableEmitsFatalError(
223       "offset 0x00000001 is not a valid debug line section offset", 1);
224 }
225 
226 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) {
227   if (!setupGenerator())
228     return;
229 
230   LineTable &LT = Gen->addLineTable();
231   LT.setCustomPrologue({{0, LineTable::Byte}});
232 
233   generate();
234 
235   checkGetOrParseLineTableEmitsFatalError(
236       "offset 0x00000001 is not a valid debug line section offset", 1);
237 }
238 
239 TEST_P(DebugLineParameterisedFixture, PrologueGetLength) {
240   if (!setupGenerator(Version))
241     return;
242   LineTable &LT = Gen->addLineTable(Format);
243   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
244   LT.setPrologue(Prologue);
245   generate();
246 
247   // + 10 for sizes of DWARF-32 unit length, version, prologue length.
248   uint64_t ExpectedLength = Prologue.PrologueLength + 10;
249   if (Version == 5)
250     // Add address and segment selector size fields.
251     ExpectedLength += 2;
252   if (Format == DWARF64)
253     // Unit length grows by 8, prologue length by 4.
254     ExpectedLength += 12;
255 
256   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
257                                                     nullptr, RecordRecoverable);
258   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
259   EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength);
260 }
261 
262 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {
263   if (!setupGenerator(Version))
264     return;
265 
266   SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
267                (Format == DWARF64 ? "DWARF64" : "DWARF32"));
268 
269   LineTable &LT = Gen->addLineTable(Format);
270   LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});
271   LT.addStandardOpcode(DW_LNS_copy, {});
272   LT.addByte(0xaa);
273   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
274 
275   LineTable &LT2 = Gen->addLineTable(Format);
276   LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}});
277   LT2.addStandardOpcode(DW_LNS_copy, {});
278   LT2.addByte(0xbb);
279   LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
280   LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}});
281   LT2.addStandardOpcode(DW_LNS_copy, {});
282   LT2.addByte(0xcc);
283   LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
284 
285   generate();
286 
287   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
288                                                     nullptr, RecordRecoverable);
289   ASSERT_TRUE(ExpectedLineTable.operator bool());
290   EXPECT_FALSE(Recoverable);
291   const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable;
292   checkDefaultPrologue(Version, Format, Expected->Prologue, 16);
293   EXPECT_EQ(Expected->Sequences.size(), 1u);
294 
295   uint64_t SecondOffset =
296       Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength;
297   Recoverable = Error::success();
298   auto ExpectedLineTable2 = Line.getOrParseLineTable(
299       LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
300   ASSERT_TRUE(ExpectedLineTable2.operator bool());
301   EXPECT_FALSE(Recoverable);
302   const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2;
303   checkDefaultPrologue(Version, Format, Expected2->Prologue, 32);
304   EXPECT_EQ(Expected2->Sequences.size(), 2u);
305 
306   EXPECT_NE(Expected, Expected2);
307 
308   // Check that if the same offset is requested, the exact same pointer is
309   // returned.
310   Recoverable = Error::success();
311   auto ExpectedLineTable3 = Line.getOrParseLineTable(
312       LineData, 0, *Context, nullptr, RecordRecoverable);
313   ASSERT_TRUE(ExpectedLineTable3.operator bool());
314   EXPECT_FALSE(Recoverable);
315   EXPECT_EQ(Expected, *ExpectedLineTable3);
316 
317   Recoverable = Error::success();
318   auto ExpectedLineTable4 = Line.getOrParseLineTable(
319       LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
320   ASSERT_TRUE(ExpectedLineTable4.operator bool());
321   EXPECT_FALSE(Recoverable);
322   EXPECT_EQ(Expected2, *ExpectedLineTable4);
323 
324   // TODO: Add tests that show that the body of the programs have been read
325   // correctly.
326 }
327 
328 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {
329   if (!setupGenerator())
330     return;
331 
332   LineTable &LT = Gen->addLineTable();
333   LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
334 
335   generate();
336 
337   checkGetOrParseLineTableEmitsFatalError(
338       "parsing line table prologue at offset 0x00000000 unsupported reserved "
339       "unit length found of value 0xfffffff0");
340 }
341 
342 struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>,
343                                             public CommonFixture {
344   void SetUp() { Version = GetParam(); }
345 
346   uint16_t Version;
347 };
348 
349 TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) {
350   if (!setupGenerator())
351     return;
352 
353   LineTable &LT = Gen->addLineTable();
354   LT.setCustomPrologue(
355       {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}});
356 
357   generate();
358 
359   checkGetOrParseLineTableEmitsFatalError(
360       "parsing line table prologue at offset 0x00000000 found unsupported "
361       "version " +
362       std::to_string(Version));
363 }
364 
365 INSTANTIATE_TEST_CASE_P(UnsupportedVersionTestParams,
366                         DebugLineUnsupportedVersionFixture,
367                         Values(/*1 below min */ 1, /* 1 above max */ 6,
368                                /* Maximum possible */ 0xffff), );
369 
370 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
371   if (!setupGenerator(5))
372     return;
373 
374   LineTable &LT = Gen->addLineTable();
375   LT.setCustomPrologue({
376       {19, LineTable::Long}, // unit length
377       {5, LineTable::Half},  // version
378       {8, LineTable::Byte},  // addr size
379       {0, LineTable::Byte},  // segment selector size
380       {11, LineTable::Long}, // prologue length
381       {1, LineTable::Byte},  // min instruction length
382       {1, LineTable::Byte},  // max ops per instruction
383       {1, LineTable::Byte},  // default is_stmt
384       {0, LineTable::Byte},  // line base
385       {14, LineTable::Byte}, // line range
386       {2, LineTable::Byte},  // opcode base (small to reduce the amount of
387                              // setup required).
388       {0, LineTable::Byte},  // standard opcode lengths
389       {0, LineTable::Byte},  // directory entry format count (should not be
390                              // zero).
391       {0, LineTable::ULEB},  // directories count
392       {0, LineTable::Byte},  // file name entry format count
393       {0, LineTable::ULEB}   // file name entry count
394   });
395 
396   generate();
397 
398   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
399                                                     nullptr, RecordRecoverable);
400   EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
401 
402   checkError(
403       {"parsing line table prologue at 0x00000000 found an invalid directory "
404        "or file table description at 0x00000014",
405        "failed to parse entry content descriptions because no path was found"},
406       std::move(Recoverable));
407 }
408 
409 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {
410   if (!setupGenerator(Version))
411     return;
412 
413   SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
414                (Format == DWARF64 ? "DWARF64" : "DWARF32"));
415 
416   LineTable &LT = Gen->addLineTable(Format);
417   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
418   ++Prologue.PrologueLength;
419   LT.setPrologue(Prologue);
420 
421   generate();
422 
423   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
424                                                     nullptr, RecordRecoverable);
425   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
426   DWARFDebugLine::LineTable Result(**ExpectedLineTable);
427   // Undo the earlier modification so that it can be compared against a
428   // "default" prologue.
429   --Result.Prologue.PrologueLength;
430   checkDefaultPrologue(Version, Format, Result.Prologue, 0);
431 
432   uint64_t ExpectedEnd =
433       Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
434   checkError(
435       (Twine("parsing line table prologue at 0x00000000 should have ended at "
436              "0x000000") +
437        Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
438        Twine::utohexstr(ExpectedEnd - 1))
439           .str(),
440       std::move(Recoverable));
441 }
442 
443 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
444   if (!setupGenerator(Version))
445     return;
446 
447   SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +
448                (Format == DWARF64 ? "DWARF64" : "DWARF32"));
449 
450   LineTable &LT = Gen->addLineTable(Format);
451   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
452   Prologue.PrologueLength -= 2;
453   LT.setPrologue(Prologue);
454 
455   generate();
456 
457   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
458                                                     nullptr, RecordRecoverable);
459   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
460   DWARFDebugLine::LineTable Result(**ExpectedLineTable);
461   // Undo the earlier modification so that it can be compared against a
462   // "default" prologue.
463   Result.Prologue.PrologueLength += 2;
464   checkDefaultPrologue(Version, Format, Result.Prologue, 0);
465 
466   uint64_t ExpectedEnd =
467       Prologue.TotalLength - 2 + Prologue.sizeofTotalLength();
468   std::vector<std::string> Errs;
469   // Parsing of a DWARFv2-4 file table stops at the end of an entry once the
470   // prologue end has been reached, whether or not the trailing null terminator
471   // has been found. As such, the expected error message will be slightly
472   // different.
473   uint64_t ActualEnd = Version == 5 ? ExpectedEnd + 2 : ExpectedEnd + 1;
474   if (Version != 5) {
475     Errs.emplace_back(
476         (Twine("parsing line table prologue at 0x00000000 found an invalid "
477                "directory or file table description at 0x000000") +
478          Twine::utohexstr(ActualEnd))
479             .str());
480     Errs.emplace_back("file names table was not null terminated before the end "
481                       "of the prologue");
482   }
483   Errs.emplace_back(
484       (Twine("parsing line table prologue at 0x00000000 should have ended at "
485              "0x000000") +
486        Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
487        Twine::utohexstr(ActualEnd))
488           .str());
489   std::vector<StringRef> ErrRefs(Errs.begin(), Errs.end());
490   checkError(ErrRefs, std::move(Recoverable));
491 }
492 
493 INSTANTIATE_TEST_CASE_P(
494     LineTableTestParams, DebugLineParameterisedFixture,
495     Values(std::make_pair(
496                2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32.
497            std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields.
498            std::make_pair(4, DWARF64), // Test v4 fields and DWARF64.
499            std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), );
500 
501 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) {
502   if (!setupGenerator())
503     return;
504 
505   LineTable &LT = Gen->addLineTable();
506   LT.addByte(0xaa);
507   // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode.
508   // The operand will be read for both the discriminator opcode and then parsed
509   // again as DW_LNS_negate_stmt, to respect the claimed length.
510   LT.addExtendedOpcode(1, DW_LNE_set_discriminator,
511                        {{DW_LNS_negate_stmt, LineTable::ULEB}});
512   LT.addByte(0xbb);
513   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
514   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
515 
516   generate();
517 
518   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
519                                                     nullptr, RecordRecoverable);
520   checkError(
521       "unexpected line op length at offset 0x00000031 expected 0x01 found 0x02",
522       std::move(Recoverable));
523   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
524   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);
525   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
526   EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u);
527   EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt);
528 }
529 
530 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) {
531   if (!setupGenerator())
532     return;
533 
534   LineTable &LT = Gen->addLineTable();
535   LT.addByte(0xaa);
536   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
537   // The Length should be 1 for an end sequence opcode.
538   LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});
539   // The negate statement opcode will be skipped.
540   LT.addStandardOpcode(DW_LNS_negate_stmt, {});
541   LT.addByte(0xbb);
542   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
543   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
544 
545   generate();
546 
547   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
548                                                     nullptr, RecordRecoverable);
549   checkError(
550       "unexpected line op length at offset 0x00000032 expected 0x02 found 0x01",
551       std::move(Recoverable));
552   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
553   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u);
554   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u);
555   ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u);
556   EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u);
557 }
558 
559 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) {
560   if (!setupGenerator())
561     return;
562 
563   LineTable &Padding = Gen->addLineTable();
564   // Add some padding to show that a non-zero offset is handled correctly.
565   Padding.setCustomPrologue({{0, LineTable::Byte}});
566   LineTable &LT = Gen->addLineTable();
567   LT.addStandardOpcode(DW_LNS_copy, {});
568   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
569   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
570   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
571   // Set the total length to 1 higher than the actual length.
572   ++Prologue.TotalLength;
573   LT.setPrologue(Prologue);
574 
575   generate();
576 
577   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context,
578                                                     nullptr, RecordRecoverable);
579   checkError("line table program with offset 0x00000001 has length 0x00000034 "
580              "but only 0x00000033 bytes are available",
581              std::move(Recoverable));
582   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
583   EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
584   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
585 }
586 
587 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
588   if (!setupGenerator(4, 8))
589     return;
590 
591   LineTable &LT = Gen->addLineTable();
592   // The line data extractor expects size 8 (Quad) addresses.
593   uint64_t Addr1 = 0x11223344;
594   LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}});
595   LT.addStandardOpcode(DW_LNS_copy, {});
596   // Show that the expected address size is unchanged, so later valid lines
597   // don't cause a problem.
598   uint64_t Addr2 = 0x1122334455667788;
599   LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}});
600   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
601 
602   generate();
603 
604   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
605                                                     nullptr, RecordRecoverable);
606   checkError(
607       "mismatching address size at offset 0x00000030 expected 0x08 found 0x04",
608       std::move(Recoverable));
609   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
610   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
611   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
612   EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1);
613   EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2);
614 }
615 
616 TEST_F(DebugLineBasicFixture,
617        ErrorForMismatchedAddressSizeUnsetInitialAddress) {
618   if (!setupGenerator(4, 0))
619     return;
620 
621   LineTable &LT = Gen->addLineTable();
622   uint64_t Addr1 = 0x11223344;
623   LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}});
624   LT.addStandardOpcode(DW_LNS_copy, {});
625   uint64_t Addr2 = 0x1122334455667788;
626   LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}});
627   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
628 
629   generate();
630 
631   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
632                                                     nullptr, RecordRecoverable);
633   checkError(
634       "mismatching address size at offset 0x00000038 expected 0x04 found 0x08",
635       std::move(Recoverable));
636   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
637   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
638   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
639   EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1);
640   EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2);
641 }
642 
643 TEST_F(DebugLineBasicFixture,
644        ErrorForUnsupportedAddressSizeInSetAddressLength) {
645   // Use DWARF v4, and 0 for data extractor address size so that the address
646   // size is derived from the opcode length.
647   if (!setupGenerator(4, 0))
648     return;
649 
650   LineTable &LT = Gen->addLineTable();
651   // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for
652   // the Half (2) + Byte (1) operand, representing the unsupported address size.
653   LT.addExtendedOpcode(4, DW_LNE_set_address,
654                        {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}});
655   LT.addStandardOpcode(DW_LNS_copy, {});
656   // Special opcode to ensure the address has changed between the first and last
657   // row in the sequence. Without this, the sequence will not be recorded.
658   LT.addByte(0xaa);
659   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
660 
661   generate();
662 
663   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
664                                                     nullptr, RecordRecoverable);
665   checkError(
666       "address size 0x03 of DW_LNE_set_address opcode at offset 0x00000030 is "
667       "unsupported",
668       std::move(Recoverable));
669   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
670   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);
671   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
672   // Show that the set address opcode is ignored in this case.
673   EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u);
674 }
675 
676 TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) {
677   // Use DWARF v4, and 0 for data extractor address size so that the address
678   // size is derived from the opcode length.
679   if (!setupGenerator(4, 0))
680     return;
681 
682   LineTable &LT = Gen->addLineTable();
683   // Specifically use an operand size that has a trailing byte of a supported
684   // size (8), so that any potential truncation would result in a valid size.
685   std::vector<LineTable::ValueAndLength> Operands(0x108);
686   LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands);
687   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
688 
689   generate();
690 
691   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
692                                                     nullptr, RecordRecoverable);
693   checkError(
694       "address size 0x108 of DW_LNE_set_address opcode at offset 0x00000031 is "
695       "unsupported",
696       std::move(Recoverable));
697   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
698 }
699 
700 TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) {
701   // Use 0 for data extractor address size so that it does not clash with the
702   // header address size.
703   if (!setupGenerator(5, 0))
704     return;
705 
706   LineTable &LT = Gen->addLineTable();
707   // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode
708   // itself and 9 for the Quad (8) + Byte (1) operand representing the
709   // unsupported address size.
710   uint8_t AddressSize = 9;
711   LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address,
712                        {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}});
713   LT.addStandardOpcode(DW_LNS_copy, {});
714   // Special opcode to ensure the address has changed between the first and last
715   // row in the sequence. Without this, the sequence will not be recorded.
716   LT.addByte(0xaa);
717   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
718   DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
719   Prologue.FormParams.AddrSize = AddressSize;
720   LT.setPrologue(Prologue);
721 
722   generate();
723 
724   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
725                                                     nullptr, RecordRecoverable);
726   checkError(
727       "address size 0x09 of DW_LNE_set_address opcode at offset 0x00000038 is "
728       "unsupported",
729       std::move(Recoverable));
730   ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
731   ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);
732   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
733   // Show that the set address opcode is ignored in this case.
734   EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u);
735 }
736 
737 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {
738   if (!setupGenerator())
739     return;
740 
741   LineTable &LT = Gen->addLineTable();
742   LT.addExtendedOpcode(9, DW_LNE_set_address,
743                        {{0x1122334455667788, LineTable::Quad}});
744   LT.addStandardOpcode(DW_LNS_copy, {});
745   LT.addByte(0xaa);
746   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
747   LT.addExtendedOpcode(9, DW_LNE_set_address,
748                        {{0x99aabbccddeeff00, LineTable::Quad}});
749   LT.addStandardOpcode(DW_LNS_copy, {});
750   LT.addByte(0xbb);
751   LT.addByte(0xcc);
752 
753   generate();
754 
755   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
756                                                     nullptr, RecordRecoverable);
757   checkError("last sequence in debug line table at offset 0x00000000 is not "
758              "terminated",
759              std::move(Recoverable));
760   ASSERT_TRUE(ExpectedLineTable.operator bool());
761   EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u);
762   // The unterminated sequence is not added to the sequence list.
763   EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
764 }
765 
766 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) {
767   if (!setupGenerator())
768     return;
769 
770   DWARFDebugLine::SectionParser Parser = setupParser();
771 
772   EXPECT_EQ(Parser.getOffset(), 0u);
773   ASSERT_FALSE(Parser.done());
774 
775   DWARFDebugLine::LineTable Parsed =
776       Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
777   checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16);
778   EXPECT_EQ(Parsed.Sequences.size(), 1u);
779   EXPECT_EQ(Parser.getOffset(), 62u);
780   ASSERT_FALSE(Parser.done());
781 
782   DWARFDebugLine::LineTable Parsed2 =
783       Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
784   checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16);
785   EXPECT_EQ(Parsed2.Sequences.size(), 1u);
786   EXPECT_EQ(Parser.getOffset(), 136u);
787   EXPECT_TRUE(Parser.done());
788 
789   EXPECT_FALSE(Recoverable);
790   EXPECT_FALSE(Unrecoverable);
791 }
792 
793 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) {
794   if (!setupGenerator())
795     return;
796 
797   DWARFDebugLine::SectionParser Parser = setupParser();
798 
799   EXPECT_EQ(Parser.getOffset(), 0u);
800   ASSERT_FALSE(Parser.done());
801 
802   Parser.skip(RecordRecoverable, RecordUnrecoverable);
803   EXPECT_EQ(Parser.getOffset(), 62u);
804   ASSERT_FALSE(Parser.done());
805 
806   Parser.skip(RecordRecoverable, RecordUnrecoverable);
807   EXPECT_EQ(Parser.getOffset(), 136u);
808   EXPECT_TRUE(Parser.done());
809 
810   EXPECT_FALSE(Recoverable);
811   EXPECT_FALSE(Unrecoverable);
812 }
813 
814 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) {
815   if (!setupGenerator())
816     return;
817 
818   generate();
819   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
820 
821   EXPECT_TRUE(Parser.done());
822 }
823 
824 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) {
825   if (!setupGenerator())
826     return;
827 
828   LineTable &LT = Gen->addLineTable();
829   LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
830   Gen->addLineTable();
831   generate();
832 
833   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
834   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
835 
836   EXPECT_EQ(Parser.getOffset(), 4u);
837   EXPECT_TRUE(Parser.done());
838   EXPECT_FALSE(Recoverable);
839 
840   checkError("parsing line table prologue at offset 0x00000000 unsupported "
841              "reserved unit length found of value 0xfffffff0",
842              std::move(Unrecoverable));
843 }
844 
845 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) {
846   if (!setupGenerator())
847     return;
848 
849   LineTable &LT = Gen->addLineTable();
850   LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
851   Gen->addLineTable();
852   generate();
853 
854   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
855   Parser.skip(RecordRecoverable, RecordUnrecoverable);
856 
857   EXPECT_EQ(Parser.getOffset(), 4u);
858   EXPECT_TRUE(Parser.done());
859   EXPECT_FALSE(Recoverable);
860 
861   checkError("parsing line table prologue at offset 0x00000000 unsupported "
862              "reserved unit length found of value 0xfffffff0",
863              std::move(Unrecoverable));
864 }
865 
866 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) {
867   if (!setupGenerator())
868     return;
869 
870   LineTable &LT = Gen->addLineTable(DWARF32);
871   LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
872   LineTable &LT2 = Gen->addLineTable(DWARF32);
873   LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
874   generate();
875 
876   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
877   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
878   ASSERT_FALSE(Parser.done());
879   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
880 
881   EXPECT_TRUE(Parser.done());
882   EXPECT_FALSE(Recoverable);
883 
884   checkError({"parsing line table prologue at offset 0x00000000 found "
885               "unsupported version 0",
886               "parsing line table prologue at offset 0x00000006 found "
887               "unsupported version 1"},
888              std::move(Unrecoverable));
889 }
890 
891 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) {
892   if (!setupGenerator())
893     return;
894 
895   LineTable &LT = Gen->addLineTable(DWARF32);
896   LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});
897   LineTable &LT2 = Gen->addLineTable(DWARF32);
898   LT2.addExtendedOpcode(9, DW_LNE_set_address,
899                         {{0x1234567890abcdef, LineTable::Quad}});
900   LT2.addStandardOpcode(DW_LNS_copy, {});
901   LT2.addByte(0xbb);
902   generate();
903 
904   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
905   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
906   EXPECT_FALSE(Unrecoverable);
907   ASSERT_FALSE(Parser.done());
908   checkError(
909       "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01",
910       std::move(Recoverable));
911 
912   // Reset the error state so that it does not confuse the next set of checks.
913   Unrecoverable = Error::success();
914   Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
915 
916   EXPECT_TRUE(Parser.done());
917   checkError("last sequence in debug line table at offset 0x00000031 is not "
918              "terminated",
919              std::move(Recoverable));
920   EXPECT_FALSE(Unrecoverable);
921 }
922 
923 TEST_F(DebugLineBasicFixture,
924        ParserReportsPrologueErrorsInEachTableWhenSkipping) {
925   if (!setupGenerator())
926     return;
927 
928   LineTable &LT = Gen->addLineTable(DWARF32);
929   LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
930   LineTable &LT2 = Gen->addLineTable(DWARF32);
931   LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
932   generate();
933 
934   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
935   Parser.skip(RecordRecoverable, RecordUnrecoverable);
936   ASSERT_FALSE(Parser.done());
937   Parser.skip(RecordRecoverable, RecordUnrecoverable);
938 
939   EXPECT_TRUE(Parser.done());
940   EXPECT_FALSE(Recoverable);
941 
942   checkError({"parsing line table prologue at offset 0x00000000 found "
943               "unsupported version 0",
944               "parsing line table prologue at offset 0x00000006 found "
945               "unsupported version 1"},
946              std::move(Unrecoverable));
947 }
948 
949 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) {
950   if (!setupGenerator())
951     return;
952 
953   LineTable &LT = Gen->addLineTable(DWARF32);
954   LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});
955   generate();
956 
957   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
958   Parser.skip(RecordRecoverable, RecordUnrecoverable);
959 
960   EXPECT_TRUE(Parser.done());
961   EXPECT_FALSE(Recoverable);
962   EXPECT_FALSE(Unrecoverable);
963 }
964 
965 TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) {
966   if (!setupGenerator())
967     return;
968 
969   using ValLen = dwarfgen::LineTable::ValueAndLength;
970   LineTable &LT = Gen->addLineTable(DWARF32);
971   LT.addStandardOpcode(DW_LNS_copy, {});
972   LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}});
973   LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}});
974   LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}});
975   LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}});
976   LT.addStandardOpcode(DW_LNS_negate_stmt, {});
977   LT.addStandardOpcode(DW_LNS_set_basic_block, {});
978   LT.addStandardOpcode(DW_LNS_const_add_pc, {});
979   LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}});
980   LT.addStandardOpcode(DW_LNS_set_prologue_end, {});
981   LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {});
982   LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}});
983   LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
984   generate();
985 
986   DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
987   std::string Output;
988   raw_string_ostream OS(Output);
989   Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS);
990   OS.flush();
991 
992   EXPECT_FALSE(Recoverable);
993   EXPECT_FALSE(Unrecoverable);
994   auto InOutput = [&Output](char const *Str) {
995     return Output.find(Str) != std::string::npos;
996   };
997   EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output;
998   EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output;
999   // FIXME: The value printed after DW_LNS_advance_line is currently the result
1000   // of the advance, but it should be the value being advanced by. See
1001   // https://bugs.llvm.org/show_bug.cgi?id=44261 for details.
1002   EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output;
1003   EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output;
1004   EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output;
1005   EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output;
1006   EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output;
1007   EXPECT_TRUE(
1008       InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n"))
1009       << Output;
1010   EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n"))
1011       << Output;
1012   EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output;
1013   EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output;
1014   EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output;
1015 }
1016 
1017 TEST_F(DebugLineBasicFixture, PrintPathsProperly) {
1018   if (!setupGenerator(5))
1019     return;
1020 
1021   LineTable &LT = Gen->addLineTable();
1022   DWARFDebugLine::Prologue P = LT.createBasicPrologue();
1023   P.IncludeDirectories.push_back(
1024       DWARFFormValue::createFromPValue(DW_FORM_string, "b dir"));
1025   P.FileNames.push_back(DWARFDebugLine::FileNameEntry());
1026   P.FileNames.back().Name =
1027       DWARFFormValue::createFromPValue(DW_FORM_string, "b file");
1028   P.FileNames.back().DirIdx = 1;
1029   P.PrologueLength += 14;
1030   LT.setPrologue(P);
1031   generate();
1032 
1033   auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
1034                                                     nullptr, RecordRecoverable);
1035   EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
1036   std::string Result;
1037   // DWARF 5 stores the compilation directory in two places: the Compilation
1038   // Unit and the directory table entry 0, and implementations are free to use
1039   // one or the other. This copy serves as the one stored in the CU.
1040   StringRef CompDir = "a dir";
1041   EXPECT_FALSE(
1042       (*ExpectedLineTable)
1043           ->Prologue.getFileNameByIndex(
1044               1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result));
1045   EXPECT_TRUE((*ExpectedLineTable)
1046                   ->Prologue.getFileNameByIndex(
1047                       1, CompDir,
1048                       DILineInfoSpecifier::FileLineInfoKind::Default, Result));
1049   EXPECT_STREQ(Result.c_str(), "b file");
1050   EXPECT_TRUE((*ExpectedLineTable)
1051                   ->Prologue.getFileNameByIndex(
1052                       1, CompDir,
1053                       DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath,
1054                       Result));
1055   EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file"));
1056   EXPECT_TRUE((*ExpectedLineTable)
1057                   ->Prologue.getFileNameByIndex(
1058                       1, CompDir,
1059                       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
1060                       Result));
1061   EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file"));
1062 }
1063 
1064 } // end anonymous namespace
1065