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