1 //===- llvm/unittest/DebugInfo/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 "llvm/BinaryFormat/Dwarf.h" 10 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 11 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 12 #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h" 13 #include "llvm/ObjectYAML/DWARFEmitter.h" 14 #include "llvm/Testing/Support/Error.h" 15 #include "gtest/gtest.h" 16 17 using namespace llvm; 18 using namespace llvm::dwarf; 19 20 namespace { 21 22 TEST(DWARFDie, getLocations) { 23 const char *yamldata = R"( 24 debug_abbrev: 25 - Table: 26 - Code: 0x00000001 27 Tag: DW_TAG_compile_unit 28 Children: DW_CHILDREN_no 29 Attributes: 30 - Attribute: DW_AT_location 31 Form: DW_FORM_sec_offset 32 - Attribute: DW_AT_data_member_location 33 Form: DW_FORM_exprloc 34 - Attribute: DW_AT_vtable_elem_location 35 Form: DW_FORM_sec_offset 36 - Attribute: DW_AT_call_data_location 37 Form: DW_FORM_sec_offset 38 debug_info: 39 - Version: 5 40 UnitType: DW_UT_compile 41 AddrSize: 4 42 Entries: 43 - AbbrCode: 0x00000001 44 Values: 45 - Value: 12 46 - Value: 0x0000000000000001 47 BlockData: [ 0x47 ] 48 - Value: 20 49 - Value: 25 50 debug_loclists: 51 - AddressSize: 4 52 OffsetEntryCount: 0 53 Lists: 54 - Entries: 55 - Operator: DW_LLE_start_length 56 Values: [ 0x01, 0x02 ] 57 - Operator: DW_LLE_end_of_list 58 - Entries: 59 - Operator: DW_LLE_startx_length 60 Values: [ 0x01, 0x02 ] 61 - Operator: DW_LLE_end_of_list 62 - Entries: 63 - Operator: DW_LLE_start_length 64 Values: [ 0x01, 0x02 ] 65 ## end_of_list intentionally missing. 66 )"; 67 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 68 DWARFYAML::emitDebugSections(StringRef(yamldata), 69 /*IsLittleEndian=*/true, 70 /*Is64BitAddrSize=*/false); 71 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 72 std::unique_ptr<DWARFContext> Ctx = 73 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 74 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 75 ASSERT_NE(nullptr, CU); 76 DWARFDie Die = CU->getUnitDIE(); 77 ASSERT_TRUE(Die.isValid()); 78 79 EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_location), 80 HasValue(testing::ElementsAre(DWARFLocationExpression{ 81 DWARFAddressRange{1, 3}, {}}))); 82 83 EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_data_member_location), 84 HasValue(testing::ElementsAre( 85 DWARFLocationExpression{std::nullopt, {0x47}}))); 86 87 EXPECT_THAT_EXPECTED( 88 Die.getLocations(DW_AT_vtable_elem_location), 89 Failed<ErrorInfoBase>(testing::Property( 90 &ErrorInfoBase::message, 91 "unable to resolve indirect address 1 for: DW_LLE_startx_length"))); 92 93 EXPECT_THAT_EXPECTED( 94 Die.getLocations(DW_AT_call_data_location), 95 FailedWithMessage( 96 "unexpected end of data at offset 0x20 while reading [0x20, 0x21)")); 97 98 EXPECT_THAT_EXPECTED( 99 Die.getLocations(DW_AT_call_data_value), 100 Failed<ErrorInfoBase>(testing::Property(&ErrorInfoBase::message, 101 "No DW_AT_call_data_value"))); 102 } 103 104 TEST(DWARFDie, getDeclFile) { 105 const char *yamldata = R"( 106 debug_str: 107 - '' 108 debug_abbrev: 109 - ID: 0 110 Table: 111 - Code: 0x1 112 Tag: DW_TAG_compile_unit 113 Children: DW_CHILDREN_yes 114 Attributes: 115 - Attribute: DW_AT_stmt_list 116 Form: DW_FORM_sec_offset 117 - Code: 0x2 118 Tag: DW_TAG_subprogram 119 Children: DW_CHILDREN_no 120 Attributes: 121 - Attribute: DW_AT_decl_file 122 Form: DW_FORM_data1 123 debug_info: 124 - Length: 0xF 125 Version: 4 126 AbbrevTableID: 0 127 AbbrOffset: 0x0 128 AddrSize: 8 129 Entries: 130 - AbbrCode: 0x1 131 Values: 132 - Value: 0x0 133 - AbbrCode: 0x2 134 Values: 135 - Value: 0x1 136 - AbbrCode: 0x0 137 debug_line: 138 - Length: 42 139 Version: 2 140 PrologueLength: 36 141 MinInstLength: 1 142 DefaultIsStmt: 1 143 LineBase: 251 144 LineRange: 14 145 OpcodeBase: 13 146 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] 147 IncludeDirs: 148 - '/tmp' 149 Files: 150 - Name: main.cpp 151 DirIdx: 1 152 ModTime: 0 153 Length: 0 154 )"; 155 156 // Given DWARF like this: 157 // 158 // 0x0000000b: DW_TAG_compile_unit 159 // DW_AT_stmt_list (0x00000000) 160 // 161 // 0x00000010: DW_TAG_subprogram 162 // DW_AT_decl_file ("/tmp/main.cpp") 163 // 164 // 0x00000012: NULL 165 // 166 // This tests that we can extract the right DW_AT_decl_file from a DIE that 167 // has a DW_AT_decl_file attribute. 168 169 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 170 DWARFYAML::emitDebugSections(StringRef(yamldata), 171 /*IsLittleEndian=*/true, 172 /*Is64BitAddrSize=*/true); 173 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 174 std::unique_ptr<DWARFContext> Ctx = 175 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 176 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 177 ASSERT_NE(nullptr, CU); 178 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); 179 ASSERT_TRUE(Die.isValid()); 180 181 DWARFDie MainDie = Die.getFirstChild(); 182 ASSERT_TRUE(MainDie.isValid()); 183 184 std::string DeclFile = MainDie.getDeclFile( 185 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); 186 187 std::string Ref = 188 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); 189 EXPECT_EQ(DeclFile, Ref); 190 } 191 192 TEST(DWARFDie, getDeclFileAbstractOrigin) { 193 const char *yamldata = R"( 194 debug_str: 195 - '' 196 debug_abbrev: 197 - ID: 0 198 Table: 199 - Code: 0x1 200 Tag: DW_TAG_compile_unit 201 Children: DW_CHILDREN_yes 202 Attributes: 203 - Attribute: DW_AT_stmt_list 204 Form: DW_FORM_sec_offset 205 - Code: 0x2 206 Tag: DW_TAG_subprogram 207 Children: DW_CHILDREN_no 208 Attributes: 209 - Attribute: DW_AT_abstract_origin 210 Form: DW_FORM_ref_addr 211 - Code: 0x3 212 Tag: DW_TAG_subprogram 213 Children: DW_CHILDREN_no 214 Attributes: 215 - Attribute: DW_AT_decl_file 216 Form: DW_FORM_data1 217 debug_info: 218 - Length: 0x14 219 Version: 4 220 AbbrevTableID: 0 221 AbbrOffset: 0x0 222 AddrSize: 8 223 Entries: 224 - AbbrCode: 0x1 225 Values: 226 - Value: 0x0 227 - AbbrCode: 0x2 228 Values: 229 - Value: 0x15 230 - AbbrCode: 0x3 231 Values: 232 - Value: 0x1 233 - AbbrCode: 0x0 234 debug_line: 235 - Length: 42 236 Version: 2 237 PrologueLength: 36 238 MinInstLength: 1 239 DefaultIsStmt: 1 240 LineBase: 251 241 LineRange: 14 242 OpcodeBase: 13 243 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] 244 IncludeDirs: 245 - '/tmp' 246 Files: 247 - Name: main.cpp 248 DirIdx: 1 249 ModTime: 0 250 Length: 0 251 )"; 252 253 // Given DWARF like this: 254 // 255 // 0x0000000b: DW_TAG_compile_unit 256 // DW_AT_stmt_list (0x00000000) 257 // 258 // 0x00000010: DW_TAG_subprogram 259 // DW_AT_abstract_origin (0x0000000000000015) 260 // 261 // 0x00000015: DW_TAG_subprogram 262 // DW_AT_decl_file ("/tmp/main.cpp") 263 // 264 // 0x00000017: NULL 265 // 266 // 267 // The DIE at 0x00000010 uses a DW_AT_abstract_origin to point to the DIE at 268 // 0x00000015, make sure that DWARFDie::getDeclFile() succeeds by extracting 269 // the right file name of "/tmp/main.cpp". 270 // 271 // This tests that when we have a DW_AT_abstract_origin with a compile unit 272 // relative form (DW_FORM_ref4) to another DIE that we get the right 273 // DW_AT_decl_file value. 274 275 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 276 DWARFYAML::emitDebugSections(StringRef(yamldata), 277 /*IsLittleEndian=*/true, 278 /*Is64BitAddrSize=*/true); 279 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 280 std::unique_ptr<DWARFContext> Ctx = 281 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 282 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 283 ASSERT_NE(nullptr, CU); 284 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); 285 ASSERT_TRUE(Die.isValid()); 286 287 DWARFDie MainDie = Die.getFirstChild(); 288 ASSERT_TRUE(MainDie.isValid()); 289 290 std::string DeclFile = MainDie.getDeclFile( 291 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); 292 293 std::string Ref = 294 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); 295 EXPECT_EQ(DeclFile, Ref); 296 } 297 298 TEST(DWARFDie, getDeclFileSpecification) { 299 const char *yamldata = R"( 300 debug_str: 301 - '' 302 debug_abbrev: 303 - ID: 0 304 Table: 305 - Code: 0x1 306 Tag: DW_TAG_compile_unit 307 Children: DW_CHILDREN_yes 308 Attributes: 309 - Attribute: DW_AT_stmt_list 310 Form: DW_FORM_sec_offset 311 - Code: 0x2 312 Tag: DW_TAG_subprogram 313 Children: DW_CHILDREN_no 314 Attributes: 315 - Attribute: DW_AT_specification 316 Form: DW_FORM_ref_addr 317 - Code: 0x3 318 Tag: DW_TAG_subprogram 319 Children: DW_CHILDREN_no 320 Attributes: 321 - Attribute: DW_AT_decl_file 322 Form: DW_FORM_data1 323 debug_info: 324 - Length: 0x14 325 Version: 4 326 AbbrevTableID: 0 327 AbbrOffset: 0x0 328 AddrSize: 8 329 Entries: 330 - AbbrCode: 0x1 331 Values: 332 - Value: 0x0 333 - AbbrCode: 0x2 334 Values: 335 - Value: 0x15 336 - AbbrCode: 0x3 337 Values: 338 - Value: 0x1 339 - AbbrCode: 0x0 340 debug_line: 341 - Length: 42 342 Version: 2 343 PrologueLength: 36 344 MinInstLength: 1 345 DefaultIsStmt: 1 346 LineBase: 251 347 LineRange: 14 348 OpcodeBase: 13 349 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] 350 IncludeDirs: 351 - '/tmp' 352 Files: 353 - Name: main.cpp 354 DirIdx: 1 355 ModTime: 0 356 Length: 0 357 )"; 358 359 // Given DWARF like this: 360 // 361 // 0x0000000b: DW_TAG_compile_unit 362 // DW_AT_stmt_list (0x00000000) 363 // 364 // 0x00000010: DW_TAG_subprogram 365 // DW_AT_specification (0x0000000000000015) 366 // 367 // 0x00000015: DW_TAG_subprogram 368 // DW_AT_decl_file ("/tmp/main.cpp") 369 // 370 // 0x00000017: NULL 371 // 372 // The DIE at 0x00000010 uses a DW_AT_specification to point to the DIE at 373 // 0x00000015, make sure that DWARFDie::getDeclFile() succeeds by extracting 374 // the right file name of "/tmp/main.cpp". 375 // 376 // This tests that when we have a DW_AT_specification with a compile unit 377 // relative form (DW_FORM_ref4) to another DIE that we get the right 378 // DW_AT_decl_file value. 379 380 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 381 DWARFYAML::emitDebugSections(StringRef(yamldata), 382 /*IsLittleEndian=*/true, 383 /*Is64BitAddrSize=*/true); 384 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 385 std::unique_ptr<DWARFContext> Ctx = 386 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 387 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 388 ASSERT_NE(nullptr, CU); 389 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); 390 ASSERT_TRUE(Die.isValid()); 391 392 DWARFDie MainDie = Die.getFirstChild(); 393 ASSERT_TRUE(MainDie.isValid()); 394 395 std::string DeclFile = MainDie.getDeclFile( 396 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); 397 398 std::string Ref = 399 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); 400 EXPECT_EQ(DeclFile, Ref); 401 } 402 403 TEST(DWARFDie, getDeclFileAbstractOriginAcrossCUBoundary) { 404 const char *yamldata = R"( 405 debug_str: 406 - '' 407 debug_abbrev: 408 - ID: 0 409 Table: 410 - Code: 0x1 411 Tag: DW_TAG_compile_unit 412 Children: DW_CHILDREN_yes 413 - Code: 0x2 414 Tag: DW_TAG_subprogram 415 Children: DW_CHILDREN_no 416 Attributes: 417 - Attribute: DW_AT_abstract_origin 418 Form: DW_FORM_ref_addr 419 - Code: 0x3 420 Tag: DW_TAG_compile_unit 421 Children: DW_CHILDREN_yes 422 Attributes: 423 - Attribute: DW_AT_stmt_list 424 Form: DW_FORM_sec_offset 425 - Code: 0x4 426 Tag: DW_TAG_subprogram 427 Children: DW_CHILDREN_no 428 Attributes: 429 - Attribute: DW_AT_decl_file 430 Form: DW_FORM_data1 431 debug_info: 432 - Length: 0xE 433 Version: 4 434 AbbrevTableID: 0 435 AbbrOffset: 0x0 436 AddrSize: 8 437 Entries: 438 - AbbrCode: 0x1 439 - AbbrCode: 0x2 440 Values: 441 - Value: 0x22 442 - AbbrCode: 0x0 443 - Length: 0xF 444 Version: 4 445 AbbrevTableID: 0 446 AbbrOffset: 0x0 447 AddrSize: 8 448 Entries: 449 - AbbrCode: 0x3 450 Values: 451 - Value: 0x0 452 - AbbrCode: 0x4 453 Values: 454 - Value: 0x1 455 - AbbrCode: 0x0 456 debug_line: 457 - Length: 42 458 Version: 2 459 PrologueLength: 36 460 MinInstLength: 1 461 DefaultIsStmt: 1 462 LineBase: 251 463 LineRange: 14 464 OpcodeBase: 13 465 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] 466 IncludeDirs: 467 - '/tmp' 468 Files: 469 - Name: main.cpp 470 DirIdx: 1 471 ModTime: 0 472 Length: 0 473 )"; 474 475 // Given DWARF like this: 476 // 477 // 0x0000000b: DW_TAG_compile_unit 478 // 479 // 0x0000000c: DW_TAG_subprogram 480 // DW_AT_abstract_origin (0x0000000000000022) 481 // 482 // 0x00000011: NULL 483 // 484 // 0x0000001d: DW_TAG_compile_unit 485 // DW_AT_stmt_list (0x00000000) 486 // 487 // 0x00000022: DW_TAG_subprogram 488 // DW_AT_decl_file ("/tmp/main.cpp") 489 // 490 // 0x00000024: NULL 491 // 492 // This tests that when we have a DW_AT_abstract_origin with a 493 // DW_FORM_ref_addr to another DIE in another compile unit that we use the 494 // right file table when converting the file index of the DW_AT_decl_file. 495 // 496 // The DIE at 0x0000000c uses a DW_AT_abstract_origin to point to the DIE at 497 // 0x00000022, make sure that DWARFDie::getDeclFile() succeeds by extracting 498 // the right file name of "/tmp/main.cpp". The DW_AT_decl_file must grab the 499 // file from the line table prologue of the compile unit at offset 500 // 0x0000001d. 501 502 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 503 DWARFYAML::emitDebugSections(StringRef(yamldata), 504 /*IsLittleEndian=*/true, 505 /*Is64BitAddrSize=*/true); 506 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 507 std::unique_ptr<DWARFContext> Ctx = 508 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 509 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 510 ASSERT_NE(nullptr, CU); 511 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); 512 ASSERT_TRUE(Die.isValid()); 513 514 DWARFDie MainDie = Die.getFirstChild(); 515 ASSERT_TRUE(MainDie.isValid()); 516 517 std::string DeclFile = MainDie.getDeclFile( 518 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); 519 520 std::string Ref = 521 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); 522 EXPECT_EQ(DeclFile, Ref); 523 } 524 525 TEST(DWARFDie, getDeclFileSpecificationAcrossCUBoundary) { 526 const char *yamldata = R"( 527 debug_str: 528 - '' 529 debug_abbrev: 530 - ID: 0 531 Table: 532 - Code: 0x1 533 Tag: DW_TAG_compile_unit 534 Children: DW_CHILDREN_yes 535 - Code: 0x2 536 Tag: DW_TAG_subprogram 537 Children: DW_CHILDREN_no 538 Attributes: 539 - Attribute: DW_AT_specification 540 Form: DW_FORM_ref_addr 541 - Code: 0x3 542 Tag: DW_TAG_compile_unit 543 Children: DW_CHILDREN_yes 544 Attributes: 545 - Attribute: DW_AT_stmt_list 546 Form: DW_FORM_sec_offset 547 - Code: 0x4 548 Tag: DW_TAG_subprogram 549 Children: DW_CHILDREN_no 550 Attributes: 551 - Attribute: DW_AT_decl_file 552 Form: DW_FORM_data1 553 debug_info: 554 - Length: 0xE 555 Version: 4 556 AbbrevTableID: 0 557 AbbrOffset: 0x0 558 AddrSize: 8 559 Entries: 560 - AbbrCode: 0x1 561 - AbbrCode: 0x2 562 Values: 563 - Value: 0x22 564 - AbbrCode: 0x0 565 - Length: 0xF 566 Version: 4 567 AbbrevTableID: 0 568 AbbrOffset: 0x0 569 AddrSize: 8 570 Entries: 571 - AbbrCode: 0x3 572 Values: 573 - Value: 0x0 574 - AbbrCode: 0x4 575 Values: 576 - Value: 0x1 577 - AbbrCode: 0x0 578 debug_line: 579 - Length: 42 580 Version: 2 581 PrologueLength: 36 582 MinInstLength: 1 583 DefaultIsStmt: 1 584 LineBase: 251 585 LineRange: 14 586 OpcodeBase: 13 587 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] 588 IncludeDirs: 589 - '/tmp' 590 Files: 591 - Name: main.cpp 592 DirIdx: 1 593 ModTime: 0 594 Length: 0 595 )"; 596 597 // Given DWARF like this: 598 // 599 // 0x0000000b: DW_TAG_compile_unit 600 // 601 // 0x0000000c: DW_TAG_subprogram 602 // DW_AT_specification (0x0000000000000022) 603 // 604 // 0x00000011: NULL 605 // 606 // 0x0000001d: DW_TAG_compile_unit 607 // DW_AT_stmt_list (0x00000000) 608 // 609 // 0x00000022: DW_TAG_subprogram 610 // DW_AT_decl_file ("/tmp/main.cpp") 611 // 612 // 0x00000024: NULL 613 // 614 // This tests that when we have a DW_AT_specification with a 615 // DW_FORM_ref_addr to another DIE in another compile unit that we use the 616 // right file table when converting the file index of the DW_AT_decl_file. 617 // 618 // The DIE at 0x0000000c uses a DW_AT_specification to point to the DIE at 619 // 0x00000022, make sure that DWARFDie::getDeclFile() succeeds by extracting 620 // the right file name of "/tmp/main.cpp". The DW_AT_decl_file must grab the 621 // file from the line table prologue of the compile unit at offset 622 // 0x0000001d. 623 624 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 625 DWARFYAML::emitDebugSections(StringRef(yamldata), 626 /*IsLittleEndian=*/true, 627 /*Is64BitAddrSize=*/true); 628 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 629 std::unique_ptr<DWARFContext> Ctx = 630 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 631 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 632 ASSERT_NE(nullptr, CU); 633 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); 634 ASSERT_TRUE(Die.isValid()); 635 636 DWARFDie MainDie = Die.getFirstChild(); 637 ASSERT_TRUE(MainDie.isValid()); 638 639 std::string DeclFile = MainDie.getDeclFile( 640 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); 641 642 std::string Ref = 643 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); 644 EXPECT_EQ(DeclFile, Ref); 645 } 646 647 TEST(DWARFDie, getNameFromTypeUnit) { 648 const char *yamldata = R"( 649 debug_abbrev: 650 - ID: 0 651 Table: 652 - Code: 0x1 653 Tag: DW_TAG_compile_unit 654 Children: DW_CHILDREN_yes 655 - Code: 0x2 656 Tag: DW_TAG_structure_type 657 Children: DW_CHILDREN_no 658 Attributes: 659 - Attribute: DW_AT_signature 660 Form: DW_FORM_ref_sig8 661 - Code: 0x3 662 Tag: DW_TAG_type_unit 663 Children: DW_CHILDREN_yes 664 - Code: 0x4 665 Tag: DW_TAG_structure_type 666 Children: DW_CHILDREN_no 667 Attributes: 668 - Attribute: DW_AT_name 669 Form: DW_FORM_string 670 debug_info: 671 - Version: 5 672 UnitType: DW_UT_compile 673 AbbrevTableID: 0 674 Entries: 675 - AbbrCode: 0x1 676 - AbbrCode: 0x2 677 Values: 678 - Value: 0xdeadbeefbaadf00d 679 - AbbrCode: 0x0 680 - Version: 5 681 UnitType: DW_UT_type 682 AbbrevTableID: 0 683 TypeSignature: 0xdeadbeefbaadf00d 684 TypeOffset: 25 685 Entries: 686 - AbbrCode: 0x3 687 - AbbrCode: 0x4 688 Values: 689 - CStr: "STRUCT" 690 - AbbrCode: 0x0 691 )"; 692 693 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 694 DWARFYAML::emitDebugSections(StringRef(yamldata), 695 /*IsLittleEndian=*/true, 696 /*Is64BitAddrSize=*/true); 697 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 698 std::unique_ptr<DWARFContext> Ctx = 699 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 700 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); 701 ASSERT_NE(nullptr, CU); 702 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false).getFirstChild(); 703 ASSERT_TRUE(Die.isValid()); 704 705 ASSERT_STREQ(Die.getName(DINameKind::ShortName), "STRUCT"); 706 } 707 708 void testAppendAndTerminateTemplateParameters(const DWARFDie &DIE, 709 const std::string &Expected) { 710 std::string TemplateName; 711 llvm::raw_string_ostream TemplateNameOS(TemplateName); 712 llvm::DWARFTypePrinter<DWARFDie> TemplateNamePrinter(TemplateNameOS); 713 TemplateNamePrinter.appendAndTerminateTemplateParameters(DIE); 714 EXPECT_THAT(TemplateName, Expected); 715 } 716 717 void testAppendQualifiedName(const DWARFDie &DIE, const std::string &Expected) { 718 std::string QualifiedName; 719 llvm::raw_string_ostream TemplateNameOS(QualifiedName); 720 llvm::DWARFTypePrinter<DWARFDie> TemplateNamePrinter(TemplateNameOS); 721 TemplateNamePrinter.appendQualifiedName(DIE); 722 EXPECT_THAT(QualifiedName, Expected); 723 } 724 725 TEST(DWARFDie, DWARFTypePrinterTest) { 726 // Make sure we can get template parameters and qualified names correctly with 727 // DWARFTypePrinter when using -gsimple-template-names. 728 729 // 0x0000000b: DW_TAG_compile_unit 730 // 0x0000000c: DW_TAG_base_type 731 // DW_AT_name ("int") 732 // 0x00000011: DW_TAG_structure_type 733 // DW_AT_name ("t1") 734 // 0x00000015: DW_TAG_template_type_parameter 735 // DW_AT_type (0x0000001f "t3<int>") 736 // 0x0000001a: DW_TAG_structure_type 737 // DW_AT_name ("t2") 738 // 0x0000001e: NULL 739 // 0x0000001f: DW_TAG_structure_type 740 // DW_AT_name ("t3") 741 // 0x00000023: DW_TAG_template_type_parameter 742 // DW_AT_type (0x0000000c "int") 743 // 0x00000028: NULL 744 // 0x00000029: NULL 745 const char *yamldata = R"( 746 debug_abbrev: 747 - ID: 0 748 Table: 749 - Code: 0x1 750 Tag: DW_TAG_compile_unit 751 Children: DW_CHILDREN_yes 752 - Code: 0x2 753 Tag: DW_TAG_base_type 754 Children: DW_CHILDREN_no 755 Attributes: 756 - Attribute: DW_AT_name 757 Form: DW_FORM_string 758 - Code: 0x3 759 Tag: DW_TAG_structure_type 760 Children: DW_CHILDREN_yes 761 Attributes: 762 - Attribute: DW_AT_name 763 Form: DW_FORM_string 764 - Code: 0x4 765 Tag: DW_TAG_template_type_parameter 766 Children: DW_CHILDREN_no 767 Attributes: 768 - Attribute: DW_AT_type 769 Form: DW_FORM_ref4 770 - Code: 0x5 771 Tag: DW_TAG_structure_type 772 Children: DW_CHILDREN_no 773 Attributes: 774 - Attribute: DW_AT_name 775 Form: DW_FORM_string 776 - Code: 0x6 777 Tag: DW_TAG_structure_type 778 Children: DW_CHILDREN_yes 779 Attributes: 780 - Attribute: DW_AT_name 781 Form: DW_FORM_string 782 - Code: 0x7 783 Tag: DW_TAG_template_type_parameter 784 Children: DW_CHILDREN_no 785 Attributes: 786 - Attribute: DW_AT_type 787 Form: DW_FORM_ref4 788 - Code: 0x8 789 Tag: DW_TAG_typedef 790 Children: DW_CHILDREN_no 791 Attributes: 792 - Attribute: DW_AT_type 793 Form: DW_FORM_ref4 794 - Attribute: DW_AT_name 795 Form: DW_FORM_string 796 debug_info: 797 - Version: 4 798 AddrSize: 8 799 Entries: 800 - AbbrCode: 0x1 801 - AbbrCode: 0x2 802 Values: 803 - Value: 0xDEADBEEFDEADBEEF 804 CStr: int 805 - AbbrCode: 0x3 806 Values: 807 - Value: 0xDEADBEEFDEADBEEF 808 CStr: t1 809 - AbbrCode: 0x4 810 Values: 811 - Value: 0x0000001f # update 812 - AbbrCode: 0x5 813 Values: 814 - Value: 0xDEADBEEFDEADBEEF 815 CStr: t2 816 - AbbrCode: 0x0 817 - AbbrCode: 0x6 818 Values: 819 - Value: 0xDEADBEEFDEADBEEF 820 CStr: t3 821 - AbbrCode: 0x7 822 Values: 823 - Value: 0x0000000c # update 824 - AbbrCode: 0x8 825 Values: 826 - Value: 0x0000000c 827 - CStr: my_int 828 - AbbrCode: 0x0 829 - AbbrCode: 0x0)"; 830 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = 831 DWARFYAML::emitDebugSections(StringRef(yamldata), 832 /*IsLittleEndian=*/true, 833 /*Is64BitAddrSize=*/true); 834 ASSERT_THAT_EXPECTED(Sections, Succeeded()); 835 std::unique_ptr<DWARFContext> Ctx = 836 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); 837 testAppendAndTerminateTemplateParameters(Ctx->getDIEForOffset(0x11), 838 "<t3<int> >"); 839 testAppendQualifiedName(Ctx->getDIEForOffset(0x1a), "t1<t3<int> >::t2"); 840 testAppendQualifiedName(Ctx->getDIEForOffset(0x28), "t3<int>::my_int"); 841 } 842 } // end anonymous namespace 843