mirror of https://github.com/Shizmob/smol
add support for more than one relocation type on x86_64, make stack alignment optional
This commit is contained in:
parent
560ce8c0f2
commit
d9a5eac2e6
|
@ -8,7 +8,9 @@ PoC by Shiz, bugfixing and 64-bit version by PoroCYon.
|
|||
|
||||
```sh
|
||||
./smol.py -lfoo -lbar input.o... smol-output.asm
|
||||
nasm -I src/ [-DUSE_NX] [-DUSE_DL_FINI] -o nasm-output.o smol-output.asm
|
||||
nasm -I src/ [-DUSE_INTERP] [-DALIGN_STACK] [-DUSE_NX] [-DUSE_DL_FINI] \
|
||||
-o nasm-output.o smol-output.asm
|
||||
# -DALIGN_STACK: 64-bit only.
|
||||
ld -T ld/link.ld -o binary nasm-output.o input.o...
|
||||
```
|
||||
|
||||
|
|
4
smol.py
4
smol.py
|
@ -52,13 +52,13 @@ def main():
|
|||
libs = list(find_libs(spaths, libnames))
|
||||
symbols = {}
|
||||
|
||||
for symbol in syms:
|
||||
for symbol, reloc in syms:
|
||||
library = find_symbol(args.scanelf, libs, libnames, symbol)
|
||||
if not library:
|
||||
eprintf("could not find symbol: {}".format(symbol))
|
||||
sys.exit(1)
|
||||
symbols.setdefault(library, [])
|
||||
symbols[library].append(symbol)
|
||||
symbols[library].append((symbol, reloc))
|
||||
|
||||
output(arch, symbols, args.output)
|
||||
|
||||
|
|
38
smolemit.py
38
smolemit.py
|
@ -15,11 +15,20 @@ def output_x86(libraries, outf):
|
|||
outf.write('dd (_symbols.{} - _symbols)\n'.format(shorts[library]))
|
||||
outf.write('.dynamic.end:\n')
|
||||
|
||||
# if needgot:
|
||||
# outf.write('global _GLOBAL_OFFSET_TABLE_\n')
|
||||
# outf.write('_GLOBAL_OFFSET_TABLE_:\n')
|
||||
# outf.write('dd dynamic\n')
|
||||
outf.write('_symbols:\n')
|
||||
for library, symbols in libraries.items():
|
||||
for library, symrels in libraries.items():
|
||||
outf.write('\t_symbols.{}: db "{}",0\n'.format(shorts[library], library))
|
||||
|
||||
for sym in symbols:
|
||||
for sym, reloc in symrels:
|
||||
# meh
|
||||
if reloc != 'R_386_PC32':
|
||||
eprintf('Relocation type ' + reloc + ' of symbol ' + sym + ' unsupported!')
|
||||
sys.exit(1)
|
||||
|
||||
hash = hash_djb2(sym)
|
||||
outf.write("""
|
||||
\t\tglobal {name}
|
||||
|
@ -46,11 +55,25 @@ def output_amd64(libraries, outf):
|
|||
outf.write('dynamic.end:\n')
|
||||
|
||||
outf.write('[section .data.smolgot]\n')
|
||||
# if needgot:
|
||||
# outf.write('global _GLOBAL_OFFSET_TABLE_\n')
|
||||
# outf.write('_GLOBAL_OFFSET_TABLE_:\n')
|
||||
# outf.write('dq dynamic\n')
|
||||
outf.write('_symbols:\n')
|
||||
for library, symbols in libraries.items():
|
||||
for library, symrels in libraries.items():
|
||||
outf.write('\t_symbols.{}: db "{}",0\n'.format(shorts[library], library))
|
||||
|
||||
for sym in symbols:
|
||||
for sym, reloc in symrels:
|
||||
if reloc != 'R_X86_64_PLT32' and reloc != 'R_X86_64_GOTPCRELX':
|
||||
eprintf('Relocation type ' + reloc + ' of symbol ' + sym + ' unsupported!')
|
||||
sys.exit(1)
|
||||
|
||||
if reloc == 'R_X86_64_GOTPCRELX':
|
||||
outf.write("""
|
||||
global {name}
|
||||
{name}:
|
||||
""".format(name=sym).lstrip('\n'))
|
||||
|
||||
hash = hash_djb2(sym)
|
||||
outf.write('\t\t_symbols.{lib}.{name}: dq 0x{hash:x}\n'\
|
||||
.format(lib=shorts[library],name=sym,hash=hash))
|
||||
|
@ -60,9 +83,10 @@ def output_amd64(libraries, outf):
|
|||
outf.write('_symbols.end:\n')
|
||||
|
||||
outf.write('_smolplt:\n')
|
||||
for library, symbols in libraries.items():
|
||||
for sym in symbols:
|
||||
outf.write("""
|
||||
for library, symrels in libraries.items():
|
||||
for sym, reloc in symrels:
|
||||
if reloc == 'R_X86_64_PLT32':
|
||||
outf.write("""
|
||||
[section .text.smolplt.{name}]
|
||||
global {name}
|
||||
{name}:
|
||||
|
|
33
smolparse.py
33
smolparse.py
|
@ -31,18 +31,45 @@ def decide_arch(inpfiles):
|
|||
|
||||
return archmagic[archn]
|
||||
|
||||
def build_reloc_typ_table(reo):
|
||||
relocs = dict({})
|
||||
|
||||
for s in reo.decode('utf-8').splitlines():
|
||||
stuff = s.split()
|
||||
|
||||
# prolly a 'header' line
|
||||
if len(stuff) < 5:
|
||||
continue
|
||||
|
||||
# yes, we're assuming every reference to the same symbol will use the
|
||||
# same relocation type. if this isn't the case, your compiler flags are
|
||||
# stupid
|
||||
relocs[stuff[4]] = stuff[2]
|
||||
|
||||
return relocs
|
||||
|
||||
def get_needed_syms(readelf_bin, inpfiles):
|
||||
output = subprocess.check_output([readelf_bin, '-s', '-W']+inpfiles,
|
||||
stderr=subprocess.DEVNULL)
|
||||
outrel = subprocess.check_output([readelf_bin, '-r', '-W']+inpfiles,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
relocs = build_reloc_typ_table(outrel)
|
||||
|
||||
syms=set({})
|
||||
for entry in output.decode('utf-8').splitlines():
|
||||
stuff = entry.split()
|
||||
if len(stuff)<8: continue
|
||||
if stuff[4] == "GLOBAL" and stuff[6] == "UND" and len(stuff[7])>0:
|
||||
syms.add(stuff[7])
|
||||
if stuff[4] == "GLOBAL" and stuff[6] == "UND" and len(stuff[7])>0 \
|
||||
and stuff[7] in relocs:
|
||||
syms.add((stuff[7], relocs[stuff[7]]))
|
||||
|
||||
return syms
|
||||
#needgot = False
|
||||
#if "_GLOBAL_OFFSET_TABLE_" in syms:
|
||||
# needgot = True
|
||||
# syms.remove("_GLOBAL_OFFSET_TABLE_")
|
||||
|
||||
return syms#, needgot
|
||||
|
||||
def get_cc_paths(cc_bin):
|
||||
output = subprocess.check_output([cc_bin, '-print-search-dirs'],
|
||||
|
|
|
@ -44,7 +44,7 @@ _smol_start:
|
|||
sub rsi, LF_ENTRY_OFF+8
|
||||
xchg rbx, rsi
|
||||
|
||||
mov rsi, _symbols
|
||||
mov esi, _symbols
|
||||
|
||||
; for (rsi = (uint8_t*)_symbols; *rsi; ++rsi) {
|
||||
.next_needed:
|
||||
|
@ -159,7 +159,9 @@ _smol_start:
|
|||
.needed_end:
|
||||
;xor rbp, rbp ; still 0 from _dl_start_user
|
||||
mov rdi, rsp
|
||||
%ifdef ALIGN_STACK
|
||||
push rax
|
||||
%endif
|
||||
%ifdef USE_DL_FINI
|
||||
xchg rsi, r13 ; _dl_fini
|
||||
%endif
|
||||
|
|
Loading…
Reference in New Issue