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/SymbolFileDWARF.h"
23 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
24 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
25 #include "TestingSupport/SubsystemRAII.h"
26 #include "TestingSupport/TestUtilities.h"
27 #include "lldb/Core/Address.h"
28 #include "lldb/Core/Module.h"
29 #include "lldb/Core/ModuleSpec.h"
30 #include "lldb/Host/FileSystem.h"
31 #include "lldb/Host/HostInfo.h"
32 #include "lldb/Symbol/CompileUnit.h"
33 #include "lldb/Symbol/LineTable.h"
34 #include "lldb/Utility/ArchSpec.h"
35 #include "lldb/Utility/DataEncoder.h"
36 #include "lldb/Utility/FileSpec.h"
37 #include "lldb/Utility/StreamString.h"
38 
39 using namespace lldb;
40 using namespace lldb_private;
41 
42 class SymbolFileDWARFTests : public testing::Test {
43   SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF,
44                 TypeSystemClang, SymbolFilePDB>
45       subsystems;
46 
47 public:
48   void SetUp() override {
49     m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
50   }
51 
52 protected:
53   std::string m_dwarf_test_exe;
54 };
55 
56 TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) {
57   // Test that when we have Dwarf debug info, SymbolFileDWARF is used.
58   FileSpec fspec(m_dwarf_test_exe);
59   ArchSpec aspec("i686-pc-windows");
60   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
61 
62   SymbolFile *symfile = module->GetSymbolFile();
63   ASSERT_NE(nullptr, symfile);
64   EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());
65 
66   uint32_t expected_abilities = SymbolFile::kAllAbilities;
67   EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
68 }
69 
70 TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) {
71   // Test that if we have a .debug_abbrev that contains ordered abbreviation
72   // codes that start at 1, that we get O(1) access.
73 
74   const auto byte_order = eByteOrderLittle;
75   const uint8_t addr_size = 4;
76   StreamString encoder(Stream::eBinary, addr_size, byte_order);
77   encoder.PutULEB128(1); // Abbrev code 1
78   encoder.PutULEB128(DW_TAG_compile_unit);
79   encoder.PutHex8(DW_CHILDREN_yes);
80   encoder.PutULEB128(DW_AT_name);
81   encoder.PutULEB128(DW_FORM_strp);
82   encoder.PutULEB128(0);
83   encoder.PutULEB128(0);
84 
85   encoder.PutULEB128(2); // Abbrev code 2
86   encoder.PutULEB128(DW_TAG_subprogram);
87   encoder.PutHex8(DW_CHILDREN_no);
88   encoder.PutULEB128(DW_AT_name);
89   encoder.PutULEB128(DW_FORM_strp);
90   encoder.PutULEB128(0);
91   encoder.PutULEB128(0);
92 
93   encoder.PutULEB128(0); // Abbrev code 0 (termination)
94 
95   DWARFDataExtractor data;
96   data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
97   DWARFAbbreviationDeclarationSet abbrev_set;
98   lldb::offset_t data_offset = 0;
99   llvm::Error error = abbrev_set.extract(data, &data_offset);
100   EXPECT_FALSE(bool(error));
101   // Make sure we have O(1) access to each abbreviation by making sure the
102   // index offset is 1 and not UINT32_MAX
103   EXPECT_EQ(abbrev_set.GetIndexOffset(), 1u);
104 
105   auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(1);
106   EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
107   EXPECT_TRUE(abbrev1->HasChildren());
108   EXPECT_EQ(abbrev1->NumAttributes(), 1u);
109   auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(2);
110   EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram);
111   EXPECT_FALSE(abbrev2->HasChildren());
112   EXPECT_EQ(abbrev2->NumAttributes(), 1u);
113 }
114 
115 TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) {
116   // Test that if we have a .debug_abbrev that contains ordered abbreviation
117   // codes that start at 5, that we get O(1) access.
118 
119   const auto byte_order = eByteOrderLittle;
120   const uint8_t addr_size = 4;
121   StreamString encoder(Stream::eBinary, addr_size, byte_order);
122   encoder.PutULEB128(5); // Abbrev code 5
123   encoder.PutULEB128(DW_TAG_compile_unit);
124   encoder.PutHex8(DW_CHILDREN_yes);
125   encoder.PutULEB128(DW_AT_name);
126   encoder.PutULEB128(DW_FORM_strp);
127   encoder.PutULEB128(0);
128   encoder.PutULEB128(0);
129 
130   encoder.PutULEB128(6); // Abbrev code 6
131   encoder.PutULEB128(DW_TAG_subprogram);
132   encoder.PutHex8(DW_CHILDREN_no);
133   encoder.PutULEB128(DW_AT_name);
134   encoder.PutULEB128(DW_FORM_strp);
135   encoder.PutULEB128(0);
136   encoder.PutULEB128(0);
137 
138   encoder.PutULEB128(0); // Abbrev code 0 (termination)
139 
140   DWARFDataExtractor data;
141   data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
142   DWARFAbbreviationDeclarationSet abbrev_set;
143   lldb::offset_t data_offset = 0;
144   llvm::Error error = abbrev_set.extract(data, &data_offset);
145   EXPECT_FALSE(bool(error));
146   // Make sure we have O(1) access to each abbreviation by making sure the
147   // index offset is 5 and not UINT32_MAX
148   EXPECT_EQ(abbrev_set.GetIndexOffset(), 5u);
149 
150   auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(5);
151   EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
152   EXPECT_TRUE(abbrev1->HasChildren());
153   EXPECT_EQ(abbrev1->NumAttributes(), 1u);
154   auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(6);
155   EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram);
156   EXPECT_FALSE(abbrev2->HasChildren());
157   EXPECT_EQ(abbrev2->NumAttributes(), 1u);
158 }
159 
160 TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) {
161   // Test that if we have a .debug_abbrev that contains unordered abbreviation
162   // codes, that we can access the information correctly.
163 
164   const auto byte_order = eByteOrderLittle;
165   const uint8_t addr_size = 4;
166   StreamString encoder(Stream::eBinary, addr_size, byte_order);
167   encoder.PutULEB128(2); // Abbrev code 2
168   encoder.PutULEB128(DW_TAG_compile_unit);
169   encoder.PutHex8(DW_CHILDREN_yes);
170   encoder.PutULEB128(DW_AT_name);
171   encoder.PutULEB128(DW_FORM_strp);
172   encoder.PutULEB128(0);
173   encoder.PutULEB128(0);
174 
175   encoder.PutULEB128(1); // Abbrev code 1
176   encoder.PutULEB128(DW_TAG_subprogram);
177   encoder.PutHex8(DW_CHILDREN_no);
178   encoder.PutULEB128(DW_AT_name);
179   encoder.PutULEB128(DW_FORM_strp);
180   encoder.PutULEB128(0);
181   encoder.PutULEB128(0);
182 
183   encoder.PutULEB128(0); // Abbrev code 0 (termination)
184 
185   DWARFDataExtractor data;
186   data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
187   DWARFAbbreviationDeclarationSet abbrev_set;
188   lldb::offset_t data_offset = 0;
189   llvm::Error error = abbrev_set.extract(data, &data_offset);
190   EXPECT_FALSE(bool(error));
191   // Make sure we don't have O(1) access to each abbreviation by making sure
192   // the index offset is UINT32_MAX
193   EXPECT_EQ(abbrev_set.GetIndexOffset(), UINT32_MAX);
194 
195   auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(2);
196   EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
197   EXPECT_TRUE(abbrev1->HasChildren());
198   EXPECT_EQ(abbrev1->NumAttributes(), 1u);
199   auto abbrev2 = abbrev_set.GetAbbreviationDeclaration(1);
200   EXPECT_EQ(abbrev2->Tag(), DW_TAG_subprogram);
201   EXPECT_FALSE(abbrev2->HasChildren());
202   EXPECT_EQ(abbrev2->NumAttributes(), 1u);
203 }
204 
205 TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) {
206   // Test that we detect when an abbreviation has a NULL tag and that we get
207   // an error when decoding.
208 
209   const auto byte_order = eByteOrderLittle;
210   const uint8_t addr_size = 4;
211   StreamString encoder(Stream::eBinary, addr_size, byte_order);
212   encoder.PutULEB128(1); // Abbrev code 1
213   encoder.PutULEB128(0); // Invalid NULL tag here!
214   encoder.PutHex8(DW_CHILDREN_no);
215   encoder.PutULEB128(0);
216   encoder.PutULEB128(0);
217 
218   encoder.PutULEB128(0); // Abbrev code 0 (termination)
219 
220   DWARFDataExtractor data;
221   data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
222   DWARFAbbreviationDeclarationSet abbrev_set;
223   lldb::offset_t data_offset = 0;
224   llvm::Error error = abbrev_set.extract(data, &data_offset);
225   // Verify we get an error
226   EXPECT_TRUE(bool(error));
227   EXPECT_EQ("abbrev decl requires non-null tag.",
228             llvm::toString(std::move(error)));
229 
230 }
231 
232 TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) {
233   // Test that we detect when an abbreviation has a NULL attribute and a non
234   // NULL form and that we get an error when decoding.
235 
236   const auto byte_order = eByteOrderLittle;
237   const uint8_t addr_size = 4;
238   StreamString encoder(Stream::eBinary, addr_size, byte_order);
239   encoder.PutULEB128(1); // Abbrev code 1
240   encoder.PutULEB128(DW_TAG_compile_unit);
241   encoder.PutHex8(DW_CHILDREN_no);
242   encoder.PutULEB128(0); // Invalid NULL DW_AT
243   encoder.PutULEB128(DW_FORM_strp); // With a valid form
244   encoder.PutULEB128(0);
245   encoder.PutULEB128(0);
246 
247   encoder.PutULEB128(0); // Abbrev code 0 (termination)
248 
249   DWARFDataExtractor data;
250   data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
251   DWARFAbbreviationDeclarationSet abbrev_set;
252   lldb::offset_t data_offset = 0;
253   llvm::Error error = abbrev_set.extract(data, &data_offset);
254   // Verify we get an error
255   EXPECT_TRUE(bool(error));
256   EXPECT_EQ("malformed abbreviation declaration attribute",
257             llvm::toString(std::move(error)));
258 
259 }
260 
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 
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 
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