Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -154,9 +154,6 @@ void writeBuildId(llvm::ArrayRef Buf); private: - void computeHash(llvm::ArrayRef Buf, - std::function)> Hash); - size_t HashSize; uint8_t *HashBuf; }; Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -36,9 +36,6 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MD5.h" -#include "llvm/Support/RandomNumberGenerator.h" -#include "llvm/Support/SHA1.h" -#include "llvm/Support/xxhash.h" #include #include @@ -303,36 +300,9 @@ HashBuf = Buf + 16; } -// Split one uint8 array into small pieces of uint8 arrays. -static std::vector> split(ArrayRef Arr, - size_t ChunkSize) { - std::vector> Ret; - while (Arr.size() > ChunkSize) { - Ret.push_back(Arr.take_front(ChunkSize)); - Arr = Arr.drop_front(ChunkSize); - } - if (!Arr.empty()) - Ret.push_back(Arr); - return Ret; -} - -// Computes a hash value of Data using a given hash function. -// In order to utilize multiple cores, we first split data into 1MB -// chunks, compute a hash for each chunk, and then compute a hash value -// of the hash values. -void BuildIdSection::computeHash( - llvm::ArrayRef Data, - std::function Arr)> HashFn) { - std::vector> Chunks = split(Data, 1024 * 1024); - std::vector Hashes(Chunks.size() * HashSize); - - // Compute hash values. - parallelForEachN(0, Chunks.size(), [&](size_t I) { - HashFn(Hashes.data() + I * HashSize, Chunks[I]); - }); - - // Write to the final output buffer. - HashFn(HashBuf, Hashes); +void BuildIdSection::writeBuildId(ArrayRef Buf) { + assert(Buf.size() == HashSize); + memcpy(HashBuf, Buf.data(), HashSize); } BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment) @@ -341,35 +311,6 @@ this->Size = Size; } -void BuildIdSection::writeBuildId(ArrayRef Buf) { - switch (Config->BuildId) { - case BuildIdKind::Fast: - computeHash(Buf, [](uint8_t *Dest, ArrayRef Arr) { - write64le(Dest, xxHash64(Arr)); - }); - break; - case BuildIdKind::Md5: - computeHash(Buf, [](uint8_t *Dest, ArrayRef Arr) { - memcpy(Dest, MD5::hash(Arr).data(), 16); - }); - break; - case BuildIdKind::Sha1: - computeHash(Buf, [](uint8_t *Dest, ArrayRef Arr) { - memcpy(Dest, SHA1::hash(Arr).data(), 20); - }); - break; - case BuildIdKind::Uuid: - if (auto EC = getRandomBytes(HashBuf, HashSize)) - error("entropy source failure: " + EC.message()); - break; - case BuildIdKind::Hexstring: - memcpy(HashBuf, Config->BuildIdVector.data(), Config->BuildIdVector.size()); - break; - default: - llvm_unreachable("unknown BuildIdKind"); - } -} - EhFrameSection::EhFrameSection() : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame") {} Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -24,6 +24,9 @@ #include "lld/Common/Threads.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/RandomNumberGenerator.h" +#include "llvm/Support/SHA1.h" +#include "llvm/Support/xxhash.h" #include using namespace llvm; @@ -2495,12 +2498,82 @@ Sec->writeTo(Out::BufferStart + Sec->Offset); } +// Split one uint8 array into small pieces of uint8 arrays. +static std::vector> split(ArrayRef Arr, + size_t ChunkSize) { + std::vector> Ret; + while (Arr.size() > ChunkSize) { + Ret.push_back(Arr.take_front(ChunkSize)); + Arr = Arr.drop_front(ChunkSize); + } + if (!Arr.empty()) + Ret.push_back(Arr); + return Ret; +} + +// Computes a hash value of Data using a given hash function. +// In order to utilize multiple cores, we first split data into 1MB +// chunks, compute a hash for each chunk, and then compute a hash value +// of the hash values. +static void +computeHash(llvm::MutableArrayRef HashBuf, + llvm::ArrayRef Data, + std::function Arr)> HashFn) { + std::vector> Chunks = split(Data, 1024 * 1024); + std::vector Hashes(Chunks.size() * HashBuf.size()); + + // Compute hash values. + parallelForEachN(0, Chunks.size(), [&](size_t I) { + HashFn(Hashes.data() + I * HashBuf.size(), Chunks[I]); + }); + + // Write to the final output buffer. + HashFn(HashBuf.data(), Hashes); +} + +static std::vector computeBuildId(llvm::ArrayRef Buf) { + std::vector BuildId; + switch (Config->BuildId) { + case BuildIdKind::Fast: + BuildId.resize(8); + computeHash(BuildId, Buf, [](uint8_t *Dest, ArrayRef Arr) { + write64le(Dest, xxHash64(Arr)); + }); + break; + case BuildIdKind::Md5: + BuildId.resize(16); + computeHash(BuildId, Buf, [](uint8_t *Dest, ArrayRef Arr) { + memcpy(Dest, MD5::hash(Arr).data(), 16); + }); + break; + case BuildIdKind::Sha1: + BuildId.resize(20); + computeHash(BuildId, Buf, [](uint8_t *Dest, ArrayRef Arr) { + memcpy(Dest, SHA1::hash(Arr).data(), 20); + }); + break; + case BuildIdKind::Uuid: + BuildId.resize(16); + if (auto EC = llvm::getRandomBytes(BuildId.data(), 16)) + error("entropy source failure: " + EC.message()); + break; + case BuildIdKind::Hexstring: + BuildId = Config->BuildIdVector; + break; + default: + llvm_unreachable("unknown BuildIdKind"); + } + return BuildId; +} + template void Writer::writeBuildId() { if (!In.BuildId || !In.BuildId->getParent()) return; // Compute a hash of all sections of the output file. - In.BuildId->writeBuildId({Out::BufferStart, size_t(FileSize)}); + std::vector BuildId = + computeBuildId({Out::BufferStart, size_t(FileSize)}); + In.BuildId->writeBuildId(BuildId); } template void elf::writeResult();