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

via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 30 16:42:50 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-coff

Author: Tomohiro Kashiwada (kikairoya)

<details>
<summary>Changes</summary>

Fixes https://github.com/llvm/llvm-project/issues/150739

---
Full diff: https://github.com/llvm/llvm-project/pull/156214.diff


5 Files Affected:

- (modified) lld/COFF/Chunks.cpp (+1-1) 
- (modified) lld/COFF/MinGW.cpp (+20-4) 
- (added) lld/test/COFF/reloc-undefined-weak.s (+52) 
- (modified) lld/test/COFF/wrap-dllimport.s (+25-8) 
- (added) lld/test/COFF/wrap-inherit-weakness.ll (+16) 


``````````diff
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 39fc25047f3b1..cb5cba5c414a1 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;
     res->emplace_back(rva + rel.VirtualAddress, ty);
   }
diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index e7117cbea2e88..7c6f4281145ce 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -233,6 +233,17 @@ 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
@@ -269,10 +280,15 @@ void lld::coff::wrapSymbols(SymbolTable &symtab) {
       // (We can't easily distinguish whether any object file actually
       // referenced it or not, though.)
       if (imp) {
-        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())) {
+          map[imp] = wrapimp;
+        } else {
+          DefinedLocalImport *localwrapimp = make<DefinedLocalImport>(
+              symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
+          symtab.localImportChunks.push_back(localwrapimp->getChunk());
+          map[imp] = localwrapimp;
+        }
       }
     }
   }
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
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
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
+}

``````````

</details>


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


More information about the llvm-commits mailing list