[lld] r343704 - [COFF] Cope with weak aliases produced by GNU tools

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 3 11:31:53 PDT 2018


Author: mstorsjo
Date: Wed Oct  3 11:31:53 2018
New Revision: 343704

URL: http://llvm.org/viewvc/llvm-project?rev=343704&view=rev
Log:
[COFF] Cope with weak aliases produced by GNU tools

When GNU tools create a weak alias, they produce a strong symbol
named .weak.<weaksymbol>.<relatedstrongsymbol>.

GNU ld allows many such weak alternatives for the same weak symbol, and
the linker picks the first one encountered.

This can't be reproduced by assembling from .s files, since llvm-mc
produces symbols named .weak.<weaksymbol>.default in these cases.

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

Added:
    lld/trunk/test/COFF/Inputs/gnu-weak.o
    lld/trunk/test/COFF/Inputs/gnu-weak2.o
    lld/trunk/test/COFF/gnu-weak.test
Modified:
    lld/trunk/COFF/InputFiles.cpp

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=343704&r1=343703&r2=343704&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Wed Oct  3 11:31:53 2018
@@ -54,8 +54,16 @@ std::vector<BitcodeFile *> BitcodeFile::
 static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F,
                                  Symbol *Source, Symbol *Target) {
   if (auto *U = dyn_cast<Undefined>(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.<weaksymbol>.<othersymbol>, where <othersymbol> 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;
   }
 }

Added: lld/trunk/test/COFF/Inputs/gnu-weak.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/gnu-weak.o?rev=343704&view=auto
==============================================================================
Binary files lld/trunk/test/COFF/Inputs/gnu-weak.o (added) and lld/trunk/test/COFF/Inputs/gnu-weak.o Wed Oct  3 11:31:53 2018 differ

Added: lld/trunk/test/COFF/Inputs/gnu-weak2.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/gnu-weak2.o?rev=343704&view=auto
==============================================================================
Binary files lld/trunk/test/COFF/Inputs/gnu-weak2.o (added) and lld/trunk/test/COFF/Inputs/gnu-weak2.o Wed Oct  3 11:31:53 2018 differ

Added: lld/trunk/test/COFF/gnu-weak.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/gnu-weak.test?rev=343704&view=auto
==============================================================================
--- lld/trunk/test/COFF/gnu-weak.test (added)
+++ lld/trunk/test/COFF/gnu-weak.test Wed Oct  3 11:31:53 2018
@@ -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.<weaksymbol>.<othersymbol>, 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.<weaksymbol>.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




More information about the llvm-commits mailing list