summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2016-09-09 19:26:03 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2016-09-09 19:26:03 +0000
commit88f6407542c55ae3723831baf6e549e045db8138 (patch)
treea8b91f4fc730a0e149ff9716ff7f6a3763434ba0
parent7d2f5c4a913604938467a865659b3e75cf672e42 (diff)
downloadbcm5719-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.cpp49
-rw-r--r--lld/test/COFF/rsds.test4
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: }
OpenPOWER on IntegriCloud