From 49ac82686bc2370a51ef7e1e33bd14f45212c6b6 Mon Sep 17 00:00:00 2001 From: blackle Date: Mon, 24 Aug 2020 00:40:14 -0400 Subject: [PATCH] Implement crc32c hashing. Add options to smoldd to handle the different hash functions --- rt/loader32.asm | 3 +-- rt/loader64.asm | 3 +-- smol/shared.py | 15 +++++++++++---- smoldd.py | 14 +++++++++++--- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/rt/loader32.asm b/rt/loader32.asm index a54f575..f07742e 100644 --- a/rt/loader32.asm +++ b/rt/loader32.asm @@ -107,8 +107,7 @@ _smol_start: ; source in eax, result in eax %ifdef USE_CRC32C_HASH - push -1 - pop eax + xor ecx, ecx %else %ifndef USE_HASH16 push ebx diff --git a/rt/loader64.asm b/rt/loader64.asm index 3ab9aaf..81a8b45 100644 --- a/rt/loader64.asm +++ b/rt/loader64.asm @@ -112,8 +112,7 @@ _smol_start: pop rbx %else ; crc32 - push -1 - pop rcx + xor ecx, ecx %endif .nexthashiter: %ifndef USE_CRC32C_HASH diff --git a/smol/shared.py b/smol/shared.py index c70003d..458cd00 100644 --- a/smol/shared.py +++ b/smol/shared.py @@ -14,7 +14,7 @@ HASH_BSD2 = 1 HASH_CRC32C=2 define_for_hash = { - HASH_DJB2: None + HASH_DJB2: None, HASH_BSD2: 'USE_HASH16', HASH_CRC32C: 'USE_CRC32C_HASH' } @@ -35,9 +35,16 @@ def hash_djb2(s): def hash_crc32c(s): - # crc32 implementation is basically: - # sum = -1; for (; *s; ++s) crc32_instr(&sum, *s); return sum - assert False, "not implemented!" # TODO + crc = 0x0 + for c in s: + k = (crc & 0xff) ^ ord(c) + for i in range(8): + j = k & 1 + if j == 1: + k ^= 0x105EC76F0 + k >>= 1 + crc = ((crc >> 8) ^ k) & 0xFFFFFFFF + return crc def eprintf(*args, **kwargs): diff --git a/smoldd.py b/smoldd.py index c23c3b2..73ee2c5 100755 --- a/smoldd.py +++ b/smoldd.py @@ -36,17 +36,18 @@ def find_libs(deflibs, libname): for d in dirs: for f in glob.glob(glob.escape(d + '/' + libname) + '*'): yield f -def build_hashtab(scanelf_bin, lib): +def build_hashtab(scanelf_bin, lib, hashid): out = subprocess.check_output([scanelf_bin, '-B', '-F', '%s', '-s', '%pd%*', lib], stderr=subprocess.DEVNULL) blah = set(out.decode('utf-8').split('\n')) ret = dict({}) + hashfn = get_hash_fn(hashid) for x in blah: y = x.split() if len(y) != 7: continue - ret[hash_djb2(y[6])] = y[6] + ret[hashfn(y[6])] = y[6] return ret @@ -153,6 +154,12 @@ def main(): "Get the address of the symbol hash table from the "+\ "linker map output instead of attempting to parse the"+\ " binary.") + parser.add_argument('-s', '--hash16', default=False, action='store_true', \ + help="Use 16-bit (BSD2) hashes instead of 32-bit djb2 hashes. "+\ + "Implies -fuse-dnload-loader. Only usable for 32-bit output.") + parser.add_argument('-c', '--crc32c', default=False, action='store_true', \ + help="Use Intel's crc32 intrinsic for hashing. "+\ + "Implies -fuse-dnload-loader. Conflicts with `--hash16'.") args = parser.parse_args() blob = args.input.read() @@ -164,7 +171,8 @@ def main(): htbl = get_hashtbl(elf, blob, args) - libhashes = dict((l, build_hashtab(args.scanelf, neededpaths[l])) for l in needed) + hashid = get_hash_id(args.hash16, args.crc32c) + libhashes = dict((l, build_hashtab(args.scanelf, neededpaths[l], hashid)) for l in needed) hashresolves = dict({}) noresolves = []