forked from OSchip/llvm-project
Resubmit "Write a hash of the executable into the PE timestamp fields."
This fixes the broken tests that were causing failures. The tests before were verifying that the time stamp was 0, but now that we are actually writing a timestamp, I just removed the match against the timestamp value. llvm-svn: 327049
This commit is contained in:
parent
50472279d4
commit
b575f46b6d
|
@ -28,6 +28,7 @@
|
|||
#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>
|
||||
|
@ -103,11 +104,18 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
|
@ -189,7 +197,7 @@ private:
|
|||
RVATableChunk *GuardFidsTable = nullptr;
|
||||
RVATableChunk *SEHTable = nullptr;
|
||||
|
||||
Chunk *DebugDirectory = nullptr;
|
||||
DebugDirectoryChunk *DebugDirectory = nullptr;
|
||||
std::vector<Chunk *> DebugRecords;
|
||||
CVDebugRecordChunk *BuildId = nullptr;
|
||||
Optional<codeview::DebugInfo> PreviousBuildId;
|
||||
|
@ -1070,22 +1078,50 @@ void Writer::writeSections() {
|
|||
}
|
||||
|
||||
void Writer::writeBuildId() {
|
||||
// If we're not writing a build id (e.g. because /debug is not specified),
|
||||
// then just return;
|
||||
if (!Config->Debug)
|
||||
return;
|
||||
|
||||
assert(BuildId && "BuildId is not set!");
|
||||
|
||||
if (PreviousBuildId.hasValue()) {
|
||||
*BuildId->BuildId = *PreviousBuildId;
|
||||
BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
|
||||
return;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
uint32_t Hash = static_cast<uint32_t>(xxHash64(OutputFileData));
|
||||
|
||||
if (DebugDirectory)
|
||||
DebugDirectory->setTimeDateStamp(Hash);
|
||||
|
||||
uint8_t *Buf = Buffer->getBufferStart();
|
||||
Buf += DOSStubSize + sizeof(PEMagic);
|
||||
object::coff_file_header *CoffHeader =
|
||||
reinterpret_cast<coff_file_header *>(Buf);
|
||||
CoffHeader->TimeDateStamp = Hash;
|
||||
}
|
||||
|
||||
// Sort .pdata section contents according to PE/COFF spec 5.5.
|
||||
|
|
|
@ -11,7 +11,7 @@ HEADER-NEXT: AddressSize: 32bit
|
|||
HEADER-NEXT: ImageFileHeader {
|
||||
HEADER-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
|
||||
HEADER-NEXT: SectionCount: 4
|
||||
HEADER-NEXT: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
|
||||
HEADER-NEXT: TimeDateStamp:
|
||||
HEADER-NEXT: PointerToSymbolTable: 0x0
|
||||
HEADER-NEXT: SymbolCount: 0
|
||||
HEADER-NEXT: OptionalHeaderSize: 224
|
||||
|
|
|
@ -9,7 +9,7 @@ HEADER-NEXT: AddressSize: 32bit
|
|||
HEADER-NEXT: ImageFileHeader {
|
||||
HEADER-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
|
||||
HEADER-NEXT: SectionCount: 4
|
||||
HEADER-NEXT: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
|
||||
HEADER-NEXT: TimeDateStamp:
|
||||
HEADER-NEXT: PointerToSymbolTable: 0x0
|
||||
HEADER-NEXT: SymbolCount: 0
|
||||
HEADER-NEXT: OptionalHeaderSize: 224
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# CHECK: DebugDirectory [
|
||||
# CHECK: DebugEntry {
|
||||
# CHECK: Characteristics: 0x0
|
||||
# CHECK: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
|
||||
# CHECK: TimeDateStamp:
|
||||
# CHECK: MajorVersion: 0x0
|
||||
# CHECK: MinorVersion: 0x0
|
||||
# CHECK: Type: CodeView (0x2)
|
||||
|
@ -37,7 +37,7 @@
|
|||
# CHECK: DebugDirectory [
|
||||
# CHECK: DebugEntry {
|
||||
# CHECK: Characteristics: 0x0
|
||||
# CHECK: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
|
||||
# CHECK: TimeDateStamp:
|
||||
# CHECK: MajorVersion: 0x0
|
||||
# CHECK: MinorVersion: 0x0
|
||||
# CHECK: Type: CodeView (0x2)
|
||||
|
|
Loading…
Reference in New Issue