[lld] r328284 - Fix PR36793.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 22 17:35:27 PDT 2018


Author: rafael
Date: Thu Mar 22 17:35:27 2018
New Revision: 328284

URL: http://llvm.org/viewvc/llvm-project?rev=328284&view=rev
Log:
Fix PR36793.

With this patch lld will iterate over compile units to find the line
tables instead of assuming there is only one at offset 0.

Added:
    lld/trunk/test/ELF/Inputs/multiple-cu.s
    lld/trunk/test/ELF/multiple-cu.s
Modified:
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=328284&r1=328283&r2=328284&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Thu Mar 22 17:35:27 2018
@@ -115,51 +115,46 @@ std::string InputFile::getSrcMsg(const S
 }
 
 template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
-  DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(this));
-  const DWARFObject &Obj = Dwarf.getDWARFObj();
+  Dwarf = make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this));
+  const DWARFObject &Obj = Dwarf->getDWARFObj();
   DwarfLine.reset(new DWARFDebugLine);
   DWARFDataExtractor LineData(Obj, Obj.getLineSection(), Config->IsLE,
                               Config->Wordsize);
 
-  // The second parameter is offset in .debug_line section
-  // for compilation unit (CU) of interest. We have only one
-  // CU (object file), so offset is always 0.
-  const DWARFDebugLine::LineTable *LT =
-      DwarfLine->getOrParseLineTable(LineData, 0, Dwarf, nullptr);
-  if (!LT)
-    return;
-
-  // Return if there is no debug information about CU available.
-  if (!Dwarf.getNumCompileUnits())
-    return;
-
-  // Loop over variable records and insert them to VariableLoc.
-  DWARFCompileUnit *CU = Dwarf.getCompileUnitAtIndex(0);
-  for (const auto &Entry : CU->dies()) {
-    DWARFDie Die(CU, &Entry);
-    // Skip all tags that are not variables.
-    if (Die.getTag() != dwarf::DW_TAG_variable)
+  for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf->compile_units()) {
+    const DWARFDebugLine::LineTable *LT = Dwarf->getLineTableForUnit(CU.get());
+    if (!LT)
       continue;
+    LineTables.push_back(LT);
 
-    // Skip if a local variable because we don't need them for generating error
-    // messages. In general, only non-local symbols can fail to be linked.
-    if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
-      continue;
-
-    // Get the source filename index for the variable.
-    unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
-    if (!LT->hasFileAtIndex(File))
-      continue;
-
-    // Get the line number on which the variable is declared.
-    unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
-
-    // Get the name of the variable and add the collected information to
-    // VariableLoc. Usually Name is non-empty, but it can be empty if the input
-    // object file lacks some debug info.
-    StringRef Name = dwarf::toString(Die.find(dwarf::DW_AT_name), "");
-    if (!Name.empty())
-      VariableLoc.insert({Name, {File, Line}});
+    // Loop over variable records and insert them to VariableLoc.
+    for (const auto &Entry : CU->dies()) {
+      DWARFDie Die(CU.get(), &Entry);
+      // Skip all tags that are not variables.
+      if (Die.getTag() != dwarf::DW_TAG_variable)
+        continue;
+
+      // Skip if a local variable because we don't need them for generating
+      // error messages. In general, only non-local symbols can fail to be
+      // linked.
+      if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
+        continue;
+
+      // Get the source filename index for the variable.
+      unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
+      if (!LT->hasFileAtIndex(File))
+        continue;
+
+      // Get the line number on which the variable is declared.
+      unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
+
+      // Get the name of the variable and add the collected information to
+      // VariableLoc. Usually Name is non-empty, but it can be empty if the
+      // input object file lacks some debug info.
+      StringRef Name = dwarf::toString(Die.find(dwarf::DW_AT_name), "");
+      if (!Name.empty())
+        VariableLoc.insert({Name, {LT, File, Line}});
+    }
   }
 }
 
@@ -170,11 +165,6 @@ Optional<std::pair<std::string, unsigned
 ObjFile<ELFT>::getVariableLoc(StringRef Name) {
   llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
 
-  // There is always only one CU so it's offset is 0.
-  const DWARFDebugLine::LineTable *LT = DwarfLine->getLineTable(0);
-  if (!LT)
-    return None;
-
   // Return if we have no debug information about data object.
   auto It = VariableLoc.find(Name);
   if (It == VariableLoc.end())
@@ -182,7 +172,7 @@ ObjFile<ELFT>::getVariableLoc(StringRef
 
   // Take file name string from line table.
   std::string FileName;
-  if (!LT->getFileNameByIndex(
+  if (!It->second.LT->getFileNameByIndex(
           It->second.File, nullptr,
           DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))
     return None;
@@ -197,20 +187,15 @@ Optional<DILineInfo> ObjFile<ELFT>::getD
                                                   uint64_t Offset) {
   llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
 
-  // The offset to CU is 0.
-  const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0);
-  if (!Tbl)
-    return None;
-
   // Use fake address calcuated by adding section file offset and offset in
   // section. See comments for ObjectInfo class.
   DILineInfo Info;
-  Tbl->getFileLineInfoForAddress(
-      S->getOffsetInFile() + Offset, nullptr,
-      DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info);
-  if (Info.Line == 0)
-    return None;
-  return Info;
+  for (const llvm::DWARFDebugLine::LineTable *LT : LineTables)
+    if (LT->getFileLineInfoForAddress(
+            S->getOffsetInFile() + Offset, nullptr,
+            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info))
+      return Info;
+  return None;
 }
 
 // Returns source line information for a given offset using DWARF debug info.

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=328284&r1=328283&r2=328284&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Thu Mar 22 17:35:27 2018
@@ -17,6 +17,7 @@
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ELF.h"
@@ -25,7 +26,6 @@
 #include <map>
 
 namespace llvm {
-class DWARFDebugLine;
 class TarWriter;
 struct DILineInfo;
 namespace lto {
@@ -215,8 +215,11 @@ private:
   // reporting. Linker may find reasonable number of errors in a
   // single object file, so we cache debugging information in order to
   // parse it only once for each object file we link.
+  std::unique_ptr<llvm::DWARFContext> Dwarf;
+  std::vector<const llvm::DWARFDebugLine::LineTable *> LineTables;
   std::unique_ptr<llvm::DWARFDebugLine> DwarfLine;
   struct VarLoc {
+    const llvm::DWARFDebugLine::LineTable *LT;
     unsigned File;
     unsigned Line;
   };

Added: lld/trunk/test/ELF/Inputs/multiple-cu.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/multiple-cu.s?rev=328284&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/multiple-cu.s (added)
+++ lld/trunk/test/ELF/Inputs/multiple-cu.s Thu Mar 22 17:35:27 2018
@@ -0,0 +1,24 @@
+        .file   1 "test2.c"
+        .loc    1 2 0
+        jmp     bar
+
+        .section        .debug_abbrev,"", at progbits
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   0                       # DW_CHILDREN_no
+        .byte   16                      # DW_AT_stmt_list
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+
+        .section        .debug_info,"", at progbits
+        .long   .Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+        .short  4                       # DWARF version number
+        .long   .debug_abbrev           # Offset Into Abbrev. Section
+        .byte   8                       # Address Size (in bytes)
+        .byte   1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+        .long   .debug_line             # DW_AT_stmt_list
+.Lend0:
+        .section        .debug_line,"", at progbits

Added: lld/trunk/test/ELF/multiple-cu.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/multiple-cu.s?rev=328284&view=auto
==============================================================================
--- lld/trunk/test/ELF/multiple-cu.s (added)
+++ lld/trunk/test/ELF/multiple-cu.s Thu Mar 22 17:35:27 2018
@@ -0,0 +1,38 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/multiple-cu.s -o %t2.o
+# RUN: ld.lld -r -o %t.o %t1.o %t2.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# CHECK:      error: undefined symbol: foo
+# CHECK-NEXT: referenced by test1.c:2
+
+# CHECK:      error: undefined symbol: bar
+# CHECK-NEXT: referenced by test2.c:2
+
+        .globl  _start
+_start:
+        .file   1 "test1.c"
+        .loc    1 2 0
+        jmp     foo
+
+        .section        .debug_abbrev,"", at progbits
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   0                       # DW_CHILDREN_no
+        .byte   16                      # DW_AT_stmt_list
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+
+        .section        .debug_info,"", at progbits
+        .long   .Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+        .short  4                       # DWARF version number
+        .long   .debug_abbrev           # Offset Into Abbrev. Section
+        .byte   8                       # Address Size (in bytes)
+        .byte   1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+        .long   .debug_line             # DW_AT_stmt_list
+.Lend0:
+        .section        .debug_line,"", at progbits




More information about the llvm-commits mailing list