1 //===-- DWARFDIETest.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 "Plugins/SymbolFile/DWARF/DWARFDIE.h" 10 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" 12 #include "TestingSupport/Symbol/YAMLModuleTester.h" 13 #include "lldb/Core/dwarf.h" 14 #include "lldb/Symbol/Type.h" 15 #include "lldb/lldb-private-enumerations.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "gmock/gmock.h" 18 #include "gtest/gtest.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 using namespace lldb_private::plugin::dwarf; 23 using namespace lldb_private::dwarf; 24 25 TEST(DWARFDIETest, ChildIteration) { 26 // Tests DWARFDIE::child_iterator. 27 28 const char *yamldata = R"( 29 --- !ELF 30 FileHeader: 31 Class: ELFCLASS64 32 Data: ELFDATA2LSB 33 Type: ET_EXEC 34 Machine: EM_386 35 DWARF: 36 debug_abbrev: 37 - Table: 38 - Code: 0x00000001 39 Tag: DW_TAG_compile_unit 40 Children: DW_CHILDREN_yes 41 Attributes: 42 - Attribute: DW_AT_language 43 Form: DW_FORM_data2 44 - Code: 0x00000002 45 Tag: DW_TAG_base_type 46 Children: DW_CHILDREN_no 47 Attributes: 48 - Attribute: DW_AT_encoding 49 Form: DW_FORM_data1 50 - Attribute: DW_AT_byte_size 51 Form: DW_FORM_data1 52 debug_info: 53 - Version: 4 54 AddrSize: 8 55 Entries: 56 - AbbrCode: 0x00000001 57 Values: 58 - Value: 0x000000000000000C 59 - AbbrCode: 0x00000002 60 Values: 61 - Value: 0x0000000000000007 # DW_ATE_unsigned 62 - Value: 0x0000000000000004 63 - AbbrCode: 0x00000002 64 Values: 65 - Value: 0x0000000000000007 # DW_ATE_unsigned 66 - Value: 0x0000000000000008 67 - AbbrCode: 0x00000002 68 Values: 69 - Value: 0x0000000000000005 # DW_ATE_signed 70 - Value: 0x0000000000000008 71 - AbbrCode: 0x00000000 72 )"; 73 74 YAMLModuleTester t(yamldata); 75 ASSERT_TRUE((bool)t.GetDwarfUnit()); 76 77 DWARFUnit *unit = t.GetDwarfUnit(); 78 const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE(); 79 80 // Create a DWARFDIE that has three DW_TAG_base_type children. 81 DWARFDIE top_die(unit, die_first); 82 83 // Create the iterator range that has the three tags as elements. 84 llvm::iterator_range<DWARFDIE::child_iterator> children = top_die.children(); 85 86 // Compare begin() to the first child DIE. 87 DWARFDIE::child_iterator child_iter = children.begin(); 88 ASSERT_NE(child_iter, children.end()); 89 const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild(); 90 EXPECT_EQ((*child_iter).GetDIE(), die_child0); 91 92 // Step to the second child DIE. 93 ++child_iter; 94 ASSERT_NE(child_iter, children.end()); 95 const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling(); 96 EXPECT_EQ((*child_iter).GetDIE(), die_child1); 97 98 // Step to the third child DIE. 99 ++child_iter; 100 ASSERT_NE(child_iter, children.end()); 101 const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling(); 102 EXPECT_EQ((*child_iter).GetDIE(), die_child2); 103 104 // Step to the end of the range. 105 ++child_iter; 106 EXPECT_EQ(child_iter, children.end()); 107 108 // Take one of the DW_TAG_base_type DIEs (which has no children) and make 109 // sure the children range is now empty. 110 DWARFDIE no_children_die(unit, die_child0); 111 EXPECT_TRUE(no_children_die.children().empty()); 112 } 113 114 TEST(DWARFDIETest, PeekName) { 115 const char *yamldata = R"( 116 --- !ELF 117 FileHeader: 118 Class: ELFCLASS64 119 Data: ELFDATA2LSB 120 Type: ET_EXEC 121 Machine: EM_386 122 DWARF: 123 debug_str: 124 - 'NameType1' 125 - 'NameType2' 126 debug_abbrev: 127 - Table: 128 - Code: 0x00000001 129 Tag: DW_TAG_compile_unit 130 Children: DW_CHILDREN_yes 131 Attributes: 132 - Attribute: DW_AT_language 133 Form: DW_FORM_data2 134 - Code: 0x00000002 135 Tag: DW_TAG_base_type 136 Children: DW_CHILDREN_no 137 Attributes: 138 - Attribute: DW_AT_name 139 Form: DW_FORM_strp 140 - Code: 0x00000003 141 Tag: DW_TAG_base_type 142 Children: DW_CHILDREN_no 143 Attributes: 144 - Attribute: DW_AT_abstract_origin 145 Form: DW_FORM_ref1 146 - Code: 0x00000004 147 Tag: DW_TAG_base_type 148 Children: DW_CHILDREN_no 149 Attributes: 150 - Attribute: DW_AT_specification 151 Form: DW_FORM_ref1 152 debug_info: 153 - Version: 4 154 AddrSize: 8 155 Entries: 156 - AbbrCode: 0x00000001 157 Values: 158 - Value: 0x000000000000000C 159 - AbbrCode: 0x00000002 160 Values: 161 - Value: 0x0000000000000000 # Name = NameType1 162 - AbbrCode: 0x00000002 163 Values: 164 - Value: 0x000000000000000a # Name = NameType2 165 - AbbrCode: 0x00000003 166 Values: 167 - Value: 0x000000000000000e # Ref abstract origin to NameType1 DIE. 168 - AbbrCode: 0x00000004 169 Values: 170 - Value: 0x0000000000000013 # Ref specification to NameType2 DIE. 171 - AbbrCode: 0x00000000 172 )"; 173 174 YAMLModuleTester t(yamldata); 175 auto *symbol_file = 176 llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile()); 177 DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0); 178 179 dw_offset_t first_die_offset = 11; 180 EXPECT_EQ(unit->PeekDIEName(first_die_offset), ""); 181 182 dw_offset_t second_die_offset = 14; 183 EXPECT_EQ(unit->PeekDIEName(second_die_offset), "NameType1"); 184 185 dw_offset_t third_die_offset = 19; 186 EXPECT_EQ(unit->PeekDIEName(third_die_offset), "NameType2"); 187 188 dw_offset_t fourth_die_offset = 24; 189 EXPECT_EQ(unit->PeekDIEName(fourth_die_offset), "NameType1"); 190 191 dw_offset_t fifth_die_offset = 26; 192 EXPECT_EQ(unit->PeekDIEName(fifth_die_offset), "NameType2"); 193 } 194 195 TEST(DWARFDIETest, GetContext) { 196 const char *yamldata = R"( 197 --- !ELF 198 FileHeader: 199 Class: ELFCLASS64 200 Data: ELFDATA2LSB 201 Type: ET_EXEC 202 Machine: EM_386 203 DWARF: 204 debug_abbrev: 205 - ID: 0 206 Table: 207 - Code: 0x1 208 Tag: DW_TAG_compile_unit 209 Children: DW_CHILDREN_yes 210 Attributes: 211 - Attribute: DW_AT_language 212 Form: DW_FORM_data2 213 - Code: 0x2 214 Tag: DW_TAG_namespace 215 Children: DW_CHILDREN_yes 216 Attributes: 217 - Attribute: DW_AT_name 218 Form: DW_FORM_string 219 - Code: 0x3 220 Tag: DW_TAG_structure_type 221 Children: DW_CHILDREN_no 222 Attributes: 223 - Attribute: DW_AT_name 224 Form: DW_FORM_string 225 - Code: 0x4 226 Tag: DW_TAG_namespace 227 Children: DW_CHILDREN_yes 228 debug_info: 229 - Version: 4 230 AddrSize: 8 231 Entries: 232 - AbbrCode: 0x1 233 Values: 234 - Value: 0x000000000000000C 235 - AbbrCode: 0x2 236 Values: 237 - CStr: NAMESPACE 238 - AbbrCode: 0x3 239 Values: 240 - CStr: STRUCT 241 - AbbrCode: 0x4 242 - AbbrCode: 0x3 243 Values: 244 - CStr: STRUCT 245 - AbbrCode: 0x0 246 - AbbrCode: 0x0 247 - AbbrCode: 0x0 248 )"; 249 250 YAMLModuleTester t(yamldata); 251 auto *symbol_file = 252 llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile()); 253 DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0); 254 ASSERT_TRUE(unit); 255 256 auto make_namespace = [](const char *name) { 257 return CompilerContext(CompilerContextKind::Namespace, ConstString(name)); 258 }; 259 auto make_struct = [](const char *name) { 260 return CompilerContext(CompilerContextKind::ClassOrStruct, 261 ConstString(name)); 262 }; 263 DWARFDIE struct_die = unit->DIE().GetFirstChild().GetFirstChild(); 264 ASSERT_TRUE(struct_die); 265 DWARFDIE anon_struct_die = struct_die.GetSibling().GetFirstChild(); 266 ASSERT_TRUE(anon_struct_die); 267 EXPECT_THAT( 268 struct_die.GetDeclContext(), 269 testing::ElementsAre(make_namespace("NAMESPACE"), make_struct("STRUCT"))); 270 EXPECT_THAT( 271 struct_die.GetTypeLookupContext(), 272 testing::ElementsAre(make_namespace("NAMESPACE"), make_struct("STRUCT"))); 273 EXPECT_THAT(struct_die.GetDWARFDeclContext(), 274 DWARFDeclContext({{DW_TAG_structure_type, "STRUCT"}, 275 {DW_TAG_namespace, "NAMESPACE"}})); 276 EXPECT_THAT(anon_struct_die.GetDeclContext(), 277 testing::ElementsAre(make_namespace("NAMESPACE"), 278 make_namespace(nullptr), 279 make_struct("STRUCT"))); 280 EXPECT_THAT(anon_struct_die.GetTypeLookupContext(), 281 testing::ElementsAre(make_namespace("NAMESPACE"), 282 make_namespace(nullptr), 283 make_struct("STRUCT"))); 284 EXPECT_THAT(anon_struct_die.GetDWARFDeclContext(), 285 DWARFDeclContext({{DW_TAG_structure_type, "STRUCT"}, 286 {DW_TAG_namespace, nullptr}, 287 {DW_TAG_namespace, "NAMESPACE"}})); 288 } 289 290 TEST(DWARFDIETest, GetContextInFunction) { 291 // Make sure we get the right context fo each "struct_t" type. The first 292 // should be "a::struct_t" and the one defined in the "foo" function should be 293 // "struct_t". Previous DWARFDIE::GetTypeLookupContext() function calls would 294 // have the "struct_t" in "foo" be "a::struct_t" because it would traverse the 295 // entire die parent tree and ignore DW_TAG_subprogram and keep traversing the 296 // parents. 297 // 298 // 0x0000000b: DW_TAG_compile_unit 299 // 0x0000000c: DW_TAG_namespace 300 // DW_AT_name("a") 301 // 0x0000000f: DW_TAG_structure_type 302 // DW_AT_name("struct_t") 303 // 0x00000019: DW_TAG_subprogram 304 // DW_AT_name("foo") 305 // 0x0000001e: DW_TAG_structure_type 306 // DW_AT_name("struct_t") 307 // 0x00000028: NULL 308 // 0x00000029: NULL 309 // 0x0000002a: NULL 310 const char *yamldata = R"( 311 --- !ELF 312 FileHeader: 313 Class: ELFCLASS64 314 Data: ELFDATA2LSB 315 Type: ET_EXEC 316 Machine: EM_386 317 DWARF: 318 debug_str: 319 - '' 320 debug_abbrev: 321 - ID: 0 322 Table: 323 - Code: 0x1 324 Tag: DW_TAG_compile_unit 325 Children: DW_CHILDREN_yes 326 - Code: 0x2 327 Tag: DW_TAG_namespace 328 Children: DW_CHILDREN_yes 329 Attributes: 330 - Attribute: DW_AT_name 331 Form: DW_FORM_string 332 - Code: 0x3 333 Tag: DW_TAG_structure_type 334 Children: DW_CHILDREN_no 335 Attributes: 336 - Attribute: DW_AT_name 337 Form: DW_FORM_string 338 - Code: 0x4 339 Tag: DW_TAG_subprogram 340 Children: DW_CHILDREN_yes 341 Attributes: 342 - Attribute: DW_AT_name 343 Form: DW_FORM_string 344 debug_info: 345 - Length: 0x27 346 Version: 4 347 AbbrevTableID: 0 348 AbbrOffset: 0x0 349 AddrSize: 8 350 Entries: 351 - AbbrCode: 0x1 352 - AbbrCode: 0x2 353 Values: 354 - Value: 0xDEADBEEFDEADBEEF 355 CStr: a 356 - AbbrCode: 0x3 357 Values: 358 - Value: 0xDEADBEEFDEADBEEF 359 CStr: struct_t 360 - AbbrCode: 0x4 361 Values: 362 - Value: 0xDEADBEEFDEADBEEF 363 CStr: foo 364 - AbbrCode: 0x3 365 Values: 366 - Value: 0xDEADBEEFDEADBEEF 367 CStr: struct_t 368 - AbbrCode: 0x0 369 - AbbrCode: 0x0 370 - AbbrCode: 0x0)"; 371 372 YAMLModuleTester t(yamldata); 373 auto *symbol_file = 374 llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile()); 375 DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0); 376 ASSERT_TRUE(unit); 377 378 auto make_namespace = [](llvm::StringRef name) { 379 return CompilerContext(CompilerContextKind::Namespace, ConstString(name)); 380 }; 381 auto make_struct = [](llvm::StringRef name) { 382 return CompilerContext(CompilerContextKind::ClassOrStruct, 383 ConstString(name)); 384 }; 385 // Grab the "a::struct_t" type from the "a" namespace 386 DWARFDIE a_struct_die = unit->DIE().GetFirstChild().GetFirstChild(); 387 ASSERT_TRUE(a_struct_die); 388 EXPECT_THAT( 389 a_struct_die.GetDeclContext(), 390 testing::ElementsAre(make_namespace("a"), make_struct("struct_t"))); 391 // Grab the "struct_t" defined in the "foo" function. 392 DWARFDIE foo_struct_die = 393 unit->DIE().GetFirstChild().GetFirstChild().GetSibling().GetFirstChild(); 394 EXPECT_THAT(foo_struct_die.GetTypeLookupContext(), 395 testing::ElementsAre(make_struct("struct_t"))); 396 } 397 398 struct GetAttributesTestFixture : public testing::TestWithParam<dw_attr_t> {}; 399 400 TEST_P(GetAttributesTestFixture, TestGetAttributes_IterationOrder) { 401 // Tests that we accumulate all current DIE's attributes first 402 // before checking the attributes of the specification. 403 404 const char *yamldata = R"( 405 --- !ELF 406 FileHeader: 407 Class: ELFCLASS64 408 Data: ELFDATA2LSB 409 Type: ET_EXEC 410 Machine: EM_AARCH64 411 DWARF: 412 debug_str: 413 - func 414 debug_abbrev: 415 - ID: 0 416 Table: 417 - Code: 0x1 418 Tag: DW_TAG_compile_unit 419 Children: DW_CHILDREN_yes 420 Attributes: 421 - Attribute: DW_AT_language 422 Form: DW_FORM_data2 423 - Code: 0x2 424 Tag: DW_TAG_subprogram 425 Children: DW_CHILDREN_no 426 Attributes: 427 - Attribute: DW_AT_high_pc 428 Form: DW_FORM_data4 429 - Attribute: DW_AT_name 430 Form: DW_FORM_strp 431 - Attribute: DW_AT_declaration 432 Form: DW_FORM_flag_present 433 - Attribute: DW_AT_external 434 Form: DW_FORM_flag_present 435 - Attribute: DW_AT_low_pc 436 Form: DW_FORM_data4 437 - Code: 0x3 438 Tag: DW_TAG_subprogram 439 Children: DW_CHILDREN_no 440 Attributes: 441 - Attribute: DW_AT_high_pc 442 Form: DW_FORM_data4 443 - Attribute: {0} 444 Form: DW_FORM_ref4 445 - Attribute: DW_AT_low_pc 446 Form: DW_FORM_data4 447 debug_info: 448 - Version: 5 449 UnitType: DW_UT_compile 450 AddrSize: 8 451 Entries: 452 453 # DW_TAG_compile_unit 454 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 455 456 - AbbrCode: 0x1 457 Values: 458 - Value: 0x04 459 460 # DW_TAG_subprogram 461 # DW_AT_high_pc [DW_FORM_data4] 462 # DW_AT_name [DW_FORM_strp] ("func") 463 # DW_AT_low_pc [DW_FORM_data4] 464 - AbbrCode: 0x2 465 Values: 466 - Value: 0xdeadbeef 467 - Value: 0x0 468 - Value: 0x1 469 - Value: 0x1 470 - Value: 0xdeadbeef 471 472 # DW_TAG_subprogram 473 # DW_AT_high_pc [DW_FORM_data4] 474 # DW_AT_specification [DW_FORM_ref4] ("func") 475 # DW_AT_low_pc [DW_FORM_data4] 476 - AbbrCode: 0x3 477 Values: 478 - Value: 0xf00dcafe 479 - Value: 0xf 480 - Value: 0xf00dcafe 481 482 - AbbrCode: 0x0 483 ... 484 )"; 485 YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str()); 486 487 DWARFUnit *unit = t.GetDwarfUnit(); 488 ASSERT_NE(unit, nullptr); 489 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 490 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 491 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 492 DWARFDIE cu_die(unit, cu_entry); 493 494 auto declaration = cu_die.GetFirstChild(); 495 ASSERT_TRUE(declaration.IsValid()); 496 ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram); 497 498 auto definition = declaration.GetSibling(); 499 ASSERT_TRUE(definition.IsValid()); 500 ASSERT_EQ(definition.Tag(), DW_TAG_subprogram); 501 ASSERT_FALSE(definition.GetAttributeValueAsOptionalUnsigned(DW_AT_external)); 502 503 auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::yes); 504 EXPECT_EQ(attrs.Size(), 7U); 505 506 // Check that the attributes on the definition (that are also present 507 // on the declaration) take precedence. 508 for (auto attr : {DW_AT_low_pc, DW_AT_high_pc}) { 509 auto idx = attrs.FindAttributeIndex(attr); 510 EXPECT_NE(idx, UINT32_MAX); 511 512 DWARFFormValue form_value; 513 auto success = attrs.ExtractFormValueAtIndex(idx, form_value); 514 EXPECT_TRUE(success); 515 516 EXPECT_EQ(form_value.Unsigned(), 0xf00dcafe); 517 } 518 } 519 520 TEST_P(GetAttributesTestFixture, TestGetAttributes_Cycle) { 521 // Tests that GetAttributes can deal with cycles in 522 // specifications/abstract origins. 523 // 524 // Contrived example: 525 // 526 // func1 -> func3 527 // ^ | 528 // | v 529 // +------func2 530 531 const char *yamldata = R"( 532 --- !ELF 533 FileHeader: 534 Class: ELFCLASS64 535 Data: ELFDATA2LSB 536 Type: ET_EXEC 537 Machine: EM_AARCH64 538 DWARF: 539 debug_abbrev: 540 - ID: 0 541 Table: 542 - Code: 0x1 543 Tag: DW_TAG_compile_unit 544 Children: DW_CHILDREN_yes 545 Attributes: 546 - Attribute: DW_AT_language 547 Form: DW_FORM_data2 548 - Code: 0x2 549 Tag: DW_TAG_subprogram 550 Children: DW_CHILDREN_no 551 Attributes: 552 - Attribute: {0} 553 Form: DW_FORM_ref4 554 debug_info: 555 - Version: 5 556 UnitType: DW_UT_compile 557 AddrSize: 8 558 Entries: 559 560 - AbbrCode: 0x1 561 Values: 562 - Value: 0x04 563 564 - AbbrCode: 0x2 565 Values: 566 - Value: 0x19 567 568 - AbbrCode: 0x2 569 Values: 570 - Value: 0xf 571 572 - AbbrCode: 0x2 573 Values: 574 - Value: 0x14 575 576 - AbbrCode: 0x0 577 ... 578 )"; 579 YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str()); 580 581 DWARFUnit *unit = t.GetDwarfUnit(); 582 ASSERT_NE(unit, nullptr); 583 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 584 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 585 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 586 DWARFDIE cu_die(unit, cu_entry); 587 588 auto func1 = cu_die.GetFirstChild(); 589 ASSERT_TRUE(func1.IsValid()); 590 ASSERT_EQ(func1.Tag(), DW_TAG_subprogram); 591 592 auto func2 = func1.GetSibling(); 593 ASSERT_TRUE(func2.IsValid()); 594 ASSERT_EQ(func2.Tag(), DW_TAG_subprogram); 595 596 auto func3 = func2.GetSibling(); 597 ASSERT_TRUE(func3.IsValid()); 598 ASSERT_EQ(func3.Tag(), DW_TAG_subprogram); 599 600 auto attrs = func1.GetAttributes(DWARFDebugInfoEntry::Recurse::yes); 601 EXPECT_EQ(attrs.Size(), 3U); 602 603 // Confirm that the specifications do form a cycle. 604 { 605 DWARFFormValue form_value; 606 auto success = attrs.ExtractFormValueAtIndex(0, form_value); 607 ASSERT_TRUE(success); 608 609 EXPECT_EQ(form_value.Reference(), func3); 610 } 611 612 { 613 DWARFFormValue form_value; 614 auto success = attrs.ExtractFormValueAtIndex(1, form_value); 615 ASSERT_TRUE(success); 616 617 EXPECT_EQ(form_value.Reference(), func2); 618 } 619 620 { 621 DWARFFormValue form_value; 622 auto success = attrs.ExtractFormValueAtIndex(2, form_value); 623 ASSERT_TRUE(success); 624 625 EXPECT_EQ(form_value.Reference(), func1); 626 } 627 } 628 629 TEST_P(GetAttributesTestFixture, 630 TestGetAttributes_SkipNonApplicableAttributes) { 631 // Tests that GetAttributes will omit attributes found through 632 // specifications/abstract origins which are not applicable. 633 634 const char *yamldata = R"( 635 --- !ELF 636 FileHeader: 637 Class: ELFCLASS64 638 Data: ELFDATA2LSB 639 Type: ET_EXEC 640 Machine: EM_AARCH64 641 DWARF: 642 debug_str: 643 - func 644 debug_abbrev: 645 - ID: 0 646 Table: 647 - Code: 0x1 648 Tag: DW_TAG_compile_unit 649 Children: DW_CHILDREN_yes 650 Attributes: 651 - Attribute: DW_AT_language 652 Form: DW_FORM_data2 653 - Code: 0x2 654 Tag: DW_TAG_subprogram 655 Children: DW_CHILDREN_no 656 Attributes: 657 - Attribute: DW_AT_declaration 658 Form: DW_FORM_flag_present 659 - Attribute: DW_AT_name 660 Form: DW_FORM_strp 661 - Attribute: DW_AT_sibling 662 Form: DW_FORM_ref4 663 - Code: 0x3 664 Tag: DW_TAG_subprogram 665 Children: DW_CHILDREN_no 666 Attributes: 667 - Attribute: DW_AT_declaration 668 Form: DW_FORM_flag_present 669 - Attribute: {0} 670 Form: DW_FORM_ref4 671 - Attribute: DW_AT_sibling 672 Form: DW_FORM_ref4 673 debug_info: 674 - Version: 5 675 UnitType: DW_UT_compile 676 AddrSize: 8 677 Entries: 678 679 # DW_TAG_compile_unit 680 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 681 682 - AbbrCode: 0x1 683 Values: 684 - Value: 0x04 685 686 # DW_TAG_subprogram 687 # DW_AT_declaration 688 # DW_AT_name [DW_FORM_strp] ("func") 689 # DW_AT_sibling 690 - AbbrCode: 0x2 691 Values: 692 - Value: 0x1 693 - Value: 0x0 694 - Value: 0x18 695 696 # DW_TAG_subprogram 697 # DW_AT_declaration 698 # DW_AT_specification [DW_FORM_ref4] ("func") 699 # DW_AT_sibling 700 - AbbrCode: 0x3 701 Values: 702 - Value: 0x1 703 - Value: 0xf 704 - Value: 0xdeadbeef 705 706 - AbbrCode: 0x0 707 ... 708 )"; 709 YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str()); 710 711 DWARFUnit *unit = t.GetDwarfUnit(); 712 ASSERT_NE(unit, nullptr); 713 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 714 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 715 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 716 DWARFDIE cu_die(unit, cu_entry); 717 718 auto declaration = cu_die.GetFirstChild(); 719 ASSERT_TRUE(declaration.IsValid()); 720 ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram); 721 722 auto definition = declaration.GetSibling(); 723 ASSERT_TRUE(definition.IsValid()); 724 ASSERT_EQ(definition.Tag(), DW_TAG_subprogram); 725 726 auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::yes); 727 EXPECT_EQ(attrs.Size(), 4U); 728 EXPECT_NE(attrs.FindAttributeIndex(DW_AT_name), UINT32_MAX); 729 EXPECT_NE(attrs.FindAttributeIndex(GetParam()), UINT32_MAX); 730 731 auto sibling_idx = attrs.FindAttributeIndex(DW_AT_sibling); 732 EXPECT_NE(sibling_idx, UINT32_MAX); 733 734 DWARFFormValue form_value; 735 auto success = attrs.ExtractFormValueAtIndex(sibling_idx, form_value); 736 ASSERT_TRUE(success); 737 738 EXPECT_EQ(form_value.Unsigned(), 0xdeadbeef); 739 } 740 741 TEST_P(GetAttributesTestFixture, TestGetAttributes_NoRecurse) { 742 // Tests that GetAttributes will not recurse if Recurse::No is passed to it. 743 744 const char *yamldata = R"( 745 --- !ELF 746 FileHeader: 747 Class: ELFCLASS64 748 Data: ELFDATA2LSB 749 Type: ET_EXEC 750 Machine: EM_AARCH64 751 DWARF: 752 debug_str: 753 - func 754 debug_abbrev: 755 - ID: 0 756 Table: 757 - Code: 0x1 758 Tag: DW_TAG_compile_unit 759 Children: DW_CHILDREN_yes 760 Attributes: 761 - Attribute: DW_AT_language 762 Form: DW_FORM_data2 763 - Code: 0x2 764 Tag: DW_TAG_subprogram 765 Children: DW_CHILDREN_no 766 Attributes: 767 - Attribute: DW_AT_name 768 Form: DW_FORM_strp 769 - Code: 0x3 770 Tag: DW_TAG_subprogram 771 Children: DW_CHILDREN_no 772 Attributes: 773 - Attribute: DW_AT_low_pc 774 Form: DW_FORM_data4 775 - Attribute: {0} 776 Form: DW_FORM_ref4 777 debug_info: 778 - Version: 5 779 UnitType: DW_UT_compile 780 AddrSize: 8 781 Entries: 782 783 # DW_TAG_compile_unit 784 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 785 786 - AbbrCode: 0x1 787 Values: 788 - Value: 0x04 789 790 # DW_TAG_subprogram 791 # DW_AT_name [DW_FORM_strp] ("func") 792 - AbbrCode: 0x2 793 Values: 794 - Value: 0x0 795 796 # DW_TAG_subprogram 797 # DW_AT_low_pc [DW_FORM_data4] 798 # DW_AT_specification [DW_FORM_ref4] 799 - AbbrCode: 0x3 800 Values: 801 - Value: 0xdeadbeef 802 - Value: 0xf 803 804 - AbbrCode: 0x0 805 ... 806 )"; 807 YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str()); 808 809 DWARFUnit *unit = t.GetDwarfUnit(); 810 ASSERT_NE(unit, nullptr); 811 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 812 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 813 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 814 DWARFDIE cu_die(unit, cu_entry); 815 816 auto declaration = cu_die.GetFirstChild(); 817 ASSERT_TRUE(declaration.IsValid()); 818 ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram); 819 820 auto definition = declaration.GetSibling(); 821 ASSERT_TRUE(definition.IsValid()); 822 ASSERT_EQ(definition.Tag(), DW_TAG_subprogram); 823 824 auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::no); 825 EXPECT_EQ(attrs.Size(), 2U); 826 EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_name), UINT32_MAX); 827 EXPECT_NE(attrs.FindAttributeIndex(GetParam()), UINT32_MAX); 828 EXPECT_NE(attrs.FindAttributeIndex(DW_AT_low_pc), UINT32_MAX); 829 } 830 831 TEST_P(GetAttributesTestFixture, TestGetAttributes_InvalidSpec) { 832 // Test that GetAttributes doesn't try following invalid 833 // specifications (but still add it to the list of attributes). 834 835 const char *yamldata = R"( 836 --- !ELF 837 FileHeader: 838 Class: ELFCLASS64 839 Data: ELFDATA2LSB 840 Type: ET_EXEC 841 Machine: EM_AARCH64 842 DWARF: 843 debug_str: 844 - func 845 debug_abbrev: 846 - ID: 0 847 Table: 848 - Code: 0x1 849 Tag: DW_TAG_compile_unit 850 Children: DW_CHILDREN_yes 851 Attributes: 852 - Attribute: DW_AT_language 853 Form: DW_FORM_data2 854 - Code: 0x2 855 Tag: DW_TAG_subprogram 856 Children: DW_CHILDREN_no 857 Attributes: 858 - Attribute: DW_AT_name 859 Form: DW_FORM_strp 860 - Code: 0x3 861 Tag: DW_TAG_subprogram 862 Children: DW_CHILDREN_no 863 Attributes: 864 - Attribute: {0} 865 Form: DW_FORM_ref4 866 debug_info: 867 - Version: 5 868 UnitType: DW_UT_compile 869 AddrSize: 8 870 Entries: 871 872 # DW_TAG_compile_unit 873 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 874 875 - AbbrCode: 0x1 876 Values: 877 - Value: 0x04 878 879 # DW_TAG_subprogram 880 # DW_AT_name [DW_FORM_strp] ("func") 881 - AbbrCode: 0x2 882 Values: 883 - Value: 0x0 884 885 # DW_TAG_subprogram 886 # DW_AT_specification [DW_FORM_ref4] 887 - AbbrCode: 0x3 888 Values: 889 - Value: 0xdeadbeef 890 891 - AbbrCode: 0x0 892 ... 893 )"; 894 YAMLModuleTester t(llvm::formatv(yamldata, GetParam()).str()); 895 896 DWARFUnit *unit = t.GetDwarfUnit(); 897 ASSERT_NE(unit, nullptr); 898 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 899 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 900 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 901 DWARFDIE cu_die(unit, cu_entry); 902 903 auto declaration = cu_die.GetFirstChild(); 904 ASSERT_TRUE(declaration.IsValid()); 905 ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram); 906 907 auto definition = declaration.GetSibling(); 908 ASSERT_TRUE(definition.IsValid()); 909 ASSERT_EQ(definition.Tag(), DW_TAG_subprogram); 910 911 auto attrs = definition.GetAttributes(DWARFDebugInfoEntry::Recurse::yes); 912 EXPECT_EQ(attrs.Size(), 1U); 913 EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_name), UINT32_MAX); 914 EXPECT_NE(attrs.FindAttributeIndex(GetParam()), UINT32_MAX); 915 } 916 917 TEST(DWARFDIETest, TestGetAttributes_Worklist) { 918 // Test that GetAttributes will follow both the abstract origin 919 // and specification on a single DIE correctly (omitting non-applicable 920 // attributes in the process). 921 922 // Contrived example where 923 // f1---> f2 --> f4 924 // `-> f3 `-> f5 925 // 926 const char *yamldata = R"( 927 --- !ELF 928 FileHeader: 929 Class: ELFCLASS64 930 Data: ELFDATA2LSB 931 Type: ET_EXEC 932 Machine: EM_AARCH64 933 DWARF: 934 debug_str: 935 - foo 936 - bar 937 debug_abbrev: 938 - ID: 0 939 Table: 940 - Code: 0x1 941 Tag: DW_TAG_compile_unit 942 Children: DW_CHILDREN_yes 943 Attributes: 944 - Attribute: DW_AT_language 945 Form: DW_FORM_data2 946 - Code: 0x2 947 Tag: DW_TAG_subprogram 948 Children: DW_CHILDREN_no 949 Attributes: 950 - Attribute: DW_AT_specification 951 Form: DW_FORM_ref4 952 - Attribute: DW_AT_abstract_origin 953 Form: DW_FORM_ref4 954 - Code: 0x3 955 Tag: DW_TAG_subprogram 956 Children: DW_CHILDREN_no 957 Attributes: 958 - Attribute: DW_AT_declaration 959 Form: DW_FORM_flag_present 960 - Attribute: DW_AT_artificial 961 Form: DW_FORM_flag_present 962 963 debug_info: 964 - Version: 5 965 UnitType: DW_UT_compile 966 AddrSize: 8 967 Entries: 968 969 - AbbrCode: 0x1 970 Values: 971 - Value: 0x04 972 973 # DW_TAG_subprogram ("f1") 974 # DW_AT_specification [DW_FORM_ref4] ("f2") 975 # DW_AT_abstract_origin [DW_FORM_ref4] ("f3") 976 - AbbrCode: 0x2 977 Values: 978 - Value: 0x18 979 - Value: 0x21 980 981 # DW_TAG_subprogram ("f2") 982 # DW_AT_specification [DW_FORM_ref4] ("f4") 983 # DW_AT_abstract_origin [DW_FORM_ref4] ("f5") 984 - AbbrCode: 0x2 985 Values: 986 - Value: 0x22 987 - Value: 0x23 988 989 # DW_TAG_subprogram ("f3") 990 # DW_AT_declaration [DW_FORM_flag_present] 991 # DW_AT_artificial [DW_FORM_flag_present] 992 - AbbrCode: 0x3 993 Values: 994 - Value: 0x1 995 - Value: 0x1 996 997 # DW_TAG_subprogram ("f4") 998 # DW_AT_declaration [DW_FORM_flag_present] 999 # DW_AT_artificial [DW_FORM_flag_present] 1000 - AbbrCode: 0x3 1001 Values: 1002 - Value: 0x1 1003 - Value: 0x1 1004 1005 # DW_TAG_subprogram ("f5") 1006 # DW_AT_declaration [DW_FORM_flag_present] 1007 # DW_AT_artificial [DW_FORM_flag_present] 1008 - AbbrCode: 0x3 1009 Values: 1010 - Value: 0x1 1011 - Value: 0x1 1012 1013 - AbbrCode: 0x0 1014 ... 1015 )"; 1016 YAMLModuleTester t(yamldata); 1017 1018 DWARFUnit *unit = t.GetDwarfUnit(); 1019 ASSERT_NE(unit, nullptr); 1020 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 1021 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 1022 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 1023 DWARFDIE cu_die(unit, cu_entry); 1024 1025 auto f1 = cu_die.GetFirstChild(); 1026 ASSERT_TRUE(f1.IsValid()); 1027 ASSERT_EQ(f1.Tag(), DW_TAG_subprogram); 1028 1029 auto attrs = f1.GetAttributes(DWARFDebugInfoEntry::Recurse::yes); 1030 EXPECT_EQ(attrs.Size(), 7U); 1031 EXPECT_EQ(attrs.FindAttributeIndex(DW_AT_declaration), UINT32_MAX); 1032 } 1033 1034 INSTANTIATE_TEST_SUITE_P(GetAttributeTests, GetAttributesTestFixture, 1035 testing::Values(DW_AT_specification, 1036 DW_AT_abstract_origin)); 1037