Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -38,6 +38,12 @@ protected: BuildIdSection(size_t HashSize); std::vector Buf; + + void + computeHash(llvm::ArrayRef Buf, + std::function Arr, uint8_t *Hash)> Hash); + + size_t HashSize; }; template Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -23,6 +23,7 @@ #include "Strings.h" #include "SymbolTable.h" +#include "lld/Core/Parallel.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MD5.h" #include "llvm/Support/RandomNumberGenerator.h" @@ -91,7 +92,8 @@ template BuildIdSection::BuildIdSection(size_t HashSize) : InputSection(SHF_ALLOC, SHT_NOTE, 1, ArrayRef(), - ".note.gnu.build-id") { + ".note.gnu.build-id"), + HashSize(HashSize) { this->Live = true; Buf.resize(16 + HashSize); @@ -108,29 +110,66 @@ return Start + this->OutSec->getFileOffset() + this->OutSecOff; } +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; +} + template -void BuildIdFastHash::writeBuildId(MutableArrayRef Buf) { - const endianness E = ELFT::TargetEndianness; +void BuildIdSection::computeHash( + llvm::ArrayRef Data, + std::function Arr, uint8_t *Hash)> Hash) { + std::vector> Chunks = split(Data, 1024 * 1024); + std::vector HashList(Chunks.size() * HashSize); + + if (Config->Threads) + parallel_for_each(Chunks.begin(), Chunks.end(), + [&](ArrayRef &Chunk) { + size_t Id = &Chunk - Chunks.data(); + Hash(Chunk, HashList.data() + Id * HashSize); + }); + else + std::for_each(Chunks.begin(), Chunks.end(), [&](ArrayRef &Chunk) { + size_t Id = &Chunk - Chunks.data(); + Hash(Chunk, HashList.data() + Id * HashSize); + }); - // 64-bit xxhash - uint64_t Hash = xxHash64(toStringRef(Buf)); - write64(this->getOutputLoc(Buf.begin()) + 16, Hash); + Hash(HashList, this->getOutputLoc((uint8_t *)Data.begin()) + 16); +} + +template +void BuildIdFastHash::writeBuildId(MutableArrayRef Buf) { + computeHash(Buf, [](ArrayRef Arr, uint8_t *Dest) { + uint64_t Hash = xxHash64(toStringRef(Arr)); + write64(Dest, Hash); + }); } template void BuildIdMd5::writeBuildId(MutableArrayRef Buf) { - MD5 Hash; - Hash.update(Buf); - MD5::MD5Result Res; - Hash.final(Res); - memcpy(this->getOutputLoc(Buf.begin()) + 16, Res, 16); + computeHash(Buf, [&](ArrayRef Arr, uint8_t *Dest) { + MD5 Hash; + Hash.update(Arr); + MD5::MD5Result Res; + Hash.final(Res); + memcpy(Dest, Res, HashSize); + }); } template void BuildIdSha1::writeBuildId(MutableArrayRef Buf) { - SHA1 Hash; - Hash.update(Buf); - memcpy(this->getOutputLoc(Buf.begin()) + 16, Hash.final().data(), 20); + computeHash(Buf, [&](ArrayRef Arr, uint8_t *Dest) { + SHA1 Hash; + Hash.update(Arr); + memcpy(Dest, Hash.final().data(), HashSize); + }); } template Index: lld/trunk/test/ELF/build-id.s =================================================================== --- lld/trunk/test/ELF/build-id.s +++ lld/trunk/test/ELF/build-id.s @@ -16,6 +16,14 @@ # RUN: ld.lld --build-id=md5 --build-id=none %t -o %t2 # RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=NONE %s +## Multithreaded cases: +# RUN: ld.lld --build-id -threads %t -o %t2 +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DEFAULT %s +# RUN: ld.lld --build-id=md5 -threads %t -o %t2 +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=MD5 %s +# RUN: ld.lld --build-id=sha1 -threads %t -o %t2 +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SHA1 %s + .globl _start _start: nop @@ -26,12 +34,19 @@ # DEFAULT: Contents of section .note.test: # DEFAULT: Contents of section .note.gnu.build-id: # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. +# DEFAULT-NEXT: ab # MD5: Contents of section .note.gnu.build-id: # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. +# MD5-NEXT: 29 # SHA1: Contents of section .note.gnu.build-id: # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. +# SHA1-NEXT: b1 + +# TREE: Contents of section .note.gnu.build-id: +# TREE-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. +# TREE-NEXT: 18 # UUID: Contents of section .note.gnu.build-id: # UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.