[lld] 3ab6209 - [LLD] [COFF] Handle manually defined __imp_ pointers in LTO (#70777)

via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 4 14:49:42 PDT 2023


Author: Martin Storsjö
Date: 2023-11-04T23:49:38+02:00
New Revision: 3ab6209a3f93bdbeec8e9b9fcc00a9a4980915ff

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

LOG: [LLD] [COFF] Handle manually defined __imp_ pointers in LTO (#70777)

Such pointers are often used by the core parts of mingw-w64, to locally
define a function that might have been referred to with dllimport.

(MSVC style linkers can automatically provide such pointers, if there
are undefined references to `__imp_<func>` left but a definition of
`<func>` is available - although this prints the warning LNK4217. GNU ld
doesn't do this, so in mingw-w64, such things are generally handled by
manually providing the relevant `__imp_` pointers.)

Make sure that a full LTO build, that does LTO of both the `__imp_`
pointer and the object file referencing it, successfully resolves such
symbols.

This solution admittedly probably reduces the effect of the LTO
compilation if there would happen to be `__imp_` prefixed symbols
included, in LTO objects, that aren't actually used. Such symbols are
mostly used in the base toolchain, not often in user code, and usually
only the relevant object files are linked in anyway.

This fixes https://github.com/llvm/llvm-project/issues/57982.

Added: 
    lld/test/COFF/lto-imp-prefix.ll

Modified: 
    lld/COFF/InputFiles.cpp

Removed: 
    


################################################################################
diff  --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 38ce29e6ab68c04..3ae05f42ac5ff63 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -1061,6 +1061,12 @@ void BitcodeFile::parse() {
     } else {
       sym = ctx.symtab.addRegular(this, symName, nullptr, fakeSC, 0,
                                   objSym.isWeak());
+      // Model all symbols with the __imp_ prefix as having external
+      // references. If one LTO object defines a __imp_<foo> symbol, and
+      // another LTO object refers to <foo> with dllimport, make sure the
+      // __imp_ symbol is kept.
+      if (symName.starts_with("__imp_"))
+        sym->isUsedInRegularObj = true;
     }
     symbols.push_back(sym);
     if (objSym.isUsed())

diff  --git a/lld/test/COFF/lto-imp-prefix.ll b/lld/test/COFF/lto-imp-prefix.ll
new file mode 100644
index 000000000000000..503e4fd0649e41d
--- /dev/null
+++ b/lld/test/COFF/lto-imp-prefix.ll
@@ -0,0 +1,39 @@
+; REQUIRES: x86
+
+; RUN: rm -rf %t.dir
+; RUN: split-file %s %t.dir
+; RUN: llvm-as %t.dir/main.ll -o %t.main.obj
+; RUN: llvm-as %t.dir/other.ll -o %t.other.obj
+
+; RUN: lld-link /entry:entry %t.main.obj %t.other.obj /out:%t.exe /subsystem:console
+
+;--- main.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-w64-windows-gnu"
+
+define void @entry() {
+entry:
+  tail call void @importedFunc()
+  tail call void @other()
+  ret void
+}
+
+declare dllimport void @importedFunc()
+
+declare void @other()
+
+;--- other.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-w64-windows-gnu"
+
+ at __imp_importedFunc = global ptr @importedFuncReplacement
+
+define internal void @importedFuncReplacement() {
+entry:
+  ret void
+}
+
+define void @other() {
+entry:
+  ret void
+}


        


More information about the llvm-commits mailing list