Skip to content

Commit 4004c58

Browse files
aganeallvmbot
authored andcommitted
[LLD][COFF] Follow up comments on pr146610 (#147152)
This is a follow-up PR for post-commit comments in #146610 - Changed "exporteddllmain" references to "importeddllmain". - Add support for x86 target and test coverage. - Changed a comment to better express why we're skipping importing `DllMain`. (cherry picked from commit fcacd4e)
1 parent 1abeeab commit 4004c58

File tree

5 files changed

+83
-17
lines changed

5 files changed

+83
-17
lines changed

lld/COFF/Config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ struct Configuration {
307307
bool warnDebugInfoUnusable = true;
308308
bool warnLongSectionNames = true;
309309
bool warnStdcallFixup = true;
310-
bool warnExportedDllMain = true;
310+
bool warnImportedDllMain = true;
311311
bool incremental = true;
312312
bool integrityCheck = false;
313313
bool killAt = false;

lld/COFF/Driver.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,8 +1643,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
16431643
config->warnLocallyDefinedImported = false;
16441644
else if (s == "longsections")
16451645
config->warnLongSectionNames = false;
1646-
else if (s == "exporteddllmain")
1647-
config->warnExportedDllMain = false;
1646+
else if (s == "importeddllmain")
1647+
config->warnImportedDllMain = false;
16481648
// Other warning numbers are ignored.
16491649
}
16501650
}

lld/COFF/InputFiles.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ static coff_symbol_generic *cloneSymbol(COFFSymbolRef sym) {
117117
// Skip importing DllMain thunks from import libraries.
118118
static bool fixupDllMain(COFFLinkerContext &ctx, llvm::object::Archive *file,
119119
const Archive::Symbol &sym, bool &skipDllMain) {
120-
if (skipDllMain)
121-
return true;
122120
const Archive::Child &c =
123121
CHECK(sym.getMember(), file->getFileName() +
124122
": could not get the member for symbol " +
@@ -128,13 +126,13 @@ static bool fixupDllMain(COFFLinkerContext &ctx, llvm::object::Archive *file,
128126
file->getFileName() +
129127
": could not get the buffer for a child buffer of the archive");
130128
if (identify_magic(mb.getBuffer()) == file_magic::coff_import_library) {
131-
if (ctx.config.warnExportedDllMain) {
129+
if (ctx.config.warnImportedDllMain) {
132130
// We won't place DllMain symbols in the symbol table if they are
133131
// coming from a import library. This message can be ignored with the flag
134-
// '/ignore:exporteddllmain'
132+
// '/ignore:importeddllmain'
135133
Warn(ctx)
136134
<< file->getFileName()
137-
<< ": skipping exported DllMain symbol [exporteddllmain]\nNOTE: this "
135+
<< ": skipping imported DllMain symbol [importeddllmain]\nNOTE: this "
138136
"might be a mistake when the DLL/library was produced.";
139137
}
140138
skipDllMain = true;
@@ -204,14 +202,24 @@ void ArchiveFile::parse() {
204202
}
205203
}
206204

207-
// Read the symbol table to construct Lazy objects.
208205
bool skipDllMain = false;
206+
StringRef mangledDllMain, impMangledDllMain;
207+
208+
// The calls below will fail if we haven't set the machine type yet. Instead
209+
// of failing, it is preferable to skip this "imported DllMain" check if we
210+
// don't know the machine type at this point.
211+
if (!file->isEmpty() && ctx.config.machine != IMAGE_FILE_MACHINE_UNKNOWN) {
212+
mangledDllMain = archiveSymtab->mangle("DllMain");
213+
impMangledDllMain = uniqueSaver().save("__imp_" + mangledDllMain);
214+
}
215+
216+
// Read the symbol table to construct Lazy objects.
209217
for (const Archive::Symbol &sym : file->symbols()) {
210-
// If the DllMain symbol was exported by mistake, skip importing it
211-
// otherwise we might end up with a import thunk in the final binary which
212-
// is wrong.
213-
if (sym.getName() == "__imp_DllMain" || sym.getName() == "DllMain") {
214-
if (fixupDllMain(ctx, file.get(), sym, skipDllMain))
218+
// If an import library provides the DllMain symbol, skip importing it, as
219+
// we should be using our own DllMain, not another DLL's DllMain.
220+
if (!mangledDllMain.empty() && (sym.getName() == mangledDllMain ||
221+
sym.getName() == impMangledDllMain)) {
222+
if (skipDllMain || fixupDllMain(ctx, file.get(), sym, skipDllMain))
215223
continue;
216224
}
217225
archiveSymtab->addLazyArchive(this, sym);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
REQUIRES: x86
2+
RUN: split-file %s %t.dir && cd %t.dir
3+
4+
RUN: llvm-mc -filetype=obj -triple=i386-windows a.s -o a.obj
5+
6+
RUN: llvm-mc -filetype=obj -triple=i386-windows b1.s -o b1.obj
7+
RUN: llvm-mc -filetype=obj -triple=i386-windows b2.s -o b2.obj
8+
9+
### This is the line where our problem occurs. Here, we export the DllMain symbol which shouldn't happen normally.
10+
RUN: lld-link b1.obj b2.obj -out:b.dll -dll -implib:b.lib -entry:DllMain -export:bar -export:DllMain -safeseh:no
11+
12+
RUN: llvm-mc -filetype=obj -triple=i386-windows c.s -o c.obj
13+
RUN: lld-link -lib c.obj -out:c.lib
14+
15+
### Later, if b.lib is provided before other libs/objs that export DllMain statically, we previously were using the dllimported DllMain from b.lib, which is wrong.
16+
RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -safeseh:no 2>&1 | FileCheck -check-prefix=WARN %s
17+
RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -ignore:importeddllmain -safeseh:no 2>&1 | FileCheck -check-prefix=IGNORED --allow-empty %s
18+
RUN: llvm-objdump --private-headers -d out.dll | FileCheck -check-prefix=DISASM %s
19+
20+
WARN: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain]
21+
IGNORED-NOT: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain]
22+
23+
DISASM: The Import Tables:
24+
DISASM: DLL Name: b.dll
25+
DISASM-NOT: DllMain
26+
DISASM: bar
27+
DISASM: Disassembly of section .text:
28+
DISASM: b0 01 movb $0x1, %al
29+
DISASM-NEXT: c3 retl
30+
31+
#--- a.s
32+
.text
33+
.globl _foo
34+
_foo:
35+
call *__imp__bar
36+
ret
37+
38+
#--- b1.s
39+
.text
40+
.globl _bar
41+
_bar:
42+
ret
43+
44+
#--- b2.s
45+
.intel_syntax noprefix
46+
.text
47+
.globl _DllMain
48+
_DllMain:
49+
xor al, al
50+
ret
51+
52+
#--- c.s
53+
.intel_syntax noprefix
54+
.text
55+
.globl _DllMain
56+
_DllMain:
57+
mov al, 1
58+
ret

lld/test/COFF/exported-dllmain.test renamed to lld/test/COFF/imported-dllmain.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ RUN: lld-link -lib c.obj -out:c.lib
1414

1515
### Later, if b.lib is provided before other libs/objs that export DllMain statically, we previously were using the dllimported DllMain from b.lib, which is wrong.
1616
RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain 2>&1 | FileCheck -check-prefix=WARN %s
17-
RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -ignore:exporteddllmain 2>&1 | FileCheck -check-prefix=IGNORED --allow-empty %s
17+
RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -ignore:importeddllmain 2>&1 | FileCheck -check-prefix=IGNORED --allow-empty %s
1818
RUN: llvm-objdump --private-headers -d out.dll | FileCheck -check-prefix=DISASM %s
1919

20-
WARN: lld-link: warning: b.lib: skipping exported DllMain symbol [exporteddllmain]
21-
IGNORED-NOT: lld-link: warning: b.lib: skipping exported DllMain symbol [exporteddllmain]
20+
WARN: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain]
21+
IGNORED-NOT: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain]
2222

2323
DISASM: The Import Tables:
2424
DISASM: DLL Name: b.dll

0 commit comments

Comments
 (0)