xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp (revision 04aea769bfad4ec78242adc2241aa751d10862f8)
13c36d8daSPavel Labath //===- DWARFDataExtractorTest.cpp -----------------------------------------===//
23c36d8daSPavel Labath //
33c36d8daSPavel Labath // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43c36d8daSPavel Labath // See https://llvm.org/LICENSE.txt for license information.
53c36d8daSPavel Labath // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63c36d8daSPavel Labath //
73c36d8daSPavel Labath //===----------------------------------------------------------------------===//
83c36d8daSPavel Labath 
93c36d8daSPavel Labath #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
10122c50d5SPavel Labath #include "llvm/DebugInfo/DWARF/DWARFContext.h"
11122c50d5SPavel Labath #include "llvm/Object/ObjectFile.h"
12122c50d5SPavel Labath #include "llvm/ObjectYAML/yaml2obj.h"
133c36d8daSPavel Labath #include "llvm/Testing/Support/Error.h"
143c36d8daSPavel Labath #include "gtest/gtest.h"
153c36d8daSPavel Labath 
163c36d8daSPavel Labath using namespace llvm;
173c36d8daSPavel Labath 
183c36d8daSPavel Labath namespace {
193c36d8daSPavel Labath 
TEST(DWARFDataExtractorTest,getRelocatedValue)20122c50d5SPavel Labath TEST(DWARFDataExtractorTest, getRelocatedValue) {
21122c50d5SPavel Labath   StringRef Yaml = R"(
22122c50d5SPavel Labath !ELF
23122c50d5SPavel Labath FileHeader:
24122c50d5SPavel Labath   Class:    ELFCLASS32
25122c50d5SPavel Labath   Data:     ELFDATA2LSB
26122c50d5SPavel Labath   Type:     ET_REL
27122c50d5SPavel Labath   Machine:  EM_386
28122c50d5SPavel Labath Sections:
29122c50d5SPavel Labath   - Name:     .text
30122c50d5SPavel Labath     Type:     SHT_PROGBITS
31122c50d5SPavel Labath     Size:     0x80
32122c50d5SPavel Labath   - Name:     .debug_line
33122c50d5SPavel Labath     Type:     SHT_PROGBITS
34122c50d5SPavel Labath     Content:  '000000000000'
35122c50d5SPavel Labath   - Name:     .rel.debug_line
36122c50d5SPavel Labath     Type:     SHT_REL
37122c50d5SPavel Labath     Info:     .debug_line
38122c50d5SPavel Labath     Relocations:
39122c50d5SPavel Labath       - Offset:   0
40122c50d5SPavel Labath         Symbol:   f
41122c50d5SPavel Labath         Type:     R_386_32
42122c50d5SPavel Labath       - Offset:   4
43122c50d5SPavel Labath         Symbol:   f
44122c50d5SPavel Labath         Type:     R_386_32
45122c50d5SPavel Labath Symbols:
46122c50d5SPavel Labath   - Name:     f
47122c50d5SPavel Labath     Type:     STT_SECTION
48122c50d5SPavel Labath     Section:  .text
49122c50d5SPavel Labath     Value:    0x42
50122c50d5SPavel Labath )";
51122c50d5SPavel Labath   SmallString<0> Storage;
52122c50d5SPavel Labath   std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(
53122c50d5SPavel Labath       Storage, Yaml, [](const Twine &Err) { errs() << Err; });
54122c50d5SPavel Labath   ASSERT_TRUE(Obj);
55122c50d5SPavel Labath   std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
56122c50d5SPavel Labath   const DWARFObject &DObj = Ctx->getDWARFObj();
57122c50d5SPavel Labath   ASSERT_EQ(6u, DObj.getLineSection().Data.size());
58122c50d5SPavel Labath 
59122c50d5SPavel Labath   DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
60122c50d5SPavel Labath                           Obj->getBytesInAddress());
61122c50d5SPavel Labath   DataExtractor::Cursor C(0);
62122c50d5SPavel Labath   EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
63122c50d5SPavel Labath   EXPECT_EQ(0u, Data.getRelocatedAddress(C));
64*04aea769SPavel Labath   EXPECT_THAT_ERROR(
65*04aea769SPavel Labath       C.takeError(),
66*04aea769SPavel Labath       FailedWithMessage(
67*04aea769SPavel Labath           "unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));
68122c50d5SPavel Labath }
69122c50d5SPavel Labath 
TEST(DWARFDataExtractorTest,getInitialLength)703c36d8daSPavel Labath TEST(DWARFDataExtractorTest, getInitialLength) {
713c36d8daSPavel Labath   auto GetWithError = [](ArrayRef<uint8_t> Bytes)
723c36d8daSPavel Labath       -> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> {
733c36d8daSPavel Labath     DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);
743c36d8daSPavel Labath     DWARFDataExtractor::Cursor C(0);
753c36d8daSPavel Labath     uint64_t Length;
763c36d8daSPavel Labath     dwarf::DwarfFormat Format;
773c36d8daSPavel Labath     std::tie(Length, Format) = Data.getInitialLength(C);
783c36d8daSPavel Labath     if (C)
793c36d8daSPavel Labath       return std::make_tuple(Length, Format, C.tell());
803c36d8daSPavel Labath 
813c36d8daSPavel Labath     EXPECT_EQ(Length, 0u);
823c36d8daSPavel Labath     EXPECT_EQ(Format, dwarf::DWARF32);
833c36d8daSPavel Labath     EXPECT_EQ(C.tell(), 0u);
843c36d8daSPavel Labath     return C.takeError();
853c36d8daSPavel Labath   };
863c36d8daSPavel Labath   auto GetWithoutError = [](ArrayRef<uint8_t> Bytes) {
873c36d8daSPavel Labath     DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);
883c36d8daSPavel Labath     uint64_t Offset = 0;
893c36d8daSPavel Labath     uint64_t Length;
903c36d8daSPavel Labath     dwarf::DwarfFormat Format;
913c36d8daSPavel Labath     std::tie(Length, Format) = Data.getInitialLength(&Offset);
923c36d8daSPavel Labath     return std::make_tuple(Length, Format, Offset);
933c36d8daSPavel Labath   };
943c36d8daSPavel Labath   auto ErrorResult = std::make_tuple(0, dwarf::DWARF32, 0);
953c36d8daSPavel Labath 
963c36d8daSPavel Labath   // Empty data.
975754a61eSPavel Labath   EXPECT_THAT_EXPECTED(
985754a61eSPavel Labath       GetWithError({}),
99*04aea769SPavel Labath       FailedWithMessage(
100*04aea769SPavel Labath           "unexpected end of data at offset 0x0 while reading [0x0, 0x4)"));
1013c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({}), ErrorResult);
1023c36d8daSPavel Labath 
1033c36d8daSPavel Labath   // Not long enough for the U32 field.
1045754a61eSPavel Labath   EXPECT_THAT_EXPECTED(
1055754a61eSPavel Labath       GetWithError({0x00, 0x01, 0x02}),
106*04aea769SPavel Labath       FailedWithMessage(
107*04aea769SPavel Labath           "unexpected end of data at offset 0x3 while reading [0x0, 0x4)"));
1083c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02}), ErrorResult);
1093c36d8daSPavel Labath 
1103c36d8daSPavel Labath   EXPECT_THAT_EXPECTED(
1113c36d8daSPavel Labath       GetWithError({0x00, 0x01, 0x02, 0x03}),
1123c36d8daSPavel Labath       HasValue(std::make_tuple(0x00010203, dwarf::DWARF32, 4)));
1133c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02, 0x03}),
1143c36d8daSPavel Labath             std::make_tuple(0x00010203, dwarf::DWARF32, 4));
1153c36d8daSPavel Labath 
1163c36d8daSPavel Labath   // Zeroes are not an error, but without the Error object it is hard to tell
1173c36d8daSPavel Labath   // them apart from a failed read.
1183c36d8daSPavel Labath   EXPECT_THAT_EXPECTED(
1193c36d8daSPavel Labath       GetWithError({0x00, 0x00, 0x00, 0x00}),
1203c36d8daSPavel Labath       HasValue(std::make_tuple(0x00000000, dwarf::DWARF32, 4)));
1213c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0x00, 0x00, 0x00, 0x00}),
1223c36d8daSPavel Labath             std::make_tuple(0x00000000, dwarf::DWARF32, 4));
1233c36d8daSPavel Labath 
1243c36d8daSPavel Labath   // Smallest invalid value.
1253c36d8daSPavel Labath   EXPECT_THAT_EXPECTED(
1263c36d8daSPavel Labath       GetWithError({0xff, 0xff, 0xff, 0xf0}),
1273c36d8daSPavel Labath       FailedWithMessage(
1283c36d8daSPavel Labath           "unsupported reserved unit length of value 0xfffffff0"));
1293c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xf0}), ErrorResult);
1303c36d8daSPavel Labath 
1313c36d8daSPavel Labath   // DWARF64 marker without the subsequent length field.
1325754a61eSPavel Labath   EXPECT_THAT_EXPECTED(
1335754a61eSPavel Labath       GetWithError({0xff, 0xff, 0xff, 0xff}),
134*04aea769SPavel Labath       FailedWithMessage(
135*04aea769SPavel Labath           "unexpected end of data at offset 0x4 while reading [0x4, 0xc)"));
1363c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff}), ErrorResult);
1373c36d8daSPavel Labath 
1383c36d8daSPavel Labath   // Not enough data for the U64 length.
1393c36d8daSPavel Labath   EXPECT_THAT_EXPECTED(
1403c36d8daSPavel Labath       GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),
141*04aea769SPavel Labath       FailedWithMessage(
142*04aea769SPavel Labath           "unexpected end of data at offset 0x8 while reading [0x4, 0xc)"));
1433c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),
1443c36d8daSPavel Labath             ErrorResult);
1453c36d8daSPavel Labath 
1463c36d8daSPavel Labath   EXPECT_THAT_EXPECTED(
1473c36d8daSPavel Labath       GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
1483c36d8daSPavel Labath                     0x06, 0x07}),
1493c36d8daSPavel Labath       HasValue(std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)));
1503c36d8daSPavel Labath   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03,
1513c36d8daSPavel Labath                              0x04, 0x05, 0x06, 0x07}),
1523c36d8daSPavel Labath             std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12));
1533c36d8daSPavel Labath }
1543c36d8daSPavel Labath 
TEST(DWARFDataExtractorTest,Truncation)155cc0acda7SPavel Labath TEST(DWARFDataExtractorTest, Truncation) {
156cc0acda7SPavel Labath   StringRef Yaml = R"(
157cc0acda7SPavel Labath !ELF
158cc0acda7SPavel Labath FileHeader:
159cc0acda7SPavel Labath   Class:    ELFCLASS32
160cc0acda7SPavel Labath   Data:     ELFDATA2LSB
161cc0acda7SPavel Labath   Type:     ET_REL
162cc0acda7SPavel Labath   Machine:  EM_386
163cc0acda7SPavel Labath Sections:
164cc0acda7SPavel Labath   - Name:     .text
165cc0acda7SPavel Labath     Type:     SHT_PROGBITS
166cc0acda7SPavel Labath     Size:     0x80
167cc0acda7SPavel Labath   - Name:     .debug_line
168cc0acda7SPavel Labath     Type:     SHT_PROGBITS
169cc0acda7SPavel Labath     Content:  '616263640000000065666768'
170cc0acda7SPavel Labath   - Name:     .rel.debug_line
171cc0acda7SPavel Labath     Type:     SHT_REL
172cc0acda7SPavel Labath     Info:     .debug_line
173cc0acda7SPavel Labath     Relocations:
174cc0acda7SPavel Labath       - Offset:   4
175cc0acda7SPavel Labath         Symbol:   f
176cc0acda7SPavel Labath         Type:     R_386_32
177cc0acda7SPavel Labath Symbols:
178cc0acda7SPavel Labath   - Name:     f
179cc0acda7SPavel Labath     Type:     STT_SECTION
180cc0acda7SPavel Labath     Section:  .text
181cc0acda7SPavel Labath     Value:    0x42
182cc0acda7SPavel Labath )";
183cc0acda7SPavel Labath   SmallString<0> Storage;
184cc0acda7SPavel Labath   std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(
185cc0acda7SPavel Labath       Storage, Yaml, [](const Twine &Err) { errs() << Err; });
186cc0acda7SPavel Labath   ASSERT_TRUE(Obj);
187cc0acda7SPavel Labath   std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
188cc0acda7SPavel Labath   const DWARFObject &DObj = Ctx->getDWARFObj();
189cc0acda7SPavel Labath   ASSERT_EQ(12u, DObj.getLineSection().Data.size());
190cc0acda7SPavel Labath 
191cc0acda7SPavel Labath   DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
192cc0acda7SPavel Labath                           Obj->getBytesInAddress());
193cc0acda7SPavel Labath   DataExtractor::Cursor C(0);
194cc0acda7SPavel Labath   EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C));
195cc0acda7SPavel Labath   EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
196cc0acda7SPavel Labath   EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C));
197cc0acda7SPavel Labath   EXPECT_THAT_ERROR(C.takeError(), Succeeded());
198cc0acda7SPavel Labath 
199cc0acda7SPavel Labath   C = DataExtractor::Cursor{0};
200cc0acda7SPavel Labath   DWARFDataExtractor Truncated8(Data, 8);
201cc0acda7SPavel Labath   EXPECT_EQ(0x64636261u, Truncated8.getRelocatedAddress(C));
202cc0acda7SPavel Labath   EXPECT_EQ(0x42u, Truncated8.getRelocatedAddress(C));
203cc0acda7SPavel Labath   EXPECT_EQ(0x0u, Truncated8.getRelocatedAddress(C));
204*04aea769SPavel Labath   EXPECT_THAT_ERROR(
205*04aea769SPavel Labath       C.takeError(),
206*04aea769SPavel Labath       FailedWithMessage(
207*04aea769SPavel Labath           "unexpected end of data at offset 0x8 while reading [0x8, 0xc)"));
208cc0acda7SPavel Labath 
209cc0acda7SPavel Labath   C = DataExtractor::Cursor{0};
210cc0acda7SPavel Labath   DWARFDataExtractor Truncated6(Data, 6);
211cc0acda7SPavel Labath   EXPECT_EQ(0x64636261u, Truncated6.getRelocatedAddress(C));
212cc0acda7SPavel Labath   EXPECT_EQ(0x0u, Truncated6.getRelocatedAddress(C));
213*04aea769SPavel Labath   EXPECT_THAT_ERROR(
214*04aea769SPavel Labath       C.takeError(),
215*04aea769SPavel Labath       FailedWithMessage(
216*04aea769SPavel Labath           "unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));
217cc0acda7SPavel Labath 
218cc0acda7SPavel Labath   C = DataExtractor::Cursor{0};
219cc0acda7SPavel Labath   DWARFDataExtractor Truncated2(Data, 2);
220cc0acda7SPavel Labath   EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C));
221*04aea769SPavel Labath   EXPECT_THAT_ERROR(
222*04aea769SPavel Labath       C.takeError(),
223*04aea769SPavel Labath       FailedWithMessage(
224*04aea769SPavel Labath           "unexpected end of data at offset 0x2 while reading [0x0, 0x4)"));
225cc0acda7SPavel Labath }
226cc0acda7SPavel Labath 
2273c36d8daSPavel Labath } // namespace
228