Skip to content

Commit 3ab6209

Browse files
authored
[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 #57982.
1 parent 97c9c94 commit 3ab6209

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

lld/COFF/InputFiles.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,12 @@ void BitcodeFile::parse() {
10611061
} else {
10621062
sym = ctx.symtab.addRegular(this, symName, nullptr, fakeSC, 0,
10631063
objSym.isWeak());
1064+
// Model all symbols with the __imp_ prefix as having external
1065+
// references. If one LTO object defines a __imp_<foo> symbol, and
1066+
// another LTO object refers to <foo> with dllimport, make sure the
1067+
// __imp_ symbol is kept.
1068+
if (symName.starts_with("__imp_"))
1069+
sym->isUsedInRegularObj = true;
10641070
}
10651071
symbols.push_back(sym);
10661072
if (objSym.isUsed())

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; REQUIRES: x86
2+
3+
; RUN: rm -rf %t.dir
4+
; RUN: split-file %s %t.dir
5+
; RUN: llvm-as %t.dir/main.ll -o %t.main.obj
6+
; RUN: llvm-as %t.dir/other.ll -o %t.other.obj
7+
8+
; RUN: lld-link /entry:entry %t.main.obj %t.other.obj /out:%t.exe /subsystem:console
9+
10+
;--- main.ll
11+
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"
12+
target triple = "x86_64-w64-windows-gnu"
13+
14+
define void @entry() {
15+
entry:
16+
tail call void @importedFunc()
17+
tail call void @other()
18+
ret void
19+
}
20+
21+
declare dllimport void @importedFunc()
22+
23+
declare void @other()
24+
25+
;--- other.ll
26+
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"
27+
target triple = "x86_64-w64-windows-gnu"
28+
29+
@__imp_importedFunc = global ptr @importedFuncReplacement
30+
31+
define internal void @importedFuncReplacement() {
32+
entry:
33+
ret void
34+
}
35+
36+
define void @other() {
37+
entry:
38+
ret void
39+
}

0 commit comments

Comments
 (0)