[lld] r281079 - COFF: make builds more reproducible

Saleem Abdulrasool via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 9 12:26:03 PDT 2016


Author: compnerd
Date: Fri Sep  9 14:26:03 2016
New Revision: 281079

URL: http://llvm.org/viewvc/llvm-project?rev=281079&view=rev
Log:
COFF: make builds more reproducible

Change the way we calculate the build id to use MD5 to give reproducible build
ids. Previously we would generate random bytes for the build id GUID.

Modified:
    lld/trunk/COFF/Writer.cpp
    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=281079&r1=281078&r2=281079&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Sep  9 14:26:03 2016
@@ -81,22 +81,21 @@ class CVDebugRecordChunk : public Chunk
   }
 
   void writeTo(uint8_t *B) const override {
-    auto *R = reinterpret_cast<codeview::DebugInfo *>(B + OutputSectionOff);
+    // Save off the DebugInfo entry to backfill the file signature (build id)
+    // in Writer::writeBuildId
+    DI = reinterpret_cast<codeview::DebugInfo *>(B + OutputSectionOff);
 
-    R->Signature.CVSignature = OMF::Signature::PDB70;
-    // TODO(compnerd) fill in a GUID by hashing the contents of the binary to
-    // get a reproducible build
-    if (getRandomBytes(R->PDB70.Signature, sizeof(R->PDB70.Signature)))
-      fatal("entropy source failure");
-    // TODO(compnerd) track the Age
-    R->PDB70.Age = 1;
+    DI->Signature.CVSignature = OMF::Signature::PDB70;
 
     // variable sized field (PDB Path)
-    auto *P = reinterpret_cast<char *>(B + OutputSectionOff + sizeof(*R));
+    auto *P = reinterpret_cast<char *>(B + OutputSectionOff + sizeof(*DI));
     if (!Config->PDBPath.empty())
       memcpy(P, Config->PDBPath.data(), Config->PDBPath.size());
     P[Config->PDBPath.size()] = '\0';
   }
+
+public:
+  mutable codeview::DebugInfo *DI = nullptr;
 };
 
 // The writer writes a SymbolTable result to a file.
@@ -119,6 +118,7 @@ private:
   void setSectionPermissions();
   void writeSections();
   void sortExceptionTable();
+  void writeBuildId();
   void applyRelocations();
 
   llvm::Optional<coff_symbol16> createSymbol(Defined *D);
@@ -146,6 +146,7 @@ private:
 
   std::unique_ptr<Chunk> DebugDirectory;
   std::vector<std::unique_ptr<Chunk>> DebugRecords;
+  CVDebugRecordChunk *BuildId = nullptr;
 
   uint64_t FileSize;
   uint32_t PointerToSymbolTable = 0;
@@ -299,6 +300,7 @@ void Writer::run() {
   fixSafeSEHSymbols();
   writeSections();
   sortExceptionTable();
+  writeBuildId();
   if (auto EC = Buffer->commit())
     fatal(EC, "failed to write the output file");
 }
@@ -359,8 +361,12 @@ void Writer::createMiscChunks() {
     DebugDirectory = llvm::make_unique<DebugDirectoryChunk>(DebugRecords);
 
     // TODO(compnerd) create a coffgrp entry if DebugType::CV is not enabled
-    if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV))
-      DebugRecords.push_back(llvm::make_unique<CVDebugRecordChunk>());
+    if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV)) {
+      auto Chunk = llvm::make_unique<CVDebugRecordChunk>();
+
+      BuildId = Chunk.get();
+      DebugRecords.push_back(std::move(Chunk));
+    }
 
     RData->addChunk(DebugDirectory.get());
     for (const std::unique_ptr<Chunk> &C : DebugRecords)
@@ -796,6 +802,27 @@ void Writer::sortExceptionTable() {
   errs() << "warning: don't know how to handle .pdata.\n";
 }
 
+// Backfill the CVSignature in a PDB70 Debug Record.  This backfilling allows us
+// to get reproducible builds.
+void Writer::writeBuildId() {
+  // There is nothing to backfill if BuildId was not setup.
+  if (BuildId == nullptr)
+    return;
+
+  MD5 Hash;
+  MD5::MD5Result Res;
+
+  Hash.update(ArrayRef<uint8_t>{Buffer->getBufferStart(),
+                                Buffer->getBufferEnd()});
+  Hash.final(Res);
+
+  assert(BuildId->DI->Signature.CVSignature == OMF::Signature::PDB70 &&
+         "only PDB 7.0 is supported");
+  memcpy(BuildId->DI->PDB70.Signature, Res, 16);
+  // TODO(compnerd) track the Age
+  BuildId->DI->PDB70.Age = 1;
+}
+
 OutputSection *Writer::findSection(StringRef Name) {
   for (OutputSection *Sec : OutputSections)
     if (Sec->getName() == Name)

Modified: lld/trunk/test/COFF/rsds.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/rsds.test?rev=281079&r1=281078&r2=281079&view=diff
==============================================================================
--- lld/trunk/test/COFF/rsds.test (original)
+++ lld/trunk/test/COFF/rsds.test Fri Sep  9 14:26:03 2016
@@ -18,7 +18,7 @@
 # CHECK:     PointerToRawData:
 # CHECK:     PDBInfo {
 # CHECK:       PDBSignature: 0x53445352
-# CHECK:       PDBGUID:
+# CHECK:       PDBGUID: (A9 01 F6 CD 45 C8 41 9F CC BC 17 55 E3 64 DF A2)
 # CHECK:       PDBAge: 1
 # CHECK:       PDBFileName: {{$}}
 # CHECK:     }
@@ -37,7 +37,7 @@
 # CHECK-PDB:     PointerToRawData:
 # CHECK-PDB:     PDBInfo {
 # CHECK-PDB:       PDBSignature: 0x53445352
-# CHECK-PDB:       PDBGUID:
+# CHECK-PDB:       PDBGUID: (9F 9F CC 10 A5 F3 90 C4 E2 48 F9 58 82 16 B3 20)
 # CHECK-PDB:       PDBAge: 1
 # CHECK-PDB:       PDBFileName: {{.*}}.pdb
 # CHECK-PDB:     }




More information about the llvm-commits mailing list