Index: COFF/InputFiles.cpp =================================================================== --- COFF/InputFiles.cpp +++ COFF/InputFiles.cpp @@ -54,8 +54,16 @@ static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, Symbol *Source, Symbol *Target) { if (auto *U = dyn_cast(Source)) { - if (U->WeakAlias && U->WeakAlias != Target) + if (U->WeakAlias && U->WeakAlias != Target) { + // Weak aliases as produced by GCC are named in the form + // .weak.., where is the name + // of another symbol emitted near the weak symbol. + // Just use the definition from the first object file that defined + // this weak symbol. + if (Config->MinGW) + return; Symtab->reportDuplicate(Source, F); + } U->WeakAlias = Target; } } Index: test/COFF/gnu-weak.test =================================================================== --- /dev/null +++ test/COFF/gnu-weak.test @@ -0,0 +1,52 @@ +RUN: lld-link -lldmingw %S/Inputs/gnu-weak.o %S/Inputs/gnu-weak2.o -out:%t.exe + +GNU ld can handle several definitions of the same weak symbol, and +unless there is a strong definition of it, it just picks the first +weak definition encountered. + +For each of the weak definitions, GNU tools produce a regular symbol +named .weak.., where the other symbol name is +another symbol defined close by. + +This can't be reproduced by assembling with llvm-mc, as llvm-mc always +produces similar regular symbols named .weak..default. + +The bundled object files can be produced from test code that looks like +this: + +$ cat gnu-weak.c +void weakfunc(void) __attribute__((weak)); +void otherfunc(void); + +__attribute__((weak)) void weakfunc() { +} + +int main(int argc, char* argv[]) { + otherfunc(); + weakfunc(); + return 0; +} +void mainCRTStartup(void) { + main(0, (char**)0); +} +void __main(void) { +} + +$ cat gnu-weak2.c +void weakfunc(void) __attribute__((weak)); + +__attribute__((weak)) void weakfunc() { +} + +void otherfunc(void) { +} + +$ x86_64-w64-mingw32-gcc -c -O2 gnu-weak.c +$ x86_64-w64-mingw32-gcc -c -O2 gnu-weak2.c + +$ x86_64-w64-mingw32-nm gnu-weak.o | grep weakfunc +0000000000000000 T .weak.weakfunc.main + w weakfunc +$ x86_64-w64-mingw32-nm gnu-weak2.o | grep weakfunc +0000000000000000 T .weak.weakfunc.otherfunc + w weakfunc