1 //===- DWARFDebugLineTest.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "DwarfGenerator.h"
10 #include "DwarfUtils.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
13 #include "llvm/Object/ObjectFile.h"
14 #include "llvm/Testing/Support/Error.h"
15 #include "gtest/gtest.h"
18 using namespace dwarf
;
19 using namespace dwarfgen
;
20 using namespace object
;
21 using namespace utils
;
22 using namespace testing
;
25 struct 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
)){};
35 EXPECT_FALSE(Recoverable
);
36 EXPECT_FALSE(Unrecoverable
);
39 // Note: ASSERT_THAT_EXPECTED cannot be used in a non-void function, so
40 // setupGenerator() is split into two.
41 void setupGeneratorImpl(uint16_t Version
, uint8_t AddrSize
) {
42 AddressSize
= AddrSize
;
43 Triple T
= getDefaultTargetTripleForAddrSize(AddressSize
? AddressSize
: 8);
44 if (!isConfigurationSupported(T
))
46 auto ExpectedGenerator
= Generator::create(T
, Version
);
47 ASSERT_THAT_EXPECTED(ExpectedGenerator
, Succeeded());
48 Gen
= std::move(*ExpectedGenerator
);
51 bool setupGenerator(uint16_t Version
= 4, uint8_t AddrSize
= 8) {
52 setupGeneratorImpl(Version
, AddrSize
);
53 return Gen
!= nullptr;
57 Context
= createContext();
58 assert(Context
!= nullptr && "test state is not valid");
59 const DWARFObject
&Obj
= Context
->getDWARFObj();
60 uint8_t TargetAddrSize
= AddressSize
== 0 ? 8 : AddressSize
;
61 LineData
= DWARFDataExtractor(
62 Obj
, Obj
.getLineSection(),
63 getDefaultTargetTripleForAddrSize(TargetAddrSize
).isLittleEndian(),
67 std::unique_ptr
<DWARFContext
> createContext() {
68 assert(Gen
!= nullptr && "Generator is not set up");
69 StringRef FileBytes
= Gen
->generate();
70 MemoryBufferRef
FileBuffer(FileBytes
, "dwarf");
71 auto Obj
= object::ObjectFile::createObjectFile(FileBuffer
);
73 return DWARFContext::create(**Obj
);
77 DWARFDebugLine::SectionParser
setupParser() {
78 LineTable
<
= Gen
->addLineTable(DWARF32
);
79 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
80 LT
.addStandardOpcode(DW_LNS_copy
, {});
82 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
84 LineTable
<2
= Gen
->addLineTable(DWARF64
);
85 LT2
.addExtendedOpcode(9, DW_LNE_set_address
,
86 {{0x11223344, LineTable::Quad
}});
87 LT2
.addStandardOpcode(DW_LNS_copy
, {});
89 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
93 return DWARFDebugLine::SectionParser(LineData
, *Context
, Units
);
96 void recordRecoverable(Error Err
) {
97 Recoverable
= joinErrors(std::move(Recoverable
), std::move(Err
));
99 void recordUnrecoverable(Error Err
) {
100 Unrecoverable
= joinErrors(std::move(Unrecoverable
), std::move(Err
));
103 Expected
<const DWARFDebugLine::LineTable
*>
104 getOrParseLineTableFatalErrors(uint64_t Offset
= 0) {
105 auto ExpectedLineTable
= Line
.getOrParseLineTable(
106 LineData
, Offset
, *Context
, nullptr, RecordRecoverable
);
107 EXPECT_THAT_ERROR(std::move(Recoverable
), Succeeded());
108 return ExpectedLineTable
;
112 std::unique_ptr
<Generator
> Gen
;
113 std::unique_ptr
<DWARFContext
> Context
;
114 DWARFDataExtractor LineData
;
117 std::function
<void(Error
)> RecordRecoverable
;
119 std::function
<void(Error
)> RecordUnrecoverable
;
121 SmallVector
<std::unique_ptr
<DWARFUnit
>, 2> Units
;
124 // Fixtures must derive from "Test", but parameterised fixtures from
125 // "TestWithParam". It does not seem possible to inherit from both, so we share
126 // the common state in a separate class, inherited by the two fixture classes.
127 struct DebugLineBasicFixture
: public Test
, public CommonFixture
{};
129 struct DebugLineParameterisedFixture
130 : public TestWithParam
<std::pair
<uint16_t, DwarfFormat
>>,
131 public CommonFixture
{
132 void SetUp() override
{ std::tie(Version
, Format
) = GetParam(); }
138 void checkDefaultPrologue(uint16_t Version
, DwarfFormat Format
,
139 DWARFDebugLine::Prologue Prologue
,
140 uint64_t BodyLength
) {
141 // Check version specific fields and values.
143 uint64_t PrologueLength
;
147 UnitLength
= PrologueLength
+ 2;
148 EXPECT_EQ(Prologue
.MaxOpsPerInst
, 1u);
153 UnitLength
= PrologueLength
+ 2;
157 UnitLength
= PrologueLength
+ 4;
158 EXPECT_EQ(Prologue
.getAddressSize(), 8u);
159 EXPECT_EQ(Prologue
.SegSelectorSize
, 0u);
162 llvm_unreachable("unsupported DWARF version");
164 UnitLength
+= BodyLength
+ (Format
== DWARF32
? 4 : 8);
166 EXPECT_EQ(Prologue
.TotalLength
, UnitLength
);
167 EXPECT_EQ(Prologue
.PrologueLength
, PrologueLength
);
168 EXPECT_EQ(Prologue
.MinInstLength
, 1u);
169 EXPECT_EQ(Prologue
.DefaultIsStmt
, 1u);
170 EXPECT_EQ(Prologue
.LineBase
, -5);
171 EXPECT_EQ(Prologue
.LineRange
, 14u);
172 EXPECT_EQ(Prologue
.OpcodeBase
, 13u);
173 std::vector
<uint8_t> ExpectedLengths
= {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
174 EXPECT_EQ(Prologue
.StandardOpcodeLengths
, ExpectedLengths
);
175 ASSERT_EQ(Prologue
.IncludeDirectories
.size(), 1u);
176 ASSERT_EQ(Prologue
.IncludeDirectories
[0].getForm(), DW_FORM_string
);
177 EXPECT_STREQ(*toString(Prologue
.IncludeDirectories
[0]), "a dir");
178 ASSERT_EQ(Prologue
.FileNames
.size(), 1u);
179 ASSERT_EQ(Prologue
.FileNames
[0].Name
.getForm(), DW_FORM_string
);
180 ASSERT_EQ(Prologue
.FileNames
[0].DirIdx
, 0u);
181 EXPECT_STREQ(*toString(Prologue
.FileNames
[0].Name
), "a file");
185 TEST_F(DebugLineBasicFixture
, DISABLED_GetOrParseLineTableAtInvalidOffset
) {
187 TEST_F(DebugLineBasicFixture
, GetOrParseLineTableAtInvalidOffset
) {
189 if (!setupGenerator())
193 EXPECT_THAT_EXPECTED(
194 getOrParseLineTableFatalErrors(0),
196 "offset 0x00000000 is not a valid debug line section offset"));
197 // Repeat to show that an error is reported each time.
198 EXPECT_THAT_EXPECTED(
199 getOrParseLineTableFatalErrors(0),
201 "offset 0x00000000 is not a valid debug line section offset"));
203 // Show that an error is reported for later offsets too.
204 EXPECT_THAT_EXPECTED(
205 getOrParseLineTableFatalErrors(1),
207 "offset 0x00000001 is not a valid debug line section offset"));
211 TEST_F(DebugLineBasicFixture
,
212 DISABLED_GetOrParseLineTableAtInvalidOffsetAfterData
) {
214 TEST_F(DebugLineBasicFixture
, GetOrParseLineTableAtInvalidOffsetAfterData
) {
216 if (!setupGenerator())
219 LineTable
<
= Gen
->addLineTable();
220 LT
.setCustomPrologue({{0, LineTable::Byte
}});
224 EXPECT_THAT_EXPECTED(
225 getOrParseLineTableFatalErrors(0),
227 "parsing line table prologue at offset 0x00000000: "
228 "unexpected end of data at offset 0x1 while reading [0x0, 0x4)"));
230 EXPECT_THAT_EXPECTED(
231 getOrParseLineTableFatalErrors(1),
233 "offset 0x00000001 is not a valid debug line section offset"));
237 TEST_P(DebugLineParameterisedFixture
, DISABLED_PrologueGetLength
) {
239 TEST_P(DebugLineParameterisedFixture
, PrologueGetLength
) {
241 if (!setupGenerator(Version
))
243 LineTable
<
= Gen
->addLineTable(Format
);
244 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
245 LT
.setPrologue(Prologue
);
248 // + 10 for sizes of DWARF-32 unit length, version, prologue length.
249 uint64_t ExpectedLength
= Prologue
.PrologueLength
+ 10;
251 // Add address and segment selector size fields.
253 if (Format
== DWARF64
)
254 // Unit length grows by 8, prologue length by 4.
255 ExpectedLength
+= 12;
257 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
258 nullptr, RecordRecoverable
);
259 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
260 EXPECT_EQ((*ExpectedLineTable
)->Prologue
.getLength(), ExpectedLength
);
264 TEST_P(DebugLineParameterisedFixture
, DISABLED_GetOrParseLineTableValidTable
) {
266 TEST_P(DebugLineParameterisedFixture
, GetOrParseLineTableValidTable
) {
268 if (!setupGenerator(Version
))
271 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
272 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
274 LineTable
<
= Gen
->addLineTable(Format
);
275 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
276 LT
.addStandardOpcode(DW_LNS_copy
, {});
278 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
280 LineTable
<2
= Gen
->addLineTable(Format
);
281 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x11223344, LineTable::Quad
}});
282 LT2
.addStandardOpcode(DW_LNS_copy
, {});
284 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
285 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x55667788, LineTable::Quad
}});
286 LT2
.addStandardOpcode(DW_LNS_copy
, {});
288 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
292 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
293 nullptr, RecordRecoverable
);
294 ASSERT_TRUE(ExpectedLineTable
.operator bool());
295 EXPECT_FALSE(Recoverable
);
296 const DWARFDebugLine::LineTable
*Expected
= *ExpectedLineTable
;
297 checkDefaultPrologue(Version
, Format
, Expected
->Prologue
, 16);
298 EXPECT_EQ(Expected
->Sequences
.size(), 1u);
300 uint64_t SecondOffset
=
301 Expected
->Prologue
.sizeofTotalLength() + Expected
->Prologue
.TotalLength
;
302 Recoverable
= Error::success();
303 auto ExpectedLineTable2
= Line
.getOrParseLineTable(
304 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
305 ASSERT_TRUE(ExpectedLineTable2
.operator bool());
306 EXPECT_FALSE(Recoverable
);
307 const DWARFDebugLine::LineTable
*Expected2
= *ExpectedLineTable2
;
308 checkDefaultPrologue(Version
, Format
, Expected2
->Prologue
, 32);
309 EXPECT_EQ(Expected2
->Sequences
.size(), 2u);
311 EXPECT_NE(Expected
, Expected2
);
313 // Check that if the same offset is requested, the exact same pointer is
315 Recoverable
= Error::success();
316 auto ExpectedLineTable3
= Line
.getOrParseLineTable(
317 LineData
, 0, *Context
, nullptr, RecordRecoverable
);
318 ASSERT_TRUE(ExpectedLineTable3
.operator bool());
319 EXPECT_FALSE(Recoverable
);
320 EXPECT_EQ(Expected
, *ExpectedLineTable3
);
322 Recoverable
= Error::success();
323 auto ExpectedLineTable4
= Line
.getOrParseLineTable(
324 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
325 ASSERT_TRUE(ExpectedLineTable4
.operator bool());
326 EXPECT_FALSE(Recoverable
);
327 EXPECT_EQ(Expected2
, *ExpectedLineTable4
);
329 // TODO: Add tests that show that the body of the programs have been read
334 TEST_P(DebugLineParameterisedFixture
, DISABLED_ClearLineValidTable
) {
336 TEST_P(DebugLineParameterisedFixture
, ClearLineValidTable
) {
338 if (!setupGenerator(Version
))
341 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
342 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
344 LineTable
<
= Gen
->addLineTable(Format
);
345 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{0xadd4e55, LineTable::Quad
}});
346 LT
.addStandardOpcode(DW_LNS_copy
, {});
348 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
350 LineTable
<2
= Gen
->addLineTable(Format
);
351 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x11223344, LineTable::Quad
}});
352 LT2
.addStandardOpcode(DW_LNS_copy
, {});
354 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
355 LT2
.addExtendedOpcode(9, DW_LNE_set_address
, {{0x55667788, LineTable::Quad
}});
356 LT2
.addStandardOpcode(DW_LNS_copy
, {});
358 LT2
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
362 // Check that we have what we expect before calling clearLineTable().
363 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
364 nullptr, RecordRecoverable
);
365 ASSERT_TRUE((bool)ExpectedLineTable
);
366 EXPECT_FALSE(Recoverable
);
367 const DWARFDebugLine::LineTable
*Expected
= *ExpectedLineTable
;
368 checkDefaultPrologue(Version
, Format
, Expected
->Prologue
, 16);
369 EXPECT_EQ(Expected
->Sequences
.size(), 1u);
371 uint64_t SecondOffset
=
372 Expected
->Prologue
.sizeofTotalLength() + Expected
->Prologue
.TotalLength
;
373 Recoverable
= Error::success();
374 auto ExpectedLineTable2
= Line
.getOrParseLineTable(
375 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
376 ASSERT_TRUE((bool)ExpectedLineTable2
);
377 EXPECT_FALSE(Recoverable
);
378 const DWARFDebugLine::LineTable
*Expected2
= *ExpectedLineTable2
;
379 checkDefaultPrologue(Version
, Format
, Expected2
->Prologue
, 32);
380 EXPECT_EQ(Expected2
->Sequences
.size(), 2u);
382 // Check that we no longer get the line tables after clearLineTable().
383 Line
.clearLineTable(0);
384 Line
.clearLineTable(SecondOffset
);
385 EXPECT_EQ(Line
.getLineTable(0), nullptr);
386 EXPECT_EQ(Line
.getLineTable(SecondOffset
), nullptr);
388 // Check that if the same offset is requested, the contents match what we
390 Recoverable
= Error::success();
391 auto ExpectedLineTable3
= Line
.getOrParseLineTable(
392 LineData
, 0, *Context
, nullptr, RecordRecoverable
);
393 ASSERT_TRUE((bool)ExpectedLineTable3
);
394 EXPECT_FALSE(Recoverable
);
395 const DWARFDebugLine::LineTable
*Expected3
= *ExpectedLineTable3
;
396 checkDefaultPrologue(Version
, Format
, Expected3
->Prologue
, 16);
397 EXPECT_EQ(Expected3
->Sequences
.size(), 1u);
399 Recoverable
= Error::success();
400 auto ExpectedLineTable4
= Line
.getOrParseLineTable(
401 LineData
, SecondOffset
, *Context
, nullptr, RecordRecoverable
);
402 ASSERT_TRUE((bool)ExpectedLineTable4
);
403 EXPECT_FALSE(Recoverable
);
404 const DWARFDebugLine::LineTable
*Expected4
= *ExpectedLineTable4
;
405 checkDefaultPrologue(Version
, Format
, Expected4
->Prologue
, 32);
406 EXPECT_EQ(Expected4
->Sequences
.size(), 2u);
410 TEST_F(DebugLineBasicFixture
, DISABLED_ErrorForReservedLength
) {
412 TEST_F(DebugLineBasicFixture
, ErrorForReservedLength
) {
414 if (!setupGenerator())
417 LineTable
<
= Gen
->addLineTable();
418 LT
.setCustomPrologue({{0xfffffff0, LineTable::Long
}});
422 EXPECT_THAT_EXPECTED(
423 getOrParseLineTableFatalErrors(),
425 "parsing line table prologue at offset 0x00000000: unsupported "
426 "reserved unit length of value 0xfffffff0"));
429 struct DebugLineUnsupportedVersionFixture
: public TestWithParam
<uint16_t>,
430 public CommonFixture
{
431 void SetUp() override
{ Version
= GetParam(); }
437 TEST_P(DebugLineUnsupportedVersionFixture
,
438 DISABLED_ErrorForUnsupportedVersion
) {
440 TEST_P(DebugLineUnsupportedVersionFixture
, ErrorForUnsupportedVersion
) {
442 if (!setupGenerator())
445 LineTable
<
= Gen
->addLineTable();
446 LT
.setCustomPrologue(
447 {{LineTable::Half
, LineTable::Long
}, {Version
, LineTable::Half
}});
451 EXPECT_THAT_EXPECTED(
452 getOrParseLineTableFatalErrors(),
453 FailedWithMessage("parsing line table prologue at offset 0x00000000: "
454 "unsupported version " +
455 std::to_string(Version
)));
458 INSTANTIATE_TEST_SUITE_P(UnsupportedVersionTestParams
,
459 DebugLineUnsupportedVersionFixture
,
460 Values(/*1 below min */ 1, /* 1 above max */ 6,
461 /* Maximum possible */ 0xffff));
464 TEST_F(DebugLineBasicFixture
, DISABLED_ErrorForInvalidV5IncludeDirTable
) {
466 TEST_F(DebugLineBasicFixture
, ErrorForInvalidV5IncludeDirTable
) {
468 if (!setupGenerator(5))
471 LineTable
<
= Gen
->addLineTable();
472 LT
.setCustomPrologue({
473 {19, LineTable::Long
}, // unit length
474 {5, LineTable::Half
}, // version
475 {8, LineTable::Byte
}, // addr size
476 {0, LineTable::Byte
}, // segment selector size
477 {11, LineTable::Long
}, // prologue length
478 {1, LineTable::Byte
}, // min instruction length
479 {1, LineTable::Byte
}, // max ops per instruction
480 {1, LineTable::Byte
}, // default is_stmt
481 {0, LineTable::Byte
}, // line base
482 {14, LineTable::Byte
}, // line range
483 {2, LineTable::Byte
}, // opcode base (small to reduce the amount of
485 {0, LineTable::Byte
}, // standard opcode lengths
486 {0, LineTable::Byte
}, // directory entry format count (should not be
488 {0, LineTable::ULEB
}, // directories count
489 {0, LineTable::Byte
}, // file name entry format count
490 {0, LineTable::ULEB
} // file name entry count
495 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
496 nullptr, RecordRecoverable
);
497 EXPECT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
500 std::move(Recoverable
),
502 "parsing line table prologue at 0x00000000 found an invalid "
503 "directory or file table description at 0x00000014",
504 "failed to parse entry content descriptions because no path was "
509 TEST_P(DebugLineParameterisedFixture
, DISABLED_ErrorForTooLargePrologueLength
) {
511 TEST_P(DebugLineParameterisedFixture
, ErrorForTooLargePrologueLength
) {
513 if (!setupGenerator(Version
))
516 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
517 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
519 LineTable
<
= Gen
->addLineTable(Format
);
520 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
521 ++Prologue
.PrologueLength
;
522 LT
.setPrologue(Prologue
);
526 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
527 nullptr, RecordRecoverable
);
528 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
529 DWARFDebugLine::LineTable
Result(**ExpectedLineTable
);
530 // Undo the earlier modification so that it can be compared against a
531 // "default" prologue.
532 --Result
.Prologue
.PrologueLength
;
533 checkDefaultPrologue(Version
, Format
, Result
.Prologue
, 0);
535 uint64_t ExpectedEnd
=
536 Prologue
.TotalLength
+ 1 + Prologue
.sizeofTotalLength();
538 std::move(Recoverable
),
540 ("unknown data in line table prologue at offset 0x00000000: "
541 "parsing ended (at offset 0x000000" +
542 Twine::utohexstr(ExpectedEnd
- 1) +
543 ") before reaching the prologue end at offset 0x000000" +
544 Twine::utohexstr(ExpectedEnd
))
549 TEST_P(DebugLineParameterisedFixture
, DISABLED_ErrorForTooShortPrologueLength
) {
551 TEST_P(DebugLineParameterisedFixture
, ErrorForTooShortPrologueLength
) {
553 if (!setupGenerator(Version
))
556 SCOPED_TRACE("Checking Version " + std::to_string(Version
) + ", Format " +
557 (Format
== DWARF64
? "DWARF64" : "DWARF32"));
559 LineTable
<
= Gen
->addLineTable(Format
);
560 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
561 Prologue
.PrologueLength
-= 2;
562 LT
.setPrologue(Prologue
);
566 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
567 nullptr, RecordRecoverable
);
568 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
569 DWARFDebugLine::LineTable
Result(**ExpectedLineTable
);
571 // Parsing will stop before reading a complete file entry.
572 ASSERT_EQ(Result
.Prologue
.IncludeDirectories
.size(), 1u);
573 EXPECT_EQ(toStringRef(Result
.Prologue
.IncludeDirectories
[0]), "a dir");
574 EXPECT_EQ(Result
.Prologue
.FileNames
.size(), 0u);
576 // The exact place where the parsing will stop depends on the structure of the
577 // prologue and the last complete field we are able to read. Before V5 we stop
578 // before reading the file length. In V5, we stop before the filename.
579 uint64_t ExpectedEnd
= Prologue
.TotalLength
+ Prologue
.sizeofTotalLength() -
580 (Version
< 5 ? 2 : 8);
581 std::vector
<std::string
> Errs
;
583 (Twine("parsing line table prologue at 0x00000000 found an invalid "
584 "directory or file table description at 0x000000") +
585 Twine::utohexstr(ExpectedEnd
))
588 Errs
.emplace_back("file names table was not null terminated before the end "
592 "failed to parse file entry because extracting the form value failed");
594 EXPECT_THAT_ERROR(std::move(Recoverable
),
595 FailedWithMessageArray(testing::ElementsAreArray(Errs
)));
598 INSTANTIATE_TEST_SUITE_P(
599 LineTableTestParams
, DebugLineParameterisedFixture
,
600 Values(std::make_pair(
601 2, DWARF32
), // Test lower-bound of v2-3 fields and DWARF32.
602 std::make_pair(3, DWARF32
), // Test upper-bound of v2-3 fields.
603 std::make_pair(4, DWARF64
), // Test v4 fields and DWARF64.
604 std::make_pair(5, DWARF32
), std::make_pair(5, DWARF64
)));
607 TEST_F(DebugLineBasicFixture
,
608 DISABLED_ErrorForExtendedOpcodeLengthSmallerThanExpected
) {
610 TEST_F(DebugLineBasicFixture
, ErrorForExtendedOpcodeLengthSmallerThanExpected
) {
612 if (!setupGenerator())
615 LineTable
<
= Gen
->addLineTable();
617 // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode.
618 // The operand will be read for both the discriminator opcode and then parsed
619 // again as DW_LNS_negate_stmt, to respect the claimed length.
620 LT
.addExtendedOpcode(1, DW_LNE_set_discriminator
,
621 {{DW_LNS_negate_stmt
, LineTable::ULEB
}});
623 LT
.addStandardOpcode(DW_LNS_const_add_pc
, {});
624 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
628 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
629 nullptr, RecordRecoverable
);
630 EXPECT_THAT_ERROR(std::move(Recoverable
),
631 FailedWithMessage("unexpected line op length at offset "
632 "0x00000031 expected 0x01 found 0x02"));
633 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
634 ASSERT_EQ((*ExpectedLineTable
)->Rows
.size(), 3u);
635 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
636 EXPECT_EQ((*ExpectedLineTable
)->Rows
[1].IsStmt
, 0u);
637 EXPECT_EQ((*ExpectedLineTable
)->Rows
[1].Discriminator
, DW_LNS_negate_stmt
);
641 TEST_F(DebugLineBasicFixture
,
642 DISABLED_ErrorForExtendedOpcodeLengthLargerThanExpected
) {
644 TEST_F(DebugLineBasicFixture
, ErrorForExtendedOpcodeLengthLargerThanExpected
) {
646 if (!setupGenerator())
649 LineTable
<
= Gen
->addLineTable();
651 LT
.addStandardOpcode(DW_LNS_const_add_pc
, {});
652 // The Length should be 1 for an end sequence opcode.
653 LT
.addExtendedOpcode(2, DW_LNE_end_sequence
, {});
654 // The negate statement opcode will be skipped.
655 LT
.addStandardOpcode(DW_LNS_negate_stmt
, {});
657 LT
.addStandardOpcode(DW_LNS_const_add_pc
, {});
658 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
662 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
663 nullptr, RecordRecoverable
);
664 EXPECT_THAT_ERROR(std::move(Recoverable
),
665 FailedWithMessage("unexpected line op length at offset "
666 "0x00000032 expected 0x02 found 0x01"));
667 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
668 ASSERT_EQ((*ExpectedLineTable
)->Rows
.size(), 4u);
669 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 2u);
670 ASSERT_EQ((*ExpectedLineTable
)->Sequences
[1].FirstRowIndex
, 2u);
671 EXPECT_EQ((*ExpectedLineTable
)->Rows
[2].IsStmt
, 1u);
675 TEST_F(DebugLineBasicFixture
, DISABLED_ErrorForUnitLengthTooLarge
) {
677 TEST_F(DebugLineBasicFixture
, ErrorForUnitLengthTooLarge
) {
679 if (!setupGenerator())
682 LineTable
&Padding
= Gen
->addLineTable();
683 // Add some padding to show that a non-zero offset is handled correctly.
684 Padding
.setCustomPrologue({{0, LineTable::Byte
}});
685 LineTable
<
= Gen
->addLineTable();
686 LT
.addStandardOpcode(DW_LNS_copy
, {});
687 LT
.addStandardOpcode(DW_LNS_const_add_pc
, {});
688 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
689 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
690 // Set the total length to 1 higher than the actual length.
691 ++Prologue
.TotalLength
;
692 LT
.setPrologue(Prologue
);
696 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 1, *Context
,
697 nullptr, RecordRecoverable
);
699 std::move(Recoverable
),
700 FailedWithMessage("line table program with offset 0x00000001 has length "
701 "0x00000034 but only 0x00000033 bytes are available"));
702 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
703 EXPECT_EQ((*ExpectedLineTable
)->Rows
.size(), 2u);
704 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
708 TEST_F(DebugLineBasicFixture
, DISABLED_ErrorForMismatchedAddressSize
) {
710 TEST_F(DebugLineBasicFixture
, ErrorForMismatchedAddressSize
) {
712 if (!setupGenerator(4, 8))
715 LineTable
<
= Gen
->addLineTable();
716 // The line data extractor expects size 8 (Quad) addresses.
717 uint64_t Addr1
= 0x11223344;
718 LT
.addExtendedOpcode(5, DW_LNE_set_address
, {{Addr1
, LineTable::Long
}});
719 LT
.addStandardOpcode(DW_LNS_copy
, {});
720 // Show that the expected address size is unchanged, so later valid lines
721 // don't cause a problem.
722 uint64_t Addr2
= 0x1122334455667788;
723 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{Addr2
, LineTable::Quad
}});
724 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
728 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
729 nullptr, RecordRecoverable
);
730 EXPECT_THAT_ERROR(std::move(Recoverable
),
731 FailedWithMessage("mismatching address size at offset "
732 "0x00000030 expected 0x08 found 0x04"));
733 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
734 ASSERT_EQ((*ExpectedLineTable
)->Rows
.size(), 2u);
735 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
736 EXPECT_EQ((*ExpectedLineTable
)->Rows
[0].Address
.Address
, Addr1
);
737 EXPECT_EQ((*ExpectedLineTable
)->Rows
[1].Address
.Address
, Addr2
);
741 TEST_F(DebugLineBasicFixture
,
742 DISABLED_ErrorForMismatchedAddressSizeUnsetInitialAddress
) {
744 TEST_F(DebugLineBasicFixture
,
745 ErrorForMismatchedAddressSizeUnsetInitialAddress
) {
747 if (!setupGenerator(4, 0))
750 LineTable
<
= Gen
->addLineTable();
751 uint64_t Addr1
= 0x11223344;
752 LT
.addExtendedOpcode(5, DW_LNE_set_address
, {{Addr1
, LineTable::Long
}});
753 LT
.addStandardOpcode(DW_LNS_copy
, {});
754 uint64_t Addr2
= 0x1122334455667788;
755 LT
.addExtendedOpcode(9, DW_LNE_set_address
, {{Addr2
, LineTable::Quad
}});
756 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
760 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
761 nullptr, RecordRecoverable
);
762 EXPECT_THAT_ERROR(std::move(Recoverable
),
763 FailedWithMessage("mismatching address size at offset "
764 "0x00000038 expected 0x04 found 0x08"));
765 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
766 ASSERT_EQ((*ExpectedLineTable
)->Rows
.size(), 2u);
767 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
768 EXPECT_EQ((*ExpectedLineTable
)->Rows
[0].Address
.Address
, Addr1
);
769 EXPECT_EQ((*ExpectedLineTable
)->Rows
[1].Address
.Address
, Addr2
);
773 TEST_F(DebugLineBasicFixture
,
774 DISABLED_ErrorForUnsupportedAddressSizeInSetAddressLength
) {
776 TEST_F(DebugLineBasicFixture
,
777 ErrorForUnsupportedAddressSizeInSetAddressLength
) {
779 // Use DWARF v4, and 0 for data extractor address size so that the address
780 // size is derived from the opcode length.
781 if (!setupGenerator(4, 0))
784 LineTable
<
= Gen
->addLineTable();
785 // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for
786 // the Half (2) + Byte (1) operand, representing the unsupported address size.
787 LT
.addExtendedOpcode(4, DW_LNE_set_address
,
788 {{0x1234, LineTable::Half
}, {0x56, LineTable::Byte
}});
789 LT
.addStandardOpcode(DW_LNS_copy
, {});
790 // Special opcode to ensure the address has changed between the first and last
791 // row in the sequence. Without this, the sequence will not be recorded.
793 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
797 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
798 nullptr, RecordRecoverable
);
800 std::move(Recoverable
),
801 FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at "
802 "offset 0x00000030 is unsupported"));
803 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
804 ASSERT_EQ((*ExpectedLineTable
)->Rows
.size(), 3u);
805 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
806 // Show that the set address opcode is ignored in this case.
807 EXPECT_EQ((*ExpectedLineTable
)->Rows
[0].Address
.Address
, 0u);
811 TEST_F(DebugLineBasicFixture
, DISABLED_ErrorForAddressSizeGreaterThanByteSize
) {
813 TEST_F(DebugLineBasicFixture
, ErrorForAddressSizeGreaterThanByteSize
) {
815 // Use DWARF v4, and 0 for data extractor address size so that the address
816 // size is derived from the opcode length.
817 if (!setupGenerator(4, 0))
820 LineTable
<
= Gen
->addLineTable();
821 // Specifically use an operand size that has a trailing byte of a supported
822 // size (8), so that any potential truncation would result in a valid size.
823 std::vector
<LineTable::ValueAndLength
> Operands(0x108);
824 LT
.addExtendedOpcode(Operands
.size() + 1, DW_LNE_set_address
, Operands
);
825 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
829 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
830 nullptr, RecordRecoverable
);
832 std::move(Recoverable
),
833 FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at "
834 "offset 0x00000031 is unsupported"));
835 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
839 TEST_F(DebugLineBasicFixture
,
840 DISABLED_ErrorForUnsupportedAddressSizeDefinedInHeader
) {
842 TEST_F(DebugLineBasicFixture
, ErrorForUnsupportedAddressSizeDefinedInHeader
) {
844 // Use 0 for data extractor address size so that it does not clash with the
845 // header address size.
846 if (!setupGenerator(5, 0))
849 LineTable
<
= Gen
->addLineTable();
850 // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode
851 // itself and 9 for the Quad (8) + Byte (1) operand representing the
852 // unsupported address size.
853 uint8_t AddressSize
= 9;
854 LT
.addExtendedOpcode(AddressSize
+ 1, DW_LNE_set_address
,
855 {{0x12345678, LineTable::Quad
}, {0, LineTable::Byte
}});
856 LT
.addStandardOpcode(DW_LNS_copy
, {});
857 // Special opcode to ensure the address has changed between the first and last
858 // row in the sequence. Without this, the sequence will not be recorded.
860 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
861 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
862 Prologue
.FormParams
.AddrSize
= AddressSize
;
863 LT
.setPrologue(Prologue
);
867 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
868 nullptr, RecordRecoverable
);
870 std::move(Recoverable
),
871 FailedWithMessage("address size 0x09 of DW_LNE_set_address opcode at "
872 "offset 0x00000038 is unsupported"));
873 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
874 ASSERT_EQ((*ExpectedLineTable
)->Rows
.size(), 3u);
875 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
876 // Show that the set address opcode is ignored in this case.
877 EXPECT_EQ((*ExpectedLineTable
)->Rows
[0].Address
.Address
, 0u);
881 TEST_F(DebugLineBasicFixture
, DISABLED_CallbackUsedForUnterminatedSequence
) {
883 TEST_F(DebugLineBasicFixture
, CallbackUsedForUnterminatedSequence
) {
885 if (!setupGenerator())
888 LineTable
<
= Gen
->addLineTable();
889 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
890 {{0x1122334455667788, LineTable::Quad
}});
891 LT
.addStandardOpcode(DW_LNS_copy
, {});
893 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
894 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
895 {{0x99aabbccddeeff00, LineTable::Quad
}});
896 LT
.addStandardOpcode(DW_LNS_copy
, {});
902 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
903 nullptr, RecordRecoverable
);
904 EXPECT_THAT_ERROR(std::move(Recoverable
),
905 FailedWithMessage("last sequence in debug line table at "
906 "offset 0x00000000 is not terminated"));
907 ASSERT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
908 EXPECT_EQ((*ExpectedLineTable
)->Rows
.size(), 6u);
909 // The unterminated sequence is not added to the sequence list.
910 EXPECT_EQ((*ExpectedLineTable
)->Sequences
.size(), 1u);
913 struct AdjustAddressFixtureBase
: public CommonFixture
{
914 virtual ~AdjustAddressFixtureBase() {}
916 // Create and update the prologue as specified by the subclass, then return
917 // the length of the table.
918 virtual uint64_t editPrologue(LineTable
<
) = 0;
920 virtual uint64_t getAdjustedAddr(uint64_t Base
, uint64_t ConstIncrs
,
921 uint64_t SpecialIncrs
,
922 uint64_t AdvanceIncrs
) {
923 return Base
+ ConstIncrs
+ SpecialIncrs
+ AdvanceIncrs
;
926 virtual uint64_t getAdjustedLine(uint64_t Base
, uint64_t Incr
) {
930 uint64_t setupNoProblemTable() {
931 LineTable
&NoProblem
= Gen
->addLineTable();
932 NoProblem
.addExtendedOpcode(9, DW_LNE_set_address
,
933 {{0xabcd, LineTable::Quad
}});
934 NoProblem
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
935 return editPrologue(NoProblem
);
938 uint64_t setupConstAddPcFirstTable() {
939 LineTable
&ConstAddPCFirst
= Gen
->addLineTable();
940 ConstAddPCFirst
.addExtendedOpcode(9, DW_LNE_set_address
,
941 {{ConstAddPCAddr
, LineTable::Quad
}});
942 ConstAddPCFirst
.addStandardOpcode(DW_LNS_const_add_pc
, {});
943 ConstAddPCFirst
.addStandardOpcode(DW_LNS_const_add_pc
, {});
944 ConstAddPCFirst
.addStandardOpcode(DW_LNS_advance_pc
,
945 {{0x10, LineTable::ULEB
}});
946 ConstAddPCFirst
.addByte(0x21); // Special opcode, +1 op, +1 line.
947 ConstAddPCFirst
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
948 return editPrologue(ConstAddPCFirst
);
951 uint64_t setupSpecialFirstTable() {
952 LineTable
&SpecialFirst
= Gen
->addLineTable();
953 SpecialFirst
.addExtendedOpcode(9, DW_LNE_set_address
,
954 {{SpecialAddr
, LineTable::Quad
}});
955 SpecialFirst
.addByte(0x22); // Special opcode, +1 op, +2 line.
956 SpecialFirst
.addStandardOpcode(DW_LNS_const_add_pc
, {});
957 SpecialFirst
.addStandardOpcode(DW_LNS_advance_pc
,
958 {{0x20, LineTable::ULEB
}});
959 SpecialFirst
.addByte(0x23); // Special opcode, +1 op, +3 line.
960 SpecialFirst
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
961 return editPrologue(SpecialFirst
);
964 uint64_t setupAdvancePcFirstTable() {
965 LineTable
&AdvancePCFirst
= Gen
->addLineTable();
966 AdvancePCFirst
.addExtendedOpcode(9, DW_LNE_set_address
,
967 {{AdvancePCAddr
, LineTable::Quad
}});
968 AdvancePCFirst
.addStandardOpcode(DW_LNS_advance_pc
,
969 {{0x30, LineTable::ULEB
}});
970 AdvancePCFirst
.addStandardOpcode(DW_LNS_const_add_pc
, {});
971 AdvancePCFirst
.addStandardOpcode(DW_LNS_advance_pc
,
972 {{0x40, LineTable::ULEB
}});
973 AdvancePCFirst
.addByte(0x24); // Special opcode, +1 op, +4 line.
974 AdvancePCFirst
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
975 return editPrologue(AdvancePCFirst
);
978 void setupTables(bool AddAdvancePCFirstTable
) {
979 LineTable
&Padding
= Gen
->addLineTable();
980 Padding
.setCustomPrologue({{0, LineTable::Byte
}});
983 // Show that no warning is generated for the case where no
984 // DW_LNS_const_add_pc or special opcode is used.
985 ConstAddPCOffset
= setupNoProblemTable() + NoProblemOffset
;
987 // Show that the warning is emitted for the first DW_LNS_const_add_pc opcode
988 // and then not again.
989 SpecialOffset
= setupConstAddPcFirstTable() + ConstAddPCOffset
;
991 // Show that the warning is emitted for the first special opcode and then
993 AdvancePCOffset
= setupSpecialFirstTable() + SpecialOffset
;
995 // Show that the warning is emitted for the first DW_LNS_advance_pc opcode
996 // (if requested) and then not again.
997 if (AddAdvancePCFirstTable
)
998 setupAdvancePcFirstTable();
1001 Expected
<const DWARFDebugLine::LineTable
*>
1002 checkTable(uint64_t Offset
, StringRef OpcodeType
, const Twine
&MsgSuffix
) {
1003 auto ExpectedTable
= Line
.getOrParseLineTable(LineData
, Offset
, *Context
,
1004 nullptr, RecordRecoverable
);
1005 EXPECT_THAT_ERROR(std::move(Unrecoverable
), Succeeded());
1006 if (!IsErrorExpected
) {
1007 EXPECT_THAT_ERROR(std::move(Recoverable
), Succeeded());
1010 return ExpectedTable
;
1011 uint64_t ExpectedOffset
= Offset
+
1012 (*ExpectedTable
)->Prologue
.getLength() +
1013 11; // 11 == size of DW_LNE_set_address.
1014 std::string OffsetHex
= Twine::utohexstr(Offset
).str();
1015 std::string OffsetZeroes
= std::string(8 - OffsetHex
.size(), '0');
1016 std::string ExpectedHex
= Twine::utohexstr(ExpectedOffset
).str();
1017 std::string ExpectedZeroes
= std::string(8 - ExpectedHex
.size(), '0');
1019 std::move(Recoverable
),
1020 FailedWithMessage(("line table program at offset 0x" + OffsetZeroes
+
1021 OffsetHex
+ " contains a " + OpcodeType
+
1022 " opcode at offset 0x" + ExpectedZeroes
+
1023 ExpectedHex
+ ", " + MsgSuffix
)
1026 return ExpectedTable
;
1029 void runTest(bool CheckAdvancePC
, Twine MsgSuffix
) {
1030 if (!setupGenerator(Version
))
1033 setupTables(/*AddAdvancePCFirstTable=*/CheckAdvancePC
);
1037 auto ExpectedNoProblem
= Line
.getOrParseLineTable(
1038 LineData
, NoProblemOffset
, *Context
, nullptr, RecordRecoverable
);
1039 EXPECT_THAT_ERROR(std::move(Recoverable
), Succeeded());
1040 EXPECT_THAT_ERROR(std::move(Unrecoverable
), Succeeded());
1041 ASSERT_THAT_EXPECTED(ExpectedNoProblem
, Succeeded());
1043 auto ExpectedConstAddPC
=
1044 checkTable(ConstAddPCOffset
, "DW_LNS_const_add_pc", MsgSuffix
);
1045 ASSERT_THAT_EXPECTED(ExpectedConstAddPC
, Succeeded());
1046 ASSERT_EQ((*ExpectedConstAddPC
)->Rows
.size(), 2u);
1047 EXPECT_EQ((*ExpectedConstAddPC
)->Rows
[0].Address
.Address
,
1048 getAdjustedAddr(ConstAddPCAddr
, ConstIncr
* 2, 0x1, 0x10));
1049 EXPECT_EQ((*ExpectedConstAddPC
)->Rows
[0].Line
, getAdjustedLine(1, 1));
1050 EXPECT_THAT_ERROR(std::move(Unrecoverable
), Succeeded());
1052 auto ExpectedSpecial
= checkTable(SpecialOffset
, "special", MsgSuffix
);
1053 ASSERT_THAT_EXPECTED(ExpectedSpecial
, Succeeded());
1054 ASSERT_EQ((*ExpectedSpecial
)->Rows
.size(), 3u);
1055 EXPECT_EQ((*ExpectedSpecial
)->Rows
[0].Address
.Address
,
1056 getAdjustedAddr(SpecialAddr
, 0, 1, 0));
1057 EXPECT_EQ((*ExpectedSpecial
)->Rows
[0].Line
, getAdjustedLine(1, 2));
1058 EXPECT_EQ((*ExpectedSpecial
)->Rows
[1].Address
.Address
,
1059 getAdjustedAddr(SpecialAddr
, ConstIncr
, 0x2, 0x20));
1060 EXPECT_EQ((*ExpectedSpecial
)->Rows
[1].Line
, getAdjustedLine(1, 5));
1061 EXPECT_THAT_ERROR(std::move(Unrecoverable
), Succeeded());
1063 if (!CheckAdvancePC
)
1066 auto ExpectedAdvancePC
=
1067 checkTable(AdvancePCOffset
, "DW_LNS_advance_pc", MsgSuffix
);
1068 ASSERT_THAT_EXPECTED(ExpectedAdvancePC
, Succeeded());
1069 ASSERT_EQ((*ExpectedAdvancePC
)->Rows
.size(), 2u);
1070 EXPECT_EQ((*ExpectedAdvancePC
)->Rows
[0].Address
.Address
,
1071 getAdjustedAddr(AdvancePCAddr
, ConstIncr
, 0x1, 0x70));
1072 EXPECT_EQ((*ExpectedAdvancePC
)->Rows
[0].Line
, getAdjustedLine(1, 4));
1075 uint64_t ConstIncr
= 0x11;
1076 uint64_t ConstAddPCAddr
= 0x1234;
1077 uint64_t SpecialAddr
= 0x5678;
1078 uint64_t AdvancePCAddr
= 0xabcd;
1079 uint64_t NoProblemOffset
;
1080 uint64_t ConstAddPCOffset
;
1081 uint64_t SpecialOffset
;
1082 uint64_t AdvancePCOffset
;
1084 uint16_t Version
= 4;
1085 bool IsErrorExpected
;
1088 struct MaxOpsPerInstFixture
1089 : TestWithParam
<std::tuple
<uint16_t, uint8_t, bool>>,
1090 AdjustAddressFixtureBase
{
1091 void SetUp() override
{
1092 std::tie(Version
, MaxOpsPerInst
, IsErrorExpected
) = GetParam();
1095 uint64_t editPrologue(LineTable
<
) override
{
1096 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
1097 Prologue
.MaxOpsPerInst
= MaxOpsPerInst
;
1098 LT
.setPrologue(Prologue
);
1099 return Prologue
.TotalLength
+ Prologue
.sizeofTotalLength();
1102 uint8_t MaxOpsPerInst
;
1106 TEST_P(MaxOpsPerInstFixture
, DISABLED_MaxOpsPerInstProblemsReportedCorrectly
) {
1108 TEST_P(MaxOpsPerInstFixture
, MaxOpsPerInstProblemsReportedCorrectly
) {
1110 runTest(/*CheckAdvancePC=*/true,
1111 "but the prologue maximum_operations_per_instruction value is " +
1112 Twine(unsigned(MaxOpsPerInst
)) +
1113 ", which is unsupported. Assuming a value of 1 instead");
1116 INSTANTIATE_TEST_SUITE_P(
1117 MaxOpsPerInstParams
, MaxOpsPerInstFixture
,
1118 Values(std::make_tuple(3, 0, false), // Test for version < 4 (no error).
1119 std::make_tuple(4, 0, true), // Test zero value for V4 (error).
1120 std::make_tuple(4, 1, false), // Test good value for V4 (no error).
1122 4, 2, true))); // Test one higher than permitted V4 (error).
1124 struct LineRangeFixture
: TestWithParam
<std::tuple
<uint8_t, bool>>,
1125 AdjustAddressFixtureBase
{
1126 void SetUp() override
{ std::tie(LineRange
, IsErrorExpected
) = GetParam(); }
1128 uint64_t editPrologue(LineTable
<
) override
{
1129 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
1130 Prologue
.LineRange
= LineRange
;
1131 LT
.setPrologue(Prologue
);
1132 return Prologue
.TotalLength
+ Prologue
.sizeofTotalLength();
1135 uint64_t getAdjustedAddr(uint64_t Base
, uint64_t ConstIncr
,
1136 uint64_t SpecialIncr
,
1137 uint64_t AdvanceIncr
) override
{
1139 return Base
+ AdvanceIncr
;
1140 return AdjustAddressFixtureBase::getAdjustedAddr(Base
, ConstIncr
,
1141 SpecialIncr
, AdvanceIncr
);
1144 uint64_t getAdjustedLine(uint64_t Base
, uint64_t Incr
) override
{
1145 return LineRange
!= 0
1146 ? AdjustAddressFixtureBase::getAdjustedLine(Base
, Incr
)
1154 TEST_P(LineRangeFixture
, DISABLED_LineRangeProblemsReportedCorrectly
) {
1156 TEST_P(LineRangeFixture
, LineRangeProblemsReportedCorrectly
) {
1158 runTest(/*CheckAdvancePC=*/false,
1159 "but the prologue line_range value is 0. The address and line will "
1163 INSTANTIATE_TEST_SUITE_P(
1164 LineRangeParams
, LineRangeFixture
,
1165 Values(std::make_tuple(0, true), // Test zero value (error).
1166 std::make_tuple(14, false))); // Test non-zero value (no error).
1168 struct BadMinInstLenFixture
: TestWithParam
<std::tuple
<uint8_t, bool>>,
1169 AdjustAddressFixtureBase
{
1170 void SetUp() override
{
1171 std::tie(MinInstLength
, IsErrorExpected
) = GetParam();
1174 uint64_t editPrologue(LineTable
<
) override
{
1175 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
1176 Prologue
.MinInstLength
= MinInstLength
;
1177 LT
.setPrologue(Prologue
);
1178 return Prologue
.TotalLength
+ Prologue
.sizeofTotalLength();
1181 uint64_t getAdjustedAddr(uint64_t Base
, uint64_t ConstIncr
,
1182 uint64_t SpecialIncr
,
1183 uint64_t AdvanceIncr
) override
{
1184 return MinInstLength
!= 0 ? AdjustAddressFixtureBase::getAdjustedAddr(
1185 Base
, ConstIncr
, SpecialIncr
, AdvanceIncr
)
1189 uint8_t MinInstLength
;
1193 TEST_P(BadMinInstLenFixture
, DISABLED_MinInstLengthProblemsReportedCorrectly
) {
1195 TEST_P(BadMinInstLenFixture
, MinInstLengthProblemsReportedCorrectly
) {
1197 runTest(/*CheckAdvancePC=*/true,
1198 "but the prologue minimum_instruction_length value is 0, which "
1199 "prevents any address advancing");
1202 INSTANTIATE_TEST_SUITE_P(
1203 BadMinInstLenParams
, BadMinInstLenFixture
,
1204 Values(std::make_tuple(0, true), // Test zero value (error).
1205 std::make_tuple(1, false))); // Test non-zero value (no error).
1208 TEST_F(DebugLineBasicFixture
, DISABLED_ParserParsesCorrectly
) {
1210 TEST_F(DebugLineBasicFixture
, ParserParsesCorrectly
) {
1212 if (!setupGenerator())
1215 DWARFDebugLine::SectionParser Parser
= setupParser();
1217 EXPECT_EQ(Parser
.getOffset(), 0u);
1218 ASSERT_FALSE(Parser
.done());
1220 DWARFDebugLine::LineTable Parsed
=
1221 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1222 checkDefaultPrologue(4, DWARF32
, Parsed
.Prologue
, 16);
1223 EXPECT_EQ(Parsed
.Sequences
.size(), 1u);
1224 EXPECT_EQ(Parser
.getOffset(), 62u);
1225 ASSERT_FALSE(Parser
.done());
1227 DWARFDebugLine::LineTable Parsed2
=
1228 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1229 checkDefaultPrologue(4, DWARF64
, Parsed2
.Prologue
, 16);
1230 EXPECT_EQ(Parsed2
.Sequences
.size(), 1u);
1231 EXPECT_EQ(Parser
.getOffset(), 136u);
1232 EXPECT_TRUE(Parser
.done());
1234 EXPECT_FALSE(Recoverable
);
1235 EXPECT_FALSE(Unrecoverable
);
1239 TEST_F(DebugLineBasicFixture
, DISABLED_ParserSkipsCorrectly
) {
1241 TEST_F(DebugLineBasicFixture
, ParserSkipsCorrectly
) {
1243 if (!setupGenerator())
1246 DWARFDebugLine::SectionParser Parser
= setupParser();
1248 EXPECT_EQ(Parser
.getOffset(), 0u);
1249 ASSERT_FALSE(Parser
.done());
1251 Parser
.skip(RecordRecoverable
, RecordUnrecoverable
);
1252 EXPECT_EQ(Parser
.getOffset(), 62u);
1253 ASSERT_FALSE(Parser
.done());
1255 Parser
.skip(RecordRecoverable
, RecordUnrecoverable
);
1256 EXPECT_EQ(Parser
.getOffset(), 136u);
1257 EXPECT_TRUE(Parser
.done());
1259 EXPECT_FALSE(Recoverable
);
1260 EXPECT_FALSE(Unrecoverable
);
1264 TEST_F(DebugLineBasicFixture
, DISABLED_ParserAlwaysDoneForEmptySection
) {
1266 TEST_F(DebugLineBasicFixture
, ParserAlwaysDoneForEmptySection
) {
1268 if (!setupGenerator())
1272 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1274 EXPECT_TRUE(Parser
.done());
1278 TEST_F(DebugLineBasicFixture
,
1279 DISABLED_ParserMarkedAsDoneForBadLengthWhenParsing
) {
1281 TEST_F(DebugLineBasicFixture
, ParserMarkedAsDoneForBadLengthWhenParsing
) {
1283 if (!setupGenerator())
1286 LineTable
<
= Gen
->addLineTable();
1287 LT
.setCustomPrologue({{0xfffffff0, LineTable::Long
}});
1288 Gen
->addLineTable();
1291 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1292 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1294 EXPECT_EQ(Parser
.getOffset(), 0u);
1295 EXPECT_TRUE(Parser
.done());
1296 EXPECT_FALSE(Recoverable
);
1299 std::move(Unrecoverable
),
1301 "parsing line table prologue at offset 0x00000000: unsupported "
1302 "reserved unit length of value 0xfffffff0"));
1306 TEST_F(DebugLineBasicFixture
,
1307 DISABLED_ParserMarkedAsDoneForBadLengthWhenSkipping
) {
1309 TEST_F(DebugLineBasicFixture
, ParserMarkedAsDoneForBadLengthWhenSkipping
) {
1311 if (!setupGenerator())
1314 LineTable
<
= Gen
->addLineTable();
1315 LT
.setCustomPrologue({{0xfffffff0, LineTable::Long
}});
1316 Gen
->addLineTable();
1319 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1320 Parser
.skip(RecordRecoverable
, RecordUnrecoverable
);
1322 EXPECT_EQ(Parser
.getOffset(), 0u);
1323 EXPECT_TRUE(Parser
.done());
1324 EXPECT_FALSE(Recoverable
);
1327 std::move(Unrecoverable
),
1329 "parsing line table prologue at offset 0x00000000: unsupported "
1330 "reserved unit length of value 0xfffffff0"));
1334 TEST_F(DebugLineBasicFixture
,
1335 DISABLED_ParserReportsFirstErrorInEachTableWhenParsing
) {
1337 TEST_F(DebugLineBasicFixture
, ParserReportsFirstErrorInEachTableWhenParsing
) {
1339 if (!setupGenerator())
1342 LineTable
<
= Gen
->addLineTable(DWARF32
);
1343 LT
.setCustomPrologue({{2, LineTable::Long
}, {0, LineTable::Half
}});
1344 LineTable
<2
= Gen
->addLineTable(DWARF32
);
1345 LT2
.setCustomPrologue({{2, LineTable::Long
}, {1, LineTable::Half
}});
1348 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1349 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1350 ASSERT_FALSE(Parser
.done());
1351 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1353 EXPECT_TRUE(Parser
.done());
1354 EXPECT_THAT_ERROR(std::move(Recoverable
), Succeeded());
1357 std::move(Unrecoverable
),
1358 FailedWithMessage("parsing line table prologue at offset 0x00000000: "
1359 "unsupported version 0",
1360 "parsing line table prologue at offset 0x00000006: "
1361 "unsupported version 1"));
1365 TEST_F(DebugLineBasicFixture
,
1366 DISABLED_ParserReportsNonPrologueProblemsWhenParsing
) {
1368 TEST_F(DebugLineBasicFixture
, ParserReportsNonPrologueProblemsWhenParsing
) {
1370 if (!setupGenerator())
1373 LineTable
<
= Gen
->addLineTable(DWARF32
);
1374 LT
.addExtendedOpcode(0x42, DW_LNE_end_sequence
, {});
1375 LineTable
<2
= Gen
->addLineTable(DWARF32
);
1376 LT2
.addExtendedOpcode(9, DW_LNE_set_address
,
1377 {{0x1234567890abcdef, LineTable::Quad
}});
1378 LT2
.addStandardOpcode(DW_LNS_copy
, {});
1382 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1383 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1384 EXPECT_FALSE(Unrecoverable
);
1385 ASSERT_FALSE(Parser
.done());
1386 EXPECT_THAT_ERROR(std::move(Recoverable
),
1387 FailedWithMessage("unexpected line op length at offset "
1388 "0x00000030 expected 0x42 found 0x01"));
1390 // Reset the error state so that it does not confuse the next set of checks.
1391 Unrecoverable
= Error::success();
1392 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
);
1394 EXPECT_TRUE(Parser
.done());
1395 EXPECT_THAT_ERROR(std::move(Recoverable
),
1396 FailedWithMessage("last sequence in debug line table at "
1397 "offset 0x00000031 is not terminated"));
1398 EXPECT_FALSE(Unrecoverable
);
1402 TEST_F(DebugLineBasicFixture
,
1403 DISABLED_ParserReportsPrologueErrorsInEachTableWhenSkipping
) {
1405 TEST_F(DebugLineBasicFixture
,
1406 ParserReportsPrologueErrorsInEachTableWhenSkipping
) {
1408 if (!setupGenerator())
1411 LineTable
<
= Gen
->addLineTable(DWARF32
);
1412 LT
.setCustomPrologue({{2, LineTable::Long
}, {0, LineTable::Half
}});
1413 LineTable
<2
= Gen
->addLineTable(DWARF32
);
1414 LT2
.setCustomPrologue({{2, LineTable::Long
}, {1, LineTable::Half
}});
1417 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1418 Parser
.skip(RecordRecoverable
, RecordUnrecoverable
);
1419 ASSERT_FALSE(Parser
.done());
1420 Parser
.skip(RecordRecoverable
, RecordUnrecoverable
);
1422 EXPECT_TRUE(Parser
.done());
1423 EXPECT_FALSE(Recoverable
);
1426 std::move(Unrecoverable
),
1427 FailedWithMessage("parsing line table prologue at offset 0x00000000: "
1428 "unsupported version 0",
1429 "parsing line table prologue at offset 0x00000006: "
1430 "unsupported version 1"));
1434 TEST_F(DebugLineBasicFixture
,
1435 DISABLED_ParserIgnoresNonPrologueErrorsWhenSkipping
) {
1437 TEST_F(DebugLineBasicFixture
, ParserIgnoresNonPrologueErrorsWhenSkipping
) {
1439 if (!setupGenerator())
1442 LineTable
<
= Gen
->addLineTable(DWARF32
);
1443 LT
.addExtendedOpcode(42, DW_LNE_end_sequence
, {});
1446 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1447 Parser
.skip(RecordRecoverable
, RecordUnrecoverable
);
1449 EXPECT_TRUE(Parser
.done());
1450 EXPECT_FALSE(Recoverable
);
1451 EXPECT_FALSE(Unrecoverable
);
1455 TEST_F(DebugLineBasicFixture
, DISABLED_VerboseOutput
) {
1457 TEST_F(DebugLineBasicFixture
, VerboseOutput
) {
1459 if (!setupGenerator(5))
1462 LineTable
<
= Gen
->addLineTable();
1463 LT
.addByte(0); // Extended opcode with zero length.
1465 // Zero-value extended opcode.
1466 LT
.addExtendedOpcode(2, 0, {{1, LineTable::Byte
}});
1467 // Unknown extended opcode.
1468 LT
.addExtendedOpcode(2, 0x42, {{1, LineTable::Byte
}});
1469 LT
.addExtendedOpcode(9, DW_LNE_set_address
,
1470 {{0x123456789abcdef, LineTable::Quad
}});
1471 LT
.addExtendedOpcode(6, DW_LNE_define_file
,
1472 {{'a', LineTable::Byte
},
1473 {'\0', LineTable::Byte
},
1474 {2, LineTable::ULEB
},
1475 {3, LineTable::ULEB
},
1476 {4, LineTable::ULEB
}});
1477 LT
.addExtendedOpcode(2, DW_LNE_set_discriminator
, {{0x7f, LineTable::ULEB
}});
1478 LT
.addStandardOpcode(DW_LNS_copy
, {});
1479 LT
.addStandardOpcode(DW_LNS_advance_pc
, {{11, LineTable::ULEB
}});
1480 LT
.addStandardOpcode(DW_LNS_advance_line
, {{22, LineTable::SLEB
}});
1481 LT
.addStandardOpcode(DW_LNS_set_file
, {{33, LineTable::ULEB
}});
1482 LT
.addStandardOpcode(DW_LNS_set_column
, {{44, LineTable::ULEB
}});
1483 LT
.addStandardOpcode(DW_LNS_negate_stmt
, {});
1484 LT
.addStandardOpcode(DW_LNS_set_basic_block
, {});
1485 LT
.addStandardOpcode(DW_LNS_const_add_pc
, {});
1486 LT
.addStandardOpcode(DW_LNS_fixed_advance_pc
, {{55, LineTable::Half
}});
1487 LT
.addStandardOpcode(DW_LNS_set_prologue_end
, {});
1488 LT
.addStandardOpcode(DW_LNS_set_epilogue_begin
, {});
1489 LT
.addStandardOpcode(DW_LNS_set_isa
, {{66, LineTable::ULEB
}});
1490 // Add unknown standard opcode with operands.
1491 LT
.addStandardOpcode(
1492 0xd, {{1, LineTable::ULEB
}, {0x123456789abcdef, LineTable::ULEB
}});
1493 // Add unknown standard opcode without operands.
1494 LT
.addStandardOpcode(0xe, {});
1495 LT
.addByte(0xff); // Special opcode.
1496 LT
.addExtendedOpcode(1, DW_LNE_end_sequence
, {});
1498 // Adjust the prologue to account for the extra standard opcode.
1499 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
1500 Prologue
.TotalLength
+= 2;
1501 Prologue
.PrologueLength
+= 2;
1502 Prologue
.OpcodeBase
+= 2;
1503 Prologue
.StandardOpcodeLengths
.push_back(2);
1504 Prologue
.StandardOpcodeLengths
.push_back(0);
1505 LT
.setPrologue(Prologue
);
1509 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1511 raw_string_ostream
OS(Output
);
1512 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
, &OS
,
1515 StringRef
OutputRef(Output
);
1518 auto NextLine
= [&Pos
, &OutputRef
]() {
1519 size_t EOL
= OutputRef
.find_first_of('\n', Pos
);
1520 StringRef Line
= OutputRef
.substr(Pos
, EOL
- Pos
);
1524 EXPECT_EQ(NextLine(), "Line table prologue:");
1525 EXPECT_EQ(NextLine(), " total_length: 0x00000078");
1526 EXPECT_EQ(NextLine(), " format: DWARF32");
1527 EXPECT_EQ(NextLine(), " version: 5");
1528 EXPECT_EQ(NextLine(), " address_size: 8");
1529 EXPECT_EQ(NextLine(), " seg_select_size: 0");
1530 EXPECT_EQ(NextLine(), " prologue_length: 0x0000002c");
1531 EXPECT_EQ(NextLine(), " min_inst_length: 1");
1532 EXPECT_EQ(NextLine(), "max_ops_per_inst: 1");
1533 EXPECT_EQ(NextLine(), " default_is_stmt: 1");
1534 EXPECT_EQ(NextLine(), " line_base: -5");
1535 EXPECT_EQ(NextLine(), " line_range: 14");
1536 EXPECT_EQ(NextLine(), " opcode_base: 15");
1537 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_copy] = 0");
1538 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_pc] = 1");
1539 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_line] = 1");
1540 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_file] = 1");
1541 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_column] = 1");
1542 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_negate_stmt] = 0");
1543 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_basic_block] = 0");
1544 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_const_add_pc] = 0");
1545 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1");
1546 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_prologue_end] = 0");
1547 EXPECT_EQ(NextLine(),
1548 "standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0");
1549 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_isa] = 1");
1550 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_d] = 2");
1551 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_e] = 0");
1552 EXPECT_EQ(NextLine(), "include_directories[ 0] = \"a dir\"");
1553 EXPECT_EQ(NextLine(), "file_names[ 0]:");
1554 EXPECT_EQ(NextLine(), " name: \"a file\"");
1555 EXPECT_EQ(NextLine(), " dir_index: 0");
1556 EXPECT_EQ(NextLine(), "");
1557 EXPECT_EQ(NextLine(), " Address Line Column File ISA Discriminator Flags");
1558 EXPECT_EQ(NextLine(), " ------------------ ------ ------ ------ --- ------------- -------------");
1559 EXPECT_EQ(NextLine(),
1560 "0x00000038: 00 Badly formed extended line op (length 0)");
1561 EXPECT_EQ(NextLine(),
1562 "0x0000003a: 00 Unrecognized extended op 0x00 length 2");
1563 EXPECT_EQ(NextLine(),
1564 "0x0000003e: 00 Unrecognized extended op 0x42 length 2");
1565 EXPECT_EQ(NextLine(),
1566 "0x00000042: 00 DW_LNE_set_address (0x0123456789abcdef)");
1567 EXPECT_EQ(NextLine(), "0x0000004d: 00 DW_LNE_define_file (a, dir=2, "
1568 "mod_time=(0x0000000000000003), length=4)");
1569 EXPECT_EQ(NextLine(), "0x00000055: 00 DW_LNE_set_discriminator (127)");
1570 EXPECT_EQ(NextLine(), "0x00000059: 01 DW_LNS_copy");
1571 EXPECT_EQ(NextLine(), " 0x0123456789abcdef 1 0 1 "
1573 EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (11)");
1574 EXPECT_EQ(NextLine(), "0x0000005c: 03 DW_LNS_advance_line (23)");
1575 EXPECT_EQ(NextLine(), "0x0000005e: 04 DW_LNS_set_file (33)");
1576 EXPECT_EQ(NextLine(), "0x00000060: 05 DW_LNS_set_column (44)");
1577 EXPECT_EQ(NextLine(), "0x00000062: 06 DW_LNS_negate_stmt");
1578 EXPECT_EQ(NextLine(), "0x00000063: 07 DW_LNS_set_basic_block");
1579 EXPECT_EQ(NextLine(),
1580 "0x00000064: 08 DW_LNS_const_add_pc (0x0000000000000011)");
1581 EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (0x0037)");
1582 EXPECT_EQ(NextLine(), "0x00000068: 0a DW_LNS_set_prologue_end");
1583 EXPECT_EQ(NextLine(), "0x00000069: 0b DW_LNS_set_epilogue_begin");
1584 EXPECT_EQ(NextLine(), "0x0000006a: 0c DW_LNS_set_isa (66)");
1585 EXPECT_EQ(NextLine(), "0x0000006c: 0d Unrecognized standard opcode "
1586 "(operands: 0x0000000000000001, 0x0123456789abcdef)");
1587 EXPECT_EQ(NextLine(), "0x00000077: 0e Unrecognized standard opcode");
1588 EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3");
1589 EXPECT_EQ(NextLine(),
1590 " 0x0123456789abce53 20 44 33 66 "
1591 " 0 basic_block prologue_end epilogue_begin");
1592 EXPECT_EQ(NextLine(), "0x00000079: 00 DW_LNE_end_sequence");
1593 EXPECT_EQ(NextLine(), " 0x0123456789abce53 20 44 33 "
1594 "66 0 end_sequence");
1595 EXPECT_EQ(NextLine(), "");
1596 EXPECT_EQ(Output
.size(), Pos
);
1599 struct TruncatedPrologueFixture
1600 : public TestWithParam
<
1601 std::tuple
<uint64_t, uint64_t, uint16_t, DwarfFormat
, StringRef
>>,
1602 public CommonFixture
{
1603 void SetUp() override
{
1604 std::tie(Length
, ExpectedOffset
, Version
, Format
, ExpectedErr
) = GetParam();
1608 uint64_t ExpectedOffset
;
1611 StringRef ExpectedErr
;
1615 TEST_P(TruncatedPrologueFixture
, DISABLED_ErrorForTruncatedPrologue
) {
1617 TEST_P(TruncatedPrologueFixture
, ErrorForTruncatedPrologue
) {
1619 if (!setupGenerator(Version
))
1622 LineTable
&Padding
= Gen
->addLineTable();
1623 // Add some padding to show that a non-zero offset is handled correctly.
1624 Padding
.setCustomPrologue({{0, LineTable::Byte
}});
1626 // Add a table with only two standard opcodes - we don't need to test the full
1628 LineTable
&Table
= Gen
->addLineTable(Format
);
1629 DWARFDebugLine::Prologue InputPrologue
= Table
.createBasicPrologue();
1630 InputPrologue
.OpcodeBase
= 3;
1631 InputPrologue
.StandardOpcodeLengths
.resize(2);
1632 Table
.setPrologue(InputPrologue
);
1635 // Truncate the data extractor to the specified length.
1636 LineData
= DWARFDataExtractor(LineData
, Length
);
1638 DWARFDebugLine::Prologue Prologue
;
1639 uint64_t Offset
= 1;
1640 Error Err
= Prologue
.parse(LineData
, &Offset
, RecordRecoverable
, *Context
);
1642 EXPECT_THAT_ERROR(std::move(Err
), FailedWithMessage(ExpectedErr
.str()));
1643 EXPECT_EQ(Offset
, ExpectedOffset
);
1646 INSTANTIATE_TEST_SUITE_P(
1647 TruncatedPrologueParams
, TruncatedPrologueFixture
,
1649 // Truncated length:
1652 "parsing line table prologue at offset 0x00000001: unexpected end "
1653 "of data at offset 0x4 while reading [0x1, 0x5)"),
1656 "parsing line table prologue at offset 0x00000001: unexpected end "
1657 "of data at offset 0x4 while reading [0x1, 0x5)"),
1660 "parsing line table prologue at offset 0x00000001: unexpected end "
1661 "of data at offset 0xc while reading [0x5, 0xd)"),
1662 // Truncated version:
1665 "parsing line table prologue at offset 0x00000001: unexpected end "
1666 "of data at offset 0x6 while reading [0x5, 0x7)"),
1667 // Truncated address size:
1670 "parsing line table prologue at offset 0x00000001: unexpected end "
1671 "of data at offset 0x7 while reading [0x7, 0x8)"),
1672 // Truncated segment selector size:
1675 "parsing line table prologue at offset 0x00000001: unexpected end "
1676 "of data at offset 0x8 while reading [0x8, 0x9)"),
1677 // Truncated prologue length:
1680 "parsing line table prologue at offset 0x00000001: unexpected end "
1681 "of data at offset 0xa while reading [0x7, 0xb)"),
1683 0x16, 0xf, 4, DWARF64
,
1684 "parsing line table prologue at offset 0x00000001: unexpected end "
1685 "of data at offset 0x16 while reading [0xf, 0x17)"),
1686 // Truncated min instruction length:
1688 0xb, 0xb, 4, DWARF32
,
1689 "parsing line table prologue at offset 0x00000001: unexpected end "
1690 "of data at offset 0xb while reading [0xb, 0xc)"),
1691 // Truncated max ops per inst:
1693 0xc, 0xc, 4, DWARF32
,
1694 "parsing line table prologue at offset 0x00000001: unexpected end "
1695 "of data at offset 0xc while reading [0xc, 0xd)"),
1696 // Truncated default is stmt:
1698 0xd, 0xd, 4, DWARF32
,
1699 "parsing line table prologue at offset 0x00000001: unexpected end "
1700 "of data at offset 0xd while reading [0xd, 0xe)"),
1701 // Truncated line base:
1703 0xe, 0xe, 4, DWARF32
,
1704 "parsing line table prologue at offset 0x00000001: unexpected end "
1705 "of data at offset 0xe while reading [0xe, 0xf)"),
1706 // Truncated line range:
1708 0xf, 0xf, 4, DWARF32
,
1709 "parsing line table prologue at offset 0x00000001: unexpected end "
1710 "of data at offset 0xf while reading [0xf, 0x10)"),
1711 // Truncated opcode base:
1713 0x10, 0x10, 4, DWARF32
,
1714 "parsing line table prologue at offset 0x00000001: unexpected end "
1715 "of data at offset 0x10 while reading [0x10, 0x11)"),
1716 // Truncated first standard opcode:
1718 0x11, 0x11, 4, DWARF32
,
1719 "parsing line table prologue at offset 0x00000001: unexpected end "
1720 "of data at offset 0x11 while reading [0x11, 0x12)"),
1721 // Truncated second standard opcode:
1723 0x12, 0x12, 4, DWARF32
,
1724 "parsing line table prologue at offset 0x00000001: unexpected end "
1725 "of data at offset 0x12 while reading [0x12, 0x13)")));
1727 using ValueAndLengths
= std::vector
<LineTable::ValueAndLength
>;
1729 struct TruncatedOpcodeFixtureBase
: public CommonFixture
{
1730 LineTable
&setupTable() {
1731 LineTable
<
= Gen
->addLineTable();
1733 // Creating the prologue before adding any opcodes ensures that the unit
1734 // length does not include the table body.
1735 DWARFDebugLine::Prologue Prologue
= LT
.createBasicPrologue();
1737 // Add an unrecognised standard opcode, and adjust prologue properties
1739 Prologue
.TotalLength
+= BodyLength
+ 1;
1740 ++Prologue
.PrologueLength
;
1741 ++Prologue
.OpcodeBase
;
1742 Prologue
.StandardOpcodeLengths
.push_back(2);
1743 LT
.setPrologue(Prologue
);
1748 void runTest(uint8_t OpcodeValue
) {
1750 DWARFDebugLine::SectionParser
Parser(LineData
, *Context
, Units
);
1752 raw_string_ostream
OS(Output
);
1753 Parser
.parseNext(RecordRecoverable
, RecordUnrecoverable
, &OS
,
1757 std::string LinePrefix
=
1758 ("0x0000002f: 0" + Twine::utohexstr(OpcodeValue
) + " ").str();
1759 StringRef
OutputRef(Output
);
1760 StringRef OutputToCheck
= OutputRef
.split(LinePrefix
).second
;
1761 // Each extended opcode ends with a new line and then the table ends with an
1762 // additional blank line.
1763 EXPECT_EQ((ExpectedOutput
+ "\n\n").str(), OutputToCheck
);
1766 uint64_t BodyLength
;
1768 ValueAndLengths Operands
;
1769 StringRef ExpectedOutput
;
1770 StringRef ExpectedErr
;
1773 struct TruncatedStandardOpcodeFixture
1774 : public TestWithParam
<
1775 std::tuple
<uint64_t, uint8_t, ValueAndLengths
, StringRef
, StringRef
>>,
1776 public TruncatedOpcodeFixtureBase
{
1777 void SetUp() override
{
1778 std::tie(BodyLength
, Opcode
, Operands
, ExpectedOutput
, ExpectedErr
) =
1783 struct TruncatedExtendedOpcodeFixture
1784 : public TestWithParam
<std::tuple
<uint64_t, uint64_t, uint8_t,
1785 ValueAndLengths
, StringRef
, StringRef
>>,
1786 public TruncatedOpcodeFixtureBase
{
1787 void SetUp() override
{
1788 std::tie(BodyLength
, OpcodeLength
, Opcode
, Operands
, ExpectedOutput
,
1789 ExpectedErr
) = GetParam();
1792 uint64_t OpcodeLength
;
1796 TEST_P(TruncatedExtendedOpcodeFixture
,
1797 DISABLED_ErrorForTruncatedExtendedOpcode
) {
1799 TEST_P(TruncatedExtendedOpcodeFixture
, ErrorForTruncatedExtendedOpcode
) {
1801 if (!setupGenerator())
1803 LineTable
<
= setupTable();
1804 LT
.addExtendedOpcode(OpcodeLength
, Opcode
, Operands
);
1806 EXPECT_THAT_ERROR(std::move(Recoverable
),
1807 FailedWithMessage(ExpectedErr
.str()));
1810 INSTANTIATE_TEST_SUITE_P(
1811 TruncatedExtendedOpcodeParams
, TruncatedExtendedOpcodeFixture
,
1813 // Truncated length:
1814 std::make_tuple(1, 1, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "",
1815 "unable to decode LEB128 at offset 0x00000030: "
1816 "malformed uleb128, extends past end"),
1817 // Truncated opcode:
1819 2, 9, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "",
1820 "unexpected end of data at offset 0x31 while reading [0x31, 0x32)"),
1821 // Truncated operands:
1823 3, 9, DW_LNE_set_address
,
1824 ValueAndLengths
{{0x1234567890abcdef, LineTable::Quad
}},
1825 "DW_LNE_set_address",
1826 "unexpected end of data at offset 0x32 while reading [0x32, 0x3a)"),
1828 10, 9, DW_LNE_set_address
,
1829 ValueAndLengths
{{0x1234567878563412, LineTable::Quad
}},
1830 "DW_LNE_set_address (<parsing error> 12 34 56 78 78 56 34)",
1831 "unexpected end of data at offset 0x39 while reading [0x32, 0x3a)"),
1832 std::make_tuple(3, 6, DW_LNE_define_file
,
1833 ValueAndLengths
{{'a', LineTable::Byte
},
1834 {'\0', LineTable::Byte
},
1835 {1, LineTable::ULEB
},
1836 {1, LineTable::ULEB
},
1837 {1, LineTable::ULEB
}},
1838 "DW_LNE_define_file",
1839 "no null terminated string at offset 0x32"),
1840 std::make_tuple(5, 6, DW_LNE_define_file
,
1841 ValueAndLengths
{{'a', LineTable::Byte
},
1842 {'\0', LineTable::Byte
},
1843 {1, LineTable::ULEB
},
1844 {1, LineTable::ULEB
},
1845 {1, LineTable::ULEB
}},
1846 "DW_LNE_define_file (<parsing error> 61 00)",
1847 "unable to decode LEB128 at offset 0x00000034: "
1848 "malformed uleb128, extends past end"),
1849 std::make_tuple(6, 6, DW_LNE_define_file
,
1850 ValueAndLengths
{{'a', LineTable::Byte
},
1851 {'\0', LineTable::Byte
},
1852 {1, LineTable::ULEB
},
1853 {1, LineTable::ULEB
},
1854 {1, LineTable::ULEB
}},
1855 "DW_LNE_define_file (<parsing error> 61 00 01)",
1856 "unable to decode LEB128 at offset 0x00000035: "
1857 "malformed uleb128, extends past end"),
1858 std::make_tuple(7, 6, DW_LNE_define_file
,
1859 ValueAndLengths
{{'a', LineTable::Byte
},
1860 {'\0', LineTable::Byte
},
1861 {1, LineTable::ULEB
},
1862 {1, LineTable::ULEB
},
1863 {1, LineTable::ULEB
}},
1864 "DW_LNE_define_file (<parsing error> 61 00 01 01)",
1865 "unable to decode LEB128 at offset 0x00000036: "
1866 "malformed uleb128, extends past end"),
1867 std::make_tuple(3, 2, DW_LNE_set_discriminator
,
1868 ValueAndLengths
{{1, LineTable::ULEB
}},
1869 "DW_LNE_set_discriminator",
1870 "unable to decode LEB128 at offset 0x00000032: "
1871 "malformed uleb128, extends past end"),
1873 6, 5, /*Unknown=*/0x7f,
1874 ValueAndLengths
{{0x12343412, LineTable::Long
}},
1875 "Unrecognized extended op 0x7f length 5 (<parsing error> 12 34 34)",
1876 "unexpected end of data at offset 0x35 while reading [0x32, "
1880 TEST_P(TruncatedStandardOpcodeFixture
,
1881 DISABLED_ErrorForTruncatedStandardOpcode
) {
1883 TEST_P(TruncatedStandardOpcodeFixture
, ErrorForTruncatedStandardOpcode
) {
1885 if (!setupGenerator())
1887 LineTable
<
= setupTable();
1888 LT
.addStandardOpcode(Opcode
, Operands
);
1890 EXPECT_THAT_ERROR(std::move(Unrecoverable
),
1891 FailedWithMessage(ExpectedErr
.str()));
1894 INSTANTIATE_TEST_SUITE_P(
1895 TruncatedStandardOpcodeParams
, TruncatedStandardOpcodeFixture
,
1897 std::make_tuple(2, DW_LNS_advance_pc
,
1898 ValueAndLengths
{{0x100, LineTable::ULEB
}},
1899 "DW_LNS_advance_pc",
1900 "unable to decode LEB128 at offset 0x00000030: "
1901 "malformed uleb128, extends past end"),
1902 std::make_tuple(2, DW_LNS_advance_line
,
1903 ValueAndLengths
{{0x200, LineTable::SLEB
}},
1904 "DW_LNS_advance_line",
1905 "unable to decode LEB128 at offset 0x00000030: "
1906 "malformed sleb128, extends past end"),
1907 std::make_tuple(2, DW_LNS_set_file
,
1908 ValueAndLengths
{{0x300, LineTable::ULEB
}},
1910 "unable to decode LEB128 at offset 0x00000030: "
1911 "malformed uleb128, extends past end"),
1912 std::make_tuple(2, DW_LNS_set_column
,
1913 ValueAndLengths
{{0x400, LineTable::ULEB
}},
1914 "DW_LNS_set_column",
1915 "unable to decode LEB128 at offset 0x00000030: "
1916 "malformed uleb128, extends past end"),
1918 2, DW_LNS_fixed_advance_pc
,
1919 ValueAndLengths
{{0x500, LineTable::Half
}},
1920 "DW_LNS_fixed_advance_pc",
1921 "unexpected end of data at offset 0x31 while reading [0x30, 0x32)"),
1922 std::make_tuple(2, DW_LNS_set_isa
,
1923 ValueAndLengths
{{0x600, LineTable::ULEB
}},
1925 "unable to decode LEB128 at offset 0x00000030: "
1926 "malformed uleb128, extends past end"),
1927 std::make_tuple(2, 0xd,
1928 ValueAndLengths
{{0x700, LineTable::ULEB
},
1929 {0x800, LineTable::ULEB
}},
1930 "Unrecognized standard opcode",
1931 "unable to decode LEB128 at offset 0x00000030: "
1932 "malformed uleb128, extends past end"),
1935 ValueAndLengths
{{0x900, LineTable::ULEB
}, {0xa00, LineTable::ULEB
}},
1936 "Unrecognized standard opcode (operands: 0x0000000000000900)",
1937 "unable to decode LEB128 at offset 0x00000032: "
1938 "malformed uleb128, extends past end")));
1941 TEST_F(DebugLineBasicFixture
, DISABLED_PrintPathsProperly
) {
1943 TEST_F(DebugLineBasicFixture
, PrintPathsProperly
) {
1945 if (!setupGenerator(5))
1948 LineTable
<
= Gen
->addLineTable();
1949 DWARFDebugLine::Prologue P
= LT
.createBasicPrologue();
1950 P
.IncludeDirectories
.push_back(
1951 DWARFFormValue::createFromPValue(DW_FORM_string
, "b dir"));
1952 P
.FileNames
.push_back(DWARFDebugLine::FileNameEntry());
1953 P
.FileNames
.back().Name
=
1954 DWARFFormValue::createFromPValue(DW_FORM_string
, "b file");
1955 P
.FileNames
.back().DirIdx
= 1;
1956 P
.TotalLength
+= 14;
1957 P
.PrologueLength
+= 14;
1961 auto ExpectedLineTable
= Line
.getOrParseLineTable(LineData
, 0, *Context
,
1962 nullptr, RecordRecoverable
);
1963 EXPECT_THAT_EXPECTED(ExpectedLineTable
, Succeeded());
1965 // DWARF 5 stores the compilation directory in two places: the Compilation
1966 // Unit and the directory table entry 0, and implementations are free to use
1967 // one or the other. This copy serves as the one stored in the CU.
1968 StringRef CompDir
= "a dir";
1970 (*ExpectedLineTable
)
1971 ->Prologue
.getFileNameByIndex(
1972 1, CompDir
, DILineInfoSpecifier::FileLineInfoKind::None
, Result
));
1973 EXPECT_TRUE((*ExpectedLineTable
)
1974 ->Prologue
.getFileNameByIndex(
1976 DILineInfoSpecifier::FileLineInfoKind::RawValue
, Result
));
1977 EXPECT_TRUE((*ExpectedLineTable
)
1978 ->Prologue
.getFileNameByIndex(
1980 DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly
,
1982 EXPECT_STREQ(Result
.c_str(), "b file");
1983 EXPECT_TRUE((*ExpectedLineTable
)
1984 ->Prologue
.getFileNameByIndex(
1986 DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath
,
1988 EXPECT_THAT(Result
.c_str(), MatchesRegex("b dir.b file"));
1989 EXPECT_TRUE((*ExpectedLineTable
)
1990 ->Prologue
.getFileNameByIndex(
1992 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
,
1994 EXPECT_THAT(Result
.c_str(), MatchesRegex("a dir.b dir.b file"));
1997 } // end anonymous namespace