[llvm] a58c2e4 - Fix DWARFDie::getDeclFile(...) to work with DW_AT_specification.
Greg Clayton via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 23 15:43:30 PDT 2021
Author: Greg Clayton
Date: 2021-08-23T15:43:18-07:00
New Revision: a58c2e4af06c9d1d6d6559cf29da4384cd7e828e
URL: https://github.com/llvm/llvm-project/commit/a58c2e4af06c9d1d6d6559cf29da4384cd7e828e
DIFF: https://github.com/llvm/llvm-project/commit/a58c2e4af06c9d1d6d6559cf29da4384cd7e828e.diff
LOG: 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
Added:
Modified:
llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 56549cd3d3bc9..3c051c3ea0186 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -119,6 +119,19 @@ class DWARFFormValue {
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.
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 2d5cd864f718c..b3d361b1a3d69 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -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,
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
index 2244a69bc1214..a03446b13d948 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -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;
+}
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
index 5525ae6b7884f..d40bf6445f40d 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
@@ -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
More information about the llvm-commits
mailing list