[lld] r332613 - [COFF] Add /Brepro and /TIMESTAMP options.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu May 17 08:11:01 PDT 2018


Author: zturner
Date: Thu May 17 08:11:01 2018
New Revision: 332613

URL: http://llvm.org/viewvc/llvm-project?rev=332613&view=rev
Log:
[COFF] Add /Brepro and /TIMESTAMP options.

Previously we would always write a hash of the binary into the
PE file, for reproducible builds.  This breaks AppCompat, which
is a feature of Windows that relies on the timestamp in the PE
header being set to a real value (or at the very least, a value
that satisfies certain properties).

To address this, we put the old behavior of writing the hash
behind the /Brepro flag, which mimics MSVC linker behavior.  We
also match MSVC default behavior, which is to write an actual
timestamp to the PE header.  Finally, we add the /TIMESTAMP
option (an lld extension) so that the user can specify the exact
value to be used in case he/she manually constructs a value which
is both reproducible and satisfies AppCompat.

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

Added:
    lld/trunk/test/COFF/timestamp.test
Modified:
    lld/trunk/COFF/Config.h
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Options.td
    lld/trunk/COFF/Writer.cpp

Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=332613&r1=332612&r2=332613&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Thu May 17 08:11:01 2018
@@ -181,6 +181,7 @@ struct Configuration {
   uint32_t MinorImageVersion = 0;
   uint32_t MajorOSVersion = 6;
   uint32_t MinorOSVersion = 0;
+  uint32_t Timestamp = 0;
   bool DynamicBase = true;
   bool AllowBind = true;
   bool NxCompat = true;
@@ -194,6 +195,7 @@ struct Configuration {
   bool WarnLocallyDefinedImported = true;
   bool Incremental = true;
   bool KillAt = false;
+  bool Repro = false;
 };
 
 extern Configuration *Config;

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=332613&r1=332612&r2=332613&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Thu May 17 08:11:01 2018
@@ -1033,6 +1033,23 @@ void LinkerDriver::link(ArrayRef<const c
     parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion,
                    &Config->MinorOSVersion);
 
+  // Handle /timestamp
+  if (llvm::opt::Arg *Arg = Args.getLastArg(OPT_timestamp, OPT_repro)) {
+    if (Arg->getOption().getID() == OPT_repro) {
+      Config->Timestamp = 0;
+      Config->Repro = true;
+    } else {
+      Config->Repro = false;
+      StringRef Value(Arg->getValue());
+      if (Value.getAsInteger(0, Config->Timestamp))
+        fatal(Twine("invalid timestamp: ") + Value +
+              ".  Expected 32-bit integer");
+    }
+  } else {
+    Config->Repro = false;
+    Config->Timestamp = time(nullptr);
+  }
+
   // Handle /alternatename
   for (auto *Arg : Args.filtered(OPT_alternatename))
     parseAlternateName(Arg->getValue());

Modified: lld/trunk/COFF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Options.td?rev=332613&r1=332612&r2=332613&view=diff
==============================================================================
--- lld/trunk/COFF/Options.td (original)
+++ lld/trunk/COFF/Options.td Thu May 17 08:11:01 2018
@@ -58,6 +58,7 @@ def section : P<"section", "Specify sect
 def stack   : P<"stack", "Size of the stack">;
 def stub    : P<"stub", "Specify DOS stub file">;
 def subsystem : P<"subsystem", "Specify subsystem">;
+def timestamp : P<"timestamp", "Specify the PE header timestamp">;
 def version : P<"version", "Specify a version number in the PE header">;
 def wholearchive_file : P<"wholearchive", "Include all object files from this archive">;
 
@@ -89,6 +90,7 @@ def driver : P<"driver", "Generate a Win
 def nodefaultlib_all : F<"nodefaultlib">;
 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 verbose : F<"verbose">;

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=332613&r1=332612&r2=332613&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Thu May 17 08:11:01 2018
@@ -1192,16 +1192,18 @@ void Writer::writeBuildId() {
       reinterpret_cast<const char *>(Buffer->getBufferStart()),
       Buffer->getBufferSize());
 
-  uint32_t Hash = static_cast<uint32_t>(xxHash64(OutputFileData));
+  uint32_t Timestamp = Config->Timestamp;
+  if (Config->Repro)
+    Timestamp = static_cast<uint32_t>(xxHash64(OutputFileData));
 
   if (DebugDirectory)
-    DebugDirectory->setTimeDateStamp(Hash);
+    DebugDirectory->setTimeDateStamp(Timestamp);
 
   uint8_t *Buf = Buffer->getBufferStart();
   Buf += DOSStubSize + sizeof(PEMagic);
   object::coff_file_header *CoffHeader =
       reinterpret_cast<coff_file_header *>(Buf);
-  CoffHeader->TimeDateStamp = Hash;
+  CoffHeader->TimeDateStamp = Timestamp;
 }
 
 // Sort .pdata section contents according to PE/COFF spec 5.5.

Added: lld/trunk/test/COFF/timestamp.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/timestamp.test?rev=332613&view=auto
==============================================================================
--- lld/trunk/test/COFF/timestamp.test (added)
+++ lld/trunk/test/COFF/timestamp.test Thu May 17 08:11:01 2018
@@ -0,0 +1,18 @@
+rm %t.*.exe
+RUN: yaml2obj %p/Inputs/generic.yaml > %t.obj
+RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.1.exe
+RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.2.exe
+RUN: lld-link %t.obj /debug /timestamp:0 /entry:main /nodefaultlib /out:%t.3.exe
+RUN: llvm-readobj -file-headers -coff-debug-directory %t.1.exe | FileCheck %s --check-prefix=HASH
+RUN: llvm-readobj -file-headers -coff-debug-directory %t.2.exe | FileCheck %s --check-prefix=HASH
+RUN: llvm-readobj -file-headers -coff-debug-directory %t.3.exe | FileCheck %s --check-prefix=ZERO
+
+HASH: ImageFileHeader {
+HASH: TimeDateStamp: [[STAMP:.*]]
+HASH: DebugDirectory [
+HASH: TimeDateStamp: [[STAMP]]
+
+ZERO: ImageFileHeader {
+ZERO: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+ZERO: DebugDirectory [
+ZERO: TimeDateStamp: 1970-01-01 00:00:00 (0x0)




More information about the llvm-commits mailing list