Browse Source

automatically adapt end-of-hashes check width to the symbols used (closes #6)

pull/17/head
PoroCYon 1 year ago
parent
commit
b71b15b572
3 changed files with 40 additions and 7 deletions
  1. +7
    -2
      rt/loader32.asm
  2. +7
    -2
      rt/loader64.asm
  3. +26
    -3
      smol/emit.py

+ 7
- 2
rt/loader32.asm View File

@ -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


+ 7
- 2
rt/loader64.asm View File

@ -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


+ 26
- 3
smol/emit.py View File

@ -4,6 +4,23 @@ from collections import OrderedDict
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 @@ dynamic.end:
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 @@ dynamic.end:
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))

Loading…
Cancel
Save