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