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

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 4 14:41:09 PDT 2023


https://github.com/mstorsjo updated https://github.com/llvm/llvm-project/pull/70777

>From 1624e873d15c1615a576a69da4e0a471afe80268 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Fri, 27 Oct 2023 14:36:11 +0300
Subject: [PATCH] [LLD] [COFF] Handle manually defined __imp_ pointers in LTO

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 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.
---
 lld/COFF/InputFiles.cpp         |  6 +++++
 lld/test/COFF/lto-imp-prefix.ll | 39 +++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 lld/test/COFF/lto-imp-prefix.ll

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