Index: lld/trunk/COFF/Config.h =================================================================== --- lld/trunk/COFF/Config.h +++ lld/trunk/COFF/Config.h @@ -205,6 +205,8 @@ bool IntegrityCheck = false; bool KillAt = false; bool Repro = false; + bool SwaprunCD = false; + bool SwaprunNet = false; }; extern Configuration *Config; Index: lld/trunk/COFF/Driver.h =================================================================== --- lld/trunk/COFF/Driver.h +++ lld/trunk/COFF/Driver.h @@ -167,6 +167,9 @@ // Parses a string in the form of "level=|uiAccess=" void parseManifestUAC(StringRef Arg); +// Parses a string in the form of "cd|net[,(cd|net)]*" +void parseSwaprun(StringRef Arg); + // Create a resource file containing a manifest XML. std::unique_ptr createManifestRes(); void createSideBySideManifest(); Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -1375,6 +1375,8 @@ Config->IntegrityCheck = Args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false); Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); + for (auto *Arg : Args.filtered(OPT_swaprun)) + parseSwaprun(Arg->getValue()); Config->TerminalServerAware = !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); Config->DebugDwarf = Debug == DebugKind::Dwarf; Index: lld/trunk/COFF/DriverUtils.cpp =================================================================== --- lld/trunk/COFF/DriverUtils.cpp +++ lld/trunk/COFF/DriverUtils.cpp @@ -315,6 +315,27 @@ } } +// Parses a string in the form of "cd|net[,(cd|net)]*" +// Results are directly written to Config. +void parseSwaprun(StringRef Arg) { + do { + StringRef Swaprun, NewArg; + std::tie(Swaprun, NewArg) = Arg.split(','); + if (Swaprun.equals_lower("cd")) + Config->SwaprunCD = true; + else if (Swaprun.equals_lower("net")) + Config->SwaprunNet = true; + else if (Swaprun.empty()) + error("/swaprun: missing argument"); + else + error("/swaprun: invalid argument: " + Swaprun); + // To catch trailing commas, e.g. `/spawrun:cd,` + if (NewArg.empty() && Arg.endswith(",")) + error("/swaprun: missing argument"); + Arg = NewArg; + } while (!Arg.empty()); +} + // An RAII temporary file class that automatically removes a temporary file. namespace { class TemporaryFile { Index: lld/trunk/COFF/Options.td =================================================================== --- lld/trunk/COFF/Options.td +++ lld/trunk/COFF/Options.td @@ -103,8 +103,12 @@ def profile : F<"profile">; def repro : F<"Brepro">, HelpText<"Use a hash of the executable as the PE header timestamp">; -def swaprun_cd : F<"swaprun:cd">; -def swaprun_net : F<"swaprun:net">; +def swaprun : P<"swaprun", + "Comma-separated list of 'cd' or 'net'">; +def swaprun_cd : F<"swaprun:cd">, Alias, AliasArgs<["cd"]>, + HelpText<"Make loader run output binary from swap instead of from CD">; +def swaprun_net : F<"swaprun:net">, Alias, AliasArgs<["net"]>, + HelpText<"Make loader run output binary from swap instead of from network">; def verbose : F<"verbose">; def wholearchive_flag : F<"wholearchive">; Index: lld/trunk/COFF/Writer.cpp =================================================================== --- lld/trunk/COFF/Writer.cpp +++ lld/trunk/COFF/Writer.cpp @@ -1217,6 +1217,10 @@ COFF->Characteristics |= IMAGE_FILE_DLL; if (!Config->Relocatable) COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED; + if (Config->SwaprunCD) + COFF->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP; + if (Config->SwaprunNet) + COFF->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP; COFF->SizeOfOptionalHeader = sizeof(PEHeaderTy) + sizeof(data_directory) * NumberOfDataDirectory; Index: lld/trunk/test/COFF/options.test =================================================================== --- lld/trunk/test/COFF/options.test +++ lld/trunk/test/COFF/options.test @@ -50,6 +50,46 @@ # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NONXCOMPAT %s NONXCOMPAT-NOT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT +# RUN: lld-link /out:%t.exe /entry:main /swaprun:CD %t.obj +# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=SWAPCD %s +# RUN: lld-link /out:%t.exe /entry:main /swaprun:cd,net %t.obj +# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=SWAPCD %s +SWAPCD: IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP + +# RUN: lld-link /out:%t.exe /entry:main %t.obj +# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOSWAPCD %s +NOSWAPCD-NOT: IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP + +# RUN: lld-link /out:%t.exe /entry:main /swaprun:NeT %t.obj +# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=SWAPNET %s +# RUN: lld-link /out:%t.exe /entry:main /swaprun:net,cd,cd,net %t.obj +# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=SWAPNET %s +SWAPNET: IMAGE_FILE_NET_RUN_FROM_SWAP + +# RUN: lld-link /out:%t.exe /entry:main %t.obj +# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOSWAPNET %s +NOSWAPNET-NOT: IMAGE_FILE_NET_RUN_FROM_SWAP + +# RUN: not lld-link /out:%t.exe /entry:main /swaprun: %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR1 %s +# RUN: not lld-link /out:%t.exe /entry:main /swaprun:cd, %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR1 %s +# RUN: not lld-link /out:%t.exe /entry:main /swaprun:,, %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR1 %s +# RUN: not lld-link /out:%t.exe /entry:main /swaprun:,cd %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR1 %s +SWAPERR1: /swaprun: missing argument + +# RUN: not lld-link /out:%t.exe /entry:main /swaprun:foo %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR2 %s +# RUN: not lld-link /out:%t.exe /entry:main /swaprun:cd,foo,net %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR2 %s +SWAPERR2: /swaprun: invalid argument: foo + +# RUN: not lld-link /out:%t.exe /entry:main /swaprun:cdfoo,net %t.obj 2>&1 | \ +# RUN: FileCheck -check-prefix=SWAPERR3 %s +SWAPERR3: /swaprun: invalid argument: cdfoo + # RUN: lld-link /out:%t.exe /entry:main %t.obj # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s # RUN: lld-link /out:%t.exe /entry:main /tsaware %t.obj