[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