Skip to content

Commit

Permalink
Implement crc32c hashing. Add options to smoldd to handle the differe…
Browse files Browse the repository at this point in the history
…nt hash functions
  • Loading branch information
blackle authored and PoroCYon committed Aug 24, 2020
1 parent 2334932 commit 4e07c4f
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 13 deletions.
3 changes: 1 addition & 2 deletions rt/loader32.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions rt/loader64.asm
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ _smol_start:
pop rbx
%else
; crc32
push -1
pop rcx
xor ecx, ecx
%endif
.nexthashiter:
%ifndef USE_CRC32C_HASH
Expand Down
15 changes: 11 additions & 4 deletions smol/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
HASH_CRC32C=2

define_for_hash = {
HASH_DJB2: None
HASH_DJB2: None,
HASH_BSD2: 'USE_HASH16',
HASH_CRC32C: 'USE_CRC32C_HASH'
}
Expand All @@ -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):
Expand Down
15 changes: 10 additions & 5 deletions smoldd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
from smol.shared import *
from smol.parse import *

# TODO: support for hashes that aren't djb2


def readbyte(blob, off): return struct.unpack('<B', blob[off:off+1])[0], (off+1)
def readint(blob, off): return struct.unpack('<I', blob[off:off+4])[0], (off+4)
Expand All @@ -36,10 +34,11 @@ def find_libs(deflibs, libname):
for d in dirs:
for f in glob.glob(glob.escape(d + '/' + libname) + '*'): yield f

def build_hashtab(readelf_bin, lib):
def build_hashtab(readelf_bin, lib, hashid):
symbols = list_symbols(readelf_bin, lib)

return { hash_djb2(symbol):symbol for symbol in symbols }
hashfn = get_hash_fn(hashid)
return { hashfn(symbol):symbol for symbol in symbols }

def addr2off(elf, addr):
for x in elf.phdrs:
Expand Down Expand Up @@ -144,6 +143,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()
Expand All @@ -155,7 +160,7 @@ def main():

htbl = get_hashtbl(elf, blob, args)

libhashes = dict((l, build_hashtab(args.readelf, neededpaths[l])) for l in needed)
libhashes = dict((l, build_hashtab(args.readelf, neededpaths[l], hashid)) for l in needed)

hashresolves = dict({})
noresolves = []
Expand Down

0 comments on commit 4e07c4f

Please sign in to comment.