mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 08:15:37 +00:00
Add python bindings for reg save/restore
This commit is contained in:
parent
f2af98942b
commit
885b809004
|
@ -308,6 +308,56 @@ def test_i386_inout():
|
||||||
print("ERROR: %s" % e)
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def test_i386_reg_save():
|
||||||
|
print("Save/restore registers in opaque blob")
|
||||||
|
address = 0
|
||||||
|
code = '\x40' # inc eax
|
||||||
|
try:
|
||||||
|
# Initialize emulator
|
||||||
|
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||||
|
|
||||||
|
# map 8KB memory for this emulation
|
||||||
|
mu.mem_map(address, 8 * 1024, UC_PROT_ALL)
|
||||||
|
|
||||||
|
# write machine code to be emulated to memory
|
||||||
|
mu.mem_write(address, code)
|
||||||
|
|
||||||
|
print(">>> set eax to 1")
|
||||||
|
mu.reg_write(UC_X86_REG_EAX, 1)
|
||||||
|
|
||||||
|
print(">>> execute 'inc eax'")
|
||||||
|
mu.emu_start(address, address+1)
|
||||||
|
|
||||||
|
print(">>> save the register state")
|
||||||
|
saved_regs = mu.save_regs()
|
||||||
|
|
||||||
|
print(">>> execute 'inc eax'")
|
||||||
|
mu.emu_start(address, address+1)
|
||||||
|
|
||||||
|
print(">>> assert eax == 3")
|
||||||
|
assert mu.reg_read(UC_X86_REG_EAX) == 3
|
||||||
|
|
||||||
|
print(">>> restore the register state")
|
||||||
|
mu.restore_regs(saved_regs)
|
||||||
|
|
||||||
|
print(">>> assert eax == 2")
|
||||||
|
assert mu.reg_read(UC_X86_REG_EAX) == 2
|
||||||
|
|
||||||
|
print(">>> execute 'inc eax'")
|
||||||
|
mu.emu_start(address, address+1)
|
||||||
|
|
||||||
|
print(">>> assert eax == 3")
|
||||||
|
assert mu.reg_read(UC_X86_REG_EAX) == 3
|
||||||
|
|
||||||
|
print(">>> restore the register state")
|
||||||
|
mu.restore_regs(saved_regs)
|
||||||
|
|
||||||
|
print(">>> assert eax == 2")
|
||||||
|
assert mu.reg_read(UC_X86_REG_EAX) == 2
|
||||||
|
|
||||||
|
except UcError as e:
|
||||||
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
def test_x86_64():
|
def test_x86_64():
|
||||||
print("Emulate x86_64 code")
|
print("Emulate x86_64 code")
|
||||||
try:
|
try:
|
||||||
|
@ -479,6 +529,8 @@ if __name__ == '__main__':
|
||||||
print("=" * 20)
|
print("=" * 20)
|
||||||
test_i386_inout()
|
test_i386_inout()
|
||||||
print("=" * 20)
|
print("=" * 20)
|
||||||
|
test_i386_reg_save()
|
||||||
|
print("=" * 20)
|
||||||
test_x86_64()
|
test_x86_64()
|
||||||
print("=" * 20)
|
print("=" * 20)
|
||||||
test_x86_64_syscall()
|
test_x86_64_syscall()
|
||||||
|
|
|
@ -127,6 +127,9 @@ _setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctype
|
||||||
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t)
|
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t)
|
||||||
_setup_prototype(_uc, "uc_mem_protect", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
|
_setup_prototype(_uc, "uc_mem_protect", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
|
||||||
_setup_prototype(_uc, "uc_query", ucerr, uc_engine, ctypes.c_uint32, ctypes.POINTER(ctypes.c_size_t))
|
_setup_prototype(_uc, "uc_query", ucerr, uc_engine, ctypes.c_uint32, ctypes.POINTER(ctypes.c_size_t))
|
||||||
|
_setup_prototype(_uc, "uc_save_regstate", ctypes.c_voidp, uc_engine, ctypes.c_voidp)
|
||||||
|
_setup_prototype(_uc, "uc_restore_regstate", None, uc_engine, ctypes.c_voidp)
|
||||||
|
_setup_prototype(_uc, "free", None, ctypes.c_voidp)
|
||||||
|
|
||||||
# uc_hook_add is special due to variable number of arguments
|
# uc_hook_add is special due to variable number of arguments
|
||||||
_uc.uc_hook_add = _uc.uc_hook_add
|
_uc.uc_hook_add = _uc.uc_hook_add
|
||||||
|
@ -449,6 +452,27 @@ class Uc(object):
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
h = 0
|
h = 0
|
||||||
|
|
||||||
|
def save_regs(self, store=None):
|
||||||
|
if store is None:
|
||||||
|
ptr = ctypes.cast(0, ctypes.c_voidp)
|
||||||
|
return _ActivePointer(_uc.uc_save_regstate(self._uch, ptr))
|
||||||
|
elif type(store) is _ActivePointer:
|
||||||
|
_uc.uc_save_regstate(self._uch, store.pointer)
|
||||||
|
return store
|
||||||
|
else:
|
||||||
|
raise TypeError("Bad register store %s" % repr(store))
|
||||||
|
|
||||||
|
def restore_regs(self, store):
|
||||||
|
if type(store) is not _ActivePointer:
|
||||||
|
raise TYpeError("Bad register store %s" % repr(store))
|
||||||
|
_uc.uc_restore_regstate(self._uch, store.pointer)
|
||||||
|
|
||||||
|
class _ActivePointer(object):
|
||||||
|
def __init__(self, pointer):
|
||||||
|
self.pointer = pointer
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
_uc.free(self.pointer)
|
||||||
|
|
||||||
# print out debugging info
|
# print out debugging info
|
||||||
def debug():
|
def debug():
|
||||||
|
|
Loading…
Reference in a new issue