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: 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 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 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 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 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 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 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 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 350 TEST_F(SymbolFileDWARFTests, ParseAranges) { 351 // Test we can successfully parse a DWARFDebugAranges. The initial error 352 // checking code had a bug where it would always return an empty address 353 // ranges for everything in .debug_aranges and no error. 354 const unsigned char binary_data[] = { 355 60, 0, 0, 0, // unit_length 356 2, 0, // DWARF version number 357 255, 0, 0, 0, // offset into the .debug_info_table 358 8, // address size 359 0, // segment size 360 0, 0, 0, 0, // pad bytes 361 // BEGIN TUPLES 362 // First tuple: [0x1000-0x1100) 363 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x1000 364 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100 365 // Second tuple: [0x2000-0x2100) 366 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x2000 367 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100 368 // Terminating tuple 369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator 370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Terminator 371 }; 372 DWARFDataExtractor data; 373 data.SetData(static_cast<const void *>(binary_data), sizeof binary_data, 374 lldb::ByteOrder::eByteOrderLittle); 375 DWARFDebugAranges debug_aranges; 376 llvm::Error error = debug_aranges.extract(data); 377 ASSERT_FALSE(bool(error)); 378 EXPECT_EQ(debug_aranges.GetNumRanges(), 2u); 379 EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET); 380 EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u); 381 EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u); 382 EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET); 383 EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET); 384 EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u); 385 EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 255u); 386 EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET); 387 } 388