Source code for pairipcore.decompiler._decompiler

from pairipcore.context import VM
from pairipcore.decompiler.code import Code
from pairipcore.decompiler.handler import VMOp_Handler
from pairipcore.insn import InsnFormat
from pairipcore.opcode import VMOpcode_Interpret


# -----------------------------------------------------------------------------
# main function
# -----------------------------------------------------------------------------
[docs] def decompiler_main(vm: VM, decomp: "Decompiler", callback=None) -> Code: """ Main function to decompile the VM bytecode, executing the appropriate handlers for each opcode. Args: vm (VM): The virtual machine instance. decomp (Decompiler): The decompiler instance with opcode handlers. callback (Optional[Callable[[VM, int], None]]): An optional callback function for handling unknown opcodes. Returns: Code: The generated code as a `Code` object. """ # 1. setip state and PC vm.state.comment = "//" # C-style output if vm.context.pc < 0: vm.context.pc = vm.entry_point() vm.state["code"] = Code(vm) while not vm.state.should_exit: # Fetch opcode = vm.current_opcode() vm.context += 2 # Decode Handler = decomp[opcode] # Execute if Handler is not None and opcode in decomp.format_ids: handler_obj = Handler(vm, opcode, decomp.format_ids) handler_obj.run(vm) handler_obj.finish(vm) if vm.state.verbose: handler_obj.debug(vm) else: if callback is not None: callback(vm, opcode) else: vm.state["code"] += ( f"// Stopped at unknown opcode {opcode:#04x}" ) vm.state.should_exit = True return vm.state["code"]
# ----------------------------------------------------------------------------- # Decompiler class # ----------------------------------------------------------------------------- class Decompiler: format_ids: dict[int, InsnFormat] __table_: dict handler_ty: type def __init__(self, handler_ty: type | None = None) -> None: self.__table_ = {} self.handler_ty = handler_ty or VMOp_Handler self.format_ids = {} def __getitem__(self, key): if key == VMOpcode_Interpret: return decompiler_main return self.__table_.get(key, self.handler_ty) def __setitem__(self, key, value): self.__table_[key] = value
[docs] def from_opcode_def( opcode_def: dict[int | str, str | dict[str, str]], ) -> Decompiler: """ Create a `Decompiler` instance from opcode definitions. >>> dec = pairipcore.decompiler.from_opcode_def(...) >>> code = pairipcore.interpret(vm, dec) >>> for line in code: ... print(line) Args: opcode_def (Dict[Union[int, str], Union[str, dict]]): A dictionary where keys are opcodes and values are format IDs or dictionaries containing format IDs. Returns: Decompiler: The initialized `Decompiler` instance. """ decomp = Decompiler() for opcode, value in opcode_def.items(): if isinstance(opcode, str): opcode = int(opcode) if isinstance(value, str): decomp.format_ids[opcode] = InsnFormat.parse(value) elif value and value["format_id"]: decomp.format_ids[opcode] = InsnFormat.parse(value["format_id"]) return decomp