gen_rpath.py (1852B)
1 #!/usr/bin/env python3 2 # Regenerates rpath.so: a minimal aarch64 ET_DYN ELF carrying a DT_RUNPATH 3 # entry, used to golden objdump's -p rpath rendering. kit can't emit a 4 # shared object yet, so this is hand-built (like test/dwarf/dwarf.o). It has 5 # only .shstrtab / .dynstr / .dynamic — just enough for read_elf's image 6 # pass to surface the runpath. Run: python3 gen_rpath.py 7 import struct 8 EM_AARCH64 = 183 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 shstr = b'\x00.shstrtab\x00.dynstr\x00.dynamic\x00' 14 n_shstr = shstr.index(b'.shstrtab') 15 n_dynstr = shstr.index(b'.dynstr') 16 n_dyn = shstr.index(b'.dynamic') 17 dynstr = b'\x00/opt/lib:$ORIGIN/../lib\x00' 18 DT_RUNPATH, DT_NULL = 29, 0 19 dynamic = struct.pack('<QQ', DT_RUNPATH, 1) + struct.pack('<QQ', DT_NULL, 0) 20 21 EH = SH = 64 22 off_shstr = EH 23 off_dynstr = off_shstr + len(shstr) 24 off_dyn = (off_dynstr + len(dynstr) + 7) & ~7 25 off_sht = (off_dyn + len(dynamic) + 7) & ~7 26 27 def shdr(name, typ, off, size, link, align, ent): 28 return (u32(name) + u32(typ) + u64(0) + u64(0) + u64(off) + u64(size) + 29 u32(link) + u32(0) + u64(align) + u64(ent)) 30 31 sht = (shdr(0, 0, 0, 0, 0, 0, 0) + 32 shdr(n_shstr, 3, off_shstr, len(shstr), 0, 1, 0) + 33 shdr(n_dynstr, 3, off_dynstr, len(dynstr), 0, 1, 0) + 34 shdr(n_dyn, 6, off_dyn, len(dynamic), 2, 8, 16)) 35 36 eh = (b'\x7fELF' + bytes([2, 1, 1, 0]) + b'\x00' * 8 + u16(3) + u16(EM_AARCH64) + 37 u32(1) + u64(0) + u64(0) + u64(off_sht) + u32(0) + u16(EH) + u16(0) + 38 u16(0) + u16(SH) + u16(4) + u16(1)) 39 40 buf = bytearray(off_sht + len(sht)) 41 buf[0:64] = eh 42 buf[off_shstr:off_shstr + len(shstr)] = shstr 43 buf[off_dynstr:off_dynstr + len(dynstr)] = dynstr 44 buf[off_dyn:off_dyn + len(dynamic)] = dynamic 45 buf[off_sht:off_sht + len(sht)] = sht 46 open('rpath.so', 'wb').write(buf)