[libc][NFC] Move aligned access implementations to separate header
[llvm-project.git] / lldb / unittests / SymbolFile / DWARF / SymbolFileDWARFTests.cpp
blob9cbdeffc59a7f815a126897efb666360e67b0a66
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 //===----------------------------------------------------------------------===//
9 #include "gtest/gtest.h"
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"
17 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
18 #include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h"
19 #include "Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h"
20 #include "Plugins/SymbolFile/DWARF/DWARFDebugAranges.h"
21 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
22 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
23 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
24 #include "TestingSupport/SubsystemRAII.h"
25 #include "TestingSupport/TestUtilities.h"
26 #include "lldb/Core/Address.h"
27 #include "lldb/Core/Module.h"
28 #include "lldb/Core/ModuleSpec.h"
29 #include "lldb/Host/FileSystem.h"
30 #include "lldb/Host/HostInfo.h"
31 #include "lldb/Symbol/CompileUnit.h"
32 #include "lldb/Symbol/LineTable.h"
33 #include "lldb/Utility/ArchSpec.h"
34 #include "lldb/Utility/DataEncoder.h"
35 #include "lldb/Utility/FileSpec.h"
36 #include "lldb/Utility/StreamString.h"
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::dwarf;
42 class SymbolFileDWARFTests : public testing::Test {
43 SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF,
44 TypeSystemClang, SymbolFilePDB>
45 subsystems;
47 public:
48 void SetUp() override {
49 m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
52 protected:
53 std::string m_dwarf_test_exe;
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);
62 SymbolFile *symfile = module->GetSymbolFile();
63 ASSERT_NE(nullptr, symfile);
64 EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());
66 uint32_t expected_abilities = SymbolFile::kAllAbilities;
67 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
70 TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) {
71 // This `.debug_aranges` table header is a valid 32bit big-endian section
72 // according to the DWARFv5 spec:6.2.1, but contains segment selectors which
73 // are not supported by lldb, and should be gracefully rejected
74 const unsigned char binary_data[] = {
75 0, 0, 0, 41, // unit_length (length field not including this field itself)
76 0, 2, // DWARF version number (half)
77 0, 0, 0, 0, // offset into the .debug_info_table (ignored for the purposes
78 // of this test
79 4, // address size
80 1, // segment size
81 // alignment for the first tuple which "begins at an offset that is a
82 // multiple of the size of a single tuple". Tuples are nine bytes in this
83 // example.
84 0, 0, 0, 0, 0, 0,
85 // BEGIN TUPLES
86 1, 0, 0, 0, 4, 0, 0, 0,
87 1, // a 1byte object starting at address 4 in segment 1
88 0, 0, 0, 0, 4, 0, 0, 0,
89 1, // a 1byte object starting at address 4 in segment 0
90 // END TUPLES
91 0, 0, 0, 0, 0, 0, 0, 0, 0 // terminator
93 DWARFDataExtractor data;
94 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
95 lldb::ByteOrder::eByteOrderBig);
96 DWARFDebugArangeSet debug_aranges;
97 offset_t off = 0;
98 llvm::Error error = debug_aranges.extract(data, &off);
99 EXPECT_TRUE(bool(error));
100 EXPECT_EQ("segmented arange entries are not supported",
101 llvm::toString(std::move(error)));
102 EXPECT_EQ(off, 12U); // Parser should read no further than the segment size
105 TEST_F(SymbolFileDWARFTests, ParseArangesWithMultipleTerminators) {
106 // This .debug_aranges set has multiple terminator entries which appear in
107 // binaries produced by popular linux compilers and linker combinations. We
108 // must be able to parse all the way through the data for each
109 // DWARFDebugArangeSet. Previously the DWARFDebugArangeSet::extract()
110 // function would stop parsing as soon as we ran into a terminator even
111 // though the length field stated that there was more data that follows. This
112 // would cause the next DWARFDebugArangeSet to be parsed immediately
113 // following the first terminator and it would attempt to decode the
114 // DWARFDebugArangeSet header using the remaining segment + address pairs
115 // from the remaining bytes.
116 unsigned char binary_data[] = {
117 0, 0, 0, 0, // unit_length that will be set correctly after this
118 0, 2, // DWARF version number (uint16_t)
119 0, 0, 0, 0, // CU offset (ignored for the purposes of this test)
120 4, // address size
121 0, // segment size
122 0, 0, 0, 0, // alignment for the first tuple
123 // BEGIN TUPLES
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator
125 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator
127 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010)
128 // END TUPLES
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
131 // Set the big endian length correctly.
132 const offset_t binary_data_size = sizeof(binary_data);
133 binary_data[3] = (uint8_t)binary_data_size - 4;
134 DWARFDataExtractor data;
135 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
136 lldb::ByteOrder::eByteOrderBig);
137 DWARFDebugArangeSet set;
138 offset_t off = 0;
139 llvm::Error error = set.extract(data, &off);
140 // Multiple terminators are not fatal as they do appear in binaries.
141 EXPECT_FALSE(bool(error));
142 // Parser should read all terminators to the end of the length specified.
143 EXPECT_EQ(off, binary_data_size);
144 ASSERT_EQ(set.NumDescriptors(), 2U);
145 ASSERT_EQ(set.GetDescriptorRef(0).address, (dw_addr_t)0x1000);
146 ASSERT_EQ(set.GetDescriptorRef(0).length, (dw_addr_t)0x100);
147 ASSERT_EQ(set.GetDescriptorRef(1).address, (dw_addr_t)0x2000);
148 ASSERT_EQ(set.GetDescriptorRef(1).length, (dw_addr_t)0x10);
151 TEST_F(SymbolFileDWARFTests, ParseArangesIgnoreEmpty) {
152 // This .debug_aranges set has some address ranges which have zero length
153 // and we ensure that these are ignored by our DWARFDebugArangeSet parser
154 // and not included in the descriptors that are returned.
155 unsigned char binary_data[] = {
156 0, 0, 0, 0, // unit_length that will be set correctly after this
157 0, 2, // DWARF version number (uint16_t)
158 0, 0, 0, 0, // CU offset (ignored for the purposes of this test)
159 4, // address size
160 0, // segment size
161 0, 0, 0, 0, // alignment for the first tuple
162 // BEGIN TUPLES
163 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)
164 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x1100-0x1100)
165 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010)
166 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // [0x2010-0x2010)
167 // END TUPLES
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
170 // Set the big endian length correctly.
171 const offset_t binary_data_size = sizeof(binary_data);
172 binary_data[3] = (uint8_t)binary_data_size - 4;
173 DWARFDataExtractor data;
174 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
175 lldb::ByteOrder::eByteOrderBig);
176 DWARFDebugArangeSet set;
177 offset_t off = 0;
178 llvm::Error error = set.extract(data, &off);
179 // Multiple terminators are not fatal as they do appear in binaries.
180 EXPECT_FALSE(bool(error));
181 // Parser should read all terminators to the end of the length specified.
182 // Previously the DWARFDebugArangeSet would stop at the first terminator
183 // entry and leave the offset in the middle of the current
184 // DWARFDebugArangeSet data, and that would cause the next extracted
185 // DWARFDebugArangeSet to fail.
186 EXPECT_EQ(off, binary_data_size);
187 ASSERT_EQ(set.NumDescriptors(), 2U);
188 ASSERT_EQ(set.GetDescriptorRef(0).address, (dw_addr_t)0x1000);
189 ASSERT_EQ(set.GetDescriptorRef(0).length, (dw_addr_t)0x100);
190 ASSERT_EQ(set.GetDescriptorRef(1).address, (dw_addr_t)0x2000);
191 ASSERT_EQ(set.GetDescriptorRef(1).length, (dw_addr_t)0x10);
194 TEST_F(SymbolFileDWARFTests, ParseAranges) {
195 // Test we can successfully parse a DWARFDebugAranges. The initial error
196 // checking code had a bug where it would always return an empty address
197 // ranges for everything in .debug_aranges and no error.
198 unsigned char binary_data[] = {
199 0, 0, 0, 0, // unit_length that will be set correctly after this
200 2, 0, // DWARF version number
201 255, 0, 0, 0, // offset into the .debug_info_table
202 8, // address size
203 0, // segment size
204 0, 0, 0, 0, // pad bytes
205 // BEGIN TUPLES
206 // First tuple: [0x1000-0x1100)
207 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x1000
208 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100
209 // Second tuple: [0x2000-0x2100)
210 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x2000
211 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100
212 // Terminating tuple
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator
215 // Set the little endian length correctly.
216 binary_data[0] = sizeof(binary_data) - 4;
217 DWARFDataExtractor data;
218 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
219 lldb::ByteOrder::eByteOrderLittle);
220 DWARFDebugAranges debug_aranges;
221 debug_aranges.extract(data);
222 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);
223 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);
224 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u);
225 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u);
226 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);
227 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);
228 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u);
229 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 255u);
230 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);
233 TEST_F(SymbolFileDWARFTests, ParseArangesSkipErrors) {
234 // Test we can successfully parse a DWARFDebugAranges that contains some
235 // valid DWARFDebugArangeSet objects and some with errors as long as their
236 // length is set correctly. This helps LLDB ensure that it can parse newer
237 // .debug_aranges version that LLDB currently doesn't support, or ignore
238 // errors in individual DWARFDebugArangeSet objects as long as the length
239 // is set correctly.
240 const unsigned char binary_data[] = {
241 // This DWARFDebugArangeSet is well formed and has a single address range
242 // for [0x1000-0x1100) with a CU offset of 0x00000000.
243 0, 0, 0, 28, // unit_length that will be set correctly after this
244 0, 2, // DWARF version number (uint16_t)
245 0, 0, 0, 0, // CU offset = 0x00000000
246 4, // address size
247 0, // segment size
248 0, 0, 0, 0, // alignment for the first tuple
249 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
251 // This DWARFDebugArangeSet has the correct length, but an invalid
252 // version. We need to be able to skip this correctly and ignore it.
253 0, 0, 0, 20, // unit_length that will be set correctly after this
254 0, 44, // invalid DWARF version number (uint16_t)
255 0, 0, 1, 0, // CU offset = 0x00000100
256 4, // address size
257 0, // segment size
258 0, 0, 0, 0, // alignment for the first tuple
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
260 // This DWARFDebugArangeSet is well formed and has a single address range
261 // for [0x2000-0x2100) with a CU offset of 0x00000000.
262 0, 0, 0, 28, // unit_length that will be set correctly after this
263 0, 2, // DWARF version number (uint16_t)
264 0, 0, 2, 0, // CU offset = 0x00000200
265 4, // address size
266 0, // segment size
267 0, 0, 0, 0, // alignment for the first tuple
268 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x2000-0x2100)
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator
272 DWARFDataExtractor data;
273 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
274 lldb::ByteOrder::eByteOrderBig);
275 DWARFDebugAranges debug_aranges;
276 debug_aranges.extract(data);
277 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);
278 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);
279 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 0u);
280 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 0u);
281 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);
282 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);
283 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 0x200u);
284 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 0x200u);
285 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);