[lld] r375218 - [LLD] [COFF] Try to report source locations for duplicate symbols

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 18 03:43:15 PDT 2019


Author: mstorsjo
Date: Fri Oct 18 03:43:15 2019
New Revision: 375218

URL: http://llvm.org/viewvc/llvm-project?rev=375218&view=rev
Log:
[LLD] [COFF] Try to report source locations for duplicate symbols

This fixes the second part of PR42407.

For files with dwarf debug info, it manually loads and iterates
.debug_info to find the declared location of variables, to allow
reporting them. (This matches the corresponding code in the ELF
linker.)

For functions, it uses the existing getFileLineDwarf which uses
LLVMSymbolizer for translating addresses to file lines.

In object files with codeview debug info, only the source location
of duplicate functions is printed. (And even there, only for the
first input file. The getFileLineCodeView function requires the
object file to be fully loaded and initialized to properly resolve
source locations, but duplicate symbols are reported at a stage when
the second object file isn't fully loaded yet.)

Differential Revision: https://reviews.llvm.org/D68975

Added:
    lld/trunk/test/COFF/duplicate-cv.s
    lld/trunk/test/COFF/duplicate-dwarf.s
Modified:
    lld/trunk/COFF/InputFiles.cpp
    lld/trunk/COFF/InputFiles.h
    lld/trunk/COFF/SymbolTable.cpp
    lld/trunk/COFF/SymbolTable.h
    lld/trunk/test/COFF/conflict-mangled.test
    lld/trunk/test/COFF/conflict.test
    lld/trunk/test/COFF/duplicate.test

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Fri Oct 18 03:43:15 2019
@@ -382,7 +382,8 @@ Symbol *ObjFile::createRegular(COFFSymbo
     StringRef name;
     coffObj->getSymbolName(sym, name);
     if (sc)
-      return symtab->addRegular(this, name, sym.getGeneric(), sc);
+      return symtab->addRegular(this, name, sym.getGeneric(), sc,
+                                sym.getValue());
     // For MinGW symbols named .weak.* that point to a discarded section,
     // don't create an Undefined symbol. If nothing ever refers to the symbol,
     // everything should be fine. If something actually refers to the symbol
@@ -536,7 +537,7 @@ void ObjFile::handleComdatSelection(COFF
     // if the two comdat sections have e.g. different alignment.
     // Match that.
     if (leaderChunk->getContents() != newChunk.getContents())
-      symtab->reportDuplicate(leader, this);
+      symtab->reportDuplicate(leader, this, &newChunk, sym.getValue());
     break;
   }
 
@@ -788,6 +789,89 @@ void ObjFile::initializeDependencies() {
   debugTypesObj = makeTpiSource(this);
 }
 
+// Used only for DWARF debug info, which is not common (except in MinGW
+// environments). This returns an optional pair of file name and line
+// number for where the variable was defined.
+Optional<std::pair<StringRef, uint32_t>>
+ObjFile::getVariableLocation(StringRef var) {
+  if (!dwarf) {
+    dwarf = DWARFContext::create(*getCOFFObj());
+    if (!dwarf)
+      return None;
+    initializeDwarf();
+  }
+  if (config->machine == I386)
+    var.consume_front("_");
+  auto it = variableLoc.find(var);
+  if (it == variableLoc.end())
+    return None;
+
+  // Take file name string from line table.
+  std::string fileName;
+  if (!it->second.lt->getFileNameByIndex(
+          it->second.file, {},
+          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
+    return None;
+
+  return std::make_pair(saver.save(fileName), it->second.line);
+}
+
+// Used only for DWARF debug info, which is not common (except in MinGW
+// environments). This initializes the dwarf, lineTables and variableLoc
+// members.
+void ObjFile::initializeDwarf() {
+  for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
+    auto report = [](Error err) {
+      handleAllErrors(std::move(err),
+                      [](ErrorInfoBase &info) { warn(info.message()); });
+    };
+    Expected<const DWARFDebugLine::LineTable *> expectedLT =
+        dwarf->getLineTableForUnit(cu.get(), report);
+    const DWARFDebugLine::LineTable *lt = nullptr;
+    if (expectedLT)
+      lt = *expectedLT;
+    else
+      report(expectedLT.takeError());
+    if (!lt)
+      continue;
+    lineTables.push_back(lt);
+
+    // 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);
+
+      // Here we want to take the variable name to add it into variableLoc.
+      // Variable can have regular and linkage name associated. At first, we try
+      // to get linkage name as it can be different, for example when we have
+      // two variables in different namespaces of the same object. Use common
+      // name otherwise, but handle the case when it also absent in case if the
+      // input object file lacks some debug info.
+      StringRef name =
+          dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
+                          dwarf::toString(die.find(dwarf::DW_AT_name), ""));
+      if (!name.empty())
+        variableLoc.insert({name, {lt, file, line}});
+    }
+  }
+}
+
 StringRef ltrim1(StringRef s, const char *chars) {
   if (!s.empty() && strchr(chars, s[0]))
     return s.substr(1);

Modified: lld/trunk/COFF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.h (original)
+++ lld/trunk/COFF/InputFiles.h Fri Oct 18 03:43:15 2019
@@ -16,6 +16,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/COFF.h"
@@ -202,6 +203,9 @@ public:
   // The .debug$T stream if there's one.
   llvm::Optional<llvm::codeview::CVTypeArray> debugTypes;
 
+  llvm::Optional<std::pair<StringRef, uint32_t>>
+  getVariableLocation(StringRef var);
+
 private:
   const coff_section* getSection(uint32_t i);
   const coff_section *getSection(COFFSymbolRef sym) {
@@ -212,6 +216,7 @@ private:
   void initializeSymbols();
   void initializeFlags();
   void initializeDependencies();
+  void initializeDwarf();
 
   SectionChunk *
   readSection(uint32_t sectionNumber,
@@ -285,6 +290,15 @@ private:
   // index. Nonexistent indices (which are occupied by auxiliary
   // symbols in the real symbol table) are filled with null pointers.
   std::vector<Symbol *> symbols;
+
+  std::unique_ptr<llvm::DWARFContext> dwarf;
+  std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
+  struct VarLoc {
+    const llvm::DWARFDebugLine::LineTable *lt;
+    unsigned file;
+    unsigned line;
+  };
+  llvm::DenseMap<StringRef, VarLoc> variableLoc;
 };
 
 // This type represents import library members that contain DLL names

Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Fri Oct 18 03:43:15 2019
@@ -520,15 +520,69 @@ void SymbolTable::addLazyObject(LazyObjF
   f->fetch();
 }
 
-void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile) {
-  std::string msg = "duplicate symbol: " + toString(*existing) + " in " +
-                    toString(existing->getFile()) + " and in " +
-                    toString(newFile);
+static std::string getSourceLocationBitcode(BitcodeFile *file) {
+  std::string res("\n>>> defined at ");
+  StringRef source = file->obj->getSourceFileName();
+  if (!source.empty())
+    res += source.str() + "\n>>>            ";
+  res += toString(file);
+  return res;
+}
+
+static std::string getSourceLocationObj(ObjFile *file, SectionChunk *sc,
+                                        uint32_t offset, StringRef name) {
+  Optional<std::pair<StringRef, uint32_t>> fileLine;
+  if (sc)
+    fileLine = getFileLine(sc, offset);
+  if (!fileLine)
+    fileLine = file->getVariableLocation(name);
+
+  std::string res;
+  llvm::raw_string_ostream os(res);
+  os << "\n>>> defined at ";
+  if (fileLine)
+    os << fileLine->first << ":" << fileLine->second << "\n>>>            ";
+  os << toString(file);
+  return os.str();
+}
+
+static std::string getSourceLocation(InputFile *file, SectionChunk *sc,
+                                     uint32_t offset, StringRef name) {
+  if (auto *o = dyn_cast<ObjFile>(file))
+    return getSourceLocationObj(o, sc, offset, name);
+  if (auto *b = dyn_cast<BitcodeFile>(file))
+    return getSourceLocationBitcode(b);
+  return "\n>>> defined at " + toString(file);
+}
+
+// Construct and print an error message in the form of:
+//
+//   lld-link: error: duplicate symbol: foo
+//   >>> defined at bar.c:30
+//   >>>            bar.o
+//   >>> defined at baz.c:563
+//   >>>            baz.o
+void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile,
+                                  SectionChunk *newSc,
+                                  uint32_t newSectionOffset) {
+  std::string msg;
+  llvm::raw_string_ostream os(msg);
+  os << "duplicate symbol: " << toString(*existing);
+
+  DefinedRegular *d = cast<DefinedRegular>(existing);
+  if (d && isa<ObjFile>(d->getFile())) {
+    os << getSourceLocation(d->getFile(), d->getChunk(), d->getValue(),
+                            existing->getName());
+  } else {
+    os << getSourceLocation(existing->getFile(), nullptr, 0, "");
+  }
+  os << getSourceLocation(newFile, newSc, newSectionOffset,
+                          existing->getName());
 
   if (config->forceMultiple)
-    warn(msg);
+    warn(os.str());
   else
-    error(msg);
+    error(os.str());
 }
 
 Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) {
@@ -568,8 +622,8 @@ Symbol *SymbolTable::addSynthetic(String
 }
 
 Symbol *SymbolTable::addRegular(InputFile *f, StringRef n,
-                                const coff_symbol_generic *sym,
-                                SectionChunk *c) {
+                                const coff_symbol_generic *sym, SectionChunk *c,
+                                uint32_t sectionOffset) {
   Symbol *s;
   bool wasInserted;
   std::tie(s, wasInserted) = insert(n, f);
@@ -577,7 +631,7 @@ Symbol *SymbolTable::addRegular(InputFil
     replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ false,
                                   /*IsExternal*/ true, sym, c);
   else
-    reportDuplicate(s, f);
+    reportDuplicate(s, f, c, sectionOffset);
   return s;
 }
 

Modified: lld/trunk/COFF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.h (original)
+++ lld/trunk/COFF/SymbolTable.h Fri Oct 18 03:43:15 2019
@@ -91,7 +91,7 @@ public:
   Symbol *addAbsolute(StringRef n, COFFSymbolRef s);
   Symbol *addRegular(InputFile *f, StringRef n,
                      const llvm::object::coff_symbol_generic *s = nullptr,
-                     SectionChunk *c = nullptr);
+                     SectionChunk *c = nullptr, uint32_t sectionOffset = 0);
   std::pair<DefinedRegular *, bool>
   addComdat(InputFile *f, StringRef n,
             const llvm::object::coff_symbol_generic *s = nullptr);
@@ -103,7 +103,9 @@ public:
                          uint16_t machine);
   void addLibcall(StringRef name);
 
-  void reportDuplicate(Symbol *existing, InputFile *newFile);
+  void reportDuplicate(Symbol *existing, InputFile *newFile,
+                       SectionChunk *newSc = nullptr,
+                       uint32_t newSectionOffset = 0);
 
   // A list of chunks which to be added to .rdata.
   std::vector<Chunk *> localImportChunks;

Modified: lld/trunk/test/COFF/conflict-mangled.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/conflict-mangled.test?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/test/COFF/conflict-mangled.test (original)
+++ lld/trunk/test/COFF/conflict-mangled.test Fri Oct 18 03:43:15 2019
@@ -5,9 +5,13 @@
 # RUN: not lld-link /out:%t.exe /demangle %t1.obj %t2.obj 2>&1 | FileCheck %s
 # RUN: not lld-link /out:%t.exe /demangle:no %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=NODEMANGLE %s
 
-# NODEMANGLE: duplicate symbol: ?mangled@@YAHXZ in {{.+}}1.obj and in {{.+}}2.obj
+# NODEMANGLE: duplicate symbol: ?mangled@@YAHXZ
+# NODEMANGLE: defined at {{.+}}1.obj
+# NODEMANGLE: defined at {{.+}}2.obj
 
-# CHECK: duplicate symbol: int __cdecl mangled(void) in {{.+}}1.obj and in {{.+}}2.obj
+# CHECK: duplicate symbol: int __cdecl mangled(void)
+# CHECK: defined at {{.+}}1.obj
+# CHECK: defined at {{.+}}2.obj
 
 --- !COFF
 header:

Modified: lld/trunk/test/COFF/conflict.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/conflict.test?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/test/COFF/conflict.test (original)
+++ lld/trunk/test/COFF/conflict.test Fri Oct 18 03:43:15 2019
@@ -1,15 +1,21 @@
 # REQUIRES: x86
 # RUN: yaml2obj < %s > %t1.obj
 # RUN: yaml2obj < %s > %t2.obj
-# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log
-# RUN: FileCheck %s < %t.log
+# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=OBJ %s
 
 # RUN: llvm-as -o %t.lto1.obj %S/Inputs/conflict.ll
 # RUN: llvm-as -o %t.lto2.obj %S/Inputs/conflict.ll
-# RUN: not lld-link /out:%t.exe %t.lto1.obj %t.lto2.obj >& %t.log
-# RUN: FileCheck %s < %t.log
+# RUN: not lld-link /out:%t.exe %t.lto1.obj %t.lto2.obj 2>&1 | FileCheck --check-prefix=BC %s
 
-# CHECK: duplicate symbol: foo in {{.+}}1.obj and in {{.+}}2.obj
+# OBJ: duplicate symbol: foo
+# OBJ: defined at {{.+}}1.obj
+# OBJ: defined at {{.+}}2.obj
+
+# BC: duplicate symbol: foo
+# BC: defined at {{.+}}conflict.ll
+# BC:            {{.+}}1.obj
+# BC: defined at {{.+}}conflict.ll
+# BC:            {{.+}}2.obj
 
 --- !COFF
 header:

Added: lld/trunk/test/COFF/duplicate-cv.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/duplicate-cv.s?rev=375218&view=auto
==============================================================================
--- lld/trunk/test/COFF/duplicate-cv.s (added)
+++ lld/trunk/test/COFF/duplicate-cv.s Fri Oct 18 03:43:15 2019
@@ -0,0 +1,30 @@
+# REQUIRES: x86
+# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
+# RUN: cp %t.obj %t.dupl.obj
+# RUN: not lld-link /out:%t.exe %t.obj %t.dupl.obj 2>&1 | FileCheck %s
+
+# CHECK: error: duplicate symbol: main
+# CHECK-NEXT: >>> defined at file1.cpp:2
+# CHECK-NEXT: >>>            {{.*}}.obj
+# CHECK-NEXT: >>> defined at {{.*}}.obj
+
+	.cv_file	1 "file1.cpp" "EDA15C78BB573E49E685D8549286F33C" 1
+	.cv_file	2 "file2.cpp" "EDA15C78BB573E49E685D8549286F33D" 1
+
+        .section        .text,"xr",one_only,main
+.globl main
+main:
+	.cv_func_id 0
+	.cv_loc	0 1 1 0 is_stmt 0
+	.cv_loc	0 1 2 0
+	retq
+.Lfunc_end0:
+
+	.section	.debug$S,"dr",associative,main
+	.long	4
+	.cv_linetable	0, main, .Lfunc_end0
+
+	.section	.debug$S,"dr"
+	.long	4
+	.cv_filechecksums
+	.cv_stringtable

Added: lld/trunk/test/COFF/duplicate-dwarf.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/duplicate-dwarf.s?rev=375218&view=auto
==============================================================================
--- lld/trunk/test/COFF/duplicate-dwarf.s (added)
+++ lld/trunk/test/COFF/duplicate-dwarf.s Fri Oct 18 03:43:15 2019
@@ -0,0 +1,213 @@
+# REQUIRES: x86
+# RUN: llvm-mc -triple=i686-windows-gnu -filetype=obj -o %t.o %s
+# RUN: cp %t.o %t.dupl.o
+# RUN: not lld-link -lldmingw -out:%t.exe %t.o %t.dupl.o -entry:_Z4funcv 2>&1 | FileCheck %s
+
+# CHECK: error: duplicate symbol: func()
+# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:6
+# CHECK-NEXT: >>>            {{.*}}.o
+# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:6
+# CHECK-NEXT: >>>            {{.*}}.o
+# CHECK-EMPTY:
+# CHECK-NEXT: error: duplicate symbol: _var
+# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:1
+# CHECK-NEXT: >>>            {{.*}}.o
+# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:1
+# CHECK-NEXT: >>>            {{.*}}.o
+# CHECK-EMPTY:
+# CHECK-NEXT: error: duplicate symbol: A::namespaceVar
+# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:3
+# CHECK-NEXT: >>>            {{.*}}.o
+# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:3
+# CHECK-NEXT: >>>            {{.*}}.o
+
+        .text
+        .file   "dupl.cpp"
+        .file   1 "/path/to/src" "dupl.cpp"
+        .def     __Z4funcv;
+        .globl  __Z4funcv               # -- Begin function _Z4funcv
+__Z4funcv:                              # @_Z4funcv
+Lfunc_begin0:
+        .loc    1 5 0                   # dupl.cpp:5:0
+# %bb.0:                                # %entry
+        .loc    1 6 1 prologue_end      # dupl.cpp:6:1
+        retl
+Lfunc_end0:
+                                        # -- End function
+        .bss
+        .globl  _var                    # @var
+_var:
+        .long   0                       # 0x0
+
+        .globl  __ZN1A12namespaceVarE   # @_ZN1A12namespaceVarE
+__ZN1A12namespaceVarE:
+        .long   0                       # 0x0
+
+        .section        .debug_str,"dr"
+Linfo_string:
+Linfo_string0:
+        .asciz  "var"
+Linfo_string1:
+        .asciz  "int"
+Linfo_string2:
+        .asciz  "A"
+Linfo_string3:
+        .asciz  "namespaceVar"
+Linfo_string4:
+        .asciz  "_ZN1A12namespaceVarE"
+Linfo_string5:
+        .asciz  "_Z4funcv"
+Linfo_string6:
+        .asciz  "func"
+        .section        .debug_abbrev,"dr"
+Lsection_abbrev:
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   1                       # DW_CHILDREN_yes
+        .byte   37                      # DW_AT_producer
+        .byte   37                      # DW_FORM_strx1
+        .byte   19                      # DW_AT_language
+        .byte   5                       # DW_FORM_data2
+        .byte   3                       # DW_AT_name
+        .byte   37                      # DW_FORM_strx1
+        .byte   16                      # DW_AT_stmt_list
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   17                      # DW_AT_low_pc
+        .byte   1                       # DW_FORM_addr
+        .byte   18                      # DW_AT_high_pc
+        .byte   6                       # DW_FORM_data4
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   2                       # Abbreviation Code
+        .byte   52                      # DW_TAG_variable
+        .byte   0                       # DW_CHILDREN_no
+        .byte   3                       # DW_AT_name
+        .byte   14                      # DW_FORM_strp
+        .byte   73                      # DW_AT_type
+        .byte   19                      # DW_FORM_ref4
+        .byte   63                      # DW_AT_external
+        .byte   25                      # DW_FORM_flag_present
+        .byte   58                      # DW_AT_decl_file
+        .byte   11                      # DW_FORM_data1
+        .byte   59                      # DW_AT_decl_line
+        .byte   11                      # DW_FORM_data1
+        .byte   2                       # DW_AT_location
+        .byte   24                      # DW_FORM_exprloc
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   3                       # Abbreviation Code
+        .byte   36                      # DW_TAG_base_type
+        .byte   0                       # DW_CHILDREN_no
+        .byte   3                       # DW_AT_name
+        .byte   14                      # DW_FORM_strp
+        .byte   62                      # DW_AT_encoding
+        .byte   11                      # DW_FORM_data1
+        .byte   11                      # DW_AT_byte_size
+        .byte   11                      # DW_FORM_data1
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   4                       # Abbreviation Code
+        .byte   57                      # DW_TAG_namespace
+        .byte   1                       # DW_CHILDREN_yes
+        .byte   3                       # DW_AT_name
+        .byte   14                      # DW_FORM_strp
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   5                       # Abbreviation Code
+        .byte   52                      # DW_TAG_variable
+        .byte   0                       # DW_CHILDREN_no
+        .byte   3                       # DW_AT_name
+        .byte   14                      # DW_FORM_strp
+        .byte   73                      # DW_AT_type
+        .byte   19                      # DW_FORM_ref4
+        .byte   63                      # DW_AT_external
+        .byte   25                      # DW_FORM_flag_present
+        .byte   58                      # DW_AT_decl_file
+        .byte   11                      # DW_FORM_data1
+        .byte   59                      # DW_AT_decl_line
+        .byte   11                      # DW_FORM_data1
+        .byte   2                       # DW_AT_location
+        .byte   24                      # DW_FORM_exprloc
+        .byte   110                     # DW_AT_linkage_name
+        .byte   14                      # DW_FORM_strp
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   6                       # Abbreviation Code
+        .byte   46                      # DW_TAG_subprogram
+        .byte   0                       # DW_CHILDREN_no
+        .byte   17                      # DW_AT_low_pc
+        .byte   1                       # DW_FORM_addr
+        .byte   18                      # DW_AT_high_pc
+        .byte   6                       # DW_FORM_data4
+        .byte   64                      # DW_AT_frame_base
+        .byte   24                      # DW_FORM_exprloc
+        .byte   110                     # DW_AT_linkage_name
+        .byte   14                      # DW_FORM_strp
+        .byte   3                       # DW_AT_name
+        .byte   14                      # DW_FORM_strp
+        .byte   58                      # DW_AT_decl_file
+        .byte   11                      # DW_FORM_data1
+        .byte   59                      # DW_AT_decl_line
+        .byte   11                      # DW_FORM_data1
+        .byte   63                      # DW_AT_external
+        .byte   25                      # DW_FORM_flag_present
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+        .section        .debug_info,"dr"
+Lsection_info:
+Lcu_begin0:
+        .long   Ldebug_info_end0-Ldebug_info_start0 # Length of Unit
+Ldebug_info_start0:
+        .short  4                       # DWARF version number
+        .secrel32       Lsection_abbrev # Offset Into Abbrev. Section
+        .byte   4                       # Address Size (in bytes)
+        .byte   1                       # Abbrev [1] 0xb:0x64 DW_TAG_compile_unit
+        .byte   0                       # DW_AT_producer
+        .short  33                      # DW_AT_language
+        .byte   0                       # DW_AT_name
+        .secrel32       Lline_table_start0 # DW_AT_stmt_list
+        .long   Lfunc_begin0            # DW_AT_low_pc
+        .long   Lfunc_end0-Lfunc_begin0 # DW_AT_high_pc
+        .byte   2                       # Abbrev [2] 0x26:0x11 DW_TAG_variable
+        .secrel32       Linfo_string0   # DW_AT_name
+        .secrel32       Linfo_type_int  # DW_AT_type
+                                        # DW_AT_external
+        .byte   1                       # DW_AT_decl_file
+        .byte   1                       # DW_AT_decl_line
+        .byte   5                       # DW_AT_location
+        .byte   3
+        .long   _var
+Linfo_type_int:
+        .byte   3                       # Abbrev [3] 0x37:0x7 DW_TAG_base_type
+        .secrel32       Linfo_string1   # DW_AT_name
+        .byte   5                       # DW_AT_encoding
+        .byte   4                       # DW_AT_byte_size
+        .byte   4                       # Abbrev [4] 0x3e:0x1b DW_TAG_namespace
+        .secrel32       Linfo_string2   # DW_AT_name
+        .byte   5                       # Abbrev [5] 0x43:0x15 DW_TAG_variable
+        .secrel32       Linfo_string3   # DW_AT_name
+        .secrel32       Linfo_type_int  # DW_AT_type
+                                        # DW_AT_external
+        .byte   1                       # DW_AT_decl_file
+        .byte   3                       # DW_AT_decl_line
+        .byte   5                       # DW_AT_location
+        .byte   3
+        .long   __ZN1A12namespaceVarE
+        .secrel32       Linfo_string4   # DW_AT_linkage_name
+        .byte   0                       # End Of Children Mark
+        .byte   6                       # Abbrev [6] 0x59:0x15 DW_TAG_subprogram
+        .long   Lfunc_begin0            # DW_AT_low_pc
+        .long   Lfunc_end0-Lfunc_begin0 # DW_AT_high_pc
+        .byte   1                       # DW_AT_frame_base
+        .byte   84
+        .secrel32       Linfo_string5   # DW_AT_linkage_name
+        .secrel32       Linfo_string6   # DW_AT_name
+        .byte   1                       # DW_AT_decl_file
+        .byte   5                       # DW_AT_decl_line
+                                        # DW_AT_external
+        .byte   0                       # End Of Children Mark
+Ldebug_info_end0:
+
+        .section        .debug_line,"dr"
+Lline_table_start0:

Modified: lld/trunk/test/COFF/duplicate.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/duplicate.test?rev=375218&r1=375217&r2=375218&view=diff
==============================================================================
--- lld/trunk/test/COFF/duplicate.test (original)
+++ lld/trunk/test/COFF/duplicate.test Fri Oct 18 03:43:15 2019
@@ -4,10 +4,14 @@ RUN: llc -mtriple x86_64-windows-msvc -f
 RUN: lld-link /out:alpha.dll /dll alpha.obj /implib:alpha.lib
 RUN: not lld-link /out:beta.dll /dll alpha.obj beta.obj alpha.lib 2>&1 | FileCheck %s -check-prefix CHECK-ALPHA
 
-CHECK-ALPHA: error: duplicate symbol: f in {{.*}}alpha.obj and in alpha.dll
+CHECK-ALPHA: error: duplicate symbol: f
+CHECK-ALPHA: defined at {{.*}}alpha.obj
+CHECK-APLHA: defined at alpha.dll
 
 RUN: llc -mtriple x86_64-windows-msvc -filetype obj -o gamma.obj %S/Inputs/gamma.ll
 RUN: not lld-link /out:gamma.exe /subsystem:console /entry:mainCRTStartup gamma.obj alpha.lib 2>&1 | FileCheck %s -check-prefix CHECK-GAMMA
 
-CHECK-GAMMA: error: duplicate symbol: __declspec(dllimport) f in {{.*}}gamma.obj and in alpha.dll
+CHECK-GAMMA: error: duplicate symbol: __declspec(dllimport) f
+CHECK-GAMMA: defined at {{.*}}gamma.obj
+CHECK-GAMMA: defined at alpha.dll
 




More information about the llvm-commits mailing list