xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp (revision d7733f84228bde1079117e82b36fac94e9b323ed)
1 //===- llvm/unittest/DebugInfo/DWARFDebugArangeSetTest.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/DWARFDebugArangeSet.h"
10 #include "llvm/Testing/Support/Error.h"
11 #include "gtest/gtest.h"
12 
13 using namespace llvm;
14 
15 namespace {
16 
17 struct WarningHandler {
18   ~WarningHandler() { EXPECT_THAT_ERROR(std::move(Err), Succeeded()); }
19 
20   void operator()(Error E) { Err = joinErrors(std::move(Err), std::move(E)); }
21 
22   Error getWarning() { return std::move(Err); }
23 
24   Error Err = Error::success();
25 };
26 
27 template <size_t SecSize>
28 void ExpectExtractError(const char (&SecDataRaw)[SecSize],
29                         const char *ErrorMessage) {
30   DWARFDataExtractor Extractor(StringRef(SecDataRaw, SecSize - 1),
31                                /* IsLittleEndian = */ true,
32                                /* AddressSize = */ 4);
33   DWARFDebugArangeSet Set;
34   uint64_t Offset = 0;
35   WarningHandler Warnings;
36   Error E = Set.extract(Extractor, &Offset, Warnings);
37   ASSERT_TRUE(E.operator bool());
38   EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str());
39 }
40 
41 TEST(DWARFDebugArangeSet, LengthExceedsSectionSize) {
42   static const char DebugArangesSecRaw[] =
43       "\x15\x00\x00\x00" // The length exceeds the section boundaries
44       "\x02\x00"         // Version
45       "\x00\x00\x00\x00" // Debug Info Offset
46       "\x04"             // Address Size
47       "\x00"             // Segment Selector Size
48       "\x00\x00\x00\x00" // Padding
49       "\x00\x00\x00\x00" // Termination tuple
50       "\x00\x00\x00\x00";
51   ExpectExtractError(
52       DebugArangesSecRaw,
53       "the length of address range table at offset 0x0 exceeds section size");
54 }
55 
56 TEST(DWARFDebugArangeSet, LengthExceedsSectionSizeDWARF64) {
57   static const char DebugArangesSecRaw[] =
58       "\xff\xff\xff\xff"                 // DWARF64 mark
59       "\x15\x00\x00\x00\x00\x00\x00\x00" // The length exceeds the section
60                                          // boundaries
61       "\x02\x00"                         // Version
62       "\x00\x00\x00\x00\x00\x00\x00\x00" // Debug Info Offset
63       "\x04"                             // Address Size
64       "\x00"                             // Segment Selector Size
65                                          // No padding
66       "\x00\x00\x00\x00"                 // Termination tuple
67       "\x00\x00\x00\x00";
68   ExpectExtractError(
69       DebugArangesSecRaw,
70       "the length of address range table at offset 0x0 exceeds section size");
71 }
72 
73 TEST(DWARFDebugArangeSet, UnsupportedAddressSize) {
74   static const char DebugArangesSecRaw[] =
75       "\x0c\x00\x00\x00"  // Length
76       "\x02\x00"          // Version
77       "\x00\x00\x00\x00"  // Debug Info Offset
78       "\x03"              // Address Size (not supported)
79       "\x00"              // Segment Selector Size
80                           // No padding
81       "\x00\x00\x00\x00"; // Termination tuple
82   ExpectExtractError(
83       DebugArangesSecRaw,
84       "address range table at offset 0x0 has unsupported address size: 3 "
85       "(supported are 2, 4, 8)");
86 }
87 
88 TEST(DWARFDebugArangeSet, UnsupportedSegmentSelectorSize) {
89   static const char DebugArangesSecRaw[] =
90       "\x14\x00\x00\x00" // Length
91       "\x02\x00"         // Version
92       "\x00\x00\x00\x00" // Debug Info Offset
93       "\x04"             // Address Size
94       "\x04"             // Segment Selector Size (not supported)
95                          // No padding
96       "\x00\x00\x00\x00" // Termination tuple
97       "\x00\x00\x00\x00"
98       "\x00\x00\x00\x00";
99   ExpectExtractError(
100       DebugArangesSecRaw,
101       "non-zero segment selector size in address range table at offset 0x0 "
102       "is not supported");
103 }
104 
105 TEST(DWARFDebugArangeSet, NoTerminationEntry) {
106   static const char DebugArangesSecRaw[] =
107       "\x14\x00\x00\x00" // Length
108       "\x02\x00"         // Version
109       "\x00\x00\x00\x00" // Debug Info Offset
110       "\x04"             // Address Size
111       "\x00"             // Segment Selector Size
112       "\x00\x00\x00\x00" // Padding
113       "\x00\x00\x00\x00" // Entry: Address
114       "\x01\x00\x00\x00" //        Length
115       ;                  // No termination tuple
116   ExpectExtractError(
117       DebugArangesSecRaw,
118       "address range table at offset 0x0 is not terminated by null entry");
119 }
120 
121 TEST(DWARFDebugArangeSet, ReservedUnitLength) {
122   // Note: 12 is the minimum length to pass the basic check for the size of
123   // the section. 1 will be automatically subtracted in ExpectExtractError().
124   static const char DebugArangesSecRaw[12 + 1] =
125       "\xf0\xff\xff\xff"; // Reserved unit length value
126   ExpectExtractError(DebugArangesSecRaw,
127                      "parsing address ranges table at offset 0x0: unsupported "
128                      "reserved unit length of value 0xfffffff0");
129 }
130 
131 TEST(DWARFDebugArangeSet, SectionTooShort) {
132   // Note: 1 will be automatically subtracted in ExpectExtractError().
133   static const char DebugArangesSecRaw[11 + 1] = {0};
134   ExpectExtractError(DebugArangesSecRaw,
135                      "parsing address ranges table at offset 0x0: unexpected "
136                      "end of data at offset 0xb while reading [0xb, 0xc)");
137 }
138 
139 TEST(DWARFDebugArangeSet, SectionTooShortDWARF64) {
140   // Note: 1 will be automatically subtracted in ExpectExtractError().
141   static const char DebugArangesSecRaw[23 + 1] =
142       "\xff\xff\xff\xff"; // DWARF64 mark
143   ExpectExtractError(DebugArangesSecRaw,
144                      "parsing address ranges table at offset 0x0: unexpected "
145                      "end of data at offset 0x17 while reading [0x17, 0x18)");
146 }
147 
148 TEST(DWARFDebugArangeSet, NoSpaceForEntries) {
149   static const char DebugArangesSecRaw[] =
150       "\x0c\x00\x00\x00" // Length
151       "\x02\x00"         // Version
152       "\x00\x00\x00\x00" // Debug Info Offset
153       "\x04"             // Address Size
154       "\x00"             // Segment Selector Size
155       "\x00\x00\x00\x00" // Padding
156       ;                  // No entries
157   ExpectExtractError(
158       DebugArangesSecRaw,
159       "address range table at offset 0x0 has an insufficient length "
160       "to contain any entries");
161 }
162 
163 TEST(DWARFDebugArangeSet, UnevenLength) {
164   static const char DebugArangesSecRaw[] =
165       "\x1b\x00\x00\x00" // Length (not a multiple of tuple size)
166       "\x02\x00"         // Version
167       "\x00\x00\x00\x00" // Debug Info Offset
168       "\x04"             // Address Size
169       "\x00"             // Segment Selector Size
170       "\x00\x00\x00\x00" // Padding
171       "\x00\x00\x00\x00" // Entry: Address
172       "\x01\x00\x00\x00" //        Length
173       "\x00\x00\x00\x00" // Termination tuple
174       "\x00\x00\x00\x00";
175   ExpectExtractError(
176       DebugArangesSecRaw,
177       "address range table at offset 0x0 has length that is not a multiple "
178       "of the tuple size");
179 }
180 
181 TEST(DWARFDebugArangeSet, ZeroAddressEntry) {
182   static const char DebugArangesSecRaw[] =
183       "\x1c\x00\x00\x00" // Length
184       "\x02\x00"         // Version
185       "\x00\x00\x00\x00" // Debug Info Offset
186       "\x04"             // Address Size
187       "\x00"             // Segment Selector Size
188       "\x00\x00\x00\x00" // Padding
189       "\x00\x00\x00\x00" // Entry1: Address
190       "\x01\x00\x00\x00" //         Length
191       "\x00\x00\x00\x00" // Termination tuple
192       "\x00\x00\x00\x00";
193   DWARFDataExtractor Extractor(
194       StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
195       /*IsLittleEndian=*/true,
196       /*AddressSize=*/4);
197   DWARFDebugArangeSet Set;
198   uint64_t Offset = 0;
199   ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()),
200                     Succeeded());
201   auto Range = Set.descriptors();
202   auto Iter = Range.begin();
203   ASSERT_EQ(std::distance(Iter, Range.end()), 1);
204   EXPECT_EQ(Iter->Address, 0u);
205   EXPECT_EQ(Iter->Length, 1u);
206 }
207 
208 TEST(DWARFDebugArangeSet, ZeroLengthEntry) {
209   static const char DebugArangesSecRaw[] =
210       "\x1c\x00\x00\x00" // Length
211       "\x02\x00"         // Version
212       "\x00\x00\x00\x00" // Debug Info Offset
213       "\x04"             // Address Size
214       "\x00"             // Segment Selector Size
215       "\x00\x00\x00\x00" // Padding
216       "\x01\x00\x00\x00" // Entry1: Address
217       "\x00\x00\x00\x00" //         Length
218       "\x00\x00\x00\x00" // Termination tuple
219       "\x00\x00\x00\x00";
220   DWARFDataExtractor Extractor(
221       StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
222       /*IsLittleEndian=*/true,
223       /*AddressSize=*/4);
224   DWARFDebugArangeSet Set;
225   uint64_t Offset = 0;
226   ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()),
227                     Succeeded());
228   auto Range = Set.descriptors();
229   auto Iter = Range.begin();
230   ASSERT_EQ(std::distance(Iter, Range.end()), 1);
231   EXPECT_EQ(Iter->Address, 1u);
232   EXPECT_EQ(Iter->Length, 0u);
233 }
234 
235 TEST(DWARFDebugArangesSet, PrematureTerminator) {
236   static const char DebugArangesSecRaw[] =
237       "\x24\x00\x00\x00" // Length
238       "\x02\x00"         // Version
239       "\x00\x00\x00\x00" // Debug Info Offset
240       "\x04"             // Address Size
241       "\x00"             // Segment Selector Size
242       "\x00\x00\x00\x00" // Padding
243       "\x00\x00\x00\x00" // Entry1: Premature
244       "\x00\x00\x00\x00" //         terminator
245       "\x01\x00\x00\x00" // Entry2: Address
246       "\x01\x00\x00\x00" //         Length
247       "\x00\x00\x00\x00" // Termination tuple
248       "\x00\x00\x00\x00";
249   DWARFDataExtractor Extractor(
250       StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
251       /*IsLittleEndian=*/true,
252       /*AddressSize=*/4);
253   DWARFDebugArangeSet Set;
254   uint64_t Offset = 0;
255   WarningHandler Warnings;
256   ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, Warnings), Succeeded());
257   auto Range = Set.descriptors();
258   auto Iter = Range.begin();
259   ASSERT_EQ(std::distance(Iter, Range.end()), 2);
260   EXPECT_EQ(Iter->Address, 0u);
261   EXPECT_EQ(Iter->Length, 0u);
262   ++Iter;
263   EXPECT_EQ(Iter->Address, 1u);
264   EXPECT_EQ(Iter->Length, 1u);
265   EXPECT_THAT_ERROR(
266       Warnings.getWarning(),
267       FailedWithMessage("address range table at offset 0x0 has a premature "
268                         "terminator entry at offset 0x10"));
269 }
270 
271 } // end anonymous namespace
272