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
|
```sh
|
||||||
./smol.py -lfoo -lbar input.o... smol-output.asm
|
./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...
|
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))
|
libs = list(find_libs(spaths, libnames))
|
||||||
symbols = {}
|
symbols = {}
|
||||||
|
|
||||||
for symbol in syms:
|
for symbol, reloc in syms:
|
||||||
library = find_symbol(args.scanelf, libs, libnames, symbol)
|
library = find_symbol(args.scanelf, libs, libnames, symbol)
|
||||||
if not library:
|
if not library:
|
||||||
eprintf("could not find symbol: {}".format(symbol))
|
eprintf("could not find symbol: {}".format(symbol))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
symbols.setdefault(library, [])
|
symbols.setdefault(library, [])
|
||||||
symbols[library].append(symbol)
|
symbols[library].append((symbol, reloc))
|
||||||
|
|
||||||
output(arch, symbols, args.output)
|
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('dd (_symbols.{} - _symbols)\n'.format(shorts[library]))
|
||||||
outf.write('.dynamic.end:\n')
|
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')
|
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))
|
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)
|
hash = hash_djb2(sym)
|
||||||
outf.write("""
|
outf.write("""
|
||||||
\t\tglobal {name}
|
\t\tglobal {name}
|
||||||
|
@ -46,11 +55,25 @@ def output_amd64(libraries, outf):
|
||||||
outf.write('dynamic.end:\n')
|
outf.write('dynamic.end:\n')
|
||||||
|
|
||||||
outf.write('[section .data.smolgot]\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')
|
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))
|
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)
|
hash = hash_djb2(sym)
|
||||||
outf.write('\t\t_symbols.{lib}.{name}: dq 0x{hash:x}\n'\
|
outf.write('\t\t_symbols.{lib}.{name}: dq 0x{hash:x}\n'\
|
||||||
.format(lib=shorts[library],name=sym,hash=hash))
|
.format(lib=shorts[library],name=sym,hash=hash))
|
||||||
|
@ -60,9 +83,10 @@ def output_amd64(libraries, outf):
|
||||||
outf.write('_symbols.end:\n')
|
outf.write('_symbols.end:\n')
|
||||||
|
|
||||||
outf.write('_smolplt:\n')
|
outf.write('_smolplt:\n')
|
||||||
for library, symbols in libraries.items():
|
for library, symrels in libraries.items():
|
||||||
for sym in symbols:
|
for sym, reloc in symrels:
|
||||||
outf.write("""
|
if reloc == 'R_X86_64_PLT32':
|
||||||
|
outf.write("""
|
||||||
[section .text.smolplt.{name}]
|
[section .text.smolplt.{name}]
|
||||||
global {name}
|
global {name}
|
||||||
{name}:
|
{name}:
|
||||||
|
|
33
smolparse.py
33
smolparse.py
|
@ -31,18 +31,45 @@ def decide_arch(inpfiles):
|
||||||
|
|
||||||
return archmagic[archn]
|
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):
|
def get_needed_syms(readelf_bin, inpfiles):
|
||||||
output = subprocess.check_output([readelf_bin, '-s', '-W']+inpfiles,
|
output = subprocess.check_output([readelf_bin, '-s', '-W']+inpfiles,
|
||||||
stderr=subprocess.DEVNULL)
|
stderr=subprocess.DEVNULL)
|
||||||
|
outrel = subprocess.check_output([readelf_bin, '-r', '-W']+inpfiles,
|
||||||
|
stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
relocs = build_reloc_typ_table(outrel)
|
||||||
|
|
||||||
syms=set({})
|
syms=set({})
|
||||||
for entry in output.decode('utf-8').splitlines():
|
for entry in output.decode('utf-8').splitlines():
|
||||||
stuff = entry.split()
|
stuff = entry.split()
|
||||||
if len(stuff)<8: continue
|
if len(stuff)<8: continue
|
||||||
if stuff[4] == "GLOBAL" and stuff[6] == "UND" and len(stuff[7])>0:
|
if stuff[4] == "GLOBAL" and stuff[6] == "UND" and len(stuff[7])>0 \
|
||||||
syms.add(stuff[7])
|
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):
|
def get_cc_paths(cc_bin):
|
||||||
output = subprocess.check_output([cc_bin, '-print-search-dirs'],
|
output = subprocess.check_output([cc_bin, '-print-search-dirs'],
|
||||||
|
|
|
@ -44,7 +44,7 @@ _smol_start:
|
||||||
sub rsi, LF_ENTRY_OFF+8
|
sub rsi, LF_ENTRY_OFF+8
|
||||||
xchg rbx, rsi
|
xchg rbx, rsi
|
||||||
|
|
||||||
mov rsi, _symbols
|
mov esi, _symbols
|
||||||
|
|
||||||
; for (rsi = (uint8_t*)_symbols; *rsi; ++rsi) {
|
; for (rsi = (uint8_t*)_symbols; *rsi; ++rsi) {
|
||||||
.next_needed:
|
.next_needed:
|
||||||
|
@ -159,7 +159,9 @@ _smol_start:
|
||||||
.needed_end:
|
.needed_end:
|
||||||
;xor rbp, rbp ; still 0 from _dl_start_user
|
;xor rbp, rbp ; still 0 from _dl_start_user
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
|
%ifdef ALIGN_STACK
|
||||||
push rax
|
push rax
|
||||||
|
%endif
|
||||||
%ifdef USE_DL_FINI
|
%ifdef USE_DL_FINI
|
||||||
xchg rsi, r13 ; _dl_fini
|
xchg rsi, r13 ; _dl_fini
|
||||||
%endif
|
%endif
|
||||||
|
|
Loading…
Reference in New Issue