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)