Implement uc_context_free (#1336)
* Implement uc_context_free * Use uc_context_free for python bindings * Format code * Simplify code * Move next,context inside while loop * Add my name to CREDITS.TXT
This commit is contained in:
parent
4441394258
commit
1044403d38
@ -72,3 +72,4 @@ Philippe Antoine (Catena cyber): fuzzing
|
||||
Huitao Chen (chenhuitao) & KaiJern Lau (xwings): Cmake support
|
||||
Huitao Chen (chenhuitao) & KaiJern Lau (xwings): Python3 support for building
|
||||
Kevin Foo (chfl4gs): Travis-CI migration
|
||||
Ziqiao Kong (lazymio): Various bug fix and improvement.
|
@ -139,6 +139,7 @@ _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_context_free", ucerr, uc_context)
|
||||
_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
|
||||
@ -661,7 +662,7 @@ class UcContext:
|
||||
def __del__(self):
|
||||
# We need this property since we shouldn't free it if the object is constructed from pickled bytes.
|
||||
if self._to_free:
|
||||
_uc.uc_free(self._context)
|
||||
_uc.uc_context_free(self._context)
|
||||
|
||||
|
||||
# print out debugging info
|
||||
|
@ -250,13 +250,15 @@ struct uc_struct {
|
||||
uint32_t target_page_align;
|
||||
uint64_t next_pc; // save next PC for some special cases
|
||||
bool hook_insert; // insert new hook at begin of the hook list (append by default)
|
||||
struct list saved_contexts; // The contexts saved by this uc_struct.
|
||||
};
|
||||
|
||||
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
||||
// We also save cpu->jmp_env, so emulation can be reentrant
|
||||
struct uc_context {
|
||||
size_t context_size; // size of the real internal context structure
|
||||
unsigned int jmp_env_size; // size of cpu->jmp_env
|
||||
size_t jmp_env_size; // size of cpu->jmp_env
|
||||
struct uc_struct* uc; // the uc_struct which creates this context
|
||||
char data[0]; // context + cpu->jmp_env
|
||||
};
|
||||
|
||||
|
@ -707,10 +707,12 @@ UNICORN_EXPORT
|
||||
uc_err uc_context_alloc(uc_engine *uc, uc_context **context);
|
||||
|
||||
/*
|
||||
Free the memory allocated by uc_context_alloc & uc_mem_regions.
|
||||
Free the memory allocated by uc_mem_regions.
|
||||
WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc should
|
||||
be free-ed by uc_context_free(). Calling uc_free() may still work, but the result
|
||||
is **undefined**.
|
||||
|
||||
@mem: memory allocated by uc_context_alloc (returned in *context), or
|
||||
by uc_mem_regions (returned in *regions)
|
||||
@mem: memory allocated by uc_mem_regions (returned in *regions).
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@ -738,7 +740,7 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context);
|
||||
state saved by uc_context_save().
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@buffer: handle returned by uc_context_alloc that has been used with uc_context_save
|
||||
@context: handle returned by uc_context_alloc that has been used with uc_context_save
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@ -758,6 +760,18 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context);
|
||||
UNICORN_EXPORT
|
||||
size_t uc_context_size(uc_engine *uc);
|
||||
|
||||
|
||||
/*
|
||||
Free the context allocated by uc_context_alloc().
|
||||
|
||||
@context: handle returned by uc_context_alloc()
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_free(uc_context *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
28
uc.c
28
uc.c
@ -348,6 +348,16 @@ uc_err uc_close(uc_engine *uc)
|
||||
|
||||
free(uc->mapped_blocks);
|
||||
|
||||
// free the saved contexts list and notify them that uc has been closed.
|
||||
cur = uc->saved_contexts.head;
|
||||
while (cur != NULL) {
|
||||
struct list_item *next = cur->next;
|
||||
struct uc_context *context = (struct uc_context*)cur->data;
|
||||
context->uc = NULL;
|
||||
cur = next;
|
||||
}
|
||||
list_clear(&uc->saved_contexts);
|
||||
|
||||
// finally, free uc itself.
|
||||
memset(uc, 0, sizeof(*uc));
|
||||
free(uc);
|
||||
@ -1327,10 +1337,15 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context)
|
||||
if (*_context) {
|
||||
(*_context)->jmp_env_size = sizeof(*uc->cpu->jmp_env);
|
||||
(*_context)->context_size = cpu_context_size(uc->arch, uc->mode);
|
||||
(*_context)->uc = uc;
|
||||
if (list_insert(&uc->saved_contexts, *_context)) {
|
||||
return UC_ERR_OK;
|
||||
} else {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
} else {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
@ -1360,7 +1375,20 @@ UNICORN_EXPORT
|
||||
uc_err uc_context_restore(uc_engine *uc, uc_context *context)
|
||||
{
|
||||
memcpy(uc->cpu->env_ptr, context->data, context->context_size);
|
||||
if (list_exists(&uc->saved_contexts, context)) {
|
||||
memcpy(uc->cpu->jmp_env, context->data + context->context_size, context->jmp_env_size);
|
||||
}
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_free(uc_context *context)
|
||||
{
|
||||
uc_engine* uc = context->uc;
|
||||
// if uc is NULL, it means that uc_engine has been free-ed.
|
||||
if (uc) {
|
||||
list_remove(&uc->saved_contexts, context);
|
||||
}
|
||||
return uc_free(context);
|
||||
}
|
Loading…
Reference in New Issue
Block a user