[PATCH] D91689: [LLD] [COFF] Allow wrapping dllimported functions

Martin Storsjö via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 18 01:35:02 PST 2020


mstorsjo created this revision.
mstorsjo added reviewers: rnk, amccarth.
Herald added a project: LLVM.
mstorsjo requested review of this revision.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D91689

Files:
  lld/COFF/MinGW.cpp
  lld/test/COFF/wrap-dllimport.s
  lld/test/COFF/wrap-import.ll


Index: lld/test/COFF/wrap-import.ll
===================================================================
--- lld/test/COFF/wrap-import.ll
+++ lld/test/COFF/wrap-import.ll
@@ -1,7 +1,8 @@
 // REQUIRES: x86
 
 // Check that wrapping works when the wrapped symbol is imported from a
-// different DLL.
+// different 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
Index: lld/test/COFF/wrap-dllimport.s
===================================================================
--- /dev/null
+++ 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
Index: lld/COFF/MinGW.cpp
===================================================================
--- lld/COFF/MinGW.cpp
+++ lld/COFF/MinGW.cpp
@@ -238,6 +238,19 @@
   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.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D91689.306002.patch
Type: text/x-patch
Size: 2975 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201118/fdaa91b3/attachment.bin>


More information about the llvm-commits mailing list