inital commit
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import pydantic
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Protocol, cast
|
||||
|
||||
|
||||
CONFIG_ROOT = Path(__file__).parent.parent.parent.resolve() / "config"
|
||||
|
||||
# enumerate languages from config dir
|
||||
LANGUAGES = [Path(f.path).name for f in os.scandir(CONFIG_ROOT) if f.is_dir()]
|
||||
|
||||
|
||||
class BytePatch(pydantic.RootModel[tuple[int, int]]):
|
||||
root: tuple[int, int]
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.root[0]
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self.root[1]
|
||||
|
||||
|
||||
class BINPatch(pydantic.RootModel[dict[str, BytePatch]]):
|
||||
root: dict[str, BytePatch]
|
||||
|
||||
|
||||
class PatchDB(pydantic.RootModel[dict[str, BINPatch]]):
|
||||
root: dict[str, BINPatch]
|
||||
|
||||
|
||||
def fix_elf(orig_elf_path: Path, built_elf_path: Path, bin_patch: BytePatch):
|
||||
with orig_elf_path.open("rb") as fh:
|
||||
fh.seek(bin_patch.address)
|
||||
data = fh.read(bin_patch.size)
|
||||
|
||||
with built_elf_path.open(mode="r+b") as wh:
|
||||
wh.seek(bin_patch.address)
|
||||
wh.write(data)
|
||||
|
||||
|
||||
def main():
|
||||
class ArgsProtocol(Protocol):
|
||||
language: str
|
||||
elf_file: Path
|
||||
|
||||
parser = argparse.ArgumentParser(description="apply asm patches to assembly files")
|
||||
parser.add_argument("language", type=str, choices=LANGUAGES, help="language of the elf that is being patched")
|
||||
parser.add_argument("elf_file", type=Path, help="elf file to patch (relative to build dir)")
|
||||
|
||||
args = cast(ArgsProtocol, parser.parse_args())
|
||||
|
||||
built_elf_file = CONFIG_ROOT / args.language / args.elf_file
|
||||
|
||||
if not built_elf_file.exists():
|
||||
print(f"ERROR: cannot find elf file {built_elf_file}")
|
||||
exit(1)
|
||||
|
||||
orig_elf_path = CONFIG_ROOT / args.language / args.elf_file.name
|
||||
|
||||
patch_db_path = CONFIG_ROOT / args.language / "bin_patches.json"
|
||||
|
||||
if not patch_db_path.exists():
|
||||
exit(0)
|
||||
|
||||
patch_db = PatchDB.model_validate_json(patch_db_path.read_text())
|
||||
|
||||
for _tu_name, bin_patch in patch_db.root.items():
|
||||
for _func_name, byte_patch in bin_patch.root.items():
|
||||
fix_elf(orig_elf_path, built_elf_file, byte_patch)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user