[lld] [LLD][COFF] Prevent to emit relocations for discarded weak wrapped symbols (PR #156214)

Tomohiro Kashiwada via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 5 06:16:22 PDT 2025


https://github.com/kikairoya updated https://github.com/llvm/llvm-project/pull/156214

>From 992b29f953b90f29a8e89e227e351107afb8f255 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Tue, 12 Aug 2025 18:06:31 +0900
Subject: [PATCH 01/12] application test

---
 lld/test/COFF/weak-wrap-import.test | 360 ++++++++++++++++++++++++++++
 1 file changed, 360 insertions(+)
 create mode 100644 lld/test/COFF/weak-wrap-import.test

diff --git a/lld/test/COFF/weak-wrap-import.test b/lld/test/COFF/weak-wrap-import.test
new file mode 100644
index 0000000000000..a4c4d56fc7597
--- /dev/null
+++ b/lld/test/COFF/weak-wrap-import.test
@@ -0,0 +1,360 @@
+REQUIRES: x86, shell
+
+RUN: rm -f %t.dir/* && split-file %s %t.dir/ && cd %t.dir
+
+RUN: llc rtdll.ll -o rtdll.o --filetype=obj
+RUN: ld.lld -m i386pep -shared -o rtdll.dll rtdll.o --entry= --out-implib rtdll.dll.a --dynamicbase
+
+RUN: llvm-mc -filetype=obj -triple=x86_64-mingw crt0-x86_64-mingw.s    -o crt0.o
+RUN: llvm-mc -filetype=obj -triple=x86_64-mingw dllcrt0-x86_64-mingw.s -o dllcrt0.o
+RUN: llc crt1.ll -o crt1.o --filetype=obj
+
+RUN: llc overrider.ll -o overrider.o --filetype=obj
+RUN: llvm-ar rc somelib.a overrider.o
+RUN: llvm-as overrider.ll -o overrider.bc
+
+RUN: llc somedll.ll -o somedll.o --filetype=obj
+RUN: ld.lld -m i386pep --dynamicbase --entry _start --wrap theweak \
+RUN:   -shared -o somedll.dll somedll.o dllcrt0.o crt1.o rtdll.dll.a --out-implib somedll.dll.a
+
+RUN: env NAME=noref         DEPS=              sh run.sh CHECK
+RUN: env NAME=use           DEPS=              sh run.sh CHECK,CHECK-IMP
+RUN: env NAME=override-only DEPS=overrider.o   sh run.sh CHECK,CHECK-IMP-LLD,CHECK-REL
+RUN: env NAME=override-use  DEPS=overrider.o   sh run.sh CHECK,CHECK-IMP,CHECK-REL
+RUN: env NAME=linklib-noref DEPS=somelib.a     sh run.sh CHECK,CHECK-IMP-LLD,CHECK-REL
+RUN: env NAME=linklib-use   DEPS=somelib.a     sh run.sh CHECK,CHECK-IMP,CHECK-REL
+RUN: env NAME=linkdll-noref DEPS=somedll.dll.a sh run.sh CHECK,CHECK-IMP-LLD,SOMEDLL
+RUN: env NAME=linkdll-use   DEPS=somedll.dll.a sh run.sh CHECK,CHECK-IMP,CHECK-REL-LLD,SOMEDLL,SOMEDLL-IMP-LLD
+
+#--- check-lld.txt
+CHECK: 0200[[#%x,ADDR:]] D ref_theweak
+CHECK: File
+SOMEDLL:          Import {
+SOMEDLL-NEXT:       Name: somedll.dll
+SOMEDLL-IMP:        Symbol: theweak
+SOMEDLL-IMP-LLD:    Symbol: theweak
+SOMEDLL:          }
+CHECK:            Import {
+CHECK-NEXT:         Name: rtdll.dll
+CHECK-IMP:          Symbol: __wrap_theweak
+CHECK-IMP-LLD:      Symbol: __wrap_theweak
+CHECK:            }
+CHECK:            BaseReloc [
+CHECK-REL:          Type: DIR64
+CHECK-REL-NEXT:     Address: 0x[[#%X,ADDR]]
+CHECK-REL-LLD:      Type: DIR64
+CHECK-REL-LLD-NEXT: Address: 0x[[#%X,ADDR]]
+CHECK:            ]
+
+#--- check-bfd.txt
+CHECK: 0200[[#%x,ADDR:]] D ref_theweak
+CHECK: File
+CHECK:            Import {
+CHECK-NEXT:         Name: rtdll.dll
+CHECK-IMP:          Symbol: __wrap_theweak
+CHECK-IMP-BFD:      Symbol: __wrap_theweak
+CHECK:            }
+SOMEDLL:          Import {
+SOMEDLL-NEXT:       Name: somedll.dll
+SOMEDLL-IMP:        Symbol: theweak
+SOMEDLL-IMP-BFD:    Symbol: theweak
+SOMEDLL:          }
+CHECK:            BaseReloc [
+CHECK-REL:          Type: DIR64
+CHECK-REL-NEXT:     Address: 0x[[#%X,ADDR]]
+CHECK-REL-BFD:      Type: DIR64
+CHECK-REL-BFD-NEXT: Address: 0x[[#%X,ADDR]]
+CHECK:            ]
+
+#--- run.sh
+set -ex
+RUNBIN=true
+LINKER=lld
+run() {
+  if [ "$ASLR" = ON ]; then
+    dynamicbase=--dynamicbase
+    ASLR=.aslr
+  else
+    dynamicbase=
+    ASLR=
+  fi
+  ld.$LINKER -m i386pep $dynamicbase --entry _start --subsystem console --wrap theweak --image-base 0x02000000 \
+    -o $NAME$LTO$ASLR.exe crt0.o crt1.o $NAME.o $DEPS rtdll.dll.a
+  llvm-nm $NAME$LTO$ASLR.exe > $NAME$LTO$ASLR.dump
+  llvm-readobj --hex-dump=.data --coff-basereloc --coff-imports $NAME$LTO$ASLR.exe >> $NAME$LTO$ASLR.dump
+  FileCheck --input-file=$NAME$LTO$ASLR.dump check-$LINKER.txt --allow-unused-prefixes --check-prefixes=$1 \
+    --implicit-check-not=.dll --implicit-check-not="Symbol: {{[a-z_]*}}theweak" --implicit-check-not=DIR64
+  [ -z "$RUNBIN" ] || ./$NAME$LTO$ASLR.exe
+}
+if ! uname -a | grep -E -iq 'cygwin|mingw|msys|wsl'; then
+  RUNBIN=
+fi
+llc $NAME.ll -o $NAME.o --filetype=obj
+run "$@"
+[ -z "$RUNBIN" ] || ASLR=ON run "$@"
+if [ $LINKER = lld ]; then
+  llvm-as $NAME.ll -o $NAME.bc
+  LTO=.lto run "$@"
+  [ -z "$RUNBIN" ] || LTO=.lto ASLR=ON run "$@"
+fi
+
+#--- noref.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %3 = icmp ne i32 %1, u0x00
+  %4 = zext i1 %3 to i32
+  ; return success if not overridden
+  ret i32 %4
+}
+
+#--- use.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %2 = call i32 @theweak(i32 %1)
+  %3 = icmp ne i32 %2, u0x02
+  %4 = zext i1 %3 to i32
+  ; return success if not overridden and used fallback
+  ret i32 %4
+}
+
+#--- overrider.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+define dso_local i32 @theweak(i32 %i) nounwind {
+  %1 = or i32 %i, u0x04
+  ret i32 %1
+}
+define i32 @anchor(i32 %i) nounwind {
+  ret i32 %i
+}
+
+#--- override-only.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %3 = icmp ne i32 %1, u0x01
+  %4 = zext i1 %3 to i32
+  ; return success if overridden
+  ret i32 %4
+}
+
+#--- override-use.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %2 = call i32 @theweak(i32 %1)
+  %3 = icmp ne i32 %2, u0x5
+  %4 = zext i1 %3 to i32
+  ; return success if overridden and used local obj
+  ret i32 %4
+}
+
+#--- linklib-noref.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+declare i32 @anchor(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %3 = icmp ne i32 %1, u0x01
+  %4 = zext i1 %3 to i32
+  %5 = call i32 @anchor(i32 %4)
+  ; return success if overridden
+  ret i32 %4
+}
+
+#--- linklib-use.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+declare i32 @anchor(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %2 = call i32 @theweak(i32 %1)
+  %3 = icmp ne i32 %2, u0x5
+  %4 = zext i1 %3 to i32
+  %5 = call i32 @anchor(i32 %4)
+  ; return success if overridden and used local obj
+  ret i32 %4
+}
+
+#--- linkdll-noref.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+declare i32 @anchor(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %3 = icmp ne i32 %1, u0x01
+  %4 = zext i1 %3 to i32
+  %5 = call i32 @anchor(i32 %4)
+  ; return success if overridden
+  ret i32 %4
+}
+
+#--- linkdll-use.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+declare i32 @theweak(i32) nounwind
+declare i32 @anchor(i32) nounwind
+
+declare dllimport i32 @is_overridden() nounwind
+define dso_local i32 @main() nounwind {
+  %1 = call i32 @is_overridden()
+  %2 = call i32 @theweak(i32 %1)
+  %3 = icmp ne i32 %2, u0x9
+  %4 = zext i1 %3 to i32
+  %5 = call i32 @anchor(i32 %4)
+  ; return success if overridden and used from dll
+  ret i32 %4
+}
+
+#--- crt0-x86_64-mingw.s
+  .text
+  .globl _start
+  .p2align 4
+_start:
+  call premain
+  sub $64, %rsp
+  xor %r8, %r8
+  movq %r8, 40(%rsp)
+  lea 40(%rsp), %rdx
+  mov %rdx, 48(%rsp)
+  movq %r8, 56(%rsp)
+  addq $8, %rdx
+  mov $1, %ecx
+  call main // ret = main(1, { "", nullptr });
+  cmp $127, %eax
+  mov $1, %edx
+  cmovbe %eax, %edx // ret = (unsigned)ret >= 128 ? 1 : ret
+  mov $-1, %rcx
+  mov %rcx, %r10
+  mov $0x2C, %eax
+  syscall   // ExitProcess(-1, ret)
+  jmp .
+
+  .section .data,"rw"
+  .globl _dummy_data
+_dummy_data:
+  .quad 0x1122334455667788
+
+  .section .rdata,"r"
+  .globl _dummy_rdata
+_dummy_rdata:
+  .quad 0x1122334455667788
+
+#--- crt1.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+ at ref_theweak = dso_local global ptr @__real_theweak
+declare extern_weak i32 @__real_theweak(i32) nounwind
+
+declare dllimport void @do_override(ptr %fn) nounwind
+
+define dso_local void @premain() nounwind {
+  %1 = load ptr, ptr @ref_theweak
+  call void @do_override(ptr %1)
+  ret void
+}
+
+ at __RUNTIME_PSEUDO_RELOC_LIST__ = external dso_local constant ptr
+ at __RUNTIME_PSEUDO_RELOC_LIST_END__ = external dso_local constant ptr
+
+define dso_local i32 @_pei386_runtime_relocator() {
+  ret i32 trunc(i64 sub(i64 ptrtoint(ptr @__RUNTIME_PSEUDO_RELOC_LIST_END__ to i64),
+    i64 ptrtoint(ptr @__RUNTIME_PSEUDO_RELOC_LIST__ to i64)) to i32)
+}
+
+#--- rtdll.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+ at fn_ptr = dso_local global ptr null
+define dllexport void @__main() nounwind {
+  ret void
+}
+define dllexport void @do_override(ptr %fn) nounwind {
+  %n = icmp eq ptr %fn, null
+  br i1 %n, label %fin, label %do
+do:
+  store ptr %fn, ptr @fn_ptr
+  br label %fin
+fin:
+  ret void
+}
+define dllexport i32 @is_overridden() nounwind {
+  %fn = load ptr, ptr @fn_ptr
+  %ne = icmp ne ptr %fn, null
+  %r = zext i1 %ne to i32
+  ret i32 %r
+}
+define dllexport i32 @__wrap_theweak(i32 %i) nounwind {
+  %fn = load ptr, ptr @fn_ptr
+  %n = icmp eq ptr %fn, null
+  br i1 %n, label %eq, label %ne
+eq:
+  %1 = tail call i32 @fallback(i32 %i)
+  ret i32 %1
+ne:
+  %2 = tail call i32 %fn(i32 %i)
+  ret i32 %2
+}
+define dso_local i32 @fallback(i32 %i) nounwind {
+  %1 = or i32 %i, u0x02
+  ret i32 %1
+}
+
+#--- dllcrt0-x86_64-mingw.s
+  .text
+  .globl _start
+  .p2align 4
+_start:
+  call premain
+  jmp dllmain
+
+#--- somedll.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+define dso_local void @dllmain() nounwind {
+  ret void
+}
+define dllexport i32 @theweak(i32 %i) nounwind {
+  %1 = or i32 %i, u0x08
+  ret i32 %1
+}
+define dllexport i32 @anchor(i32 %i) nounwind {
+  ret i32 %i
+}

>From 720b0cb3fada39af66c4be9f8c54ea6b7debd15d Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 27 Jul 2025 22:25:25 +0900
Subject: [PATCH 02/12] add logs for tracing

---
 lld/COFF/Chunks.cpp      |  5 +++++
 lld/COFF/MinGW.cpp       |  8 +++++++-
 lld/COFF/SymbolTable.cpp | 10 ++++++++++
 lld/COFF/Symbols.h       |  2 +-
 lld/COFF/Writer.cpp      |  1 +
 5 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 39fc25047f3b1..d4ff65dad1e1a 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -566,6 +566,11 @@ void SectionChunk::getBaserels(std::vector<Baserel> *res) {
     Symbol *target = file->getSymbol(rel.SymbolTableIndex);
     if (!target || isa<DefinedAbsolute>(target))
       continue;
+    if (target && target->getName().size() > 2)
+      Log(file->symtab.ctx)
+          << "base reloc for " << target->getName() << ": " << target->kind()
+          << ',' << !!target->isUsedInRegularObj << " (in " << file->getName()
+          << ")";
     res->emplace_back(rva + rel.VirtualAddress, ty);
   }
 
diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index e7117cbea2e88..135c428c64e51 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -226,6 +226,8 @@ void lld::coff::addWrappedSymbols(SymbolTable &symtab,
     Symbol *sym = symtab.findUnderscore(name);
     if (!sym)
       continue;
+    Log(symtab.ctx) << "adding wrapped symbol entry for: " << name << ": "
+                    << sym->kind() << ',' << !!sym->isUsedInRegularObj;
 
     Symbol *real =
         symtab.addUndefined(mangle("__real_" + name, symtab.machine));
@@ -269,6 +271,7 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
       // (We can't easily distinguish whether any object file actually
       // referenced it or not, though.)
       if (imp) {
+        Log(symtab.ctx) << "wrapping imported symbol: " << imp->getName();
         DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
             symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
         symtab.localImportChunks.push_back(wrapimp->getChunk());
@@ -281,7 +284,10 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
   parallelForEach(symtab.ctx.objFileInstances, [&](ObjFile *file) {
     MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
     for (auto &sym : syms)
-      if (Symbol *s = map.lookup(sym))
+      if (Symbol *s = map.lookup(sym)) {
+        Log(symtab.ctx) << "overriding " << sym->getName() << " by "
+                        << s->getName() << " (in " << file->getName() << ")";
         sym = s;
+      }
   });
 }
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 0a88807c00dd5..cce0075b6cfb2 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -257,6 +257,8 @@ void SymbolTable::loadMinGWSymbols() {
   }
 
   for (auto sym : undefs) {
+    Log(ctx) << "trying fixup " << sym->getName() << ": " << sym->kind() << ','
+             << !!sym->isUsedInRegularObj;
     auto *undef = dyn_cast<Undefined>(sym);
     if (!undef)
       continue;
@@ -459,6 +461,13 @@ void SymbolTable::resolveRemainingUndefines(std::vector<Undefined *> &aliases) {
 
   for (auto &i : symMap) {
     Symbol *sym = i.second;
+
+    if (auto name = sym->getName(); !name.ends_with("__") &&
+                                    !name.starts_with("__guard") &&
+                                    !name.starts_with("__nm_"))
+      Log(ctx) << "checking for " << name << ": " << sym->kind()
+               << " used: " << (sym->isUsedInRegularObj != 0);
+
     auto *undef = dyn_cast<Undefined>(sym);
     if (!undef)
       continue;
@@ -525,6 +534,7 @@ void SymbolTable::resolveRemainingUndefines(std::vector<Undefined *> &aliases) {
 }
 
 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {
+  Log(ctx) << "inserting " << name;
   bool inserted = false;
   Symbol *&sym = symMap[CachedHashStringRef(name)];
   if (!sym) {
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index c86ded860876b..9e8cd4aa0cfdc 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -56,7 +56,7 @@ class Symbol {
     DefinedAbsoluteKind,
     DefinedSyntheticKind,
 
-    UndefinedKind,
+    UndefinedKind, // = 7
     LazyArchiveKind,
     LazyObjectKind,
     LazyDLLSymbolKind,
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 21ab9d17a26f9..9664215f4bdc8 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1299,6 +1299,7 @@ void Writer::createImportTables() {
                    << file->symtab.printSymbol(impSym);
       delayIdata.add(impSym);
     } else {
+      Log(ctx) << "populating import entry for " << impSym->getName();
       idata.add(impSym);
     }
   }

>From 9b7600fb3fc9dc5dad0db2430a572cd55c764864 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sat, 30 Aug 2025 08:59:52 +0900
Subject: [PATCH 03/12] test for "inherit weak"

---
 lld/test/COFF/wrap-inherit-weakness.ll | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 lld/test/COFF/wrap-inherit-weakness.ll

diff --git a/lld/test/COFF/wrap-inherit-weakness.ll b/lld/test/COFF/wrap-inherit-weakness.ll
new file mode 100644
index 0000000000000..e050e8fda37f2
--- /dev/null
+++ b/lld/test/COFF/wrap-inherit-weakness.ll
@@ -0,0 +1,16 @@
+; REQUIRES: x86
+
+; Check that 'weak' attribute will be inherited to the wrapped symbols.
+
+; RUN: llc %s -mtriple x86_64-mingw -o %t.o --filetype=obj
+; RUN: ld.lld -m i386pep -shared -o %t.dll %t.o --entry= --wrap fn
+
+declare extern_weak dso_local void @__real_fn() nounwind
+declare dso_local void @fn() nounwind
+declare dso_local void @__wrap_fn() nounwind
+
+define dllexport void @caller() nounwind {
+  call void @__real_fn()
+  call void @fn()
+  ret void
+}

>From c08ec16dd3950d4da98c1cd6855a0e6341ea4740 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 13 Aug 2025 21:23:46 +0900
Subject: [PATCH 04/12] inherit weak

---
 lld/COFF/MinGW.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 135c428c64e51..24c75997aa737 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -235,6 +235,19 @@ void lld::coff::addWrappedSymbols(SymbolTable &symtab,
         symtab.addUndefined(mangle("__wrap_" + name, symtab.machine));
     v.push_back({sym, real, wrap});
 
+    if (auto *usym = dyn_cast<Undefined>(sym)) {
+      if (auto *ureal = dyn_cast<Undefined>(real);
+          ureal && ureal->weakAlias && !usym->weakAlias) {
+        Log(symtab.ctx) << "inheriting weak alias to: " << usym->getName();
+        usym->weakAlias = ureal->weakAlias;
+      }
+      if (auto *uwrap = dyn_cast<Undefined>(wrap);
+          uwrap && usym->weakAlias && !uwrap->weakAlias) {
+        Log(symtab.ctx) << "inheriting weak alias to: " << uwrap->getName();
+        uwrap->weakAlias = usym->weakAlias;
+      }
+    }
+
     // These symbols may seem undefined initially, but don't bail out
     // at symtab.reportUnresolvable() due to them, but let wrapSymbols
     // below sort things out before checking finally with

>From da17b36d1294400e081c425d179f39c9f7f364e8 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sat, 30 Aug 2025 09:33:37 +0900
Subject: [PATCH 05/12] test for "reuse existing symbol when wrapping imports"

---
 lld/test/COFF/wrap-dllimport.s | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/lld/test/COFF/wrap-dllimport.s b/lld/test/COFF/wrap-dllimport.s
index d7662b29fdc78..a1b4521fd75fa 100644
--- a/lld/test/COFF/wrap-dllimport.s
+++ b/lld/test/COFF/wrap-dllimport.s
@@ -1,42 +1,59 @@
 // REQUIRES: x86
 
 // Check that we can wrap a dllimported symbol, so that references to
-// __imp_<symbol> gets redirected to a defined local import instead.
+// __imp_<symbol> gets redirected to a symbol already exists or a defined local import instead
 
 // RUN: split-file %s %t.dir
 // RUN: llvm-mc -filetype=obj -triple=i686-win32-gnu %t.dir/main.s -o %t.main.obj
 // RUN: llvm-mc -filetype=obj -triple=i686-win32-gnu %t.dir/other.s -o %t.other.obj
 
-// RUN: lld-link -dll -out:%t.dll %t.other.obj -noentry -safeseh:no -export:foo -implib:%t.lib
-// RUN: lld-link -out:%t.exe %t.main.obj %t.lib -entry:entry -subsystem:console -debug:symtab -safeseh:no -wrap:foo -lldmap:%t.map
+// RUN: lld-link -dll -out:%t.dll %t.other.obj -noentry -safeseh:no -export:foo -export:bar -implib:%t.lib
+// RUN: lld-link -out:%t.exe %t.main.obj %t.lib -entry:entry -subsystem:console -debug:symtab -safeseh:no -wrap:foo -wrap:bar -lldmap:%t.map
 // RUN: llvm-objdump -s -d --print-imm-hex %t.exe | FileCheck %s
 
 // CHECK:      Contents of section .rdata:
-// CHECK-NEXT:  402000 06104000
+// CHECK-NEXT:  402000 0c104000
 
 // CHECK:      Disassembly of section .text:
 // CHECK-EMPTY:
 // CHECK:      00401000 <_entry>:
 // CHECK-NEXT:   401000: ff 25 00 20 40 00             jmpl    *0x402000
+// CHECK-NEXT:   401006: ff 25 00 00 00 00             jmpl    *0x0
 // CHECK-EMPTY:
-// CHECK-NEXT: 00401006 <___wrap_foo>:
-// CHECK-NEXT:   401006: c3                            retl
+// CHECK-NEXT: 0040100c <___wrap_foo>:
+// CHECK-NEXT:   40100c: c3                            retl
+// CHECK-EMPTY:
+// CHECK-NEXT: 0040100d <___wrap_bar>:
+// CHECK-NEXT:   40100d: c3                            retl
 
-// The jmpl instruction in _entry points at an address in 0x402000,
+// The first jmpl instruction in _entry points at an address in 0x402000,
 // which is the first 4 bytes of the .rdata section (above), which is a
 // pointer that points at ___wrap_foo.
 
+// The second jmpl instruction in _entry points the null since the referenced symbol
+// `__imp____wrap_bar` is declared as a weak reference to prevent pull a reference
+// from an external DLL.
+
 #--- main.s
 .global _entry
 _entry:
   jmpl *__imp__foo
+  jmpl *__imp__bar
 
 .global ___wrap_foo
 ___wrap_foo:
   ret
 
+.weak __imp____wrap_bar
+.global ___wrap_bar
+___wrap_bar:
+  ret
+
 #--- other.s
 .global _foo
-
 _foo:
   ret
+
+.global _bar
+_bar:
+  ret

>From 6bf8c44ce87373610ef59a989ecdc7ed1733b6ad Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 13 Aug 2025 10:43:37 +0900
Subject: [PATCH 06/12] reuse existing symbol when wrapping imports

---
 lld/COFF/MinGW.cpp | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 24c75997aa737..47029ad18594c 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -278,17 +278,27 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
     map[w.sym] = w.wrap;
     map[w.real] = w.sym;
     if (Defined *d = dyn_cast<Defined>(w.wrap)) {
+      Log(symtab.ctx) << "checking for importing with unwrapping: "
+                      << d->getName();
       Symbol *imp = symtab.find(("__imp_" + w.sym->getName()).str());
       // Create a new defined local import for the wrap symbol. If
       // no imp prefixed symbol existed, there's no need for it.
       // (We can't easily distinguish whether any object file actually
       // referenced it or not, though.)
       if (imp) {
-        Log(symtab.ctx) << "wrapping imported symbol: " << imp->getName();
-        DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
-            symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
-        symtab.localImportChunks.push_back(wrapimp->getChunk());
-        map[imp] = wrapimp;
+        if (Symbol *wrapimp =
+                symtab.find(("__imp_" + w.wrap->getName()).str())) {
+          Log(symtab.ctx) << "using unwrapped imported symbol: "
+                          << imp->getName();
+          map[imp] = wrapimp;
+        } else {
+          Log(symtab.ctx) << "create local unwrapped imported symbol: "
+                          << imp->getName();
+          DefinedLocalImport *localwrapimp = make<DefinedLocalImport>(
+              symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
+          symtab.localImportChunks.push_back(localwrapimp->getChunk());
+          map[imp] = localwrapimp;
+        }
       }
     }
   }

>From 2c5d613094bc0d2509f0188087daa0c0de40ee17 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sat, 30 Aug 2025 18:46:54 +0900
Subject: [PATCH 07/12] test for "skip undefined baserel"

---
 lld/test/COFF/reloc-undefined-weak.s | 52 ++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 lld/test/COFF/reloc-undefined-weak.s

diff --git a/lld/test/COFF/reloc-undefined-weak.s b/lld/test/COFF/reloc-undefined-weak.s
new file mode 100644
index 0000000000000..5f9baa7a3dfb0
--- /dev/null
+++ b/lld/test/COFF/reloc-undefined-weak.s
@@ -0,0 +1,52 @@
+// REQUIRES: x86
+
+// Check that base-relocations for unresolved weak symbols will be omitted.
+
+// RUN: rm -rf %t.dir && split-file %s %t.dir && cd %t.dir
+// RUN: llvm-mc -filetype=obj -triple=x86_64-mingw main.s -o main.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-mingw other.s -o other.o
+
+// RUN: ld.lld -m i386pep -dll -o other.dll other.o -entry= --export-all-symbols --out-implib other.dll.a
+// RUN: ld.lld -m i386pep -o main.exe main.o other.dll.a -e entry --wrap foo --verbose
+// RUN: llvm-readobj --sections --symbols --coff-imports --coff-basereloc main.exe | FileCheck %s --implicit-check-not=other.dll
+
+// CHECK:      Number: 4
+// CHECK-NEXT: Name: .data
+// CHECK-NEXT: VirtualSize:
+// CHECK-NEXT: VirtualAddress: 0x[[#%x,SECTOP:0x4000]]
+// CHECK:      Name: ref_foo
+// CHECK-NEXT: Value: [[#%d,SYMVAL:]]
+// CHECK:      BaseReloc [
+// CHECK-NOT:    Address: 0x[[#%x,SECTOP+SYMVAL]]
+
+#--- main.s
+.global entry
+entry:
+  movq ref_foo(%rip), %rax
+  call *%rax
+
+.global __wrap_foo
+__wrap_foo:
+  ret
+
+.data
+.global ref_foo
+.p2align 3
+ref_foo:
+  .quad __real_foo
+
+.globl _pei386_runtime_relocator
+_pei386_runtime_relocator:
+  movl __RUNTIME_PSEUDO_RELOC_LIST__(%rip), %eax
+  movl __RUNTIME_PSEUDO_RELOC_LIST_END__(%rip), %eax
+
+.weak __real_foo
+.addrsig
+.addrsig_sym __real_foo
+.addrsig_sym ref_foo
+
+#--- other.s
+.global foo
+
+foo:
+  ret

>From 54a710952f9f9e25f0acd3adb14c9584e4c589a7 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 13 Aug 2025 10:44:08 +0900
Subject: [PATCH 08/12] skip undefined baserel

---
 lld/COFF/Chunks.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index d4ff65dad1e1a..259fffc847590 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -564,7 +564,7 @@ void SectionChunk::getBaserels(std::vector<Baserel> *res) {
     if (ty == IMAGE_REL_BASED_ABSOLUTE)
       continue;
     Symbol *target = file->getSymbol(rel.SymbolTableIndex);
-    if (!target || isa<DefinedAbsolute>(target))
+    if (!isa_and_nonnull<Defined>(target) || isa<DefinedAbsolute>(target))
       continue;
     if (target && target->getName().size() > 2)
       Log(file->symtab.ctx)

>From ca3488caec539244f982f859b02fb10b97c9cd9a Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 31 Aug 2025 07:41:30 +0900
Subject: [PATCH 09/12] cleanup

Revert "add logs for tracing"
Revert "application test"
---
 lld/COFF/Chunks.cpp                 |   5 -
 lld/COFF/MinGW.cpp                  |  15 +-
 lld/COFF/SymbolTable.cpp            |  10 -
 lld/COFF/Symbols.h                  |   2 +-
 lld/COFF/Writer.cpp                 |   1 -
 lld/test/COFF/weak-wrap-import.test | 360 ----------------------------
 6 files changed, 2 insertions(+), 391 deletions(-)
 delete mode 100644 lld/test/COFF/weak-wrap-import.test

diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 259fffc847590..cb5cba5c414a1 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -566,11 +566,6 @@ void SectionChunk::getBaserels(std::vector<Baserel> *res) {
     Symbol *target = file->getSymbol(rel.SymbolTableIndex);
     if (!isa_and_nonnull<Defined>(target) || isa<DefinedAbsolute>(target))
       continue;
-    if (target && target->getName().size() > 2)
-      Log(file->symtab.ctx)
-          << "base reloc for " << target->getName() << ": " << target->kind()
-          << ',' << !!target->isUsedInRegularObj << " (in " << file->getName()
-          << ")";
     res->emplace_back(rva + rel.VirtualAddress, ty);
   }
 
diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 47029ad18594c..7c6f4281145ce 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -226,8 +226,6 @@ void lld::coff::addWrappedSymbols(SymbolTable &symtab,
     Symbol *sym = symtab.findUnderscore(name);
     if (!sym)
       continue;
-    Log(symtab.ctx) << "adding wrapped symbol entry for: " << name << ": "
-                    << sym->kind() << ',' << !!sym->isUsedInRegularObj;
 
     Symbol *real =
         symtab.addUndefined(mangle("__real_" + name, symtab.machine));
@@ -238,12 +236,10 @@ void lld::coff::addWrappedSymbols(SymbolTable &symtab,
     if (auto *usym = dyn_cast<Undefined>(sym)) {
       if (auto *ureal = dyn_cast<Undefined>(real);
           ureal && ureal->weakAlias && !usym->weakAlias) {
-        Log(symtab.ctx) << "inheriting weak alias to: " << usym->getName();
         usym->weakAlias = ureal->weakAlias;
       }
       if (auto *uwrap = dyn_cast<Undefined>(wrap);
           uwrap && usym->weakAlias && !uwrap->weakAlias) {
-        Log(symtab.ctx) << "inheriting weak alias to: " << uwrap->getName();
         uwrap->weakAlias = usym->weakAlias;
       }
     }
@@ -278,8 +274,6 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
     map[w.sym] = w.wrap;
     map[w.real] = w.sym;
     if (Defined *d = dyn_cast<Defined>(w.wrap)) {
-      Log(symtab.ctx) << "checking for importing with unwrapping: "
-                      << d->getName();
       Symbol *imp = symtab.find(("__imp_" + w.sym->getName()).str());
       // Create a new defined local import for the wrap symbol. If
       // no imp prefixed symbol existed, there's no need for it.
@@ -288,12 +282,8 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
       if (imp) {
         if (Symbol *wrapimp =
                 symtab.find(("__imp_" + w.wrap->getName()).str())) {
-          Log(symtab.ctx) << "using unwrapped imported symbol: "
-                          << imp->getName();
           map[imp] = wrapimp;
         } else {
-          Log(symtab.ctx) << "create local unwrapped imported symbol: "
-                          << imp->getName();
           DefinedLocalImport *localwrapimp = make<DefinedLocalImport>(
               symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
           symtab.localImportChunks.push_back(localwrapimp->getChunk());
@@ -307,10 +297,7 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
   parallelForEach(symtab.ctx.objFileInstances, [&](ObjFile *file) {
     MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
     for (auto &sym : syms)
-      if (Symbol *s = map.lookup(sym)) {
-        Log(symtab.ctx) << "overriding " << sym->getName() << " by "
-                        << s->getName() << " (in " << file->getName() << ")";
+      if (Symbol *s = map.lookup(sym))
         sym = s;
-      }
   });
 }
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index cce0075b6cfb2..0a88807c00dd5 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -257,8 +257,6 @@ void SymbolTable::loadMinGWSymbols() {
   }
 
   for (auto sym : undefs) {
-    Log(ctx) << "trying fixup " << sym->getName() << ": " << sym->kind() << ','
-             << !!sym->isUsedInRegularObj;
     auto *undef = dyn_cast<Undefined>(sym);
     if (!undef)
       continue;
@@ -461,13 +459,6 @@ void SymbolTable::resolveRemainingUndefines(std::vector<Undefined *> &aliases) {
 
   for (auto &i : symMap) {
     Symbol *sym = i.second;
-
-    if (auto name = sym->getName(); !name.ends_with("__") &&
-                                    !name.starts_with("__guard") &&
-                                    !name.starts_with("__nm_"))
-      Log(ctx) << "checking for " << name << ": " << sym->kind()
-               << " used: " << (sym->isUsedInRegularObj != 0);
-
     auto *undef = dyn_cast<Undefined>(sym);
     if (!undef)
       continue;
@@ -534,7 +525,6 @@ void SymbolTable::resolveRemainingUndefines(std::vector<Undefined *> &aliases) {
 }
 
 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {
-  Log(ctx) << "inserting " << name;
   bool inserted = false;
   Symbol *&sym = symMap[CachedHashStringRef(name)];
   if (!sym) {
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 9e8cd4aa0cfdc..c86ded860876b 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -56,7 +56,7 @@ class Symbol {
     DefinedAbsoluteKind,
     DefinedSyntheticKind,
 
-    UndefinedKind, // = 7
+    UndefinedKind,
     LazyArchiveKind,
     LazyObjectKind,
     LazyDLLSymbolKind,
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 9664215f4bdc8..21ab9d17a26f9 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1299,7 +1299,6 @@ void Writer::createImportTables() {
                    << file->symtab.printSymbol(impSym);
       delayIdata.add(impSym);
     } else {
-      Log(ctx) << "populating import entry for " << impSym->getName();
       idata.add(impSym);
     }
   }
diff --git a/lld/test/COFF/weak-wrap-import.test b/lld/test/COFF/weak-wrap-import.test
deleted file mode 100644
index a4c4d56fc7597..0000000000000
--- a/lld/test/COFF/weak-wrap-import.test
+++ /dev/null
@@ -1,360 +0,0 @@
-REQUIRES: x86, shell
-
-RUN: rm -f %t.dir/* && split-file %s %t.dir/ && cd %t.dir
-
-RUN: llc rtdll.ll -o rtdll.o --filetype=obj
-RUN: ld.lld -m i386pep -shared -o rtdll.dll rtdll.o --entry= --out-implib rtdll.dll.a --dynamicbase
-
-RUN: llvm-mc -filetype=obj -triple=x86_64-mingw crt0-x86_64-mingw.s    -o crt0.o
-RUN: llvm-mc -filetype=obj -triple=x86_64-mingw dllcrt0-x86_64-mingw.s -o dllcrt0.o
-RUN: llc crt1.ll -o crt1.o --filetype=obj
-
-RUN: llc overrider.ll -o overrider.o --filetype=obj
-RUN: llvm-ar rc somelib.a overrider.o
-RUN: llvm-as overrider.ll -o overrider.bc
-
-RUN: llc somedll.ll -o somedll.o --filetype=obj
-RUN: ld.lld -m i386pep --dynamicbase --entry _start --wrap theweak \
-RUN:   -shared -o somedll.dll somedll.o dllcrt0.o crt1.o rtdll.dll.a --out-implib somedll.dll.a
-
-RUN: env NAME=noref         DEPS=              sh run.sh CHECK
-RUN: env NAME=use           DEPS=              sh run.sh CHECK,CHECK-IMP
-RUN: env NAME=override-only DEPS=overrider.o   sh run.sh CHECK,CHECK-IMP-LLD,CHECK-REL
-RUN: env NAME=override-use  DEPS=overrider.o   sh run.sh CHECK,CHECK-IMP,CHECK-REL
-RUN: env NAME=linklib-noref DEPS=somelib.a     sh run.sh CHECK,CHECK-IMP-LLD,CHECK-REL
-RUN: env NAME=linklib-use   DEPS=somelib.a     sh run.sh CHECK,CHECK-IMP,CHECK-REL
-RUN: env NAME=linkdll-noref DEPS=somedll.dll.a sh run.sh CHECK,CHECK-IMP-LLD,SOMEDLL
-RUN: env NAME=linkdll-use   DEPS=somedll.dll.a sh run.sh CHECK,CHECK-IMP,CHECK-REL-LLD,SOMEDLL,SOMEDLL-IMP-LLD
-
-#--- check-lld.txt
-CHECK: 0200[[#%x,ADDR:]] D ref_theweak
-CHECK: File
-SOMEDLL:          Import {
-SOMEDLL-NEXT:       Name: somedll.dll
-SOMEDLL-IMP:        Symbol: theweak
-SOMEDLL-IMP-LLD:    Symbol: theweak
-SOMEDLL:          }
-CHECK:            Import {
-CHECK-NEXT:         Name: rtdll.dll
-CHECK-IMP:          Symbol: __wrap_theweak
-CHECK-IMP-LLD:      Symbol: __wrap_theweak
-CHECK:            }
-CHECK:            BaseReloc [
-CHECK-REL:          Type: DIR64
-CHECK-REL-NEXT:     Address: 0x[[#%X,ADDR]]
-CHECK-REL-LLD:      Type: DIR64
-CHECK-REL-LLD-NEXT: Address: 0x[[#%X,ADDR]]
-CHECK:            ]
-
-#--- check-bfd.txt
-CHECK: 0200[[#%x,ADDR:]] D ref_theweak
-CHECK: File
-CHECK:            Import {
-CHECK-NEXT:         Name: rtdll.dll
-CHECK-IMP:          Symbol: __wrap_theweak
-CHECK-IMP-BFD:      Symbol: __wrap_theweak
-CHECK:            }
-SOMEDLL:          Import {
-SOMEDLL-NEXT:       Name: somedll.dll
-SOMEDLL-IMP:        Symbol: theweak
-SOMEDLL-IMP-BFD:    Symbol: theweak
-SOMEDLL:          }
-CHECK:            BaseReloc [
-CHECK-REL:          Type: DIR64
-CHECK-REL-NEXT:     Address: 0x[[#%X,ADDR]]
-CHECK-REL-BFD:      Type: DIR64
-CHECK-REL-BFD-NEXT: Address: 0x[[#%X,ADDR]]
-CHECK:            ]
-
-#--- run.sh
-set -ex
-RUNBIN=true
-LINKER=lld
-run() {
-  if [ "$ASLR" = ON ]; then
-    dynamicbase=--dynamicbase
-    ASLR=.aslr
-  else
-    dynamicbase=
-    ASLR=
-  fi
-  ld.$LINKER -m i386pep $dynamicbase --entry _start --subsystem console --wrap theweak --image-base 0x02000000 \
-    -o $NAME$LTO$ASLR.exe crt0.o crt1.o $NAME.o $DEPS rtdll.dll.a
-  llvm-nm $NAME$LTO$ASLR.exe > $NAME$LTO$ASLR.dump
-  llvm-readobj --hex-dump=.data --coff-basereloc --coff-imports $NAME$LTO$ASLR.exe >> $NAME$LTO$ASLR.dump
-  FileCheck --input-file=$NAME$LTO$ASLR.dump check-$LINKER.txt --allow-unused-prefixes --check-prefixes=$1 \
-    --implicit-check-not=.dll --implicit-check-not="Symbol: {{[a-z_]*}}theweak" --implicit-check-not=DIR64
-  [ -z "$RUNBIN" ] || ./$NAME$LTO$ASLR.exe
-}
-if ! uname -a | grep -E -iq 'cygwin|mingw|msys|wsl'; then
-  RUNBIN=
-fi
-llc $NAME.ll -o $NAME.o --filetype=obj
-run "$@"
-[ -z "$RUNBIN" ] || ASLR=ON run "$@"
-if [ $LINKER = lld ]; then
-  llvm-as $NAME.ll -o $NAME.bc
-  LTO=.lto run "$@"
-  [ -z "$RUNBIN" ] || LTO=.lto ASLR=ON run "$@"
-fi
-
-#--- noref.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %3 = icmp ne i32 %1, u0x00
-  %4 = zext i1 %3 to i32
-  ; return success if not overridden
-  ret i32 %4
-}
-
-#--- use.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %2 = call i32 @theweak(i32 %1)
-  %3 = icmp ne i32 %2, u0x02
-  %4 = zext i1 %3 to i32
-  ; return success if not overridden and used fallback
-  ret i32 %4
-}
-
-#--- overrider.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-define dso_local i32 @theweak(i32 %i) nounwind {
-  %1 = or i32 %i, u0x04
-  ret i32 %1
-}
-define i32 @anchor(i32 %i) nounwind {
-  ret i32 %i
-}
-
-#--- override-only.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %3 = icmp ne i32 %1, u0x01
-  %4 = zext i1 %3 to i32
-  ; return success if overridden
-  ret i32 %4
-}
-
-#--- override-use.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %2 = call i32 @theweak(i32 %1)
-  %3 = icmp ne i32 %2, u0x5
-  %4 = zext i1 %3 to i32
-  ; return success if overridden and used local obj
-  ret i32 %4
-}
-
-#--- linklib-noref.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-declare i32 @anchor(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %3 = icmp ne i32 %1, u0x01
-  %4 = zext i1 %3 to i32
-  %5 = call i32 @anchor(i32 %4)
-  ; return success if overridden
-  ret i32 %4
-}
-
-#--- linklib-use.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-declare i32 @anchor(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %2 = call i32 @theweak(i32 %1)
-  %3 = icmp ne i32 %2, u0x5
-  %4 = zext i1 %3 to i32
-  %5 = call i32 @anchor(i32 %4)
-  ; return success if overridden and used local obj
-  ret i32 %4
-}
-
-#--- linkdll-noref.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-declare i32 @anchor(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %3 = icmp ne i32 %1, u0x01
-  %4 = zext i1 %3 to i32
-  %5 = call i32 @anchor(i32 %4)
-  ; return success if overridden
-  ret i32 %4
-}
-
-#--- linkdll-use.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-declare i32 @theweak(i32) nounwind
-declare i32 @anchor(i32) nounwind
-
-declare dllimport i32 @is_overridden() nounwind
-define dso_local i32 @main() nounwind {
-  %1 = call i32 @is_overridden()
-  %2 = call i32 @theweak(i32 %1)
-  %3 = icmp ne i32 %2, u0x9
-  %4 = zext i1 %3 to i32
-  %5 = call i32 @anchor(i32 %4)
-  ; return success if overridden and used from dll
-  ret i32 %4
-}
-
-#--- crt0-x86_64-mingw.s
-  .text
-  .globl _start
-  .p2align 4
-_start:
-  call premain
-  sub $64, %rsp
-  xor %r8, %r8
-  movq %r8, 40(%rsp)
-  lea 40(%rsp), %rdx
-  mov %rdx, 48(%rsp)
-  movq %r8, 56(%rsp)
-  addq $8, %rdx
-  mov $1, %ecx
-  call main // ret = main(1, { "", nullptr });
-  cmp $127, %eax
-  mov $1, %edx
-  cmovbe %eax, %edx // ret = (unsigned)ret >= 128 ? 1 : ret
-  mov $-1, %rcx
-  mov %rcx, %r10
-  mov $0x2C, %eax
-  syscall   // ExitProcess(-1, ret)
-  jmp .
-
-  .section .data,"rw"
-  .globl _dummy_data
-_dummy_data:
-  .quad 0x1122334455667788
-
-  .section .rdata,"r"
-  .globl _dummy_rdata
-_dummy_rdata:
-  .quad 0x1122334455667788
-
-#--- crt1.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
- at ref_theweak = dso_local global ptr @__real_theweak
-declare extern_weak i32 @__real_theweak(i32) nounwind
-
-declare dllimport void @do_override(ptr %fn) nounwind
-
-define dso_local void @premain() nounwind {
-  %1 = load ptr, ptr @ref_theweak
-  call void @do_override(ptr %1)
-  ret void
-}
-
- at __RUNTIME_PSEUDO_RELOC_LIST__ = external dso_local constant ptr
- at __RUNTIME_PSEUDO_RELOC_LIST_END__ = external dso_local constant ptr
-
-define dso_local i32 @_pei386_runtime_relocator() {
-  ret i32 trunc(i64 sub(i64 ptrtoint(ptr @__RUNTIME_PSEUDO_RELOC_LIST_END__ to i64),
-    i64 ptrtoint(ptr @__RUNTIME_PSEUDO_RELOC_LIST__ to i64)) to i32)
-}
-
-#--- rtdll.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
- at fn_ptr = dso_local global ptr null
-define dllexport void @__main() nounwind {
-  ret void
-}
-define dllexport void @do_override(ptr %fn) nounwind {
-  %n = icmp eq ptr %fn, null
-  br i1 %n, label %fin, label %do
-do:
-  store ptr %fn, ptr @fn_ptr
-  br label %fin
-fin:
-  ret void
-}
-define dllexport i32 @is_overridden() nounwind {
-  %fn = load ptr, ptr @fn_ptr
-  %ne = icmp ne ptr %fn, null
-  %r = zext i1 %ne to i32
-  ret i32 %r
-}
-define dllexport i32 @__wrap_theweak(i32 %i) nounwind {
-  %fn = load ptr, ptr @fn_ptr
-  %n = icmp eq ptr %fn, null
-  br i1 %n, label %eq, label %ne
-eq:
-  %1 = tail call i32 @fallback(i32 %i)
-  ret i32 %1
-ne:
-  %2 = tail call i32 %fn(i32 %i)
-  ret i32 %2
-}
-define dso_local i32 @fallback(i32 %i) nounwind {
-  %1 = or i32 %i, u0x02
-  ret i32 %1
-}
-
-#--- dllcrt0-x86_64-mingw.s
-  .text
-  .globl _start
-  .p2align 4
-_start:
-  call premain
-  jmp dllmain
-
-#--- somedll.ll
-target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-windows-gnu"
-
-define dso_local void @dllmain() nounwind {
-  ret void
-}
-define dllexport i32 @theweak(i32 %i) nounwind {
-  %1 = or i32 %i, u0x08
-  ret i32 %1
-}
-define dllexport i32 @anchor(i32 %i) nounwind {
-  ret i32 %i
-}

>From ddbec97bd06c962eb66f8886228aa991d516f27f Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Fri, 5 Sep 2025 22:14:53 +0900
Subject: [PATCH 10/12] not to use ld.lld

---
 lld/test/COFF/reloc-undefined-weak.s | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lld/test/COFF/reloc-undefined-weak.s b/lld/test/COFF/reloc-undefined-weak.s
index 5f9baa7a3dfb0..dc0a230c37d4a 100644
--- a/lld/test/COFF/reloc-undefined-weak.s
+++ b/lld/test/COFF/reloc-undefined-weak.s
@@ -3,17 +3,17 @@
 // Check that base-relocations for unresolved weak symbols will be omitted.
 
 // RUN: rm -rf %t.dir && split-file %s %t.dir && cd %t.dir
-// RUN: llvm-mc -filetype=obj -triple=x86_64-mingw main.s -o main.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64-mingw other.s -o other.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-mingw main.s -o main.obj
+// RUN: llvm-mc -filetype=obj -triple=x86_64-mingw other.s -o other.obj
 
-// RUN: ld.lld -m i386pep -dll -o other.dll other.o -entry= --export-all-symbols --out-implib other.dll.a
-// RUN: ld.lld -m i386pep -o main.exe main.o other.dll.a -e entry --wrap foo --verbose
+// RUN: lld-link -lldmingw -machine:x64 -dll -out:other.dll other.obj -noentry -export:foo -implib:other.lib
+// RUN: lld-link -lldmingw -machine:x64 -out:main.exe main.obj other.lib -entry:entry -wrap:foo -debug:symtab
 // RUN: llvm-readobj --sections --symbols --coff-imports --coff-basereloc main.exe | FileCheck %s --implicit-check-not=other.dll
 
-// CHECK:      Number: 4
+// CHECK:      Number: 3
 // CHECK-NEXT: Name: .data
 // CHECK-NEXT: VirtualSize:
-// CHECK-NEXT: VirtualAddress: 0x[[#%x,SECTOP:0x4000]]
+// CHECK-NEXT: VirtualAddress: 0x[[#%x,SECTOP:0x3000]]
 // CHECK:      Name: ref_foo
 // CHECK-NEXT: Value: [[#%d,SYMVAL:]]
 // CHECK:      BaseReloc [

>From 118d33098dd77b4eabfa00e8d7f66d9a8d55cf2a Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Fri, 5 Sep 2025 22:15:19 +0900
Subject: [PATCH 11/12] rewording

---
 lld/test/COFF/wrap-dllimport.s | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lld/test/COFF/wrap-dllimport.s b/lld/test/COFF/wrap-dllimport.s
index a1b4521fd75fa..a26e43b698960 100644
--- a/lld/test/COFF/wrap-dllimport.s
+++ b/lld/test/COFF/wrap-dllimport.s
@@ -1,7 +1,8 @@
 // REQUIRES: x86
 
 // Check that we can wrap a dllimported symbol, so that references to
-// __imp_<symbol> gets redirected to a symbol already exists or a defined local import instead
+// __imp_<symbol> gets redirected to a symbol that already exists or a defined
+// local import instead.
 
 // RUN: split-file %s %t.dir
 // RUN: llvm-mc -filetype=obj -triple=i686-win32-gnu %t.dir/main.s -o %t.main.obj
@@ -30,9 +31,9 @@
 // which is the first 4 bytes of the .rdata section (above), which is a
 // pointer that points at ___wrap_foo.
 
-// The second jmpl instruction in _entry points the null since the referenced symbol
-// `__imp____wrap_bar` is declared as a weak reference to prevent pull a reference
-// from an external DLL.
+// The second jmpl instruction in _entry points to null because the referenced
+// symbol `__imp____wrap_bar` is declared as a weak reference to prevent pull a
+// reference from an external DLL.
 
 #--- main.s
 .global _entry

>From 0f2c0e2c5fad4ebc9f113d68c3bfc525be92d0a6 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Fri, 5 Sep 2025 22:13:01 +0900
Subject: [PATCH 12/12] drop "inherit weak"

---
 lld/COFF/MinGW.cpp                     | 11 -----------
 lld/test/COFF/wrap-inherit-weakness.ll | 16 ----------------
 2 files changed, 27 deletions(-)
 delete mode 100644 lld/test/COFF/wrap-inherit-weakness.ll

diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 7c6f4281145ce..597c508115a34 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -233,17 +233,6 @@ void lld::coff::addWrappedSymbols(SymbolTable &symtab,
         symtab.addUndefined(mangle("__wrap_" + name, symtab.machine));
     v.push_back({sym, real, wrap});
 
-    if (auto *usym = dyn_cast<Undefined>(sym)) {
-      if (auto *ureal = dyn_cast<Undefined>(real);
-          ureal && ureal->weakAlias && !usym->weakAlias) {
-        usym->weakAlias = ureal->weakAlias;
-      }
-      if (auto *uwrap = dyn_cast<Undefined>(wrap);
-          uwrap && usym->weakAlias && !uwrap->weakAlias) {
-        uwrap->weakAlias = usym->weakAlias;
-      }
-    }
-
     // These symbols may seem undefined initially, but don't bail out
     // at symtab.reportUnresolvable() due to them, but let wrapSymbols
     // below sort things out before checking finally with
diff --git a/lld/test/COFF/wrap-inherit-weakness.ll b/lld/test/COFF/wrap-inherit-weakness.ll
deleted file mode 100644
index e050e8fda37f2..0000000000000
--- a/lld/test/COFF/wrap-inherit-weakness.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; REQUIRES: x86
-
-; Check that 'weak' attribute will be inherited to the wrapped symbols.
-
-; RUN: llc %s -mtriple x86_64-mingw -o %t.o --filetype=obj
-; RUN: ld.lld -m i386pep -shared -o %t.dll %t.o --entry= --wrap fn
-
-declare extern_weak dso_local void @__real_fn() nounwind
-declare dso_local void @fn() nounwind
-declare dso_local void @__wrap_fn() nounwind
-
-define dllexport void @caller() nounwind {
-  call void @__real_fn()
-  call void @fn()
-  ret void
-}



More information about the llvm-commits mailing list