[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