diff options
-rw-r--r-- | lld/COFF/Config.h | 2 | ||||
-rw-r--r-- | lld/COFF/Driver.cpp | 2 | ||||
-rw-r--r-- | lld/COFF/Driver.h | 3 | ||||
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 21 | ||||
-rw-r--r-- | lld/COFF/Options.td | 8 | ||||
-rw-r--r-- | lld/COFF/Writer.cpp | 4 | ||||
-rw-r--r-- | lld/test/COFF/options.test | 40 |
7 files changed, 78 insertions, 2 deletions
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index b13ef3a7ece..ecd579fc873 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -205,6 +205,8 @@ struct Configuration { bool IntegrityCheck = false; bool KillAt = false; bool Repro = false; + bool SwaprunCD = false; + bool SwaprunNet = false; }; extern Configuration *Config; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 96c9ba31324..4c45ad9a41f 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1375,6 +1375,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { 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; diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 02c806741be..f9448bd2d3b 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -167,6 +167,9 @@ void parseManifest(StringRef Arg); // Parses a string in the form of "level=<string>|uiAccess=<string>" 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<MemoryBuffer> createManifestRes(); void createSideBySideManifest(); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index a2f10085e4d..ca3f878089a 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -315,6 +315,27 @@ void parseManifestUAC(StringRef Arg) { } } +// 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 { diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 58b2dca23b1..0013bb4643f 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -103,8 +103,12 @@ def noentry : F<"noentry">, 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<swaprun>, AliasArgs<["cd"]>, + HelpText<"Make loader run output binary from swap instead of from CD">; +def swaprun_net : F<"swaprun:net">, Alias<swaprun>, AliasArgs<["net"]>, + HelpText<"Make loader run output binary from swap instead of from network">; def verbose : F<"verbose">; def wholearchive_flag : F<"wholearchive">; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index ff1363e7b13..af2e4236764 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1217,6 +1217,10 @@ template <typename PEHeaderTy> void Writer::writeHeader() { 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; diff --git a/lld/test/COFF/options.test b/lld/test/COFF/options.test index 6b9f2ca06fa..695e3d3cdb0 100644 --- a/lld/test/COFF/options.test +++ b/lld/test/COFF/options.test @@ -50,6 +50,46 @@ NXCOMPAT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT # 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 |