Handle serialization of cpu context save (#1129)

* Handle the cpu context save in a more pythonic way, so the context can be serialized and reuse in an other process using the same emulator architecture and modes

* Fix type error ; mistakes a size_t uint64_t ; breaks in 32bit...

Backports commit 8987ad0fffadd16669aa3b402e7e8aaab70ad700 from qemu
This commit is contained in:
BAYET 2020-01-14 09:02:45 -05:00 committed by Lioncash
parent 221333ceaf
commit bcef414231
3 changed files with 35 additions and 17 deletions

View file

@ -138,6 +138,7 @@ _setup_prototype(_uc, "uc_context_alloc", ucerr, uc_engine, ctypes.POINTER(uc_co
_setup_prototype(_uc, "uc_free", ucerr, ctypes.c_void_p)
_setup_prototype(_uc, "uc_context_save", ucerr, uc_engine, uc_context)
_setup_prototype(_uc, "uc_context_restore", ucerr, uc_engine, uc_context)
_setup_prototype(_uc, "uc_context_size", ctypes.c_size_t, uc_engine)
_setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32))
# uc_hook_add is special due to variable number of arguments
@ -582,24 +583,23 @@ class Uc(object):
h = 0
def context_save(self):
ptr = ctypes.cast(0, ctypes.c_voidp)
status = _uc.uc_context_alloc(self._uch, ctypes.byref(ptr))
size = _uc.uc_context_size(self._uch)
context = context_factory(size)
status = _uc.uc_context_save(self._uch, ctypes.byref(context))
if status != uc.UC_ERR_OK:
raise UcError(status)
status = _uc.uc_context_save(self._uch, ptr)
if status != uc.UC_ERR_OK:
raise UcError(status)
return SavedContext(ptr)
return ctypes.string_at(ctypes.byref(context), ctypes.sizeof(context))
def context_update(self, context):
status = _uc.uc_context_save(self._uch, context.pointer)
status = _uc.uc_context_save(self._uch, context)
if status != uc.UC_ERR_OK:
raise UcError(status)
def context_restore(self, context):
status = _uc.uc_context_restore(self._uch, context.pointer)
status = _uc.uc_context_restore(self._uch, context)
if status != uc.UC_ERR_OK:
raise UcError(status)
@ -618,14 +618,15 @@ class Uc(object):
_uc.uc_free(regions)
class SavedContext(object):
def __init__(self, pointer):
self.pointer = pointer
def __del__(self):
status = _uc.uc_free(self.pointer)
if status != uc.UC_ERR_OK:
raise UcError(status)
def context_factory(size):
class SavedContext(ctypes.Structure):
_fields_ = [
('size', ctypes.c_size_t),
('data', ctypes.c_char*size)
]
ctxt = SavedContext()
ctxt.size = size
return ctxt
# print out debugging info
def debug():

View file

@ -729,6 +729,17 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context);
UNICORN_EXPORT
uc_err uc_context_restore(uc_engine *uc, uc_context *context);
/*
Return the size needed to store the cpu context. Can be used to allocate a buffer
to contain the cpu context and directly call uc_context_save.
@uc: handle returned by uc_open()
@return the size for needed to store the cpu context as as size_t.
*/
UNICORN_EXPORT
size_t uc_context_size(uc_engine *uc);
#ifdef __cplusplus
}
#endif

6
uc.c
View file

@ -1304,6 +1304,12 @@ uc_err uc_free(void *mem)
return UC_ERR_OK;
}
UNICORN_EXPORT
size_t uc_context_size(uc_engine *uc)
{
return cpu_context_size(uc->arch, uc->mode);
}
UNICORN_EXPORT
uc_err uc_context_save(uc_engine *uc, uc_context *context)
{