49 lines
1.6 KiB
Python
Executable File
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)
|