Commit 6613bab2 authored by PoroCYon's avatar PoroCYon
Browse files

CRC32C-based hash (thanks Intel) (Python part is still TODO)

parent 494d3263
/bin
/obj
__pycache__
smol-20*-*-*/
smol*.tar.xz
......@@ -98,34 +98,44 @@ _smol_start:
add esi, ebx
push ecx
%ifndef USE_HASH16
; source in eax, result in eax
%ifdef USE_CRC32C_HASH
push -1
pop eax
%else
%ifndef USE_HASH16
push ebx
push 33
push 5381
pop eax
pop ebx
%else
%else
xor eax, eax
%endif
%endif
xor ecx, ecx
%endif
.nexthashiter:
;
xchg eax, ecx
lodsb
or al, al
xchg eax, ecx
jz short .breakhash
%ifndef USE_HASH16
%ifdef USE_CRC32C_HASH
crc32 eax, cl
%else
%ifndef USE_HASH16
push edx
mul ebx
pop edx
; add eax, ecx
%else
%else
ror ax, 2
; add ax, cx
%endif
%endif
add eax, ecx
%endif
jmp short .nexthashiter
.breakhash:
......
; vim: set ft=nasm:
; vim: set ft=nasm et:
;%define R10_BIAS (0x2B4)
%define R10_BIAS (0x2B4+0x40)
......@@ -96,6 +96,8 @@ _smol_start:
mov esi, dword [rdx + ST_NAME_OFF]
add rsi, r8;9
%ifndef USE_CRC32C_HASH
; djb2
xor ecx, ecx
push 33
push 5381
......@@ -103,22 +105,45 @@ _smol_start:
; pop rcx
pop rax
pop rbx
%else
; crc32
push -1
pop rcx
%endif
.nexthashiter:
%ifndef USE_CRC32C_HASH
; djb2
; TODO: optimize register usage a bit more
xchg eax, ecx
%endif
lodsb
or al, al
%ifndef USE_CRC32C_HASH
; djb2
xchg eax, ecx
%endif
jz short .breakhash
%ifndef USE_CRC32C_HASH
; djb2
push rdx
mul ebx
pop rdx
add eax, ecx
%else
; crc32c
crc32 ecx, al
%endif
jmp short .nexthashiter
.breakhash:
%ifdef USE_CRC32C_HASH
; crc32c
cmp r14d, ecx
%else
; djb2
cmp r14d, eax
%endif
je short .hasheq
add rdx, SYMTAB_SIZE
......
......@@ -20,13 +20,16 @@ def sort_imports(libraries, hashfn):
if sys.version_info < (3, 6): return OrderedDict(ll)
else: return dict(ll)
def output_x86(libraries, nx, h16, outf, det):
def output_x86(libraries, nx, hashid, outf, det):
outf.write('; vim: set ft=nasm:\n') # be friendly
if nx: outf.write('%define USE_NX 1\n')
if h16: outf.write('%define USE_HASH16 1\n')
defff = define_for_hash[hashid]
if defff is not None:
outf.write('%define {} 1\n'.format(defff))
if nx:
outf.write('%define USE_NX 1\n')
hashfn = hash_bsd2 if h16 else hash_djb2
hashfn = get_hash_fn(hashid)
if det: libraries = sort_imports(libraries, hashfn)
usedrelocs = set({})
......@@ -108,19 +111,22 @@ global {name}
# end output_x86
def output_amd64(libraries, nx, h16, outf, det):
if h16:
def output_amd64(libraries, nx, hashid, outf, det):
if hashid == HASH_BSD2:
error("--hash16 not supported yet for x86_64 outputs.")
if nx: outf.write('%define USE_NX 1\n')
# if h16: outf.write('%define USE_HASH16 1\n')
hashfn = hash_djb2 #hash_bsd2 if h16 else hash_djb2
if det: libraries = sort_imports(libraries, hashfn)
outf.write('; vim: set ft=nasm:\n')
outf.write('bits 64\n')
defff = define_for_hash[hashid]
if defff is not None:
outf.write('%define {} 1\n'.format(defff))
if nx:
outf.write('%define USE_NX 1\n')
hashfn = get_hash_fn(hashid)
if det: libraries = sort_imports(libraries, hashfn)
shorts = { l: l.split('.', 1)[0].lower().replace('-', '_') for l in libraries }
outf.write('%include "header64.asm"\n')
......@@ -185,9 +191,9 @@ global {name}
# end output_amd64
def output(arch, libraries, nx, h16, outf, det):
if arch == 'i386': output_x86(libraries, nx, h16, outf, det)
elif arch == 'x86_64': output_amd64(libraries, nx, h16, outf, det)
def output(arch, libraries, nx, hashid, outf, det):
if arch == 'i386': output_x86(libraries, nx, hashid, outf, det)
elif arch == 'x86_64': output_amd64(libraries, nx, hashid, outf, det)
else:
error("E: cannot emit for arch '" + str(arch) + "'")
......@@ -7,6 +7,16 @@ archmagic = {
'x86_64': 62, 62: 'x86_64',
}
HASH_DJB2 = 0
HASH_BSD2 = 1
HASH_CRC32C=2
define_for_hash = {
HASH_DJB2: None
HASH_BSD2: 'USE_HASH16',
HASH_CRC32C: 'USE_CRC32C_HASH'
}
def hash_bsd2(s):
h = 0
for c in s:
......@@ -19,6 +29,24 @@ def hash_djb2(s):
h = (h * 33 + ord(c)) & 0xFFFFFFFF
return h
def hash_crc32c(s):
# crc32 implementation is basically:
# sum = -1; for (; *s; ++s) crc32_instr(&sum, *s); return sum
assert False, "not implemented!" # TODO
def get_hash_id(h16, c32):
if not h16 and not c32:
return HASH_DJB2
elif h16 and not c32:
return HASH_BSD2
elif not h16 and c32:
return HASH_CRC32C
else:
return False, "??????? (shouldn't happen)"
def get_hash_fn(hid):
return (hash_djb2, hash_bsd2, hash_crc32c)[hid]
def eprintf(*args, **kwargs): print(*args, file=sys.stderr, **kwargs)
def error(*args, **kwargs):
......
......@@ -24,8 +24,11 @@ def main():
help="directories to search libraries in")
parser.add_argument('-s', '--hash16', default=False, action='store_true', \
help="Use 16-bit (BSD) hashes instead of 32-bit djb2 hashes. "+\
"Implies -fuse-dnload-loader")
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'.")
parser.add_argument('-n', '--nx', default=False, action='store_true', \
help="Use NX (i.e. don't use RWE pages). Costs the size of one phdr, "+\
"plus some extra bytes on i386.")
......@@ -105,7 +108,10 @@ def main():
args = parser.parse_args()
if args.hash16:
if args.hash16 and args.crc32c:
error("Cannot combine --hash16 and --crc32c!")
if args.hash16 or args.crc32c:
args.fuse_dnload_loader = True
if args.fskip_zero_value: args.asflags.insert(0, "-DSKIP_ZERO_VALUE")
......@@ -130,6 +136,9 @@ def main():
error("Unknown/unsupported architecture '" + str(arch) + "'")
if args.verbose: eprintf("arch: %s" % arch)
if args.hash16 and arch not in ('i386', 3):
error("Cannot use --hash16 for arch `%s' (not i386)" % (arch))
objinput = None
objinputistemp = False
tmp_asm_file = tempfile.mkstemp(prefix='smoltab',suffix='.asm',text=True)
......@@ -162,7 +171,7 @@ def main():
symbols[library].append((symbol, reloc))
with os.fdopen(tmp_asm_fd, mode='w') as taf:
output(arch, symbols, args.nx, args.hash16, taf, args.det)
output(arch, symbols, args.nx, get_hash_id(args.hash16, args.crc32c), taf, args.det)
if args.verbose:
eprintf("wrote symtab to %s" % tmp_asm_file)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment