mirror of
https://github.com/icicle-emu/icicle-python
synced 2026-06-21 13:53:41 +00:00
170 lines
4.2 KiB
Python
170 lines
4.2 KiB
Python
from typing import List, Dict, Tuple
|
|
from enum import Enum
|
|
|
|
class MemoryProtection(Enum):
|
|
NoAccess = ...
|
|
ReadOnly = ...
|
|
ReadWrite = ...
|
|
ExecuteOnly = ...
|
|
ExecuteRead = ...
|
|
ExecuteReadWrite = ...
|
|
|
|
class MemoryExceptionCode(Enum):
|
|
Unallocated = ...
|
|
Unmapped = ...
|
|
UnmappedRegisters = ...
|
|
Uninitialized = ...
|
|
ReadViolation = ...
|
|
WriteViolation = ...
|
|
ExecViolation = ...
|
|
ReadWatch = ...
|
|
WriteWatch = ...
|
|
Unaligned = ...
|
|
OutOfMemory = ...
|
|
SelfModifyingCode = ...
|
|
AddressOverflow = ...
|
|
Unknown = ...
|
|
|
|
class RunStatus(Enum):
|
|
Running = ...
|
|
InstructionLimit = ...
|
|
Breakpoint = ...
|
|
Interrupted = ...
|
|
Halt = ...
|
|
Killed = ...
|
|
Deadlock = ...
|
|
OutOfMemory = ...
|
|
Unimplemented = ...
|
|
UnhandledException = ...
|
|
|
|
class ExceptionCode(Enum):
|
|
NoException = ...
|
|
InstructionLimit = ...
|
|
Halt = ...
|
|
Sleep = ...
|
|
Syscall = ...
|
|
CpuStateChanged = ...
|
|
DivisionException = ...
|
|
ReadUnmapped = ...
|
|
ReadPerm = ...
|
|
ReadUnaligned = ...
|
|
ReadWatch = ...
|
|
ReadUninitialized = ...
|
|
WriteUnmapped = ...
|
|
WritePerm = ...
|
|
WriteWatch = ...
|
|
WriteUnaligned = ...
|
|
ExecViolation = ...
|
|
SelfModifyingCode = ...
|
|
OutOfMemory = ...
|
|
AddressOverflow = ...
|
|
InvalidInstruction = ...
|
|
UnknownInterrupt = ...
|
|
UnknownCpuID = ...
|
|
InvalidOpSize = ...
|
|
InvalidFloatSize = ...
|
|
CodeNotTranslated = ...
|
|
ShadowStackOverflow = ...
|
|
ShadowStackInvalid = ...
|
|
InvalidTarget = ...
|
|
UnimplementedOp = ...
|
|
ExternalAddr = ...
|
|
Environment = ...
|
|
JitError = ...
|
|
InternalError = ...
|
|
UnmappedRegister = ...
|
|
UnknownError = ...
|
|
|
|
class Icicle:
|
|
def __init__(self, architecture: str, *,
|
|
jit = True,
|
|
jit_mem = True,
|
|
shadow_stack = False,
|
|
recompilation = True,
|
|
track_uninitialized = False,
|
|
optimize_instructions = True,
|
|
optimize_block = False,
|
|
tracing = False,
|
|
) -> None: ...
|
|
|
|
@property
|
|
def architecture(self) -> str: ...
|
|
|
|
@property
|
|
def exception_code(self) -> ExceptionCode: ...
|
|
|
|
@property
|
|
def exception_value(self) -> int: ...
|
|
|
|
icount: int
|
|
|
|
icount_limit: int
|
|
|
|
pc: int
|
|
|
|
sp: int
|
|
|
|
"""
|
|
Physical memory capacity in pages (adjust when seeing OutOfMemory)
|
|
The default limit is set so that the maximum corresponds to ~400 MB of host memory.
|
|
"""
|
|
mem_capacity: int
|
|
|
|
# TODO: API to get memory information?
|
|
|
|
def mem_map(self, address: int, size: int, protection: MemoryProtection): ...
|
|
|
|
def mem_unmap(self, address: int, size: int): ...
|
|
|
|
def mem_protect(self, address: int, size: int, protection: MemoryProtection): ...
|
|
|
|
def mem_read(self, address: int, size: int) -> bytes: ...
|
|
|
|
def mem_write(self, address: int, data: bytes) -> None: ...
|
|
|
|
def reg_list(self) -> Dict[str, Tuple[int, int]]: ...
|
|
|
|
def reg_offset(self, name: str) -> int: ...
|
|
|
|
def reg_size(self, name: str) -> int: ...
|
|
|
|
def reg_read(self, name: str) -> int: ...
|
|
|
|
def reg_write(self, name: str, value: int) -> None: ...
|
|
|
|
def reset(self): ...
|
|
|
|
def run(self) -> RunStatus: ...
|
|
|
|
def run_until(self, address: int) -> RunStatus: ...
|
|
|
|
def step(self, count: int) -> RunStatus: ...
|
|
|
|
def add_breakpoint(self, address: int) -> bool: ...
|
|
|
|
def remove_breakpoint(self, address: int) -> bool: ...
|
|
|
|
def architectures() -> List[str]: ...
|
|
|
|
class MemoryException(Exception):
|
|
def __init__(self, message: str, code: MemoryExceptionCode):
|
|
super().__init__(message)
|
|
self.code = code
|
|
|
|
def __str__(self):
|
|
return f"{super().__str__()} ({self.code})"
|
|
|
|
def __ghidra_init():
|
|
import os
|
|
for path in __path__ + [os.getenv("GHIDRA_SRC", ".")]:
|
|
processors_dir = os.path.join(path, "Ghidra", "Processors")
|
|
if os.path.isdir(processors_dir):
|
|
os.putenv("GHIDRA_SRC", path)
|
|
os.environ["GHIDRA_SRC"] = path
|
|
return
|
|
raise FileNotFoundError("Ghidra processor definitions not found")
|
|
|
|
__ghidra_init()
|
|
|
|
# NOTE: This overrides the stubs at runtime with the actual implementation
|
|
from .icicle import * |