1 //===-- SymbolFileDWARFTests.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 "gtest/gtest.h"
10
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
13 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/Path.h"
16
17 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
18 #include "Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h"
19 #include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h"
20 #include "Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h"
21 #include "Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h"
22 #include "Plugins/SymbolFile/DWARF/DWARFDebugAranges.h"
23 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
24 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
25 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
26 #include "TestingSupport/SubsystemRAII.h"
27 #include "TestingSupport/TestUtilities.h"
28 #include "lldb/Core/Address.h"
29 #include "lldb/Core/Module.h"
30 #include "lldb/Core/ModuleSpec.h"
31 #include "lldb/Host/FileSystem.h"
32 #include "lldb/Host/HostInfo.h"
33 #include "lldb/Symbol/CompileUnit.h"
34 #include "lldb/Symbol/LineTable.h"
35 #include "lldb/Utility/ArchSpec.h"
36 #include "lldb/Utility/DataEncoder.h"
37 #include "lldb/Utility/FileSpec.h"
38 #include "lldb/Utility/StreamString.h"
39
40 using namespace lldb;
41 using namespace lldb_private;
42 using namespace lldb_private::dwarf;
43
44 class SymbolFileDWARFTests : public testing::Test {
45 SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF,
46 TypeSystemClang, SymbolFilePDB>
47 subsystems;
48
49 public:
SetUp()50 void SetUp() override {
51 m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
52 }
53
54 protected:
55 std::string m_dwarf_test_exe;
56 };
57
TEST_F(SymbolFileDWARFTests,TestAbilitiesForDWARF)58 TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) {
59 // Test that when we have Dwarf debug info, SymbolFileDWARF is used.
60 FileSpec fspec(m_dwarf_test_exe);
61 ArchSpec aspec("i686-pc-windows");
62 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
63
64 SymbolFile *symfile = module->GetSymbolFile();
65 ASSERT_NE(nullptr, symfile);
66 EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());
67
68 uint32_t expected_abilities = SymbolFile::kAllAbilities;
69 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
70 }
71
TEST_F(SymbolFileDWARFTests,TestAbbrevOrder1Start1)72 TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) {
73 // Test that if we have a .debug_abbrev that contains ordered abbreviation
74 // codes that start at 1, that we get O(1) access.
75
76 const auto byte_order = eByteOrderLittle;
77 const uint8_t addr_size = 4;
78 StreamString encoder(Stream::eBinary, addr_size, byte_order);
79 encoder.PutULEB128(1); // Abbrev code 1
80 encoder.PutULEB128(DW_TAG_compile_unit);
81 encoder.PutHex8(DW_CHILDREN_yes);
82 encoder.PutULEB128(DW_AT_name);
83 encoder.PutULEB128(DW_FORM_strp);
84 encoder.PutULEB128(0);
85 encoder.PutULEB128(0);
86
87 encoder.PutULEB128(2); // Abbrev code 2
88 encoder.PutULEB128(DW_TAG_subprogram);
89 encoder.PutHex8(DW_CHILDREN_no);
90 encoder.PutULEB128(DW_AT_name);
91 encoder.PutULEB128(DW_FORM_strp);
92 encoder.PutULEB128(0);
93 encoder.PutULEB128(0);
94
95 encoder.PutULEB128(0); // Abbrev code 0 (termination)
96
97 DWARFDataExtractor data;
98 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
99 DWARFAbbreviationDeclarationSet abbrev_set;
100 lldb::offset_t data_offset = 0;
101 llvm::Error error = abbrev_set.extract(data, &data_offset);
102 EXPECT_FALSE(bool(error));
103 // Make sure we have O(1) access to each abbreviation by making sure the
104 // index offset is 1 and not UINT32_MAX
105 EXPECT_EQ(abbrev_set.GetIndexOffset(), 1u);
106
107 auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(1);
108 EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
109 EXPECT_TRUE(abbrev1->HasChildren());
110 EXPECT_EQ(abbrev1->NumAttributes(), 1u);
111 auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(2);
112 EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram);
113 EXPECT_FALSE(abbrev2->HasChildren());
114 EXPECT_EQ(abbrev2->NumAttributes(), 1u);
115 }
116
TEST_F(SymbolFileDWARFTests,TestAbbrevOrder1Start5)117 TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) {
118 // Test that if we have a .debug_abbrev that contains ordered abbreviation
119 // codes that start at 5, that we get O(1) access.
120
121 const auto byte_order = eByteOrderLittle;
122 const uint8_t addr_size = 4;
123 StreamString encoder(Stream::eBinary, addr_size, byte_order);
124 encoder.PutULEB128(5); // Abbrev code 5
125 encoder.PutULEB128(DW_TAG_compile_unit);
126 encoder.PutHex8(DW_CHILDREN_yes);
127 encoder.PutULEB128(DW_AT_name);
128 encoder.PutULEB128(DW_FORM_strp);
129 encoder.PutULEB128(0);
130 encoder.PutULEB128(0);
131
132 encoder.PutULEB128(6); // Abbrev code 6
133 encoder.PutULEB128(DW_TAG_subprogram);
134 encoder.PutHex8(DW_CHILDREN_no);
135 encoder.PutULEB128(DW_AT_name);
136 encoder.PutULEB128(DW_FORM_strp);
137 encoder.PutULEB128(0);
138 encoder.PutULEB128(0);
139
140 encoder.PutULEB128(0); // Abbrev code 0 (termination)
141
142 DWARFDataExtractor data;
143 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
144 DWARFAbbreviationDeclarationSet abbrev_set;
145 lldb::offset_t data_offset = 0;
146 llvm::Error error = abbrev_set.extract(data, &data_offset);
147 EXPECT_FALSE(bool(error));
148 // Make sure we have O(1) access to each abbreviation by making sure the
149 // index offset is 5 and not UINT32_MAX
150 EXPECT_EQ(abbrev_set.GetIndexOffset(), 5u);
151
152 auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(5);
153 EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
154 EXPECT_TRUE(abbrev1->HasChildren());
155 EXPECT_EQ(abbrev1->NumAttributes(), 1u);
156 auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(6);
157 EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram);
158 EXPECT_FALSE(abbrev2->HasChildren());
159 EXPECT_EQ(abbrev2->NumAttributes(), 1u);
160 }
161
TEST_F(SymbolFileDWARFTests,TestAbbrevOutOfOrder)162 TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) {
163 // Test that if we have a .debug_abbrev that contains unordered abbreviation
164 // codes, that we can access the information correctly.
165
166 const auto byte_order = eByteOrderLittle;
167 const uint8_t addr_size = 4;
168 StreamString encoder(Stream::eBinary, addr_size, byte_order);
169 encoder.PutULEB128(2); // Abbrev code 2
170 encoder.PutULEB128(DW_TAG_compile_unit);
171 encoder.PutHex8(DW_CHILDREN_yes);
172 encoder.PutULEB128(DW_AT_name);
173 encoder.PutULEB128(DW_FORM_strp);
174 encoder.PutULEB128(0);
175 encoder.PutULEB128(0);
176
177 encoder.PutULEB128(1); // Abbrev code 1
178 encoder.PutULEB128(DW_TAG_subprogram);
179 encoder.PutHex8(DW_CHILDREN_no);
180 encoder.PutULEB128(DW_AT_name);
181 encoder.PutULEB128(DW_FORM_strp);
182 encoder.PutULEB128(0);
183 encoder.PutULEB128(0);
184
185 encoder.PutULEB128(0); // Abbrev code 0 (termination)
186
187 DWARFDataExtractor data;
188 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
189 DWARFAbbreviationDeclarationSet abbrev_set;
190 lldb::offset_t data_offset = 0;
191 llvm::Error error = abbrev_set.extract(data, &data_offset);
192 EXPECT_FALSE(bool(error));
193 // Make sure we don't have O(1) access to each abbreviation by making sure
194 // the index offset is UINT32_MAX
195 EXPECT_EQ(abbrev_set.GetIndexOffset(), UINT32_MAX);
196
197 auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(2);
198 EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
199 EXPECT_TRUE(abbrev1->HasChildren());
200 EXPECT_EQ(abbrev1->NumAttributes(), 1u);
201 auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(1);
202 EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram);
203 EXPECT_FALSE(abbrev2->HasChildren());
204 EXPECT_EQ(abbrev2->NumAttributes(), 1u);
205 }
206
TEST_F(SymbolFileDWARFTests,TestAbbrevInvalidNULLTag)207 TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) {
208 // Test that we detect when an abbreviation has a NULL tag and that we get
209 // an error when decoding.
210
211 const auto byte_order = eByteOrderLittle;
212 const uint8_t addr_size = 4;
213 StreamString encoder(Stream::eBinary, addr_size, byte_order);
214 encoder.PutULEB128(1); // Abbrev code 1
215 encoder.PutULEB128(0); // Invalid NULL tag here!
216 encoder.PutHex8(DW_CHILDREN_no);
217 encoder.PutULEB128(0);
218 encoder.PutULEB128(0);
219
220 encoder.PutULEB128(0); // Abbrev code 0 (termination)
221
222 DWARFDataExtractor data;
223 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
224 DWARFAbbreviationDeclarationSet abbrev_set;
225 lldb::offset_t data_offset = 0;
226 llvm::Error error = abbrev_set.extract(data, &data_offset);
227 // Verify we get an error
228 EXPECT_TRUE(bool(error));
229 EXPECT_EQ("abbrev decl requires non-null tag.",
230 llvm::toString(std::move(error)));
231
232 }
233
TEST_F(SymbolFileDWARFTests,TestAbbrevNullAttrValidForm)234 TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) {
235 // Test that we detect when an abbreviation has a NULL attribute and a non
236 // NULL form and that we get an error when decoding.
237
238 const auto byte_order = eByteOrderLittle;
239 const uint8_t addr_size = 4;
240 StreamString encoder(Stream::eBinary, addr_size, byte_order);
241 encoder.PutULEB128(1); // Abbrev code 1
242 encoder.PutULEB128(DW_TAG_compile_unit);
243 encoder.PutHex8(DW_CHILDREN_no);
244 encoder.PutULEB128(0); // Invalid NULL DW_AT
245 encoder.PutULEB128(DW_FORM_strp); // With a valid form
246 encoder.PutULEB128(0);
247 encoder.PutULEB128(0);
248
249 encoder.PutULEB128(0); // Abbrev code 0 (termination)
250
251 DWARFDataExtractor data;
252 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
253 DWARFAbbreviationDeclarationSet abbrev_set;
254 lldb::offset_t data_offset = 0;
255 llvm::Error error = abbrev_set.extract(data, &data_offset);
256 // Verify we get an error
257 EXPECT_TRUE(bool(error));
258 EXPECT_EQ("malformed abbreviation declaration attribute",
259 llvm::toString(std::move(error)));
260 }
261
TEST_F(SymbolFileDWARFTests,TestAbbrevValidAttrNullForm)262 TEST_F(SymbolFileDWARFTests, TestAbbrevValidAttrNullForm) {
263 // Test that we detect when an abbreviation has a valid attribute and a
264 // NULL form and that we get an error when decoding.
265
266 const auto byte_order = eByteOrderLittle;
267 const uint8_t addr_size = 4;
268 StreamString encoder(Stream::eBinary, addr_size, byte_order);
269 encoder.PutULEB128(1); // Abbrev code 1
270 encoder.PutULEB128(DW_TAG_compile_unit);
271 encoder.PutHex8(DW_CHILDREN_no);
272 encoder.PutULEB128(DW_AT_name); // Valid attribute
273 encoder.PutULEB128(0); // NULL form
274 encoder.PutULEB128(0);
275 encoder.PutULEB128(0);
276
277 encoder.PutULEB128(0); // Abbrev code 0 (termination)
278
279 DWARFDataExtractor data;
280 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
281 DWARFAbbreviationDeclarationSet abbrev_set;
282 lldb::offset_t data_offset = 0;
283 llvm::Error error = abbrev_set.extract(data, &data_offset);
284 // Verify we get an error
285 EXPECT_TRUE(bool(error));
286 EXPECT_EQ("malformed abbreviation declaration attribute",
287 llvm::toString(std::move(error)));
288 }
289
TEST_F(SymbolFileDWARFTests,TestAbbrevMissingTerminator)290 TEST_F(SymbolFileDWARFTests, TestAbbrevMissingTerminator) {
291 // Test that we detect when an abbreviation has a valid attribute and a
292 // form, but is missing the NULL attribute and form that terminates an
293 // abbreviation
294
295 const auto byte_order = eByteOrderLittle;
296 const uint8_t addr_size = 4;
297 StreamString encoder(Stream::eBinary, addr_size, byte_order);
298 encoder.PutULEB128(1); // Abbrev code 1
299 encoder.PutULEB128(DW_TAG_compile_unit);
300 encoder.PutHex8(DW_CHILDREN_no);
301 encoder.PutULEB128(DW_AT_name);
302 encoder.PutULEB128(DW_FORM_strp);
303 // Don't add the NULL DW_AT and NULL DW_FORM terminator
304
305 DWARFDataExtractor data;
306 data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
307 DWARFAbbreviationDeclarationSet abbrev_set;
308 lldb::offset_t data_offset = 0;
309 llvm::Error error = abbrev_set.extract(data, &data_offset);
310 // Verify we get an error
311 EXPECT_TRUE(bool(error));
312 EXPECT_EQ("abbreviation declaration attribute list not terminated with a "
313 "null entry", llvm::toString(std::move(error)));
314 }
315
TEST_F(SymbolFileDWARFTests,ParseArangesNonzeroSegmentSize)316 TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) {
317 // This `.debug_aranges` table header is a valid 32bit big-endian section
318 // according to the DWARFv5 spec:6.2.1, but contains segment selectors which
319 // are not supported by lldb, and should be gracefully rejected
320 const unsigned char binary_data[] = {
321 0, 0, 0, 41, // unit_length (length field not including this field itself)
322 0, 2, // DWARF version number (half)
323 0, 0, 0, 0, // offset into the .debug_info_table (ignored for the purposes
324 // of this test
325 4, // address size
326 1, // segment size
327 // alignment for the first tuple which "begins at an offset that is a
328 // multiple of the size of a single tuple". Tuples are nine bytes in this
329 // example.
330 0, 0, 0, 0, 0, 0,
331 // BEGIN TUPLES
332 1, 0, 0, 0, 4, 0, 0, 0,
333 1, // a 1byte object starting at address 4 in segment 1
334 0, 0, 0, 0, 4, 0, 0, 0,
335 1, // a 1byte object starting at address 4 in segment 0
336 // END TUPLES
337 0, 0, 0, 0, 0, 0, 0, 0, 0 // terminator
338 };
339 DWARFDataExtractor data;
340 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
341 lldb::ByteOrder::eByteOrderBig);
342 DWARFDebugArangeSet debug_aranges;
343 offset_t off = 0;
344 llvm::Error error = debug_aranges.extract(data, &off);
345 EXPECT_TRUE(bool(error));
346 EXPECT_EQ("segmented arange entries are not supported",
347 llvm::toString(std::move(error)));
348 EXPECT_EQ(off, 12U); // Parser should read no further than the segment size
349 }
350
TEST_F(SymbolFileDWARFTests,ParseArangesWithMultipleTerminators)351 TEST_F(SymbolFileDWARFTests, ParseArangesWithMultipleTerminators) {
352 // This .debug_aranges set has multiple terminator entries which appear in
353 // binaries produced by popular linux compilers and linker combinations. We
354 // must be able to parse all the way through the data for each
355 // DWARFDebugArangeSet. Previously the DWARFDebugArangeSet::extract()
356 // function would stop parsing as soon as we ran into a terminator even
357 // though the length field stated that there was more data that follows. This
358 // would cause the next DWARFDebugArangeSet to be parsed immediately
359 // following the first terminator and it would attempt to decode the
360 // DWARFDebugArangeSet header using the remaining segment + address pairs
361 // from the remaining bytes.
362 unsigned char binary_data[] = {
363 0, 0, 0, 0, // unit_length that will be set correctly after this
364 0, 2, // DWARF version number (uint16_t)
365 0, 0, 0, 0, // CU offset (ignored for the purposes of this test)
366 4, // address size
367 0, // segment size
368 0, 0, 0, 0, // alignment for the first tuple
369 // BEGIN TUPLES
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator
371 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator
373 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010)
374 // END TUPLES
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
376 };
377 // Set the big endian length correctly.
378 const offset_t binary_data_size = sizeof(binary_data);
379 binary_data[3] = (uint8_t)binary_data_size - 4;
380 DWARFDataExtractor data;
381 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
382 lldb::ByteOrder::eByteOrderBig);
383 DWARFDebugArangeSet set;
384 offset_t off = 0;
385 llvm::Error error = set.extract(data, &off);
386 // Multiple terminators are not fatal as they do appear in binaries.
387 EXPECT_FALSE(bool(error));
388 // Parser should read all terminators to the end of the length specified.
389 EXPECT_EQ(off, binary_data_size);
390 ASSERT_EQ(set.NumDescriptors(), 2U);
391 ASSERT_EQ(set.GetDescriptorRef(0).address, (dw_addr_t)0x1000);
392 ASSERT_EQ(set.GetDescriptorRef(0).length, (dw_addr_t)0x100);
393 ASSERT_EQ(set.GetDescriptorRef(1).address, (dw_addr_t)0x2000);
394 ASSERT_EQ(set.GetDescriptorRef(1).length, (dw_addr_t)0x10);
395 }
396
TEST_F(SymbolFileDWARFTests,ParseArangesIgnoreEmpty)397 TEST_F(SymbolFileDWARFTests, ParseArangesIgnoreEmpty) {
398 // This .debug_aranges set has some address ranges which have zero length
399 // and we ensure that these are ignored by our DWARFDebugArangeSet parser
400 // and not included in the descriptors that are returned.
401 unsigned char binary_data[] = {
402 0, 0, 0, 0, // unit_length that will be set correctly after this
403 0, 2, // DWARF version number (uint16_t)
404 0, 0, 0, 0, // CU offset (ignored for the purposes of this test)
405 4, // address size
406 0, // segment size
407 0, 0, 0, 0, // alignment for the first tuple
408 // BEGIN TUPLES
409 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)
410 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x1100-0x1100)
411 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010)
412 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // [0x2010-0x2010)
413 // END TUPLES
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
415 };
416 // Set the big endian length correctly.
417 const offset_t binary_data_size = sizeof(binary_data);
418 binary_data[3] = (uint8_t)binary_data_size - 4;
419 DWARFDataExtractor data;
420 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
421 lldb::ByteOrder::eByteOrderBig);
422 DWARFDebugArangeSet set;
423 offset_t off = 0;
424 llvm::Error error = set.extract(data, &off);
425 // Multiple terminators are not fatal as they do appear in binaries.
426 EXPECT_FALSE(bool(error));
427 // Parser should read all terminators to the end of the length specified.
428 // Previously the DWARFDebugArangeSet would stop at the first terminator
429 // entry and leave the offset in the middle of the current
430 // DWARFDebugArangeSet data, and that would cause the next extracted
431 // DWARFDebugArangeSet to fail.
432 EXPECT_EQ(off, binary_data_size);
433 ASSERT_EQ(set.NumDescriptors(), 2U);
434 ASSERT_EQ(set.GetDescriptorRef(0).address, (dw_addr_t)0x1000);
435 ASSERT_EQ(set.GetDescriptorRef(0).length, (dw_addr_t)0x100);
436 ASSERT_EQ(set.GetDescriptorRef(1).address, (dw_addr_t)0x2000);
437 ASSERT_EQ(set.GetDescriptorRef(1).length, (dw_addr_t)0x10);
438 }
439
TEST_F(SymbolFileDWARFTests,ParseAranges)440 TEST_F(SymbolFileDWARFTests, ParseAranges) {
441 // Test we can successfully parse a DWARFDebugAranges. The initial error
442 // checking code had a bug where it would always return an empty address
443 // ranges for everything in .debug_aranges and no error.
444 unsigned char binary_data[] = {
445 0, 0, 0, 0, // unit_length that will be set correctly after this
446 2, 0, // DWARF version number
447 255, 0, 0, 0, // offset into the .debug_info_table
448 8, // address size
449 0, // segment size
450 0, 0, 0, 0, // pad bytes
451 // BEGIN TUPLES
452 // First tuple: [0x1000-0x1100)
453 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x1000
454 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100
455 // Second tuple: [0x2000-0x2100)
456 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x2000
457 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100
458 // Terminating tuple
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator
460 };
461 // Set the little endian length correctly.
462 binary_data[0] = sizeof(binary_data) - 4;
463 DWARFDataExtractor data;
464 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
465 lldb::ByteOrder::eByteOrderLittle);
466 DWARFDebugAranges debug_aranges;
467 debug_aranges.extract(data);
468 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);
469 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);
470 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u);
471 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u);
472 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);
473 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);
474 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u);
475 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 255u);
476 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);
477 }
478
TEST_F(SymbolFileDWARFTests,ParseArangesSkipErrors)479 TEST_F(SymbolFileDWARFTests, ParseArangesSkipErrors) {
480 // Test we can successfully parse a DWARFDebugAranges that contains some
481 // valid DWARFDebugArangeSet objects and some with errors as long as their
482 // length is set correctly. This helps LLDB ensure that it can parse newer
483 // .debug_aranges version that LLDB currently doesn't support, or ignore
484 // errors in individual DWARFDebugArangeSet objects as long as the length
485 // is set correctly.
486 const unsigned char binary_data[] = {
487 // This DWARFDebugArangeSet is well formed and has a single address range
488 // for [0x1000-0x1100) with a CU offset of 0x00000000.
489 0, 0, 0, 28, // unit_length that will be set correctly after this
490 0, 2, // DWARF version number (uint16_t)
491 0, 0, 0, 0, // CU offset = 0x00000000
492 4, // address size
493 0, // segment size
494 0, 0, 0, 0, // alignment for the first tuple
495 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
497 // This DWARFDebugArangeSet has the correct length, but an invalid
498 // version. We need to be able to skip this correctly and ignore it.
499 0, 0, 0, 20, // unit_length that will be set correctly after this
500 0, 44, // invalid DWARF version number (uint16_t)
501 0, 0, 1, 0, // CU offset = 0x00000100
502 4, // address size
503 0, // segment size
504 0, 0, 0, 0, // alignment for the first tuple
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
506 // This DWARFDebugArangeSet is well formed and has a single address range
507 // for [0x2000-0x2100) with a CU offset of 0x00000000.
508 0, 0, 0, 28, // unit_length that will be set correctly after this
509 0, 2, // DWARF version number (uint16_t)
510 0, 0, 2, 0, // CU offset = 0x00000200
511 4, // address size
512 0, // segment size
513 0, 0, 0, 0, // alignment for the first tuple
514 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x2000-0x2100)
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
516 };
517
518 DWARFDataExtractor data;
519 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
520 lldb::ByteOrder::eByteOrderBig);
521 DWARFDebugAranges debug_aranges;
522 debug_aranges.extract(data);
523 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);
524 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);
525 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 0u);
526 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 0u);
527 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);
528 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);
529 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 0x200u);
530 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 0x200u);
531 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);
532 }
533