#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>
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;
};
RVATableChunk *GuardFidsTable = nullptr;
RVATableChunk *SEHTable = nullptr;
- DebugDirectoryChunk *DebugDirectory = nullptr;
+ Chunk *DebugDirectory = nullptr;
std::vector<Chunk *> DebugRecords;
CVDebugRecordChunk *BuildId = nullptr;
Optional<codeview::DebugInfo> PreviousBuildId;
}
void Writer::writeBuildId() {
- // There are two important parts to the build ID.
- // 1) If building with debug info, the COFF debug directory contains a
- // timestamp as well as a Guid and Age of the PDB.
- // 2) In all cases, the PE COFF file header also contains a timestamp.
- // For reproducibility, instead of a timestamp we want to use a hash of the
- // binary, however when building with debug info the hash needs to take into
- // account the debug info, since it's possible to add blank lines to a file
- // which causes the debug info to change but not the generated code.
- //
- // To handle this, we first set the Guid and Age in the debug directory (but
- // only if we're doing a debug build). Then, we hash the binary (thus causing
- // the hash to change if only the debug info changes, since the Age will be
- // different). Finally, we write that hash into the debug directory (if
- // present) as well as the COFF file header (always).
- if (Config->Debug) {
- assert(BuildId && "BuildId is not set!");
- if (PreviousBuildId.hasValue()) {
- *BuildId->BuildId = *PreviousBuildId;
- BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
- } else {
- BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
- BuildId->BuildId->PDB70.Age = 1;
- llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
- }
- }
-
- // At this point the only fields in the COFF file which remain unset are the
- // "timestamp" in the COFF file header, and the ones in the coff debug
- // directory. Now we can hash the file and write that hash to the various
- // timestamp fields in the file.
- StringRef OutputFileData(
- reinterpret_cast<const char *>(Buffer->getBufferStart()),
- Buffer->getBufferSize());
+ // If we're not writing a build id (e.g. because /debug is not specified),
+ // then just return;
+ if (!Config->Debug)
+ return;
- uint32_t Hash = static_cast<uint32_t>(xxHash64(OutputFileData));
+ assert(BuildId && "BuildId is not set!");
- if (DebugDirectory)
- DebugDirectory->setTimeDateStamp(Hash);
+ if (PreviousBuildId.hasValue()) {
+ *BuildId->BuildId = *PreviousBuildId;
+ BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
+ return;
+ }
- uint8_t *Buf = Buffer->getBufferStart();
- Buf += DOSStubSize + sizeof(PEMagic);
- object::coff_file_header *CoffHeader =
- reinterpret_cast<coff_file_header *>(Buf);
- CoffHeader->TimeDateStamp = Hash;
+ 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.