[LLD] [COFF] Support ENTRY and SUBSYSTEM in .drectve sections

Adds support for "/ENTRY" and "/SUBSYSTEM" linker options in .drectve
sections. Some Mozilla binaries were using these directives and MSVC
link.exe appears to allow them. No attempt is made to reconcile these
with the options on the command line.

Patch by David Major!

Differential Revision: https://reviews.llvm.org/D39972

llvm-svn: 319356
This commit is contained in:
Rui Ueyama 2017-11-29 20:46:13 +00:00
parent e48f223ed6
commit 215286f2a4
3 changed files with 66 additions and 12 deletions

View File

@ -241,6 +241,9 @@ void LinkerDriver::parseDirectives(StringRef S) {
if (Optional<StringRef> Path = findLib(Arg->getValue()))
enqueuePath(*Path, false);
break;
case OPT_entry:
Config->Entry = addUndefined(mangle(Arg->getValue()));
break;
case OPT_export: {
Export E = parseExport(Arg->getValue());
if (Config->Machine == I386 && Config->MinGW) {
@ -268,6 +271,10 @@ void LinkerDriver::parseDirectives(StringRef S) {
case OPT_section:
parseSection(Arg->getValue());
break;
case OPT_subsystem:
parseSubsystem(Arg->getValue(), &Config->Subsystem,
&Config->MajorOSVersion, &Config->MinorOSVersion);
break;
case OPT_editandcontinue:
case OPT_fastfail:
case OPT_guardsym:
@ -1076,18 +1083,20 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Handle /entry and /dll
if (auto *Arg = Args.getLastArg(OPT_entry)) {
Config->Entry = addUndefined(mangle(Arg->getValue()));
} else if (Args.hasArg(OPT_dll) && !Config->NoEntry) {
StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12"
: "_DllMainCRTStartup";
Config->Entry = addUndefined(S);
} else if (!Config->NoEntry) {
// Windows specific -- If entry point name is not given, we need to
// infer that from user-defined entry name.
StringRef S = findDefaultEntry();
if (S.empty())
fatal("entry point must be defined");
Config->Entry = addUndefined(S);
log("Entry name inferred: " + S);
} else if (!Config->Entry && !Config->NoEntry) {
if (Args.hasArg(OPT_dll)) {
StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12"
: "_DllMainCRTStartup";
Config->Entry = addUndefined(S);
} else {
// Windows specific -- If entry point name is not given, we need to
// infer that from user-defined entry name.
StringRef S = findDefaultEntry();
if (S.empty())
fatal("entry point must be defined");
Config->Entry = addUndefined(S);
log("Entry name inferred: " + S);
}
}
// Handle /export

View File

@ -0,0 +1,24 @@
# RUN: yaml2obj < %s > %t.obj
# RUN: lld-link /subsystem:console /out:%t.exe %t.obj
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B800000000506800000000680000000050E80000000050E800000000
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
SectionData: 2f656e7472793a437573746f6d456e74727900 # /entry:CustomEntry
symbols:
- Name: _CustomEntry
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -0,0 +1,21 @@
# RUN: yaml2obj < %s > %t.obj
# RUN: lld-link /dll /noentry /out:%t.dll %t.obj
# RUN: llvm-readobj -file-headers %t.dll | FileCheck %s
# CHECK: MajorOperatingSystemVersion: 42
# CHECK: MinorOperatingSystemVersion: 43
# CHECK: MajorSubsystemVersion: 42
# CHECK: MinorSubsystemVersion: 43
# CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
sections:
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
SectionData: 2f73756273797374656d3a636f6e736f6c652c34322e343300 # /subsystem:console,42.43
symbols:
...