[lld] r327049 - Resubmit "Write a hash of the executable into the PE timestamp fields."

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 8 11:33:47 PST 2018


Author: zturner
Date: Thu Mar  8 11:33:47 2018
New Revision: 327049

URL: http://llvm.org/viewvc/llvm-project?rev=327049&view=rev
Log:
Resubmit "Write a hash of the executable into the PE timestamp fields."

This fixes the broken tests that were causing failures.  The tests
before were verifying that the time stamp was 0, but now that we
are actually writing a timestamp, I just removed the match against
the timestamp value.

Modified:
    lld/trunk/COFF/Writer.cpp
    lld/trunk/test/COFF/hello32.test
    lld/trunk/test/COFF/largeaddressaware.test
    lld/trunk/test/COFF/rsds.test

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=327049&r1=327048&r2=327049&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Thu Mar  8 11:33:47 2018
@@ -28,6 +28,7 @@
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/xxhash.h"
 #include <algorithm>
 #include <cstdio>
 #include <map>
@@ -103,11 +104,18 @@ public:
       uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA());
       D->PointerToRawData = Offs;
 
+      TimeDateStamps.push_back(&D->TimeDateStamp);
       ++D;
     }
   }
 
+  void setTimeDateStamp(uint32_t TimeDateStamp) {
+    for (support::ulittle32_t *TDS : TimeDateStamps)
+      *TDS = TimeDateStamp;
+  }
+
 private:
+  mutable std::vector<support::ulittle32_t *> TimeDateStamps;
   const std::vector<Chunk *> &Records;
 };
 
@@ -189,7 +197,7 @@ private:
   RVATableChunk *GuardFidsTable = nullptr;
   RVATableChunk *SEHTable = nullptr;
 
-  Chunk *DebugDirectory = nullptr;
+  DebugDirectoryChunk *DebugDirectory = nullptr;
   std::vector<Chunk *> DebugRecords;
   CVDebugRecordChunk *BuildId = nullptr;
   Optional<codeview::DebugInfo> PreviousBuildId;
@@ -1070,22 +1078,50 @@ void Writer::writeSections() {
 }
 
 void Writer::writeBuildId() {
-  // If we're not writing a build id (e.g. because /debug is not specified),
-  // then just return;
-  if (!Config->Debug)
-    return;
+  // There are two important parts to the build ID.
+  // 1) If building with debug info, the COFF debug directory contains a
+  //    timestamp as well as a Guid and Age of the PDB.
+  // 2) In all cases, the PE COFF file header also contains a timestamp.
+  // For reproducibility, instead of a timestamp we want to use a hash of the
+  // binary, however when building with debug info the hash needs to take into
+  // account the debug info, since it's possible to add blank lines to a file
+  // which causes the debug info to change but not the generated code.
+  //
+  // To handle this, we first set the Guid and Age in the debug directory (but
+  // only if we're doing a debug build).  Then, we hash the binary (thus causing
+  // the hash to change if only the debug info changes, since the Age will be
+  // different).  Finally, we write that hash into the debug directory (if
+  // present) as well as the COFF file header (always).
+  if (Config->Debug) {
+    assert(BuildId && "BuildId is not set!");
+    if (PreviousBuildId.hasValue()) {
+      *BuildId->BuildId = *PreviousBuildId;
+      BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
+    } else {
+      BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
+      BuildId->BuildId->PDB70.Age = 1;
+      llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
+    }
+  }
 
-  assert(BuildId && "BuildId is not set!");
+  // At this point the only fields in the COFF file which remain unset are the
+  // "timestamp" in the COFF file header, and the ones in the coff debug
+  // directory.  Now we can hash the file and write that hash to the various
+  // timestamp fields in the file.
+  StringRef OutputFileData(
+      reinterpret_cast<const char *>(Buffer->getBufferStart()),
+      Buffer->getBufferSize());
 
-  if (PreviousBuildId.hasValue()) {
-    *BuildId->BuildId = *PreviousBuildId;
-    BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
-    return;
-  }
+  uint32_t Hash = static_cast<uint32_t>(xxHash64(OutputFileData));
+
+  if (DebugDirectory)
+    DebugDirectory->setTimeDateStamp(Hash);
 
-  BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
-  BuildId->BuildId->PDB70.Age = 1;
-  llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
+  uint8_t *Buf = Buffer->getBufferStart();
+  Buf += DOSStubSize + sizeof(PEMagic);
+  object::coff_file_header *CoffHeader =
+      reinterpret_cast<coff_file_header *>(Buf);
+  CoffHeader->TimeDateStamp = Hash;
 }
 
 // Sort .pdata section contents according to PE/COFF spec 5.5.

Modified: lld/trunk/test/COFF/hello32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/hello32.test?rev=327049&r1=327048&r2=327049&view=diff
==============================================================================
--- lld/trunk/test/COFF/hello32.test (original)
+++ lld/trunk/test/COFF/hello32.test Thu Mar  8 11:33:47 2018
@@ -11,7 +11,7 @@ HEADER-NEXT: AddressSize: 32bit
 HEADER-NEXT: ImageFileHeader {
 HEADER-NEXT:   Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
 HEADER-NEXT:   SectionCount: 4
-HEADER-NEXT:   TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+HEADER-NEXT:   TimeDateStamp: 
 HEADER-NEXT:   PointerToSymbolTable: 0x0
 HEADER-NEXT:   SymbolCount: 0
 HEADER-NEXT:   OptionalHeaderSize: 224

Modified: lld/trunk/test/COFF/largeaddressaware.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/largeaddressaware.test?rev=327049&r1=327048&r2=327049&view=diff
==============================================================================
--- lld/trunk/test/COFF/largeaddressaware.test (original)
+++ lld/trunk/test/COFF/largeaddressaware.test Thu Mar  8 11:33:47 2018
@@ -9,7 +9,7 @@ HEADER-NEXT: AddressSize: 32bit
 HEADER-NEXT: ImageFileHeader {
 HEADER-NEXT:   Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
 HEADER-NEXT:   SectionCount: 4
-HEADER-NEXT:   TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+HEADER-NEXT:   TimeDateStamp: 
 HEADER-NEXT:   PointerToSymbolTable: 0x0
 HEADER-NEXT:   SymbolCount: 0
 HEADER-NEXT:   OptionalHeaderSize: 224

Modified: lld/trunk/test/COFF/rsds.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/rsds.test?rev=327049&r1=327048&r2=327049&view=diff
==============================================================================
--- lld/trunk/test/COFF/rsds.test (original)
+++ lld/trunk/test/COFF/rsds.test Thu Mar  8 11:33:47 2018
@@ -18,7 +18,7 @@
 # CHECK: DebugDirectory [
 # CHECK:   DebugEntry {
 # CHECK:     Characteristics: 0x0
-# CHECK:     TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+# CHECK:     TimeDateStamp: 
 # CHECK:     MajorVersion: 0x0
 # CHECK:     MinorVersion: 0x0
 # CHECK:     Type: CodeView (0x2)
@@ -37,7 +37,7 @@
 # CHECK: DebugDirectory [
 # CHECK:   DebugEntry {
 # CHECK:     Characteristics: 0x0
-# CHECK:     TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+# CHECK:     TimeDateStamp: 
 # CHECK:     MajorVersion: 0x0
 # CHECK:     MinorVersion: 0x0
 # CHECK:     Type: CodeView (0x2)




More information about the llvm-commits mailing list