summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Config.h2
-rw-r--r--lld/COFF/Driver.cpp2
-rw-r--r--lld/COFF/Driver.h3
-rw-r--r--lld/COFF/DriverUtils.cpp21
-rw-r--r--lld/COFF/Options.td8
-rw-r--r--lld/COFF/Writer.cpp4
-rw-r--r--lld/test/COFF/options.test40
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
OpenPOWER on IntegriCloud