[LLD] [COFF] Fix export directives in object files from -includeoptional

When an object file contains an export directive, we normally do some
amount of deferred processing of them at the end of the linking
process. The -includeoptional option was handled after this, and
any object files (defining new exports) weren't handled.

Move the handling of the -includeoptional into the same late loop
which does the fixups for e.g. export directives.

Ideally, this would also be done for object files that are pulled
in by the wrap options, and for mingw autoimports, but those changes
require more modifications, to make them safe for potentially
being executed multiple times.

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

Differential Revision: https://reviews.llvm.org/D132361
This commit is contained in:
Martin Storsjö 2022-08-22 11:48:08 +03:00
parent 770685e24d
commit af39e6f6fc
2 changed files with 58 additions and 8 deletions

View File

@ -2231,15 +2231,14 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// Windows specific -- if __load_config_used can be resolved, resolve it.
if (ctx.symtab.findUnderscore("_load_config_used"))
addUndefined(mangle("_load_config_used"));
} while (run());
if (args.hasArg(OPT_include_optional)) {
// Handle /includeoptional
for (auto *arg : args.filtered(OPT_include_optional))
if (isa_and_nonnull<LazyArchive>(ctx.symtab.find(arg->getValue())))
addUndefined(arg->getValue());
while (run());
}
if (args.hasArg(OPT_include_optional)) {
// Handle /includeoptional
for (auto *arg : args.filtered(OPT_include_optional))
if (isa_and_nonnull<LazyArchive>(ctx.symtab.find(arg->getValue())))
addUndefined(arg->getValue());
}
} while (run());
// Create wrapped symbols for -wrap option.
std::vector<WrappedSymbol> wrapped = addWrappedSymbols(ctx, args);

View File

@ -0,0 +1,51 @@
// REQUIRES: x86
// RUN: split-file %s %t.dir
// RUN: llvm-mc -filetype=obj -triple=x86_64-win32-gnu %t.dir/main.s -o %t.main.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-win32-gnu %t.dir/lib1.s -o %t.lib1.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-win32-gnu %t.dir/lib2.s -o %t.lib2.o
// RUN: rm -f %t.lib.a
// RUN: llvm-ar cru %t.lib.a %t.lib1.o %t.lib2.o
// RUN: lld-link -dll -out:%t-1.dll -entry:entry %t.main.o %t.lib.a
// RUN: lld-link -dll -out:%t-2.dll -entry:entry %t.main.o %t.lib.a -includeoptional:libfunc
// RUN: llvm-readobj --coff-exports %t-1.dll | FileCheck --implicit-check-not=Name: %s --check-prefix=CHECK-DEFAULT
// RUN: llvm-readobj --coff-exports %t-2.dll | FileCheck --implicit-check-not=Name: %s --check-prefix=CHECK-INCLUDEOPTIONAL
// CHECK-DEFAULT: Name:
// CHECK-DEFAULT: Name: myfunc
// CHECK-INCLUDEOPTIONAL: Name:
// CHECK-INCLUDEOPTIONAL: Name: libfunc
// CHECK-INCLUDEOPTIONAL: Name: myfunc
// CHECK-INCLUDEOPTIONAL: Name: otherlibfunc
#--- main.s
.global entry
entry:
ret
.global myfunc
myfunc:
ret
.section .drectve
.ascii "-export:myfunc "
#--- lib1.s
.global libfunc
libfunc:
call otherlibfunc
ret
.section .drectve
.ascii "-export:libfunc "
#--- lib2.s
.global otherlibfunc
otherlibfunc:
ret
.section .drectve
.ascii "-export:otherlibfunc "