[lld] 45c4c54 - [LLD] [COFF] Add a private option for setting the os version separately from subsystem version

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 5 13:08:50 PDT 2020


Author: Martin Storsjö
Date: 2020-10-05T23:08:01+03:00
New Revision: 45c4c54003641f2bb225eaf305c07906451d6096

URL: https://github.com/llvm/llvm-project/commit/45c4c54003641f2bb225eaf305c07906451d6096
DIFF: https://github.com/llvm/llvm-project/commit/45c4c54003641f2bb225eaf305c07906451d6096.diff

LOG: [LLD] [COFF] Add a private option for setting the os version separately from subsystem version

The MinGW driver has separate options for OS and subsystem version.
Having this available in lld-link allows the MinGW driver to both match
GNU ld better and simplifies the code for merging two (potentially
mismatching) arguments into one.

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

Added: 
    

Modified: 
    lld/COFF/Config.h
    lld/COFF/Driver.cpp
    lld/COFF/Driver.h
    lld/COFF/DriverUtils.cpp
    lld/COFF/Options.td
    lld/COFF/Writer.cpp
    lld/test/COFF/subsystem.test

Removed: 
    


################################################################################
diff  --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 286b67b437a8..f0a26c19e955 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -223,6 +223,8 @@ struct Configuration {
   uint32_t minorImageVersion = 0;
   uint32_t majorOSVersion = 6;
   uint32_t minorOSVersion = 0;
+  uint32_t majorSubsystemVersion = 6;
+  uint32_t minorSubsystemVersion = 0;
   uint32_t timestamp = 0;
   uint32_t functionPadMin = 0;
   bool dynamicBase = true;

diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 56717de226c2..3560f1066f29 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -408,10 +408,17 @@ void LinkerDriver::parseDirectives(InputFile *file) {
     case OPT_section:
       parseSection(arg->getValue());
       break;
-    case OPT_subsystem:
+    case OPT_subsystem: {
+      bool gotVersion = false;
       parseSubsystem(arg->getValue(), &config->subsystem,
-                     &config->majorOSVersion, &config->minorOSVersion);
+                     &config->majorSubsystemVersion,
+                     &config->minorSubsystemVersion, &gotVersion);
+      if (gotVersion) {
+        config->majorOSVersion = config->majorSubsystemVersion;
+        config->minorOSVersion = config->minorSubsystemVersion;
+      }
       break;
+    }
     // Only add flags here that link.exe accepts in
     // `#pragma comment(linker, "/flag")`-generated sections.
     case OPT_editandcontinue:
@@ -1459,8 +1466,18 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
 
   // Handle /subsystem
   if (auto *arg = args.getLastArg(OPT_subsystem))
-    parseSubsystem(arg->getValue(), &config->subsystem, &config->majorOSVersion,
-                   &config->minorOSVersion);
+    parseSubsystem(arg->getValue(), &config->subsystem,
+                   &config->majorSubsystemVersion,
+                   &config->minorSubsystemVersion);
+
+  // Handle /osversion
+  if (auto *arg = args.getLastArg(OPT_osversion)) {
+    parseVersion(arg->getValue(), &config->majorOSVersion,
+                 &config->minorOSVersion);
+  } else {
+    config->majorOSVersion = config->majorSubsystemVersion;
+    config->minorOSVersion = config->minorSubsystemVersion;
+  }
 
   // Handle /timestamp
   if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) {

diff  --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 3fee9b1fe50e..5de05a1ef325 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -168,7 +168,7 @@ void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor);
 
 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
 void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
-                    uint32_t *minor);
+                    uint32_t *minor, bool *gotVersion = nullptr);
 
 void parseAlternateName(StringRef);
 void parseMerge(StringRef);

diff  --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index d4449709e1b7..7de73f2cfe49 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -112,7 +112,7 @@ void parseGuard(StringRef fullArg) {
 
 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
 void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
-                    uint32_t *minor) {
+                    uint32_t *minor, bool *gotVersion) {
   StringRef sysStr, ver;
   std::tie(sysStr, ver) = arg.split(',');
   std::string sysStrLower = sysStr.lower();
@@ -132,6 +132,8 @@ void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
     fatal("unknown subsystem: " + sysStr);
   if (!ver.empty())
     parseVersion(ver, major, minor);
+  if (gotVersion)
+    *gotVersion = !ver.empty();
 }
 
 // Parse a string of the form of "<from>=<to>".

diff  --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index d1badf0fdd2f..d27e95f9bd60 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -9,6 +9,11 @@ class F<string name> : Flag<["/", "-", "/?", "-?"], name>;
 class P<string name, string help> :
       Joined<["/", "-", "/?", "-?"], name#":">, HelpText<help>;
 
+// Same as P<> above, but without help texts, for private undocumented
+// options.
+class P_priv<string name> :
+      Joined<["/", "-", "/?", "-?"], name#":">;
+
 // Boolean flag which can be suffixed by ":no". Using it unsuffixed turns the
 // flag on and using it suffixed by ":no" turns it off.
 multiclass B<string name, string help_on, string help_off> {
@@ -205,6 +210,7 @@ def include_optional : Joined<["/", "-", "/?", "-?"], "includeoptional:">,
 def kill_at : F<"kill-at">;
 def lldmingw : F<"lldmingw">;
 def noseh : F<"noseh">;
+def osversion : P_priv<"osversion">;
 def output_def : Joined<["/", "-", "/?", "-?"], "output-def:">;
 def pdb_source_path : P<"pdbsourcepath",
     "Base path used to make relative source file path absolute in PDB">;

diff  --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index d1081b008ea4..145d517c9c0e 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1373,8 +1373,8 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
   pe->MinorImageVersion = config->minorImageVersion;
   pe->MajorOperatingSystemVersion = config->majorOSVersion;
   pe->MinorOperatingSystemVersion = config->minorOSVersion;
-  pe->MajorSubsystemVersion = config->majorOSVersion;
-  pe->MinorSubsystemVersion = config->minorOSVersion;
+  pe->MajorSubsystemVersion = config->majorSubsystemVersion;
+  pe->MinorSubsystemVersion = config->minorSubsystemVersion;
   pe->Subsystem = config->subsystem;
   pe->SizeOfImage = sizeOfImage;
   pe->SizeOfHeaders = sizeOfHeaders;

diff  --git a/lld/test/COFF/subsystem.test b/lld/test/COFF/subsystem.test
index a43035eb396e..e9a6966a01da 100644
--- a/lld/test/COFF/subsystem.test
+++ b/lld/test/COFF/subsystem.test
@@ -30,3 +30,21 @@ CHECK3: MajorOperatingSystemVersion: 8
 CHECK3: MinorOperatingSystemVersion: 9
 CHECK3: MajorSubsystemVersion: 8
 CHECK3: MinorSubsystemVersion: 9
+
+# RUN: lld-link /entry:main /out:%t.exe /osversion:1.2 \
+# RUN:   %p/Inputs/ret42.obj
+# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK4 %s
+
+CHECK4: MajorOperatingSystemVersion: 1
+CHECK4: MinorOperatingSystemVersion: 2
+CHECK4: MajorSubsystemVersion: 6
+CHECK4: MinorSubsystemVersion: 0
+
+# RUN: lld-link /entry:main /out:%t.exe /osversion:1.2 /subsystem:default,3.4 \
+# RUN:   %p/Inputs/ret42.obj
+# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK5 %s
+
+CHECK5: MajorOperatingSystemVersion: 1
+CHECK5: MinorOperatingSystemVersion: 2
+CHECK5: MajorSubsystemVersion: 3
+CHECK5: MinorSubsystemVersion: 4


        


More information about the llvm-commits mailing list