Skip to content

Commit

Permalink
Replace our SipHash implementation with https://github.com/rui314/sip…
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed May 18, 2024
1 parent 91f9c4d commit a25226e
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 125 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,6 @@ target_sources(mold PRIVATE
common/multi-glob.cc
common/perf.cc
common/random.cc
common/siphash.cc
common/tar.cc
elf/arch-alpha.cc
elf/arch-arm32.cc
Expand Down
17 changes: 0 additions & 17 deletions common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,23 +726,6 @@ class ConcurrentMap {

void get_random_bytes(u8 *buf, i64 size);

//
// siphash.cc
//

class SipHash {
public:
SipHash(u8 *key);
void update(u8 *msg, i64 msglen);
void finish(u8 *out);

private:
u64 v0, v1, v2, v3;
u8 buf[8];
u8 buflen = 0;
i64 total_bytes = 0;
};

//
// output-file.h
//
Expand Down
105 changes: 0 additions & 105 deletions common/siphash.cc

This file was deleted.

144 changes: 144 additions & 0 deletions common/siphash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// This is a header-only C++20 implementation of SipHash based on the
// reference implementation. To use, just copy this header file into
// your project and #include it.
//
// https://github.com/rui314/siphash/blob/main/siphash.h

#include <bit>
#include <cstdint>
#include <cstring>

template <int C_ROUNDS, int D_ROUNDS, int OUTLEN>
class SipHashTmpl {
public:
static_assert(OUTLEN == 64 || OUTLEN == 128);

SipHashTmpl(void *key) {
uint64_t k0 = read64(key);
uint64_t k1 = read64((char *)key + 8);

v0 = 0x736f6d6570736575 ^ k0;
v1 = 0x646f72616e646f6d ^ k1;
v2 = 0x6c7967656e657261 ^ k0;
v3 = 0x7465646279746573 ^ k1;

if (OUTLEN == 128)
v1 ^= 0xee;
}

void update(void *msgp, int64_t msglen) {
char *msg = (char *)msgp;
sum += msglen;

if (buflen) {
if (buflen + msglen < 8) {
memcpy(buf + buflen, msg, msglen);
buflen += msglen;
return;
}

int j = 8 - buflen;
memcpy(buf + buflen, msg, j);
compress(read64(buf));

msg += j;
msglen -= j;
buflen = 0;
}

while (msglen >= 8) {
compress(read64(msg));
msg += 8;
msglen -= 8;
}

memcpy(buf, msg, msglen);
buflen = msglen;
}

void finish(void *out) {
memset(buf + buflen, 0, 8 - buflen);
compress(((uint64_t)sum << 56) | read64(buf));

v2 ^= (OUTLEN == 128) ? 0xee : 0xff;
finalize();
write64(out, v0 ^ v1 ^ v2 ^ v3);

if (OUTLEN == 128) {
v1 ^= 0xdd;
finalize();
write64((char *)out + 8, v0 ^ v1 ^ v2 ^ v3);
}
}

static void hash(void *out, void *key, void *in, int inlen) {
SipHashTmpl<C_ROUNDS, D_ROUNDS, OUTLEN> h(key);
h.update(in, inlen);
h.finish(out);
}

private:
uint64_t v0, v1, v2, v3;
uint8_t buf[8];
uint8_t buflen = 0;
uint8_t sum = 0;

uint64_t read64(void *loc) {
uint64_t val;
memcpy(&val, loc, 8);
if (std::endian::native == std::endian::big)
val = bswap(val);
return val;
}

void write64(void *loc, uint64_t val) {
if (std::endian::native == std::endian::big)
val = bswap(val);
memcpy(loc, &val, 8);
}

uint64_t bswap(uint64_t val) {
return ((val << 56) & 0xff00000000000000) |
((val << 40) & 0x00ff000000000000) |
((val << 24) & 0x0000ff0000000000) |
((val << 8) & 0x000000ff00000000) |
((val >> 8) & 0x00000000ff000000) |
((val >> 24) & 0x0000000000ff0000) |
((val >> 40) & 0x000000000000ff00) |
((val >> 56) & 0x00000000000000ff);
}

void round() {
v0 += v1;
v1 = std::rotl(v1, 13);
v1 ^= v0;
v0 = std::rotl(v0, 32);
v2 += v3;
v3 = std::rotl(v3, 16);
v3 ^= v2;
v0 += v3;
v3 = std::rotl(v3, 21);
v3 ^= v0;
v2 += v1;
v1 = std::rotl(v1, 17);
v1 ^= v2;
v2 = std::rotl(v2, 32);
}

void compress(uint64_t m) {
v3 ^= m;
for (int i = 0; i < C_ROUNDS; i++)
round();
v0 ^= m;
}

void finalize() {
for (int i = 0; i < D_ROUNDS; i++)
round();
}
};

using SipHash = SipHashTmpl<2, 4, 64>;
using SipHash128 = SipHashTmpl<2, 4, 128>;
using SipHash13 = SipHashTmpl<1, 3, 64>;
using SipHash13_128 = SipHashTmpl<1, 3, 128>;
5 changes: 3 additions & 2 deletions elf/icf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
// conditions.

#include "mold.h"
#include "../common/siphash.h"

#include <array>
#include <cstdio>
Expand Down Expand Up @@ -230,7 +231,7 @@ static void merge_leaf_nodes(Context<E> &ctx) {

template <typename E>
static Digest compute_digest(Context<E> &ctx, InputSection<E> &isec) {
SipHash hasher(hmac_key);
SipHash13_128 hasher(hmac_key);

auto hash = [&](auto val) {
hasher.update((u8 *)&val, sizeof(val));
Expand Down Expand Up @@ -409,7 +410,7 @@ static i64 propagate(std::span<std::vector<Digest>> digests,
if (converged[i])
return;

SipHash hasher(hmac_key);
SipHash13_128 hasher(hmac_key);
hasher.update(digests[2][i].data(), HASH_SIZE);

i64 begin = edge_indices[i];
Expand Down

0 comments on commit a25226e

Please sign in to comment.