mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-28 04:23:37 +01:00
fxsdk: add ELF patch mechanism for HH2 to specify filename for stage-2
This commit is contained in:
parent
69f70eac10
commit
181ed5cccd
3 changed files with 94 additions and 3 deletions
|
@ -29,8 +29,8 @@ function(generate_hh2_bin)
|
|||
|
||||
add_custom_command(
|
||||
TARGET "${HH2_TARGET}" POST_BUILD
|
||||
COMMAND fxsdk script patch_hh2_filename.py ${HH2_TARGET} ${HH2_OUTPUT}
|
||||
COMMAND ${OBJCOPY} -O binary -R .bss -R .gint_bss ${HH2_TARGET} ${HH2_OUTPUT}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
COMMAND_EXPAND_LISTS
|
||||
)
|
||||
COMMAND_EXPAND_LISTS)
|
||||
endfunction()
|
||||
|
|
|
@ -8,7 +8,8 @@ import elftools.elf.elffile
|
|||
|
||||
if len(sys.argv) != 2 or "-h" in sys.argv or "--help" in sys.argv:
|
||||
print(f"usage: {sys.argv[0]} <FOLDER>", file=sys.stderr)
|
||||
print("Prints sections of *.o/*.obj files in the folder, sorted by size")
|
||||
print("Prints sections of *.o/*.obj files in the folder, sorted by size",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
files = glob.glob(sys.argv[1] + "/**/*.o", recursive=True)
|
||||
|
|
90
fxsdk/scripts/patch_hh2_filename.py
Executable file
90
fxsdk/scripts/patch_hh2_filename.py
Executable file
|
@ -0,0 +1,90 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import subprocess
|
||||
import struct
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
eprint = lambda *args, **kwargs: print(*args, **kwargs, file=sys.stderr)
|
||||
def error(*args, **kwargs):
|
||||
eprint("error:", *args, **kwargs)
|
||||
sys.exit(1)
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
eprint(f"usage: {sys.argv[0]} <ELF> <BIN>")
|
||||
eprint("Patches filenames into HH2-targeted ELF files for stage-2 load")
|
||||
sys.exit(1)
|
||||
|
||||
# Check that the filename fits
|
||||
path = sys.argv[1]
|
||||
name = os.path.basename(sys.argv[2])
|
||||
encoded_name = bytes(name, "utf-8")
|
||||
if len(encoded_name) > 31:
|
||||
error(f"output filename {name} is too long (max. 31 bytes)")
|
||||
|
||||
# Run a command and return its stdout
|
||||
def cmd(command):
|
||||
rc = subprocess.run(command, stdout=subprocess.PIPE, check=True)
|
||||
return rc.stdout.decode("utf-8")
|
||||
|
||||
# Get the list of addresses at which a symbol called "name" is defined
|
||||
def getsym(path, name):
|
||||
# All syms as a list of (address, type, name)
|
||||
syms = [l.split(" ") for l in cmd(["sh-elf-nm", path]).splitlines()]
|
||||
return [int(t[0], 16) for t in syms if t[2] == name]
|
||||
|
||||
# Get the section info for the section that contains address "addr"
|
||||
def getsection(path, addr):
|
||||
RE_SECTION = re.compile(
|
||||
r'^\s*\[\s*\d+\]\s*([\w._]+)\s+([A-Z]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)')
|
||||
lines = cmd(["sh-elf-readelf", "-S", path]).splitlines()
|
||||
|
||||
# Parse sections from the output of readelf
|
||||
sections = []
|
||||
for l in lines:
|
||||
m = RE_SECTION.match(l)
|
||||
if m is None:
|
||||
continue
|
||||
sections.append((m[1], m[2], int(m[3], 16), int(m[4], 16), int(m[5], 16)))
|
||||
|
||||
# Find sections that contain the given address
|
||||
matches = []
|
||||
for name, kind, start, off, size in sections:
|
||||
if kind == "PROGBITS" and start <= addr < start + size:
|
||||
matches.append((name, off + (addr - start)))
|
||||
|
||||
return matches
|
||||
|
||||
# Get the address of symbol .stage2_filename
|
||||
s = getsym(path, ".stage2_filename")
|
||||
if len(s) == 0:
|
||||
error(f"no symbol .stage2_filename, is this built for fx-CP?")
|
||||
if len(s) > 1:
|
||||
error(f"multiple ({len(s)}) symbols named .stage2_filename, what?")
|
||||
filename_address = s[0]
|
||||
|
||||
s = getsection(path, filename_address)
|
||||
if len(s) == 0:
|
||||
error(f".stage2_filename is not in any section?")
|
||||
if len(s) > 1:
|
||||
error(f"overlapping sections ({', '.join(e[0] for e in s)}), excuse me?")
|
||||
if s[0][0] != ".hh2":
|
||||
error("how is .stage2_filename not in the .hh2 section?")
|
||||
name_offset = s[0][1]
|
||||
|
||||
# Load file contents
|
||||
with open(path, "rb+") as fp:
|
||||
fp.seek(name_offset)
|
||||
name_placeholder = struct.unpack(">8i", fp.read(32))
|
||||
if name_placeholder != tuple(range(1, 8+1)):
|
||||
error("name placeholder is wrong, check binary format and ELF parsing")
|
||||
|
||||
# Pad to 32 bytes
|
||||
encoded_name += bytes(32 - len(encoded_name))
|
||||
assert len(encoded_name) == 32
|
||||
|
||||
fp.seek(name_offset)
|
||||
fp.write(encoded_name)
|
||||
|
||||
sys.exit(0)
|
Loading…
Reference in a new issue