kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

gen_libc_so.py (2957B)


      1 #!/usr/bin/env python3
      2 # Minimal x86_64 ET_DYN "libc.so": a .dynsym exporting libc_marker, a .dynstr,
      3 # and a .dynamic carrying DT_SONAME=libc.so. Just enough for kit's read_elf_dso
      4 # to load it as a DSO (it requires SHT_DYNSYM) and record DT_NEEDED from the
      5 # soname. kit can't emit a shared object yet, so this is hand-built like
      6 # test/objdump/aarch64/cases/gen_rpath.py and test/dwarf/dwarf.o.
      7 import struct, sys
      8 EM_X86_64 = 62
      9 def u16(x): return struct.pack('<H', x)
     10 def u32(x): return struct.pack('<I', x)
     11 def u64(x): return struct.pack('<Q', x)
     12 
     13 SHT_STRTAB, SHT_DYNAMIC, SHT_DYNSYM = 3, 6, 11
     14 STB_GLOBAL, STT_FUNC = 1, 2
     15 DT_SONAME, DT_STRTAB, DT_SYMTAB, DT_STRSZ, DT_SYMENT, DT_NULL = 14, 5, 6, 10, 11, 0
     16 SHN_ABS = 0xfff1
     17 
     18 shstr = b'\x00.dynsym\x00.dynstr\x00.dynamic\x00.shstrtab\x00'
     19 n_dynsym = shstr.index(b'.dynsym')
     20 n_dynstr = shstr.index(b'.dynstr')
     21 n_dynamic = shstr.index(b'.dynamic')
     22 n_shstrtab = shstr.index(b'.shstrtab')
     23 
     24 dynstr = b'\x00libc_marker\x00libc.so\x00'
     25 o_marker = dynstr.index(b'libc_marker')
     26 o_soname = dynstr.index(b'libc.so')
     27 
     28 def sym(name, info, other, shndx, value, size):
     29     return u32(name) + bytes([info, other]) + u16(shndx) + u64(value) + u64(size)
     30 dynsym = (sym(0, 0, 0, 0, 0, 0) +
     31           sym(o_marker, (STB_GLOBAL << 4) | STT_FUNC, 0, SHN_ABS, 0, 0))
     32 
     33 EH = SH = 64
     34 off_dynsym = (EH + 7) & ~7
     35 off_dynstr = off_dynsym + len(dynsym)
     36 off_dynamic = (off_dynstr + len(dynstr) + 7) & ~7
     37 
     38 def dyn(tag, val): return u64(tag) + u64(val)
     39 dynamic = (dyn(DT_SONAME, o_soname) + dyn(DT_SYMTAB, off_dynsym) +
     40            dyn(DT_STRTAB, off_dynstr) + dyn(DT_STRSZ, len(dynstr)) +
     41            dyn(DT_SYMENT, 24) + dyn(DT_NULL, 0))
     42 
     43 off_shstr = (off_dynamic + len(dynamic) + 7) & ~7
     44 off_sht = (off_shstr + len(shstr) + 7) & ~7
     45 
     46 # section indices: 0 NULL, 1 .dynsym, 2 .dynstr, 3 .dynamic, 4 .shstrtab
     47 IDX_DYNSTR = 2
     48 def shdr(name, typ, off, size, link, info, align, ent):
     49     return (u32(name) + u32(typ) + u64(0) + u64(0) + u64(off) + u64(size) +
     50             u32(link) + u32(info) + u64(align) + u64(ent))
     51 sht = (shdr(0, 0, 0, 0, 0, 0, 0, 0) +
     52        shdr(n_dynsym, SHT_DYNSYM, off_dynsym, len(dynsym), IDX_DYNSTR, 1, 8, 24) +
     53        shdr(n_dynstr, SHT_STRTAB, off_dynstr, len(dynstr), 0, 0, 1, 0) +
     54        shdr(n_dynamic, SHT_DYNAMIC, off_dynamic, len(dynamic), IDX_DYNSTR, 0, 8, 16) +
     55        shdr(n_shstrtab, SHT_STRTAB, off_shstr, len(shstr), 0, 0, 1, 0))
     56 
     57 eh = (b'\x7fELF' + bytes([2, 1, 1, 0]) + b'\x00' * 8 + u16(3) + u16(EM_X86_64) +
     58       u32(1) + u64(0) + u64(0) + u64(off_sht) + u32(0) + u16(EH) + u16(0) +
     59       u16(0) + u16(SH) + u16(5) + u16(4))
     60 
     61 buf = bytearray(off_sht + len(sht))
     62 buf[0:64] = eh
     63 buf[off_dynsym:off_dynsym + len(dynsym)] = dynsym
     64 buf[off_dynstr:off_dynstr + len(dynstr)] = dynstr
     65 buf[off_dynamic:off_dynamic + len(dynamic)] = dynamic
     66 buf[off_shstr:off_shstr + len(shstr)] = shstr
     67 buf[off_sht:off_sht + len(sht)] = sht
     68 out = sys.argv[1] if len(sys.argv) > 1 else 'libc.so'
     69 open(out, 'wb').write(buf)