| //===- llvm/unittest/DebugInfo/DWARFDieTest.cpp ---------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/BinaryFormat/Dwarf.h" |
| #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" |
| #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
| #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h" |
| #include "llvm/ObjectYAML/DWARFEmitter.h" |
| #include "llvm/Testing/Support/Error.h" |
| #include "gtest/gtest.h" |
| |
| using namespace llvm; |
| using namespace llvm::dwarf; |
| |
| namespace { |
| |
| TEST(DWARFDie, getLocations) { |
| const char *yamldata = R"( |
| debug_abbrev: |
| - Table: |
| - Code: 0x00000001 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_location |
| Form: DW_FORM_sec_offset |
| - Attribute: DW_AT_data_member_location |
| Form: DW_FORM_exprloc |
| - Attribute: DW_AT_vtable_elem_location |
| Form: DW_FORM_sec_offset |
| - Attribute: DW_AT_call_data_location |
| Form: DW_FORM_sec_offset |
| debug_info: |
| - Version: 5 |
| UnitType: DW_UT_compile |
| AddrSize: 4 |
| Entries: |
| - AbbrCode: 0x00000001 |
| Values: |
| - Value: 12 |
| - Value: 0x0000000000000001 |
| BlockData: [ 0x47 ] |
| - Value: 20 |
| - Value: 25 |
| debug_loclists: |
| - AddressSize: 4 |
| OffsetEntryCount: 0 |
| Lists: |
| - Entries: |
| - Operator: DW_LLE_start_length |
| Values: [ 0x01, 0x02 ] |
| - Operator: DW_LLE_end_of_list |
| - Entries: |
| - Operator: DW_LLE_startx_length |
| Values: [ 0x01, 0x02 ] |
| - Operator: DW_LLE_end_of_list |
| - Entries: |
| - Operator: DW_LLE_start_length |
| Values: [ 0x01, 0x02 ] |
| ## end_of_list intentionally missing. |
| )"; |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/false); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(); |
| ASSERT_TRUE(Die.isValid()); |
| |
| EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_location), |
| HasValue(testing::ElementsAre(DWARFLocationExpression{ |
| DWARFAddressRange{1, 3}, {}}))); |
| |
| EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_data_member_location), |
| HasValue(testing::ElementsAre( |
| DWARFLocationExpression{std::nullopt, {0x47}}))); |
| |
| EXPECT_THAT_EXPECTED( |
| Die.getLocations(DW_AT_vtable_elem_location), |
| Failed<ErrorInfoBase>(testing::Property( |
| &ErrorInfoBase::message, |
| "unable to resolve indirect address 1 for: DW_LLE_startx_length"))); |
| |
| EXPECT_THAT_EXPECTED( |
| Die.getLocations(DW_AT_call_data_location), |
| FailedWithMessage( |
| "unexpected end of data at offset 0x20 while reading [0x20, 0x21)")); |
| |
| EXPECT_THAT_EXPECTED( |
| Die.getLocations(DW_AT_call_data_value), |
| Failed<ErrorInfoBase>(testing::Property(&ErrorInfoBase::message, |
| "No DW_AT_call_data_value"))); |
| } |
| |
| TEST(DWARFDie, getDeclFile) { |
| const char *yamldata = R"( |
| debug_str: |
| - '' |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_stmt_list |
| Form: DW_FORM_sec_offset |
| - Code: 0x2 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_decl_file |
| Form: DW_FORM_data1 |
| debug_info: |
| - Length: 0xF |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x1 |
| Values: |
| - Value: 0x0 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0x1 |
| - AbbrCode: 0x0 |
| debug_line: |
| - Length: 42 |
| Version: 2 |
| PrologueLength: 36 |
| MinInstLength: 1 |
| DefaultIsStmt: 1 |
| LineBase: 251 |
| LineRange: 14 |
| OpcodeBase: 13 |
| StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] |
| IncludeDirs: |
| - '/tmp' |
| Files: |
| - Name: main.cpp |
| DirIdx: 1 |
| ModTime: 0 |
| Length: 0 |
| )"; |
| |
| // Given DWARF like this: |
| // |
| // 0x0000000b: DW_TAG_compile_unit |
| // DW_AT_stmt_list (0x00000000) |
| // |
| // 0x00000010: DW_TAG_subprogram |
| // DW_AT_decl_file ("/tmp/main.cpp") |
| // |
| // 0x00000012: NULL |
| // |
| // This tests that we can extract the right DW_AT_decl_file from a DIE that |
| // has a DW_AT_decl_file attribute. |
| |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); |
| ASSERT_TRUE(Die.isValid()); |
| |
| DWARFDie MainDie = Die.getFirstChild(); |
| ASSERT_TRUE(MainDie.isValid()); |
| |
| std::string DeclFile = MainDie.getDeclFile( |
| DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); |
| |
| std::string Ref = |
| ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); |
| EXPECT_EQ(DeclFile, Ref); |
| } |
| |
| TEST(DWARFDie, getDeclFileAbstractOrigin) { |
| const char *yamldata = R"( |
| debug_str: |
| - '' |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_stmt_list |
| Form: DW_FORM_sec_offset |
| - Code: 0x2 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_abstract_origin |
| Form: DW_FORM_ref_addr |
| - Code: 0x3 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_decl_file |
| Form: DW_FORM_data1 |
| debug_info: |
| - Length: 0x14 |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x1 |
| Values: |
| - Value: 0x0 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0x15 |
| - AbbrCode: 0x3 |
| Values: |
| - Value: 0x1 |
| - AbbrCode: 0x0 |
| debug_line: |
| - Length: 42 |
| Version: 2 |
| PrologueLength: 36 |
| MinInstLength: 1 |
| DefaultIsStmt: 1 |
| LineBase: 251 |
| LineRange: 14 |
| OpcodeBase: 13 |
| StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] |
| IncludeDirs: |
| - '/tmp' |
| Files: |
| - Name: main.cpp |
| DirIdx: 1 |
| ModTime: 0 |
| Length: 0 |
| )"; |
| |
| // Given DWARF like this: |
| // |
| // 0x0000000b: DW_TAG_compile_unit |
| // DW_AT_stmt_list (0x00000000) |
| // |
| // 0x00000010: DW_TAG_subprogram |
| // DW_AT_abstract_origin (0x0000000000000015) |
| // |
| // 0x00000015: DW_TAG_subprogram |
| // DW_AT_decl_file ("/tmp/main.cpp") |
| // |
| // 0x00000017: NULL |
| // |
| // |
| // The DIE at 0x00000010 uses a DW_AT_abstract_origin to point to the DIE at |
| // 0x00000015, make sure that DWARFDie::getDeclFile() succeeds by extracting |
| // the right file name of "/tmp/main.cpp". |
| // |
| // This tests that when we have a DW_AT_abstract_origin with a compile unit |
| // relative form (DW_FORM_ref4) to another DIE that we get the right |
| // DW_AT_decl_file value. |
| |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); |
| ASSERT_TRUE(Die.isValid()); |
| |
| DWARFDie MainDie = Die.getFirstChild(); |
| ASSERT_TRUE(MainDie.isValid()); |
| |
| std::string DeclFile = MainDie.getDeclFile( |
| DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); |
| |
| std::string Ref = |
| ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); |
| EXPECT_EQ(DeclFile, Ref); |
| } |
| |
| TEST(DWARFDie, getDeclFileSpecification) { |
| const char *yamldata = R"( |
| debug_str: |
| - '' |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_stmt_list |
| Form: DW_FORM_sec_offset |
| - Code: 0x2 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_specification |
| Form: DW_FORM_ref_addr |
| - Code: 0x3 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_decl_file |
| Form: DW_FORM_data1 |
| debug_info: |
| - Length: 0x14 |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x1 |
| Values: |
| - Value: 0x0 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0x15 |
| - AbbrCode: 0x3 |
| Values: |
| - Value: 0x1 |
| - AbbrCode: 0x0 |
| debug_line: |
| - Length: 42 |
| Version: 2 |
| PrologueLength: 36 |
| MinInstLength: 1 |
| DefaultIsStmt: 1 |
| LineBase: 251 |
| LineRange: 14 |
| OpcodeBase: 13 |
| StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] |
| IncludeDirs: |
| - '/tmp' |
| Files: |
| - Name: main.cpp |
| DirIdx: 1 |
| ModTime: 0 |
| Length: 0 |
| )"; |
| |
| // Given DWARF like this: |
| // |
| // 0x0000000b: DW_TAG_compile_unit |
| // DW_AT_stmt_list (0x00000000) |
| // |
| // 0x00000010: DW_TAG_subprogram |
| // DW_AT_specification (0x0000000000000015) |
| // |
| // 0x00000015: DW_TAG_subprogram |
| // DW_AT_decl_file ("/tmp/main.cpp") |
| // |
| // 0x00000017: NULL |
| // |
| // The DIE at 0x00000010 uses a DW_AT_specification to point to the DIE at |
| // 0x00000015, make sure that DWARFDie::getDeclFile() succeeds by extracting |
| // the right file name of "/tmp/main.cpp". |
| // |
| // This tests that when we have a DW_AT_specification with a compile unit |
| // relative form (DW_FORM_ref4) to another DIE that we get the right |
| // DW_AT_decl_file value. |
| |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); |
| ASSERT_TRUE(Die.isValid()); |
| |
| DWARFDie MainDie = Die.getFirstChild(); |
| ASSERT_TRUE(MainDie.isValid()); |
| |
| std::string DeclFile = MainDie.getDeclFile( |
| DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); |
| |
| std::string Ref = |
| ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); |
| EXPECT_EQ(DeclFile, Ref); |
| } |
| |
| TEST(DWARFDie, getDeclFileAbstractOriginAcrossCUBoundary) { |
| const char *yamldata = R"( |
| debug_str: |
| - '' |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| - Code: 0x2 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_abstract_origin |
| Form: DW_FORM_ref_addr |
| - Code: 0x3 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_stmt_list |
| Form: DW_FORM_sec_offset |
| - Code: 0x4 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_decl_file |
| Form: DW_FORM_data1 |
| debug_info: |
| - Length: 0xE |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x1 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0x22 |
| - AbbrCode: 0x0 |
| - Length: 0xF |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x3 |
| Values: |
| - Value: 0x0 |
| - AbbrCode: 0x4 |
| Values: |
| - Value: 0x1 |
| - AbbrCode: 0x0 |
| debug_line: |
| - Length: 42 |
| Version: 2 |
| PrologueLength: 36 |
| MinInstLength: 1 |
| DefaultIsStmt: 1 |
| LineBase: 251 |
| LineRange: 14 |
| OpcodeBase: 13 |
| StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] |
| IncludeDirs: |
| - '/tmp' |
| Files: |
| - Name: main.cpp |
| DirIdx: 1 |
| ModTime: 0 |
| Length: 0 |
| )"; |
| |
| // Given DWARF like this: |
| // |
| // 0x0000000b: DW_TAG_compile_unit |
| // |
| // 0x0000000c: DW_TAG_subprogram |
| // DW_AT_abstract_origin (0x0000000000000022) |
| // |
| // 0x00000011: NULL |
| // |
| // 0x0000001d: DW_TAG_compile_unit |
| // DW_AT_stmt_list (0x00000000) |
| // |
| // 0x00000022: DW_TAG_subprogram |
| // DW_AT_decl_file ("/tmp/main.cpp") |
| // |
| // 0x00000024: NULL |
| // |
| // This tests that when we have a DW_AT_abstract_origin with a |
| // DW_FORM_ref_addr to another DIE in another compile unit that we use the |
| // right file table when converting the file index of the DW_AT_decl_file. |
| // |
| // The DIE at 0x0000000c uses a DW_AT_abstract_origin to point to the DIE at |
| // 0x00000022, make sure that DWARFDie::getDeclFile() succeeds by extracting |
| // the right file name of "/tmp/main.cpp". The DW_AT_decl_file must grab the |
| // file from the line table prologue of the compile unit at offset |
| // 0x0000001d. |
| |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); |
| ASSERT_TRUE(Die.isValid()); |
| |
| DWARFDie MainDie = Die.getFirstChild(); |
| ASSERT_TRUE(MainDie.isValid()); |
| |
| std::string DeclFile = MainDie.getDeclFile( |
| DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); |
| |
| std::string Ref = |
| ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); |
| EXPECT_EQ(DeclFile, Ref); |
| } |
| |
| TEST(DWARFDie, getDeclFileSpecificationAcrossCUBoundary) { |
| const char *yamldata = R"( |
| debug_str: |
| - '' |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| - Code: 0x2 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_specification |
| Form: DW_FORM_ref_addr |
| - Code: 0x3 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_stmt_list |
| Form: DW_FORM_sec_offset |
| - Code: 0x4 |
| Tag: DW_TAG_subprogram |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_decl_file |
| Form: DW_FORM_data1 |
| debug_info: |
| - Length: 0xE |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x1 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0x22 |
| - AbbrCode: 0x0 |
| - Length: 0xF |
| Version: 4 |
| AbbrevTableID: 0 |
| AbbrOffset: 0x0 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x3 |
| Values: |
| - Value: 0x0 |
| - AbbrCode: 0x4 |
| Values: |
| - Value: 0x1 |
| - AbbrCode: 0x0 |
| debug_line: |
| - Length: 42 |
| Version: 2 |
| PrologueLength: 36 |
| MinInstLength: 1 |
| DefaultIsStmt: 1 |
| LineBase: 251 |
| LineRange: 14 |
| OpcodeBase: 13 |
| StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] |
| IncludeDirs: |
| - '/tmp' |
| Files: |
| - Name: main.cpp |
| DirIdx: 1 |
| ModTime: 0 |
| Length: 0 |
| )"; |
| |
| // Given DWARF like this: |
| // |
| // 0x0000000b: DW_TAG_compile_unit |
| // |
| // 0x0000000c: DW_TAG_subprogram |
| // DW_AT_specification (0x0000000000000022) |
| // |
| // 0x00000011: NULL |
| // |
| // 0x0000001d: DW_TAG_compile_unit |
| // DW_AT_stmt_list (0x00000000) |
| // |
| // 0x00000022: DW_TAG_subprogram |
| // DW_AT_decl_file ("/tmp/main.cpp") |
| // |
| // 0x00000024: NULL |
| // |
| // This tests that when we have a DW_AT_specification with a |
| // DW_FORM_ref_addr to another DIE in another compile unit that we use the |
| // right file table when converting the file index of the DW_AT_decl_file. |
| // |
| // The DIE at 0x0000000c uses a DW_AT_specification to point to the DIE at |
| // 0x00000022, make sure that DWARFDie::getDeclFile() succeeds by extracting |
| // the right file name of "/tmp/main.cpp". The DW_AT_decl_file must grab the |
| // file from the line table prologue of the compile unit at offset |
| // 0x0000001d. |
| |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); |
| ASSERT_TRUE(Die.isValid()); |
| |
| DWARFDie MainDie = Die.getFirstChild(); |
| ASSERT_TRUE(MainDie.isValid()); |
| |
| std::string DeclFile = MainDie.getDeclFile( |
| DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); |
| |
| std::string Ref = |
| ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str(); |
| EXPECT_EQ(DeclFile, Ref); |
| } |
| |
| TEST(DWARFDie, getNameFromTypeUnit) { |
| const char *yamldata = R"( |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| - Code: 0x2 |
| Tag: DW_TAG_structure_type |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_signature |
| Form: DW_FORM_ref_sig8 |
| - Code: 0x3 |
| Tag: DW_TAG_type_unit |
| Children: DW_CHILDREN_yes |
| - Code: 0x4 |
| Tag: DW_TAG_structure_type |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_name |
| Form: DW_FORM_string |
| debug_info: |
| - Version: 5 |
| UnitType: DW_UT_compile |
| AbbrevTableID: 0 |
| Entries: |
| - AbbrCode: 0x1 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0xdeadbeefbaadf00d |
| - AbbrCode: 0x0 |
| - Version: 5 |
| UnitType: DW_UT_type |
| AbbrevTableID: 0 |
| TypeSignature: 0xdeadbeefbaadf00d |
| TypeOffset: 25 |
| Entries: |
| - AbbrCode: 0x3 |
| - AbbrCode: 0x4 |
| Values: |
| - CStr: "STRUCT" |
| - AbbrCode: 0x0 |
| )"; |
| |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); |
| ASSERT_NE(nullptr, CU); |
| DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false).getFirstChild(); |
| ASSERT_TRUE(Die.isValid()); |
| |
| ASSERT_STREQ(Die.getName(DINameKind::ShortName), "STRUCT"); |
| } |
| |
| void testAppendAndTerminateTemplateParameters(const DWARFDie &DIE, |
| const std::string &Expected) { |
| std::string TemplateName; |
| llvm::raw_string_ostream TemplateNameOS(TemplateName); |
| llvm::DWARFTypePrinter<DWARFDie> TemplateNamePrinter(TemplateNameOS); |
| TemplateNamePrinter.appendAndTerminateTemplateParameters(DIE); |
| EXPECT_THAT(TemplateName, Expected); |
| } |
| |
| void testAppendQualifiedName(const DWARFDie &DIE, const std::string &Expected) { |
| std::string QualifiedName; |
| llvm::raw_string_ostream TemplateNameOS(QualifiedName); |
| llvm::DWARFTypePrinter<DWARFDie> TemplateNamePrinter(TemplateNameOS); |
| TemplateNamePrinter.appendQualifiedName(DIE); |
| EXPECT_THAT(QualifiedName, Expected); |
| } |
| |
| TEST(DWARFDie, DWARFTypePrinterTest) { |
| // Make sure we can get template parameters and qualified names correctly with |
| // DWARFTypePrinter when using -gsimple-template-names. |
| |
| // 0x0000000b: DW_TAG_compile_unit |
| // 0x0000000c: DW_TAG_base_type |
| // DW_AT_name ("int") |
| // 0x00000011: DW_TAG_structure_type |
| // DW_AT_name ("t1") |
| // 0x00000015: DW_TAG_template_type_parameter |
| // DW_AT_type (0x0000001f "t3<int>") |
| // 0x0000001a: DW_TAG_structure_type |
| // DW_AT_name ("t2") |
| // 0x0000001e: NULL |
| // 0x0000001f: DW_TAG_structure_type |
| // DW_AT_name ("t3") |
| // 0x00000023: DW_TAG_template_type_parameter |
| // DW_AT_type (0x0000000c "int") |
| // 0x00000028: NULL |
| // 0x00000029: NULL |
| const char *yamldata = R"( |
| debug_abbrev: |
| - ID: 0 |
| Table: |
| - Code: 0x1 |
| Tag: DW_TAG_compile_unit |
| Children: DW_CHILDREN_yes |
| - Code: 0x2 |
| Tag: DW_TAG_base_type |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_name |
| Form: DW_FORM_string |
| - Code: 0x3 |
| Tag: DW_TAG_structure_type |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_name |
| Form: DW_FORM_string |
| - Code: 0x4 |
| Tag: DW_TAG_template_type_parameter |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_type |
| Form: DW_FORM_ref4 |
| - Code: 0x5 |
| Tag: DW_TAG_structure_type |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_name |
| Form: DW_FORM_string |
| - Code: 0x6 |
| Tag: DW_TAG_structure_type |
| Children: DW_CHILDREN_yes |
| Attributes: |
| - Attribute: DW_AT_name |
| Form: DW_FORM_string |
| - Code: 0x7 |
| Tag: DW_TAG_template_type_parameter |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_type |
| Form: DW_FORM_ref4 |
| - Code: 0x8 |
| Tag: DW_TAG_typedef |
| Children: DW_CHILDREN_no |
| Attributes: |
| - Attribute: DW_AT_type |
| Form: DW_FORM_ref4 |
| - Attribute: DW_AT_name |
| Form: DW_FORM_string |
| debug_info: |
| - Version: 4 |
| AddrSize: 8 |
| Entries: |
| - AbbrCode: 0x1 |
| - AbbrCode: 0x2 |
| Values: |
| - Value: 0xDEADBEEFDEADBEEF |
| CStr: int |
| - AbbrCode: 0x3 |
| Values: |
| - Value: 0xDEADBEEFDEADBEEF |
| CStr: t1 |
| - AbbrCode: 0x4 |
| Values: |
| - Value: 0x0000001f # update |
| - AbbrCode: 0x5 |
| Values: |
| - Value: 0xDEADBEEFDEADBEEF |
| CStr: t2 |
| - AbbrCode: 0x0 |
| - AbbrCode: 0x6 |
| Values: |
| - Value: 0xDEADBEEFDEADBEEF |
| CStr: t3 |
| - AbbrCode: 0x7 |
| Values: |
| - Value: 0x0000000c # update |
| - AbbrCode: 0x8 |
| Values: |
| - Value: 0x0000000c |
| - CStr: my_int |
| - AbbrCode: 0x0 |
| - AbbrCode: 0x0)"; |
| Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = |
| DWARFYAML::emitDebugSections(StringRef(yamldata), |
| /*IsLittleEndian=*/true, |
| /*Is64BitAddrSize=*/true); |
| ASSERT_THAT_EXPECTED(Sections, Succeeded()); |
| std::unique_ptr<DWARFContext> Ctx = |
| DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); |
| testAppendAndTerminateTemplateParameters(Ctx->getDIEForOffset(0x11), |
| "<t3<int> >"); |
| testAppendQualifiedName(Ctx->getDIEForOffset(0x1a), "t1<t3<int> >::t2"); |
| testAppendQualifiedName(Ctx->getDIEForOffset(0x28), "t3<int>::my_int"); |
| } |
| } // end anonymous namespace |