xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp (revision 04aea769bfad4ec78242adc2241aa751d10862f8)
1 //===- DWARFDataExtractorTest.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
10 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
11 #include "llvm/Object/ObjectFile.h"
12 #include "llvm/ObjectYAML/yaml2obj.h"
13 #include "llvm/Testing/Support/Error.h"
14 #include "gtest/gtest.h"
15 
16 using namespace llvm;
17 
18 namespace {
19 
TEST(DWARFDataExtractorTest,getRelocatedValue)20 TEST(DWARFDataExtractorTest, getRelocatedValue) {
21   StringRef Yaml = R"(
22 !ELF
23 FileHeader:
24   Class:    ELFCLASS32
25   Data:     ELFDATA2LSB
26   Type:     ET_REL
27   Machine:  EM_386
28 Sections:
29   - Name:     .text
30     Type:     SHT_PROGBITS
31     Size:     0x80
32   - Name:     .debug_line
33     Type:     SHT_PROGBITS
34     Content:  '000000000000'
35   - Name:     .rel.debug_line
36     Type:     SHT_REL
37     Info:     .debug_line
38     Relocations:
39       - Offset:   0
40         Symbol:   f
41         Type:     R_386_32
42       - Offset:   4
43         Symbol:   f
44         Type:     R_386_32
45 Symbols:
46   - Name:     f
47     Type:     STT_SECTION
48     Section:  .text
49     Value:    0x42
50 )";
51   SmallString<0> Storage;
52   std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(
53       Storage, Yaml, [](const Twine &Err) { errs() << Err; });
54   ASSERT_TRUE(Obj);
55   std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
56   const DWARFObject &DObj = Ctx->getDWARFObj();
57   ASSERT_EQ(6u, DObj.getLineSection().Data.size());
58 
59   DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
60                           Obj->getBytesInAddress());
61   DataExtractor::Cursor C(0);
62   EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
63   EXPECT_EQ(0u, Data.getRelocatedAddress(C));
64   EXPECT_THAT_ERROR(
65       C.takeError(),
66       FailedWithMessage(
67           "unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));
68 }
69 
TEST(DWARFDataExtractorTest,getInitialLength)70 TEST(DWARFDataExtractorTest, getInitialLength) {
71   auto GetWithError = [](ArrayRef<uint8_t> Bytes)
72       -> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> {
73     DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);
74     DWARFDataExtractor::Cursor C(0);
75     uint64_t Length;
76     dwarf::DwarfFormat Format;
77     std::tie(Length, Format) = Data.getInitialLength(C);
78     if (C)
79       return std::make_tuple(Length, Format, C.tell());
80 
81     EXPECT_EQ(Length, 0u);
82     EXPECT_EQ(Format, dwarf::DWARF32);
83     EXPECT_EQ(C.tell(), 0u);
84     return C.takeError();
85   };
86   auto GetWithoutError = [](ArrayRef<uint8_t> Bytes) {
87     DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);
88     uint64_t Offset = 0;
89     uint64_t Length;
90     dwarf::DwarfFormat Format;
91     std::tie(Length, Format) = Data.getInitialLength(&Offset);
92     return std::make_tuple(Length, Format, Offset);
93   };
94   auto ErrorResult = std::make_tuple(0, dwarf::DWARF32, 0);
95 
96   // Empty data.
97   EXPECT_THAT_EXPECTED(
98       GetWithError({}),
99       FailedWithMessage(
100           "unexpected end of data at offset 0x0 while reading [0x0, 0x4)"));
101   EXPECT_EQ(GetWithoutError({}), ErrorResult);
102 
103   // Not long enough for the U32 field.
104   EXPECT_THAT_EXPECTED(
105       GetWithError({0x00, 0x01, 0x02}),
106       FailedWithMessage(
107           "unexpected end of data at offset 0x3 while reading [0x0, 0x4)"));
108   EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02}), ErrorResult);
109 
110   EXPECT_THAT_EXPECTED(
111       GetWithError({0x00, 0x01, 0x02, 0x03}),
112       HasValue(std::make_tuple(0x00010203, dwarf::DWARF32, 4)));
113   EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02, 0x03}),
114             std::make_tuple(0x00010203, dwarf::DWARF32, 4));
115 
116   // Zeroes are not an error, but without the Error object it is hard to tell
117   // them apart from a failed read.
118   EXPECT_THAT_EXPECTED(
119       GetWithError({0x00, 0x00, 0x00, 0x00}),
120       HasValue(std::make_tuple(0x00000000, dwarf::DWARF32, 4)));
121   EXPECT_EQ(GetWithoutError({0x00, 0x00, 0x00, 0x00}),
122             std::make_tuple(0x00000000, dwarf::DWARF32, 4));
123 
124   // Smallest invalid value.
125   EXPECT_THAT_EXPECTED(
126       GetWithError({0xff, 0xff, 0xff, 0xf0}),
127       FailedWithMessage(
128           "unsupported reserved unit length of value 0xfffffff0"));
129   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xf0}), ErrorResult);
130 
131   // DWARF64 marker without the subsequent length field.
132   EXPECT_THAT_EXPECTED(
133       GetWithError({0xff, 0xff, 0xff, 0xff}),
134       FailedWithMessage(
135           "unexpected end of data at offset 0x4 while reading [0x4, 0xc)"));
136   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff}), ErrorResult);
137 
138   // Not enough data for the U64 length.
139   EXPECT_THAT_EXPECTED(
140       GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),
141       FailedWithMessage(
142           "unexpected end of data at offset 0x8 while reading [0x4, 0xc)"));
143   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),
144             ErrorResult);
145 
146   EXPECT_THAT_EXPECTED(
147       GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
148                     0x06, 0x07}),
149       HasValue(std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)));
150   EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03,
151                              0x04, 0x05, 0x06, 0x07}),
152             std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12));
153 }
154 
TEST(DWARFDataExtractorTest,Truncation)155 TEST(DWARFDataExtractorTest, Truncation) {
156   StringRef Yaml = R"(
157 !ELF
158 FileHeader:
159   Class:    ELFCLASS32
160   Data:     ELFDATA2LSB
161   Type:     ET_REL
162   Machine:  EM_386
163 Sections:
164   - Name:     .text
165     Type:     SHT_PROGBITS
166     Size:     0x80
167   - Name:     .debug_line
168     Type:     SHT_PROGBITS
169     Content:  '616263640000000065666768'
170   - Name:     .rel.debug_line
171     Type:     SHT_REL
172     Info:     .debug_line
173     Relocations:
174       - Offset:   4
175         Symbol:   f
176         Type:     R_386_32
177 Symbols:
178   - Name:     f
179     Type:     STT_SECTION
180     Section:  .text
181     Value:    0x42
182 )";
183   SmallString<0> Storage;
184   std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(
185       Storage, Yaml, [](const Twine &Err) { errs() << Err; });
186   ASSERT_TRUE(Obj);
187   std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
188   const DWARFObject &DObj = Ctx->getDWARFObj();
189   ASSERT_EQ(12u, DObj.getLineSection().Data.size());
190 
191   DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
192                           Obj->getBytesInAddress());
193   DataExtractor::Cursor C(0);
194   EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C));
195   EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
196   EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C));
197   EXPECT_THAT_ERROR(C.takeError(), Succeeded());
198 
199   C = DataExtractor::Cursor{0};
200   DWARFDataExtractor Truncated8(Data, 8);
201   EXPECT_EQ(0x64636261u, Truncated8.getRelocatedAddress(C));
202   EXPECT_EQ(0x42u, Truncated8.getRelocatedAddress(C));
203   EXPECT_EQ(0x0u, Truncated8.getRelocatedAddress(C));
204   EXPECT_THAT_ERROR(
205       C.takeError(),
206       FailedWithMessage(
207           "unexpected end of data at offset 0x8 while reading [0x8, 0xc)"));
208 
209   C = DataExtractor::Cursor{0};
210   DWARFDataExtractor Truncated6(Data, 6);
211   EXPECT_EQ(0x64636261u, Truncated6.getRelocatedAddress(C));
212   EXPECT_EQ(0x0u, Truncated6.getRelocatedAddress(C));
213   EXPECT_THAT_ERROR(
214       C.takeError(),
215       FailedWithMessage(
216           "unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));
217 
218   C = DataExtractor::Cursor{0};
219   DWARFDataExtractor Truncated2(Data, 2);
220   EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C));
221   EXPECT_THAT_ERROR(
222       C.takeError(),
223       FailedWithMessage(
224           "unexpected end of data at offset 0x2 while reading [0x0, 0x4)"));
225 }
226 
227 } // namespace
228