#!/usr/bin/env python3 from elftools.elf.elffile import ELFFile from elftools.elf.relocation import RelocationSection import sys, struct, itertools, re, os SYMTRANSLATION = {key: int(value) for key, value in [z.split(":") for z in sys.argv[3:]]} print(f"Converting {os.path.realpath(sys.argv[1])} to {os.path.realpath(sys.argv[2])}...") with open(sys.argv[1], "rb") as inp, open(sys.argv[2], "wb") as outp: elf = ELFFile(inp) loadhdr = next(elf.get_segment(i) for i in itertools.count() if elf.get_segment(i)["p_type"] == "PT_LOAD") relsec = elf.get_section_by_name(".rel.dyn") datasec = elf.get_section_by_name(".text") data = bytearray(datasec.data()) data += bytearray(loadhdr["p_memsz"] - len(data)) #Make space to fit .bss outp.write(b"MOD\0") syms = [s for s in elf.get_section_by_name(".symtab").iter_symbols() if s.name in SYMTRANSLATION] syms.sort(key = lambda s: SYMTRANSLATION[s.name]) relocs = [r for r in relsec.iter_relocations()] if relsec else [] outp.write(struct.pack("H", len(syms))) outp.write(struct.pack("H", len(relocs))) outp.write(struct.pack("I", len(data))) for i, s in enumerate(syms): outp.write(struct.pack("H", i)) #struct.pack emits 8 bytes when you put HI directly outp.write(struct.pack("I", s.entry["st_value"] - datasec["sh_addr"])) for r in relocs: assert(r["r_info"] % 256 == 8) idx = r["r_offset"] - datasec["sh_addr"] data[idx:idx + 4] = struct.pack("I", struct.unpack("I", data[idx:idx + 4])[0] - datasec["sh_addr"]) outp.write(struct.pack("I", idx)) # Align to 16 if outp.tell() % 16 != 0: outp.write(b"\0" * (16 - outp.tell() % 16)) outp.write(data)