copapy/tools/extract_code.py

80 lines
3.3 KiB
Python

from copapy.binwrite import data_reader, Command, ByteOrder
from copapy.stencil_db import RelocationType
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("input_file", type=str, help="Input file path with copapy commands")
parser.add_argument("output_file", type=str, help="Output file with patched code")
parser.add_argument("--data_section_offset", type=int, default=0x2000, help="Offset for data relative to code section")
parser.add_argument("--byteorder", type=str, choices=['little', 'big'], default='little', help="Select byteorder")
args = parser.parse_args()
input_file: str = args.input_file
output_file: str = args.output_file
data_section_offset: int = args.data_section_offset
byteorder: ByteOrder = args.byteorder
with open(input_file, mode='rb') as f:
dr = data_reader(f.read(), byteorder)
buffer_index: int = 0
end_flag: int = 0
program_data: bytearray = bytearray([])
while (end_flag == 0):
com = dr.read_com()
if com == Command.ALLOCATE_DATA:
size = dr.read_int()
print(f"ALLOCATE_DATA size={size}")
elif com == Command.ALLOCATE_CODE:
size = dr.read_int()
program_data = bytearray(size)
print(f"ALLOCATE_CODE size={size}")
elif com == Command.COPY_DATA:
offs = dr.read_int()
size = dr.read_int()
datab = dr.read_bytes(size)
print(f"COPY_DATA offs={offs} size={size} data={' '.join(hex(d) for d in datab)}")
elif com == Command.COPY_CODE:
offs = dr.read_int()
size = dr.read_int()
datab = dr.read_bytes(size)
program_data[offs:offs + size] = datab
print(f"COPY_CODE offs={offs} size={size} data={' '.join(hex(d) for d in datab[:5])}...")
elif com == Command.PATCH_FUNC:
offs = dr.read_int()
reloc_type = dr.read_int()
value = dr.read_int(signed=True)
print(f"PATCH_FUNC patch_offs={offs} reloc_type={reloc_type} value={value}")
elif com == Command.PATCH_OBJECT:
offs = dr.read_int()
reloc_type = dr.read_int()
value = dr.read_int(signed=True)
assert reloc_type == RelocationType.RELOC_RELATIVE_32.value
program_data[offs:offs + 4] = (value + data_section_offset).to_bytes(4, byteorder, signed=True)
print(f"PATCH_OBJECT patch_offs={offs} reloc_type={reloc_type} value={value}")
elif com == Command.ENTRY_POINT:
rel_entr_point = dr.read_int()
print(f"ENTRY_POINT rel_entr_point={rel_entr_point}")
elif com == Command.RUN_PROG:
rel_entr_point = dr.read_int()
print(f"RUN_PROG")
elif com == Command.READ_DATA:
offs = dr.read_int()
size = dr.read_int()
print(f"READ_DATA offs={offs} size={size}")
elif com == Command.FREE_MEMORY:
print("READ_DATA")
elif com == Command.END_COM:
print("END_COM")
end_flag = 1
else:
assert False, f"Unknown command: {com}"
with open(output_file, mode='wb') as f:
f.write(program_data)
print(f"Code written to {output_file}.")