diff options
| author | Saleem Abdulrasool <compnerd@compnerd.org> | 2016-09-09 19:26:03 +0000 |
|---|---|---|
| committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2016-09-09 19:26:03 +0000 |
| commit | 88f6407542c55ae3723831baf6e549e045db8138 (patch) | |
| tree | a8b91f4fc730a0e149ff9716ff7f6a3763434ba0 | |
| parent | 7d2f5c4a913604938467a865659b3e75cf672e42 (diff) | |
| download | bcm5719-llvm-88f6407542c55ae3723831baf6e549e045db8138.tar.gz bcm5719-llvm-88f6407542c55ae3723831baf6e549e045db8138.zip | |
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
| -rw-r--r-- | lld/COFF/Writer.cpp | 49 | ||||
| -rw-r--r-- | 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 4e66076ffcb..2be922cde01 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<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) diff --git a/lld/test/COFF/rsds.test b/lld/test/COFF/rsds.test index 37ec48b5068..0bfd1f88dc1 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: } |

