Skip to content

Commit b38f577

Browse files
committedOct 18, 2019
[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 llvm-svn: 375218
1 parent 651f079 commit b38f577

9 files changed

+433
-22
lines changed
 

‎lld/COFF/InputFiles.cpp

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,8 @@ Symbol *ObjFile::createRegular(COFFSymbolRef sym) {
382382
StringRef name;
383383
coffObj->getSymbolName(sym, name);
384384
if (sc)
385-
return symtab->addRegular(this, name, sym.getGeneric(), sc);
385+
return symtab->addRegular(this, name, sym.getGeneric(), sc,
386+
sym.getValue());
386387
// For MinGW symbols named .weak.* that point to a discarded section,
387388
// don't create an Undefined symbol. If nothing ever refers to the symbol,
388389
// everything should be fine. If something actually refers to the symbol
@@ -536,7 +537,7 @@ void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection,
536537
// if the two comdat sections have e.g. different alignment.
537538
// Match that.
538539
if (leaderChunk->getContents() != newChunk.getContents())
539-
symtab->reportDuplicate(leader, this);
540+
symtab->reportDuplicate(leader, this, &newChunk, sym.getValue());
540541
break;
541542
}
542543

@@ -788,6 +789,89 @@ void ObjFile::initializeDependencies() {
788789
debugTypesObj = makeTpiSource(this);
789790
}
790791

792+
// Used only for DWARF debug info, which is not common (except in MinGW
793+
// environments). This returns an optional pair of file name and line
794+
// number for where the variable was defined.
795+
Optional<std::pair<StringRef, uint32_t>>
796+
ObjFile::getVariableLocation(StringRef var) {
797+
if (!dwarf) {
798+
dwarf = DWARFContext::create(*getCOFFObj());
799+
if (!dwarf)
800+
return None;
801+
initializeDwarf();
802+
}
803+
if (config->machine == I386)
804+
var.consume_front("_");
805+
auto it = variableLoc.find(var);
806+
if (it == variableLoc.end())
807+
return None;
808+
809+
// Take file name string from line table.
810+
std::string fileName;
811+
if (!it->second.lt->getFileNameByIndex(
812+
it->second.file, {},
813+
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
814+
return None;
815+
816+
return std::make_pair(saver.save(fileName), it->second.line);
817+
}
818+
819+
// Used only for DWARF debug info, which is not common (except in MinGW
820+
// environments). This initializes the dwarf, lineTables and variableLoc
821+
// members.
822+
void ObjFile::initializeDwarf() {
823+
for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
824+
auto report = [](Error err) {
825+
handleAllErrors(std::move(err),
826+
[](ErrorInfoBase &info) { warn(info.message()); });
827+
};
828+
Expected<const DWARFDebugLine::LineTable *> expectedLT =
829+
dwarf->getLineTableForUnit(cu.get(), report);
830+
const DWARFDebugLine::LineTable *lt = nullptr;
831+
if (expectedLT)
832+
lt = *expectedLT;
833+
else
834+
report(expectedLT.takeError());
835+
if (!lt)
836+
continue;
837+
lineTables.push_back(lt);
838+
839+
// Loop over variable records and insert them to variableLoc.
840+
for (const auto &entry : cu->dies()) {
841+
DWARFDie die(cu.get(), &entry);
842+
// Skip all tags that are not variables.
843+
if (die.getTag() != dwarf::DW_TAG_variable)
844+
continue;
845+
846+
// Skip if a local variable because we don't need them for generating
847+
// error messages. In general, only non-local symbols can fail to be
848+
// linked.
849+
if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
850+
continue;
851+
852+
// Get the source filename index for the variable.
853+
unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
854+
if (!lt->hasFileAtIndex(file))
855+
continue;
856+
857+
// Get the line number on which the variable is declared.
858+
unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
859+
860+
// Here we want to take the variable name to add it into variableLoc.
861+
// Variable can have regular and linkage name associated. At first, we try
862+
// to get linkage name as it can be different, for example when we have
863+
// two variables in different namespaces of the same object. Use common
864+
// name otherwise, but handle the case when it also absent in case if the
865+
// input object file lacks some debug info.
866+
StringRef name =
867+
dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
868+
dwarf::toString(die.find(dwarf::DW_AT_name), ""));
869+
if (!name.empty())
870+
variableLoc.insert({name, {lt, file, line}});
871+
}
872+
}
873+
}
874+
791875
StringRef ltrim1(StringRef s, const char *chars) {
792876
if (!s.empty() && strchr(chars, s[0]))
793877
return s.substr(1);

‎lld/COFF/InputFiles.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/DenseSet.h"
1717
#include "llvm/BinaryFormat/Magic.h"
1818
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
19+
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
1920
#include "llvm/LTO/LTO.h"
2021
#include "llvm/Object/Archive.h"
2122
#include "llvm/Object/COFF.h"
@@ -202,6 +203,9 @@ class ObjFile : public InputFile {
202203
// The .debug$T stream if there's one.
203204
llvm::Optional<llvm::codeview::CVTypeArray> debugTypes;
204205

206+
llvm::Optional<std::pair<StringRef, uint32_t>>
207+
getVariableLocation(StringRef var);
208+
205209
private:
206210
const coff_section* getSection(uint32_t i);
207211
const coff_section *getSection(COFFSymbolRef sym) {
@@ -212,6 +216,7 @@ class ObjFile : public InputFile {
212216
void initializeSymbols();
213217
void initializeFlags();
214218
void initializeDependencies();
219+
void initializeDwarf();
215220

216221
SectionChunk *
217222
readSection(uint32_t sectionNumber,
@@ -285,6 +290,15 @@ class ObjFile : public InputFile {
285290
// index. Nonexistent indices (which are occupied by auxiliary
286291
// symbols in the real symbol table) are filled with null pointers.
287292
std::vector<Symbol *> symbols;
293+
294+
std::unique_ptr<llvm::DWARFContext> dwarf;
295+
std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
296+
struct VarLoc {
297+
const llvm::DWARFDebugLine::LineTable *lt;
298+
unsigned file;
299+
unsigned line;
300+
};
301+
llvm::DenseMap<StringRef, VarLoc> variableLoc;
288302
};
289303

290304
// This type represents import library members that contain DLL names

‎lld/COFF/SymbolTable.cpp

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -520,15 +520,69 @@ void SymbolTable::addLazyObject(LazyObjFile *f, StringRef n) {
520520
f->fetch();
521521
}
522522

523-
void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile) {
524-
std::string msg = "duplicate symbol: " + toString(*existing) + " in " +
525-
toString(existing->getFile()) + " and in " +
526-
toString(newFile);
523+
static std::string getSourceLocationBitcode(BitcodeFile *file) {
524+
std::string res("\n>>> defined at ");
525+
StringRef source = file->obj->getSourceFileName();
526+
if (!source.empty())
527+
res += source.str() + "\n>>> ";
528+
res += toString(file);
529+
return res;
530+
}
531+
532+
static std::string getSourceLocationObj(ObjFile *file, SectionChunk *sc,
533+
uint32_t offset, StringRef name) {
534+
Optional<std::pair<StringRef, uint32_t>> fileLine;
535+
if (sc)
536+
fileLine = getFileLine(sc, offset);
537+
if (!fileLine)
538+
fileLine = file->getVariableLocation(name);
539+
540+
std::string res;
541+
llvm::raw_string_ostream os(res);
542+
os << "\n>>> defined at ";
543+
if (fileLine)
544+
os << fileLine->first << ":" << fileLine->second << "\n>>> ";
545+
os << toString(file);
546+
return os.str();
547+
}
548+
549+
static std::string getSourceLocation(InputFile *file, SectionChunk *sc,
550+
uint32_t offset, StringRef name) {
551+
if (auto *o = dyn_cast<ObjFile>(file))
552+
return getSourceLocationObj(o, sc, offset, name);
553+
if (auto *b = dyn_cast<BitcodeFile>(file))
554+
return getSourceLocationBitcode(b);
555+
return "\n>>> defined at " + toString(file);
556+
}
557+
558+
// Construct and print an error message in the form of:
559+
//
560+
// lld-link: error: duplicate symbol: foo
561+
// >>> defined at bar.c:30
562+
// >>> bar.o
563+
// >>> defined at baz.c:563
564+
// >>> baz.o
565+
void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile,
566+
SectionChunk *newSc,
567+
uint32_t newSectionOffset) {
568+
std::string msg;
569+
llvm::raw_string_ostream os(msg);
570+
os << "duplicate symbol: " << toString(*existing);
571+
572+
DefinedRegular *d = cast<DefinedRegular>(existing);
573+
if (d && isa<ObjFile>(d->getFile())) {
574+
os << getSourceLocation(d->getFile(), d->getChunk(), d->getValue(),
575+
existing->getName());
576+
} else {
577+
os << getSourceLocation(existing->getFile(), nullptr, 0, "");
578+
}
579+
os << getSourceLocation(newFile, newSc, newSectionOffset,
580+
existing->getName());
527581

528582
if (config->forceMultiple)
529-
warn(msg);
583+
warn(os.str());
530584
else
531-
error(msg);
585+
error(os.str());
532586
}
533587

534588
Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) {
@@ -568,16 +622,16 @@ Symbol *SymbolTable::addSynthetic(StringRef n, Chunk *c) {
568622
}
569623

570624
Symbol *SymbolTable::addRegular(InputFile *f, StringRef n,
571-
const coff_symbol_generic *sym,
572-
SectionChunk *c) {
625+
const coff_symbol_generic *sym, SectionChunk *c,
626+
uint32_t sectionOffset) {
573627
Symbol *s;
574628
bool wasInserted;
575629
std::tie(s, wasInserted) = insert(n, f);
576630
if (wasInserted || !isa<DefinedRegular>(s))
577631
replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ false,
578632
/*IsExternal*/ true, sym, c);
579633
else
580-
reportDuplicate(s, f);
634+
reportDuplicate(s, f, c, sectionOffset);
581635
return s;
582636
}
583637

‎lld/COFF/SymbolTable.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class SymbolTable {
9191
Symbol *addAbsolute(StringRef n, COFFSymbolRef s);
9292
Symbol *addRegular(InputFile *f, StringRef n,
9393
const llvm::object::coff_symbol_generic *s = nullptr,
94-
SectionChunk *c = nullptr);
94+
SectionChunk *c = nullptr, uint32_t sectionOffset = 0);
9595
std::pair<DefinedRegular *, bool>
9696
addComdat(InputFile *f, StringRef n,
9797
const llvm::object::coff_symbol_generic *s = nullptr);
@@ -103,7 +103,9 @@ class SymbolTable {
103103
uint16_t machine);
104104
void addLibcall(StringRef name);
105105

106-
void reportDuplicate(Symbol *existing, InputFile *newFile);
106+
void reportDuplicate(Symbol *existing, InputFile *newFile,
107+
SectionChunk *newSc = nullptr,
108+
uint32_t newSectionOffset = 0);
107109

108110
// A list of chunks which to be added to .rdata.
109111
std::vector<Chunk *> localImportChunks;

‎lld/test/COFF/conflict-mangled.test

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
# RUN: not lld-link /out:%t.exe /demangle %t1.obj %t2.obj 2>&1 | FileCheck %s
66
# RUN: not lld-link /out:%t.exe /demangle:no %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=NODEMANGLE %s
77

8-
# NODEMANGLE: duplicate symbol: ?mangled@@YAHXZ in {{.+}}1.obj and in {{.+}}2.obj
8+
# NODEMANGLE: duplicate symbol: ?mangled@@YAHXZ
9+
# NODEMANGLE: defined at {{.+}}1.obj
10+
# NODEMANGLE: defined at {{.+}}2.obj
911

10-
# CHECK: duplicate symbol: int __cdecl mangled(void) in {{.+}}1.obj and in {{.+}}2.obj
12+
# CHECK: duplicate symbol: int __cdecl mangled(void)
13+
# CHECK: defined at {{.+}}1.obj
14+
# CHECK: defined at {{.+}}2.obj
1115

1216
--- !COFF
1317
header:

‎lld/test/COFF/conflict.test

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
# REQUIRES: x86
22
# RUN: yaml2obj < %s > %t1.obj
33
# RUN: yaml2obj < %s > %t2.obj
4-
# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log
5-
# RUN: FileCheck %s < %t.log
4+
# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=OBJ %s
65

76
# RUN: llvm-as -o %t.lto1.obj %S/Inputs/conflict.ll
87
# RUN: llvm-as -o %t.lto2.obj %S/Inputs/conflict.ll
9-
# RUN: not lld-link /out:%t.exe %t.lto1.obj %t.lto2.obj >& %t.log
10-
# RUN: FileCheck %s < %t.log
8+
# RUN: not lld-link /out:%t.exe %t.lto1.obj %t.lto2.obj 2>&1 | FileCheck --check-prefix=BC %s
119

12-
# CHECK: duplicate symbol: foo in {{.+}}1.obj and in {{.+}}2.obj
10+
# OBJ: duplicate symbol: foo
11+
# OBJ: defined at {{.+}}1.obj
12+
# OBJ: defined at {{.+}}2.obj
13+
14+
# BC: duplicate symbol: foo
15+
# BC: defined at {{.+}}conflict.ll
16+
# BC: {{.+}}1.obj
17+
# BC: defined at {{.+}}conflict.ll
18+
# BC: {{.+}}2.obj
1319

1420
--- !COFF
1521
header:

‎lld/test/COFF/duplicate-cv.s

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# REQUIRES: x86
2+
# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
3+
# RUN: cp %t.obj %t.dupl.obj
4+
# RUN: not lld-link /out:%t.exe %t.obj %t.dupl.obj 2>&1 | FileCheck %s
5+
6+
# CHECK: error: duplicate symbol: main
7+
# CHECK-NEXT: >>> defined at file1.cpp:2
8+
# CHECK-NEXT: >>> {{.*}}.obj
9+
# CHECK-NEXT: >>> defined at {{.*}}.obj
10+
11+
.cv_file 1 "file1.cpp" "EDA15C78BB573E49E685D8549286F33C" 1
12+
.cv_file 2 "file2.cpp" "EDA15C78BB573E49E685D8549286F33D" 1
13+
14+
.section .text,"xr",one_only,main
15+
.globl main
16+
main:
17+
.cv_func_id 0
18+
.cv_loc 0 1 1 0 is_stmt 0
19+
.cv_loc 0 1 2 0
20+
retq
21+
.Lfunc_end0:
22+
23+
.section .debug$S,"dr",associative,main
24+
.long 4
25+
.cv_linetable 0, main, .Lfunc_end0
26+
27+
.section .debug$S,"dr"
28+
.long 4
29+
.cv_filechecksums
30+
.cv_stringtable

‎lld/test/COFF/duplicate-dwarf.s

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# REQUIRES: x86
2+
# RUN: llvm-mc -triple=i686-windows-gnu -filetype=obj -o %t.o %s
3+
# RUN: cp %t.o %t.dupl.o
4+
# RUN: not lld-link -lldmingw -out:%t.exe %t.o %t.dupl.o -entry:_Z4funcv 2>&1 | FileCheck %s
5+
6+
# CHECK: error: duplicate symbol: func()
7+
# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:6
8+
# CHECK-NEXT: >>> {{.*}}.o
9+
# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:6
10+
# CHECK-NEXT: >>> {{.*}}.o
11+
# CHECK-EMPTY:
12+
# CHECK-NEXT: error: duplicate symbol: _var
13+
# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:1
14+
# CHECK-NEXT: >>> {{.*}}.o
15+
# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:1
16+
# CHECK-NEXT: >>> {{.*}}.o
17+
# CHECK-EMPTY:
18+
# CHECK-NEXT: error: duplicate symbol: A::namespaceVar
19+
# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:3
20+
# CHECK-NEXT: >>> {{.*}}.o
21+
# CHECK-NEXT: >>> defined at /path/to/src{{[/\\]}}dupl.cpp:3
22+
# CHECK-NEXT: >>> {{.*}}.o
23+
24+
.text
25+
.file "dupl.cpp"
26+
.file 1 "/path/to/src" "dupl.cpp"
27+
.def __Z4funcv;
28+
.globl __Z4funcv # -- Begin function _Z4funcv
29+
__Z4funcv: # @_Z4funcv
30+
Lfunc_begin0:
31+
.loc 1 5 0 # dupl.cpp:5:0
32+
# %bb.0: # %entry
33+
.loc 1 6 1 prologue_end # dupl.cpp:6:1
34+
retl
35+
Lfunc_end0:
36+
# -- End function
37+
.bss
38+
.globl _var # @var
39+
_var:
40+
.long 0 # 0x0
41+
42+
.globl __ZN1A12namespaceVarE # @_ZN1A12namespaceVarE
43+
__ZN1A12namespaceVarE:
44+
.long 0 # 0x0
45+
46+
.section .debug_str,"dr"
47+
Linfo_string:
48+
Linfo_string0:
49+
.asciz "var"
50+
Linfo_string1:
51+
.asciz "int"
52+
Linfo_string2:
53+
.asciz "A"
54+
Linfo_string3:
55+
.asciz "namespaceVar"
56+
Linfo_string4:
57+
.asciz "_ZN1A12namespaceVarE"
58+
Linfo_string5:
59+
.asciz "_Z4funcv"
60+
Linfo_string6:
61+
.asciz "func"
62+
.section .debug_abbrev,"dr"
63+
Lsection_abbrev:
64+
.byte 1 # Abbreviation Code
65+
.byte 17 # DW_TAG_compile_unit
66+
.byte 1 # DW_CHILDREN_yes
67+
.byte 37 # DW_AT_producer
68+
.byte 37 # DW_FORM_strx1
69+
.byte 19 # DW_AT_language
70+
.byte 5 # DW_FORM_data2
71+
.byte 3 # DW_AT_name
72+
.byte 37 # DW_FORM_strx1
73+
.byte 16 # DW_AT_stmt_list
74+
.byte 23 # DW_FORM_sec_offset
75+
.byte 17 # DW_AT_low_pc
76+
.byte 1 # DW_FORM_addr
77+
.byte 18 # DW_AT_high_pc
78+
.byte 6 # DW_FORM_data4
79+
.byte 0 # EOM(1)
80+
.byte 0 # EOM(2)
81+
.byte 2 # Abbreviation Code
82+
.byte 52 # DW_TAG_variable
83+
.byte 0 # DW_CHILDREN_no
84+
.byte 3 # DW_AT_name
85+
.byte 14 # DW_FORM_strp
86+
.byte 73 # DW_AT_type
87+
.byte 19 # DW_FORM_ref4
88+
.byte 63 # DW_AT_external
89+
.byte 25 # DW_FORM_flag_present
90+
.byte 58 # DW_AT_decl_file
91+
.byte 11 # DW_FORM_data1
92+
.byte 59 # DW_AT_decl_line
93+
.byte 11 # DW_FORM_data1
94+
.byte 2 # DW_AT_location
95+
.byte 24 # DW_FORM_exprloc
96+
.byte 0 # EOM(1)
97+
.byte 0 # EOM(2)
98+
.byte 3 # Abbreviation Code
99+
.byte 36 # DW_TAG_base_type
100+
.byte 0 # DW_CHILDREN_no
101+
.byte 3 # DW_AT_name
102+
.byte 14 # DW_FORM_strp
103+
.byte 62 # DW_AT_encoding
104+
.byte 11 # DW_FORM_data1
105+
.byte 11 # DW_AT_byte_size
106+
.byte 11 # DW_FORM_data1
107+
.byte 0 # EOM(1)
108+
.byte 0 # EOM(2)
109+
.byte 4 # Abbreviation Code
110+
.byte 57 # DW_TAG_namespace
111+
.byte 1 # DW_CHILDREN_yes
112+
.byte 3 # DW_AT_name
113+
.byte 14 # DW_FORM_strp
114+
.byte 0 # EOM(1)
115+
.byte 0 # EOM(2)
116+
.byte 5 # Abbreviation Code
117+
.byte 52 # DW_TAG_variable
118+
.byte 0 # DW_CHILDREN_no
119+
.byte 3 # DW_AT_name
120+
.byte 14 # DW_FORM_strp
121+
.byte 73 # DW_AT_type
122+
.byte 19 # DW_FORM_ref4
123+
.byte 63 # DW_AT_external
124+
.byte 25 # DW_FORM_flag_present
125+
.byte 58 # DW_AT_decl_file
126+
.byte 11 # DW_FORM_data1
127+
.byte 59 # DW_AT_decl_line
128+
.byte 11 # DW_FORM_data1
129+
.byte 2 # DW_AT_location
130+
.byte 24 # DW_FORM_exprloc
131+
.byte 110 # DW_AT_linkage_name
132+
.byte 14 # DW_FORM_strp
133+
.byte 0 # EOM(1)
134+
.byte 0 # EOM(2)
135+
.byte 6 # Abbreviation Code
136+
.byte 46 # DW_TAG_subprogram
137+
.byte 0 # DW_CHILDREN_no
138+
.byte 17 # DW_AT_low_pc
139+
.byte 1 # DW_FORM_addr
140+
.byte 18 # DW_AT_high_pc
141+
.byte 6 # DW_FORM_data4
142+
.byte 64 # DW_AT_frame_base
143+
.byte 24 # DW_FORM_exprloc
144+
.byte 110 # DW_AT_linkage_name
145+
.byte 14 # DW_FORM_strp
146+
.byte 3 # DW_AT_name
147+
.byte 14 # DW_FORM_strp
148+
.byte 58 # DW_AT_decl_file
149+
.byte 11 # DW_FORM_data1
150+
.byte 59 # DW_AT_decl_line
151+
.byte 11 # DW_FORM_data1
152+
.byte 63 # DW_AT_external
153+
.byte 25 # DW_FORM_flag_present
154+
.byte 0 # EOM(1)
155+
.byte 0 # EOM(2)
156+
.byte 0 # EOM(3)
157+
.section .debug_info,"dr"
158+
Lsection_info:
159+
Lcu_begin0:
160+
.long Ldebug_info_end0-Ldebug_info_start0 # Length of Unit
161+
Ldebug_info_start0:
162+
.short 4 # DWARF version number
163+
.secrel32 Lsection_abbrev # Offset Into Abbrev. Section
164+
.byte 4 # Address Size (in bytes)
165+
.byte 1 # Abbrev [1] 0xb:0x64 DW_TAG_compile_unit
166+
.byte 0 # DW_AT_producer
167+
.short 33 # DW_AT_language
168+
.byte 0 # DW_AT_name
169+
.secrel32 Lline_table_start0 # DW_AT_stmt_list
170+
.long Lfunc_begin0 # DW_AT_low_pc
171+
.long Lfunc_end0-Lfunc_begin0 # DW_AT_high_pc
172+
.byte 2 # Abbrev [2] 0x26:0x11 DW_TAG_variable
173+
.secrel32 Linfo_string0 # DW_AT_name
174+
.secrel32 Linfo_type_int # DW_AT_type
175+
# DW_AT_external
176+
.byte 1 # DW_AT_decl_file
177+
.byte 1 # DW_AT_decl_line
178+
.byte 5 # DW_AT_location
179+
.byte 3
180+
.long _var
181+
Linfo_type_int:
182+
.byte 3 # Abbrev [3] 0x37:0x7 DW_TAG_base_type
183+
.secrel32 Linfo_string1 # DW_AT_name
184+
.byte 5 # DW_AT_encoding
185+
.byte 4 # DW_AT_byte_size
186+
.byte 4 # Abbrev [4] 0x3e:0x1b DW_TAG_namespace
187+
.secrel32 Linfo_string2 # DW_AT_name
188+
.byte 5 # Abbrev [5] 0x43:0x15 DW_TAG_variable
189+
.secrel32 Linfo_string3 # DW_AT_name
190+
.secrel32 Linfo_type_int # DW_AT_type
191+
# DW_AT_external
192+
.byte 1 # DW_AT_decl_file
193+
.byte 3 # DW_AT_decl_line
194+
.byte 5 # DW_AT_location
195+
.byte 3
196+
.long __ZN1A12namespaceVarE
197+
.secrel32 Linfo_string4 # DW_AT_linkage_name
198+
.byte 0 # End Of Children Mark
199+
.byte 6 # Abbrev [6] 0x59:0x15 DW_TAG_subprogram
200+
.long Lfunc_begin0 # DW_AT_low_pc
201+
.long Lfunc_end0-Lfunc_begin0 # DW_AT_high_pc
202+
.byte 1 # DW_AT_frame_base
203+
.byte 84
204+
.secrel32 Linfo_string5 # DW_AT_linkage_name
205+
.secrel32 Linfo_string6 # DW_AT_name
206+
.byte 1 # DW_AT_decl_file
207+
.byte 5 # DW_AT_decl_line
208+
# DW_AT_external
209+
.byte 0 # End Of Children Mark
210+
Ldebug_info_end0:
211+
212+
.section .debug_line,"dr"
213+
Lline_table_start0:

‎lld/test/COFF/duplicate.test

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ RUN: llc -mtriple x86_64-windows-msvc -filetype obj -o beta.obj %S/Inputs/beta.l
44
RUN: lld-link /out:alpha.dll /dll alpha.obj /implib:alpha.lib
55
RUN: not lld-link /out:beta.dll /dll alpha.obj beta.obj alpha.lib 2>&1 | FileCheck %s -check-prefix CHECK-ALPHA
66

7-
CHECK-ALPHA: error: duplicate symbol: f in {{.*}}alpha.obj and in alpha.dll
7+
CHECK-ALPHA: error: duplicate symbol: f
8+
CHECK-ALPHA: defined at {{.*}}alpha.obj
9+
CHECK-APLHA: defined at alpha.dll
810

911
RUN: llc -mtriple x86_64-windows-msvc -filetype obj -o gamma.obj %S/Inputs/gamma.ll
1012
RUN: not lld-link /out:gamma.exe /subsystem:console /entry:mainCRTStartup gamma.obj alpha.lib 2>&1 | FileCheck %s -check-prefix CHECK-GAMMA
1113

12-
CHECK-GAMMA: error: duplicate symbol: __declspec(dllimport) f in {{.*}}gamma.obj and in alpha.dll
14+
CHECK-GAMMA: error: duplicate symbol: __declspec(dllimport) f
15+
CHECK-GAMMA: defined at {{.*}}gamma.obj
16+
CHECK-GAMMA: defined at alpha.dll
1317

0 commit comments

Comments
 (0)
Please sign in to comment.