[lld] 0b2d84f - [LLD] [COFF] Allow wrapping dllimported functions

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 24 00:15:35 PST 2020


Author: Martin Storsjö
Date: 2020-11-24T10:15:20+02:00
New Revision: 0b2d84fba84b098a2060862fcbcfccfb4ad1e3f2

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

LOG: [LLD] [COFF] Allow wrapping dllimported functions

GNU ld doesn't seem to do this though, but it looks like a reasonable
use case, is easy to implement, and was requested in
https://bugs.llvm.org/show_bug.cgi?id=47384.

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

Added: 
    lld/test/COFF/wrap-dllimport.s

Modified: 
    lld/COFF/MinGW.cpp
    lld/test/COFF/wrap-import.ll

Removed: 
    


################################################################################
diff  --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index f7f45464bcf5..5bb7467afe5e 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -238,6 +238,19 @@ void lld::coff::wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
   for (const WrappedSymbol &w : wrapped) {
     map[w.sym] = w.wrap;
     map[w.real] = w.sym;
+    if (Defined *d = dyn_cast<Defined>(w.wrap)) {
+      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) {
+        DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
+            saver.save("__imp_" + w.wrap->getName()), d);
+        symtab->localImportChunks.push_back(wrapimp->getChunk());
+        map[imp] = wrapimp;
+      }
+    }
   }
 
   // Update pointers in input files.

diff  --git a/lld/test/COFF/wrap-dllimport.s b/lld/test/COFF/wrap-dllimport.s
new file mode 100644
index 000000000000..d7662b29fdc7
--- /dev/null
+++ b/lld/test/COFF/wrap-dllimport.s
@@ -0,0 +1,42 @@
+// REQUIRES: x86
+
+// Check that we can wrap a dllimported symbol, so that references to
+// __imp_<symbol> gets redirected to 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: llvm-objdump -s -d --print-imm-hex %t.exe | FileCheck %s
+
+// CHECK:      Contents of section .rdata:
+// CHECK-NEXT:  402000 06104000
+
+// CHECK:      Disassembly of section .text:
+// CHECK-EMPTY:
+// CHECK:      00401000 <_entry>:
+// CHECK-NEXT:   401000: ff 25 00 20 40 00             jmpl    *0x402000
+// CHECK-EMPTY:
+// CHECK-NEXT: 00401006 <___wrap_foo>:
+// CHECK-NEXT:   401006: c3                            retl
+
+// The 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.
+
+#--- main.s
+.global _entry
+_entry:
+  jmpl *__imp__foo
+
+.global ___wrap_foo
+___wrap_foo:
+  ret
+
+#--- other.s
+.global _foo
+
+_foo:
+  ret

diff  --git a/lld/test/COFF/wrap-import.ll b/lld/test/COFF/wrap-import.ll
index c9a72de36e32..e03af1e9c7f0 100644
--- a/lld/test/COFF/wrap-import.ll
+++ b/lld/test/COFF/wrap-import.ll
@@ -1,7 +1,8 @@
 // REQUIRES: x86
 
 // Check that wrapping works when the wrapped symbol is imported from a
-// 
diff erent DLL.
+// 
diff erent DLL, redirecting references that used to point at the import
+// thunk, towards the local wrap function instead.
 
 // RUN: split-file %s %t.dir
 // RUN: llc %t.dir/main.ll -o %t.main.obj --filetype=obj


        


More information about the llvm-commits mailing list