[lld] b34006d - [lld][COFF] Add support for overriding weak symbols in LLVM bitcode input

Alan Zhao via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 8 10:17:09 PDT 2022


Author: Alan Zhao
Date: 2022-09-08T13:17:02-04:00
New Revision: b34006dd0a5126a7b3c2c5ba4d575456ab8a4894

URL: https://github.com/llvm/llvm-project/commit/b34006dd0a5126a7b3c2c5ba4d575456ab8a4894
DIFF: https://github.com/llvm/llvm-project/commit/b34006dd0a5126a7b3c2c5ba4d575456ab8a4894.diff

LOG: [lld][COFF] Add support for overriding weak symbols in LLVM bitcode input

LLVM bitcode contains support for weak symbols, so we can add support
for overriding weak symbols in the output COFF even though COFF doesn't
have inherent support for weak symbols.

The motivation for this patch is that Chromium is trying to use libc++'s
assertion handler mechanism, which relies on weak symbols [0], but we're
unable to perform a ThinLTO build on Windows due to this problem [1].

[0]: https://reviews.llvm.org/D121478
[1]: https://crrev.com/c/3863576

Reviewed By: rnk

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

Added: 
    lld/test/COFF/Inputs/strong-def.ll
    lld/test/COFF/Inputs/weak-def.ll
    lld/test/COFF/weak-override.ll

Modified: 
    lld/COFF/InputFiles.cpp
    lld/COFF/SymbolTable.cpp
    lld/COFF/SymbolTable.h
    lld/COFF/Symbols.h

Removed: 
    


################################################################################
diff  --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 0f3f5e0ffe7c5..9c1b2696fb787 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -1070,7 +1070,8 @@ void BitcodeFile::parse() {
         sym = ctx.symtab.addUndefined(symName, this, false);
       }
     } else {
-      sym = ctx.symtab.addRegular(this, symName, nullptr, fakeSC);
+      sym = ctx.symtab.addRegular(this, symName, nullptr, fakeSC, 0,
+                                  objSym.isWeak());
     }
     symbols.push_back(sym);
     if (objSym.isUsed())

diff  --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 9e5edb65bcf06..95f7b4e15b88c 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -698,12 +698,12 @@ Symbol *SymbolTable::addSynthetic(StringRef n, Chunk *c) {
 
 Symbol *SymbolTable::addRegular(InputFile *f, StringRef n,
                                 const coff_symbol_generic *sym, SectionChunk *c,
-                                uint32_t sectionOffset) {
+                                uint32_t sectionOffset, bool isWeak) {
   auto [s, wasInserted] = insert(n, f);
-  if (wasInserted || !isa<DefinedRegular>(s))
+  if (wasInserted || !isa<DefinedRegular>(s) || s->isWeak)
     replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ false,
-                                  /*IsExternal*/ true, sym, c);
-  else
+                                  /*IsExternal*/ true, sym, c, isWeak);
+  else if (!isWeak)
     reportDuplicate(s, f, c, sectionOffset);
   return s;
 }

diff  --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index 167377ef3bc46..15cb5334df481 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -95,7 +95,8 @@ class SymbolTable {
   Symbol *addAbsolute(StringRef n, COFFSymbolRef s);
   Symbol *addRegular(InputFile *f, StringRef n,
                      const llvm::object::coff_symbol_generic *s = nullptr,
-                     SectionChunk *c = nullptr, uint32_t sectionOffset = 0);
+                     SectionChunk *c = nullptr, uint32_t sectionOffset = 0,
+                     bool isWeak = false);
   std::pair<DefinedRegular *, bool>
   addComdat(InputFile *f, StringRef n,
             const llvm::object::coff_symbol_generic *s = nullptr);

diff  --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index a4c6f893f10cf..7e99b02629df8 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -106,7 +106,8 @@ class Symbol {
       : symbolKind(k), isExternal(true), isCOMDAT(false),
         writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false),
         isRuntimePseudoReloc(false), deferUndefined(false), canInline(true),
-        nameSize(n.size()), nameData(n.empty() ? nullptr : n.data()) {
+        isWeak(false), nameSize(n.size()),
+        nameData(n.empty() ? nullptr : n.data()) {
     assert((!n.empty() || k <= LastDefinedCOFFKind) &&
            "If the name is empty, the Symbol must be a DefinedCOFF.");
   }
@@ -145,6 +146,11 @@ class Symbol {
   // doesn't know the final contents of the symbol.
   unsigned canInline : 1;
 
+  // True if the symbol is weak. This is only tracked for bitcode/LTO symbols.
+  // This information isn't written to the output; rather, it's used for
+  // managing weak symbol overrides.
+  unsigned isWeak : 1;
+
 protected:
   // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
   uint32_t nameSize;
@@ -200,10 +206,11 @@ class DefinedRegular : public DefinedCOFF {
   DefinedRegular(InputFile *f, StringRef n, bool isCOMDAT,
                  bool isExternal = false,
                  const coff_symbol_generic *s = nullptr,
-                 SectionChunk *c = nullptr)
+                 SectionChunk *c = nullptr, bool isWeak = false)
       : DefinedCOFF(DefinedRegularKind, f, n, s), data(c ? &c->repl : nullptr) {
     this->isExternal = isExternal;
     this->isCOMDAT = isCOMDAT;
+    this->isWeak = isWeak;
   }
 
   static bool classof(const Symbol *s) {

diff  --git a/lld/test/COFF/Inputs/strong-def.ll b/lld/test/COFF/Inputs/strong-def.ll
new file mode 100644
index 0000000000000..ea5d78ca21baa
--- /dev/null
+++ b/lld/test/COFF/Inputs/strong-def.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define dso_local noundef i32 @foo() local_unnamed_addr {
+  ret i32 5678
+}

diff  --git a/lld/test/COFF/Inputs/weak-def.ll b/lld/test/COFF/Inputs/weak-def.ll
new file mode 100644
index 0000000000000..9e1315a046351
--- /dev/null
+++ b/lld/test/COFF/Inputs/weak-def.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define weak dso_local noundef i32 @foo() local_unnamed_addr {
+  ret i32 1234
+}

diff  --git a/lld/test/COFF/weak-override.ll b/lld/test/COFF/weak-override.ll
new file mode 100644
index 0000000000000..93f2d8e5915dc
--- /dev/null
+++ b/lld/test/COFF/weak-override.ll
@@ -0,0 +1,30 @@
+; REQUIRES: x86
+; RUN: llvm-as -o %t-weak.obj %S/Inputs/weak-def.ll
+; RUN: llvm-as -o %t-strong.obj %S/Inputs/strong-def.ll
+; RUN: llvm-as -o %t.obj %s
+; RUN: lld-link /dll /out:%t-weak-first.dll %t.obj %t-weak.obj %t-strong.obj
+; RUN: lld-link /dll /out:%t-strong-first.dll %t.obj %t-strong.obj %t-weak.obj
+; RUN: lld-link /dll /out:%t-weak-only.dll %t.obj %t-weak.obj
+; RUN: llvm-objdump -d %t-weak-first.dll | FileCheck --check-prefix=CHECK-STRONG %s
+; RUN: llvm-objdump -d %t-strong-first.dll | FileCheck --check-prefix=CHECK-STRONG %s
+; RUN: llvm-objdump -d %t-weak-only.dll | FileCheck --check-prefix=CHECK-WEAK %s
+
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+declare noundef i32 @foo() local_unnamed_addr
+
+define dllexport i32 @bar() local_unnamed_addr {
+  %1 = tail call noundef i32 @foo()
+  ret i32 %1
+}
+
+define void @_DllMainCRTStartup() {
+entry:
+  ret void
+}
+
+; CHECK-STRONG: movl $5678, %eax
+; CHECK-STRONG-NOT: movl $1234, %eax
+; CHECK-WEAK: movl $1234, %eax
+; CHECK-WEAK-NOT: movl $5678, %eax


        


More information about the llvm-commits mailing list