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