[PATCH] D43978: Write a hash of the binary as the PE Debug Directory Timestamp

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 1 15:48:47 PST 2018


zturner created this revision.
zturner added reviewers: rnk, ruiu, smeenai, compnerd.

Previously we were writing 0 for this field.  This breaks symbol servers, and the value needs to be something, although it doesn't necessarily need to be a timestamp.  I chose to use a hash of the binary here, calculated while the value of this field is still 0.  Then, the 0 is replaced with the hash.


https://reviews.llvm.org/D43978

Files:
  lld/COFF/Writer.cpp


Index: lld/COFF/Writer.cpp
===================================================================
--- lld/COFF/Writer.cpp
+++ lld/COFF/Writer.cpp
@@ -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>
@@ -71,11 +72,18 @@
       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;
 };
 
@@ -157,7 +165,7 @@
   RVATableChunk *GuardFidsTable = nullptr;
   RVATableChunk *SEHTable = nullptr;
 
-  Chunk *DebugDirectory = nullptr;
+  DebugDirectoryChunk *DebugDirectory = nullptr;
   std::vector<Chunk *> DebugRecords;
   CVDebugRecordChunk *BuildId = nullptr;
   Optional<codeview::DebugInfo> PreviousBuildId;
@@ -1032,16 +1040,25 @@
     return;
 
   assert(BuildId && "BuildId is not set!");
+  assert(DebugDirectory && "DebugDirectory is not set!");
+
+  // Set the build it to a hash of the executable file, but do this before
+  // actually setting the guid and age, since those introduce some
+  // non-determinism.  This way at least the hash will be deterministic.
+  StringRef OutputFileData(
+      reinterpret_cast<const char *>(Buffer->getBufferStart()),
+      Buffer->getBufferSize());
+  DebugDirectory->setTimeDateStamp(
+      static_cast<uint32_t>(xxHash64(OutputFileData)));
 
   if (PreviousBuildId.hasValue()) {
     *BuildId->BuildId = *PreviousBuildId;
     BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
-    return;
+  } else {
+    BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
+    BuildId->BuildId->PDB70.Age = 1;
+    llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
   }
-
-  BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
-  BuildId->BuildId->PDB70.Age = 1;
-  llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
 }
 
 // Sort .pdata section contents according to PE/COFF spec 5.5.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D43978.136628.patch
Type: text/x-patch
Size: 2338 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180301/1acc1718/attachment.bin>


More information about the llvm-commits mailing list