callback to count number of instructions in uc_emu_start() should be executed first. fix #727

This commit is contained in:
Nguyen Anh Quynh 2017-06-16 13:22:38 +08:00
parent 8f2d6cd70f
commit fe466d003a
4 changed files with 62 additions and 7 deletions

View file

@ -12,9 +12,19 @@ struct list {
struct list_item *head, *tail; struct list_item *head, *tail;
}; };
// create a new list
struct list *list_new(void); struct list *list_new(void);
// removed linked list nodes but does not free their content
void list_clear(struct list *list); void list_clear(struct list *list);
// insert a new item at the begin of the list.
void *list_insert(struct list *list, void *data);
// append a new item at the end of the list.
void *list_append(struct list *list, void *data); void *list_append(struct list *list, void *data);
// returns true if entry was removed, false otherwise
bool list_remove(struct list *list, void *data); bool list_remove(struct list *list, void *data);
#endif #endif

View file

@ -244,6 +244,7 @@ struct uc_struct {
uint32_t target_page_size; uint32_t target_page_size;
uint32_t target_page_align; uint32_t target_page_align;
uint64_t next_pc; // save next PC for some special cases 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)
}; };
// Metadata stub for the variable-size cpu context used with uc_context_*() // Metadata stub for the variable-size cpu context used with uc_context_*()

22
list.c
View file

@ -22,6 +22,28 @@ void list_clear(struct list *list)
list->tail = NULL; list->tail = NULL;
} }
// insert a new item at the begin of the list.
// returns generated linked list node, or NULL on failure
void *list_insert(struct list *list, void *data)
{
struct list_item *item = malloc(sizeof(struct list_item));
if (item == NULL) {
return NULL;
}
item->data = data;
item->next = list->head;
if (list->tail == NULL) {
list->tail = item;
}
list->head = item;
return item;
}
// append a new item at the end of the list.
// returns generated linked list node, or NULL on failure // returns generated linked list node, or NULL on failure
void *list_append(struct list *list, void *data) void *list_append(struct list *list, void *data)
{ {

22
uc.c
View file

@ -594,7 +594,13 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time
} }
// set up count hook to count instructions. // set up count hook to count instructions.
if (count > 0 && uc->count_hook == 0) { if (count > 0 && uc->count_hook == 0) {
// callback to count instructions must be run before everything else,
// so instead of appending, we must insert the hook at the begin
// of the hook list
uc->hook_insert = 1;
uc_err err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL, 1, 0); uc_err err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL, 1, 0);
// restore to append mode for uc_hook_add()
uc->hook_insert = 0;
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
return err; return err;
} }
@ -1043,10 +1049,17 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
} }
} }
if (uc->hook_insert) {
if (list_insert(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) {
free(hook);
return UC_ERR_NOMEM;
}
} else {
if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) { if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) {
free(hook); free(hook);
return UC_ERR_NOMEM; return UC_ERR_NOMEM;
} }
}
hook->refs++; hook->refs++;
return UC_ERR_OK; return UC_ERR_OK;
@ -1056,12 +1069,21 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
if ((type >> i) & 1) { if ((type >> i) & 1) {
// TODO: invalid hook error? // TODO: invalid hook error?
if (i < UC_HOOK_MAX) { if (i < UC_HOOK_MAX) {
if (uc->hook_insert) {
if (list_insert(&uc->hook[i], hook) == NULL) {
if (hook->refs == 0) {
free(hook);
}
return UC_ERR_NOMEM;
}
} else {
if (list_append(&uc->hook[i], hook) == NULL) { if (list_append(&uc->hook[i], hook) == NULL) {
if (hook->refs == 0) { if (hook->refs == 0) {
free(hook); free(hook);
} }
return UC_ERR_NOMEM; return UC_ERR_NOMEM;
} }
}
hook->refs++; hook->refs++;
} }
} }