From 88f6407542c55ae3723831baf6e549e045db8138 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 9 Sep 2016 19:26:03 +0000 Subject: [PATCH] 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. llvm-svn: 281079 --- lld/COFF/Writer.cpp | 49 ++++++++++++++++++++++++++++++++++++++----------- lld/test/COFF/rsds.test | 4 ++-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 4e66076..2be922c 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -81,22 +81,21 @@ class CVDebugRecordChunk : public Chunk { } void writeTo(uint8_t *B) const override { - auto *R = reinterpret_cast(B + OutputSectionOff); + // Save off the DebugInfo entry to backfill the file signature (build id) + // in Writer::writeBuildId + DI = reinterpret_cast(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(B + OutputSectionOff + sizeof(*R)); + auto *P = reinterpret_cast(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 createSymbol(Defined *D); @@ -146,6 +146,7 @@ private: std::unique_ptr DebugDirectory; std::vector> 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(DebugRecords); // TODO(compnerd) create a coffgrp entry if DebugType::CV is not enabled - if (Config->DebugTypes & static_cast(coff::DebugType::CV)) - DebugRecords.push_back(llvm::make_unique()); + if (Config->DebugTypes & static_cast(coff::DebugType::CV)) { + auto Chunk = llvm::make_unique(); + + BuildId = Chunk.get(); + DebugRecords.push_back(std::move(Chunk)); + } RData->addChunk(DebugDirectory.get()); for (const std::unique_ptr &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{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) diff --git a/lld/test/COFF/rsds.test b/lld/test/COFF/rsds.test index 37ec48b..0bfd1f8 100644 --- a/lld/test/COFF/rsds.test +++ b/lld/test/COFF/rsds.test @@ -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: } -- 2.7.4