[PATCH] D52601: [LLD] [COFF] Cope with weak aliases produced by GNU tools

Martin Storsjö via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 27 04:18:11 PDT 2018


mstorsjo created this revision.
mstorsjo added reviewers: ruiu, rnk, pcc.

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.


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D52601

Files:
  COFF/InputFiles.cpp
  test/COFF/Inputs/gnu-weak.o
  test/COFF/Inputs/gnu-weak2.o
  test/COFF/gnu-weak.test


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.<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
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<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;
   }
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D52601.167273.patch
Type: text/x-patch
Size: 2470 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180927/06c63720/attachment.bin>


More information about the llvm-commits mailing list