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, 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 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 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 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