blob: f566bee1702364b9906ab7c3bcccc0adc3749912 [file] [log] [blame] [edit]
//===- 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