1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Give InfoStreamBuilder an opt-in method to write a hash of the PDB as GUID.

Naively computing the hash after the PDB data has been generated is in practice
as fast as other approaches I tried. I also tried online-computing the hash as
parts of the PDB were written out (https://reviews.llvm.org/D51887; that's also
where all the measuring data is) and computing the hash in parallel
(https://reviews.llvm.org/D51957). This approach here is simplest, without
being slower.

Differential Revision: https://reviews.llvm.org/D51956

llvm-svn: 342333
This commit is contained in:
Nico Weber 2018-09-15 18:35:51 +00:00
parent c2ace82589
commit 26d9f839bc
5 changed files with 52 additions and 14 deletions

View File

@ -35,11 +35,18 @@ public:
InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete;
void setVersion(PdbRaw_ImplVer V);
void addFeature(PdbRaw_FeatureSig Sig);
// If this is true, the PDB contents are hashed and this hash is used as
// PDB GUID and as Signature. The age is always 1.
void setHashPDBContentsToGUID(bool B);
// These only have an effect if hashPDBContentsToGUID() is false.
void setSignature(uint32_t S);
void setAge(uint32_t A);
void setGuid(codeview::GUID G);
void addFeature(PdbRaw_FeatureSig Sig);
bool hashPDBContentsToGUID() const { return HashPDBContentsToGUID; }
uint32_t getAge() const { return Age; }
codeview::GUID getGuid() const { return Guid; }
Optional<uint32_t> getSignature() const { return Signature; }
@ -60,6 +67,8 @@ private:
Optional<uint32_t> Signature;
codeview::GUID Guid;
bool HashPDBContentsToGUID = false;
NamedStreamMap &NamedStreams;
};
}

View File

@ -53,7 +53,9 @@ public:
PDBStringTableBuilder &getStringTableBuilder();
GSIStreamBuilder &getGsiBuilder();
Error commit(StringRef Filename);
// If HashPDBContentsToGUID is true on the InfoStreamBuilder, Guid is filled
// with the computed PDB GUID on return.
Error commit(StringRef Filename, codeview::GUID *Guid);
Expected<uint32_t> getNamedStreamIndex(StringRef Name) const;
Error addNamedStream(StringRef Name, StringRef Data);

View File

@ -32,15 +32,20 @@ InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf,
void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
Features.push_back(Sig);
}
void InfoStreamBuilder::setHashPDBContentsToGUID(bool B) {
HashPDBContentsToGUID = B;
}
void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; }
void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
Features.push_back(Sig);
}
Error InfoStreamBuilder::finalizeMsfLayout() {
uint32_t Length = sizeof(InfoStreamHeader) +

View File

@ -25,6 +25,7 @@
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/JamCRC.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/xxhash.h"
using namespace llvm;
using namespace llvm::codeview;
@ -261,13 +262,14 @@ void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
}
}
Error PDBFileBuilder::commit(StringRef Filename) {
Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
assert(!Filename.empty());
if (auto EC = finalizeMsfLayout())
return EC;
MSFLayout Layout;
auto ExpectedMsfBuffer = Msf->commit(Filename, Layout);
Expected<FileBufferByteStream> ExpectedMsfBuffer =
Msf->commit(Filename, Layout);
if (!ExpectedMsfBuffer)
return ExpectedMsfBuffer.takeError();
FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
@ -329,11 +331,28 @@ Error PDBFileBuilder::commit(StringRef Filename) {
// Set the build id at the very end, after every other byte of the PDB
// has been written.
// FIXME: Use a hash of the PDB rather than time(nullptr) for the signature.
H->Age = Info->getAge();
H->Guid = Info->getGuid();
Optional<uint32_t> Sig = Info->getSignature();
H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
if (Info->hashPDBContentsToGUID()) {
// Compute a hash of all sections of the output file.
uint64_t Digest =
xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()});
H->Age = 1;
memcpy(H->Guid.Guid, &Digest, 8);
// xxhash only gives us 8 bytes, so put some fixed data in the other half.
memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
// Put the hash in the Signature field too.
H->Signature = static_cast<uint32_t>(Digest);
// Return GUID to caller.
memcpy(Guid, H->Guid.Guid, 16);
} else {
H->Age = Info->getAge();
H->Guid = Info->getGuid();
Optional<uint32_t> Sig = Info->getSignature();
H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
}
return Buffer.commit();
}

View File

@ -803,7 +803,8 @@ static void yamlToPdb(StringRef Path) {
Builder.getStringTableBuilder().setStrings(*Strings.strings());
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
codeview::GUID IgnoredOutGuid;
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
}
static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
@ -1263,7 +1264,9 @@ static void mergePdbs() {
OutFile = opts::merge::InputFilenames[0];
llvm::sys::path::replace_extension(OutFile, "merged.pdb");
}
ExitOnErr(Builder.commit(OutFile));
codeview::GUID IgnoredOutGuid;
ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));
}
static void explain() {