luma/elftomod.py
2025-05-22 22:16:46 +03:00

49 lines
1.6 KiB
Python
Executable File

#!/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)