diff --git a/include/list.h b/include/list.h index 67734cc8..84917ab3 100644 --- a/include/list.h +++ b/include/list.h @@ -12,9 +12,19 @@ struct list { struct list_item *head, *tail; }; +// create a new list struct list *list_new(void); + +// removed linked list nodes but does not free their content 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); + +// returns true if entry was removed, false otherwise bool list_remove(struct list *list, void *data); #endif diff --git a/include/uc_priv.h b/include/uc_priv.h index 5c47fb91..22f494e4 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -244,6 +244,7 @@ struct uc_struct { uint32_t target_page_size; 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) }; // Metadata stub for the variable-size cpu context used with uc_context_*() diff --git a/list.c b/list.c index 69a66491..0703c10c 100644 --- a/list.c +++ b/list.c @@ -22,6 +22,28 @@ void list_clear(struct list *list) 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 void *list_append(struct list *list, void *data) { diff --git a/uc.c b/uc.c index 40466940..c39ea48c 100644 --- a/uc.c +++ b/uc.c @@ -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. 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); + // restore to append mode for uc_hook_add() + uc->hook_insert = 0; if (err != UC_ERR_OK) { return err; } @@ -1043,9 +1049,16 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, } } - if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) { - free(hook); - return UC_ERR_NOMEM; + 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) { + free(hook); + return UC_ERR_NOMEM; + } } hook->refs++; @@ -1056,11 +1069,20 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, if ((type >> i) & 1) { // TODO: invalid hook error? if (i < UC_HOOK_MAX) { - if (list_append(&uc->hook[i], hook) == NULL) { - if (hook->refs == 0) { - free(hook); + 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 (hook->refs == 0) { + free(hook); + } + return UC_ERR_NOMEM; } - return UC_ERR_NOMEM; } hook->refs++; }