diff --git a/rt/loader32.asm b/rt/loader32.asm index 13bdb8f..e4a98d7 100644 --- a/rt/loader32.asm +++ b/rt/loader32.asm @@ -2,6 +2,11 @@ %include "rtld.inc" +%ifndef HASH_END_TYP +%warning "W: HASH_END_TYP not defined, falling back to 16-bit!" +%define HASH_END_TYP word +%endif + %define R10_BIAS (0x178) %ifdef ELF_TYPE @@ -186,7 +191,7 @@ _smol_start: %ifdef USE_JMP_BYTES inc edi ; skip 0xE9 (jmp) offset %endif - cmp word [edi], 0 + cmp HASH_END_TYP [edi], 0 jne short .next_hash ; if USE_DNLOAD_LOADER @@ -300,7 +305,7 @@ repne scasd %ifdef USE_JMP_BYTES inc edi %endif - cmp word [edi], 0 + cmp HASH_END_TYP [edi], 0 jne short .next_hash pop eax ; get rid of leftover ecx on stack diff --git a/rt/loader64.asm b/rt/loader64.asm index d704685..336ef65 100644 --- a/rt/loader64.asm +++ b/rt/loader64.asm @@ -1,5 +1,10 @@ ; vim: set ft=nasm: +%ifndef HASH_END_TYP +%warning "W: HASH_END_TYP not defined, falling back to 16-bit!" +%define HASH_END_TYP word +%endif + ;%define R10_BIAS (0x2B4) %define R10_BIAS (0x2B4+0x40) @@ -153,7 +158,7 @@ _smol_start: %endif %endif stosq - cmp word [rdi], 0 + cmp HASH_END_TYP [rdi], 0 %ifdef IFUNC_SUPPORT %ifdef SKIP_ZERO_VALUE jne .next_hash;short .next_hash @@ -311,7 +316,7 @@ repne scasd ; technically, scasq should be used, but meh. this is 1 byte smaller ; IFUNC_SUPPORT %endif stosq ; *phash = finaladdr - cmp word [rdi], 0 + cmp HASH_END_TYP [rdi], 0 jne short .next_hash ; } while (1) ; jmp short .next_hash diff --git a/smol/emit.py b/smol/emit.py index 55e7e40..56aae42 100644 --- a/smol/emit.py +++ b/smol/emit.py @@ -4,6 +4,23 @@ from .shared import * +fetch_width_from_bits = { 8: 'byte', 16: 'word', 32: 'dword', 64: 'qword' } + +def get_min_check_width(libraries, hashfn): + minv = 8 # can't go lower + for k, v in libraries.items(): + for sym in v: + hv = hashfn(sym[0]) # sym == (name, reloc) + if (hv & 0xffffffff) == 0: + # this should (hopefully) NEVER happen + error("Aiee, all-zero hash for sym '%s'!" % sym) + elif (hv & 0xFFFF) == 0: + minv = max(minv, 32) # need at least 32 bits + elif (hv & 0xFF) == 0: + minv = max(minv, 16) # need at least 16 bits + + return minv + def sort_imports(libraries, hashfn): #eprintf("in: " + str(libraries)) @@ -29,6 +46,9 @@ def output_x86(libraries, nx, h16, outf, det): hashfn = hash_bsd2 if h16 else hash_djb2 if det: libraries = sort_imports(libraries, hashfn) + outf.write('%%define HASH_END_TYP %s\n' % + fetch_width_from_bits[get_min_check_width(libraries, hashfn)]) + usedrelocs = set({}) for library, symrels in libraries.items(): for sym, reloc in symrels: usedrelocs.add(reloc) @@ -74,7 +94,7 @@ def output_x86(libraries, nx, h16, outf, det): for sym, reloc in symrels: # meh if reloc != 'R_386_PC32' and reloc != 'R_386_GOT32X': - eprintf('Relocation type ' + reloc + ' of symbol ' + sym + ' unsupported!') + eprintf('Relocation type %s of symbol %s unsupported!' % (reloc, sym)) sys.exit(1) if nx: @@ -118,6 +138,9 @@ def output_amd64(libraries, nx, h16, outf, det): hashfn = hash_djb2 #hash_bsd2 if h16 else hash_djb2 if det: libraries = sort_imports(libraries, hashfn) + outf.write('%%define HASH_END_TYP %s\n' % + fetch_width_from_bits[get_min_check_width(libraries, hashfn)]) + outf.write('; vim: set ft=nasm:\n') outf.write('bits 64\n') @@ -153,7 +176,7 @@ def output_amd64(libraries, nx, h16, outf, det): for sym, reloc in symrels: if reloc not in ['R_X86_64_PLT32', 'R_X86_64_GOTPCRELX', \ 'R_X86_64_REX_GOTPCRELX', 'R_X86_64_GOTPCREL']: - error('Relocation type ' + reloc + ' of symbol ' + sym + ' unsupported!') + error('Relocation type %s of symbol %s unsupported!' % (reloc, sym)) if reloc in ['R_X86_64_GOTPCRELX', 'R_X86_64_REX_GOTPCRELX', \ 'R_X86_64_GOTPCREL']: @@ -189,5 +212,5 @@ 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) else: - error("E: cannot emit for arch '" + str(arch) + "'") + error("E: cannot emit for arch '%s'" % str(arch))