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