forked from OSchip/llvm-project
Fix DWARFDie::getDeclFile(...) to work with DW_AT_specification.
DWARFDie::getDeclFile(...) previously only supported getting the DW_AT_decl_file if the DIE itself contained the DW_AT_decl_file attribute, or if the DIE had a DW_AT_abstract_origin that pointed to another DIE that had a DW_AT_decl_file. This patch allows the function to get the right attribute value if there is a DW_AT_specification that points to another DIE. We also test that if a DW_AT_abtract_origin or DW_AT_specification points to a DIE in another CU with a DW_FORM_ref_addr, that the right line table is used to extract the file index. Full tests were added for the following cases: - DIE has a DW_AT_decl_file attribute - DIE has a DW_AT_abtract_origin that points to another die in the same CU - DIE has a DW_AT_abtract_origin that points to another die in another CU - DIE has a DW_AT_specification that points to another die in the same CU - DIE has a DW_AT_specification that points to another die in another CU Differential Revision: https://reviews.llvm.org/D108480
This commit is contained in:
parent
d26000e4cc
commit
a58c2e4af0
|
@ -119,6 +119,19 @@ public:
|
|||
Optional<ArrayRef<uint8_t>> getAsBlock() const;
|
||||
Optional<uint64_t> getAsCStringOffset() const;
|
||||
Optional<uint64_t> getAsReferenceUVal() const;
|
||||
/// Correctly extract any file paths from a form value.
|
||||
///
|
||||
/// These attributes can be in the from DW_AT_decl_file or DW_AT_call_file
|
||||
/// attributes. We need to use the file index in the correct DWARFUnit's line
|
||||
/// table prologue, and each DWARFFormValue has the DWARFUnit the form value
|
||||
/// was extracted from.
|
||||
///
|
||||
/// \param Kind The kind of path to extract.
|
||||
///
|
||||
/// \returns A valid string value on success, or llvm::None if the form class
|
||||
/// is not FC_Constant, or if the file index is not valid.
|
||||
Optional<std::string>
|
||||
getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const;
|
||||
|
||||
/// Skip a form's value in \p DebugInfoData at the offset specified by
|
||||
/// \p OffsetPtr.
|
||||
|
|
|
@ -566,18 +566,10 @@ uint64_t DWARFDie::getDeclLine() const {
|
|||
|
||||
std::string
|
||||
DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
|
||||
auto D = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
|
||||
if (!D)
|
||||
D = *this;
|
||||
std::string FileName;
|
||||
if (auto DeclFile = toUnsigned(D.find(DW_AT_decl_file))) {
|
||||
if (const auto *LineTable =
|
||||
getDwarfUnit()->getContext().getLineTableForUnit(
|
||||
D.getDwarfUnit()->getLinkedUnit()))
|
||||
LineTable->getFileNameByIndex(
|
||||
*DeclFile, D.getDwarfUnit()->getCompilationDir(), Kind, FileName);
|
||||
}
|
||||
return FileName;
|
||||
if (auto FormValue = findRecursively(DW_AT_decl_file))
|
||||
if (auto OptString = FormValue->getAsFile(Kind))
|
||||
return *OptString;
|
||||
return {};
|
||||
}
|
||||
|
||||
void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
|
||||
|
|
|
@ -690,7 +690,7 @@ Optional<uint64_t> DWARFFormValue::getAsReference() const {
|
|||
return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset;
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
Optional<DWARFFormValue::UnitOffset> DWARFFormValue::getAsRelativeReference() const {
|
||||
if (!isFormClass(FC_Reference))
|
||||
return None;
|
||||
|
@ -762,3 +762,17 @@ Optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
|
|||
return None;
|
||||
return Value.uval;
|
||||
}
|
||||
|
||||
Optional<std::string>
|
||||
DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
|
||||
if (U == nullptr || !isFormClass(FC_Constant))
|
||||
return None;
|
||||
DWARFUnit *DU = const_cast<DWARFUnit *>(U);
|
||||
if (auto *LT = U->getContext().getLineTableForUnit(DU->getLinkedUnit())) {
|
||||
std::string FileName;
|
||||
if (LT->getFileNameByIndex(Value.uval, DU->getCompilationDir(), Kind,
|
||||
FileName))
|
||||
return FileName;
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -100,4 +100,557 @@ TEST(DWARFDie, getLocations) {
|
|||
"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);
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(DeclFile, "/tmp\\main.cpp");
|
||||
#else
|
||||
EXPECT_EQ(DeclFile, "/tmp/main.cpp");
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(DeclFile, "/tmp\\main.cpp");
|
||||
#else
|
||||
EXPECT_EQ(DeclFile, "/tmp/main.cpp");
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(DeclFile, "/tmp\\main.cpp");
|
||||
#else
|
||||
EXPECT_EQ(DeclFile, "/tmp/main.cpp");
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(DeclFile, "/tmp\\main.cpp");
|
||||
#else
|
||||
EXPECT_EQ(DeclFile, "/tmp/main.cpp");
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(DeclFile, "/tmp\\main.cpp");
|
||||
#else
|
||||
EXPECT_EQ(DeclFile, "/tmp/main.cpp");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
Loading…
Reference in New Issue