Skip to content

Commit fdd129f

Browse files
committed
Remember the regions a hook has intrumented and clear cache on deletion
1 parent 637dc8a commit fdd129f

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

include/uc_priv.h

+49
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <stdio.h>
1010

1111
#include "qemu.h"
12+
#include "qemu/xxhash.h"
1213
#include "unicorn/unicorn.h"
1314
#include "list.h"
1415

@@ -157,6 +158,7 @@ struct hook {
157158
// address (depends on hook type)
158159
void *callback; // a uc_cb_* type
159160
void *user_data;
161+
GHashTable *hooked_regions; // The regions this hook instrumented on
160162
};
161163

162164
// Add an inline hook to helper_table
@@ -414,6 +416,53 @@ static inline int uc_addr_is_exit(uc_engine *uc, uint64_t addr)
414416
}
415417
}
416418

419+
typedef struct HookedRegion {
420+
uint64_t start;
421+
uint64_t length;
422+
} HookedRegion;
423+
424+
// hooked_regions related functions
425+
static inline guint hooked_regions_hash(const void* p) {
426+
HookedRegion *region = (HookedRegion*)p;
427+
428+
return qemu_xxhash4(region->start, region->length);
429+
}
430+
431+
static inline gboolean hooked_regions_equal(const void* lhs, const void* rhs) {
432+
HookedRegion *l = (HookedRegion*)lhs;
433+
HookedRegion *r = (HookedRegion*)rhs;
434+
435+
return l->start == r->start && l->length == r->length;
436+
}
437+
438+
static inline void hooked_regions_add(struct hook* h, uint64_t start, uint64_t length) {
439+
HookedRegion tmp;
440+
tmp.start = start;
441+
tmp.length = length;
442+
443+
if (!g_hash_table_lookup(h->hooked_regions, (void*)&tmp)) {
444+
HookedRegion* r = malloc(sizeof(HookedRegion));
445+
r->start = start;
446+
r->length = length;
447+
g_hash_table_insert(h->hooked_regions, (void*)r, (void*)1);
448+
}
449+
}
450+
451+
static inline void hooked_regions_check_single(struct list_item *cur, uint64_t start, uint64_t length) {
452+
while (cur != NULL) {
453+
if (HOOK_BOUND_CHECK((struct hook *)cur->data, start)) {
454+
hooked_regions_add((struct hook *)cur->data, start, length);
455+
}
456+
cur = cur->next;
457+
}
458+
}
459+
460+
static inline void hooked_regions_check(uc_engine *uc, uint64_t start, uint64_t length) {
461+
// Only UC_HOOK_BLOCK and UC_HOOK_CODE might be wrongle cached!
462+
hooked_regions_check_single(uc->hook[UC_HOOK_CODE_IDX].head, start, length);
463+
hooked_regions_check_single(uc->hook[UC_HOOK_BLOCK_IDX].head, start, length);
464+
}
465+
417466
#ifdef UNICORN_TRACER
418467
#define UC_TRACE_START(loc) trace_start(get_tracer(), loc)
419468
#define UC_TRACE_END(loc, fmt, ...) \

qemu/accel/tcg/translator.c

+2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
147147
db->tb->size = db->pc_next - db->pc_first;
148148
db->tb->icount = db->num_insns;
149149

150+
hooked_regions_check(uc, db->tb->pc, db->tb->size);
151+
150152
if (block_hook) {
151153
TCGOp *tcg_op;
152154

uc.c

+12
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,22 @@ static void *hook_append(struct list *l, struct hook *h)
4949
return item;
5050
}
5151

52+
static void hook_invalidate_region(void* key, void* data, void* opaq)
53+
{
54+
uc_engine* uc = (uc_engine*)opaq;
55+
HookedRegion* region = (HookedRegion*)key;
56+
57+
uc->uc_invalidate_tb(uc, region->start, region->length);
58+
}
59+
5260
static void hook_delete(void *data)
5361
{
5462
struct hook *h = (struct hook *)data;
5563

5664
h->refs--;
5765

5866
if (h->refs == 0) {
67+
g_hash_table_destroy(h->hooked_regions);
5968
free(h);
6069
}
6170
}
@@ -1561,6 +1570,7 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
15611570
hook->user_data = user_data;
15621571
hook->refs = 0;
15631572
hook->to_delete = false;
1573+
hook->hooked_regions = g_hash_table_new_full(hooked_regions_hash, hooked_regions_equal, g_free, NULL);
15641574
*hh = (uc_hook)hook;
15651575

15661576
// UC_HOOK_INSN has an extra argument for instruction ID
@@ -1670,6 +1680,8 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh)
16701680
// and store the type mask in the hook pointer.
16711681
for (i = 0; i < UC_HOOK_MAX; i++) {
16721682
if (list_exists(&uc->hook[i], (void *)hook)) {
1683+
g_hash_table_foreach(hook->hooked_regions, hook_invalidate_region, uc);
1684+
g_hash_table_remove_all(hook->hooked_regions);
16731685
hook->to_delete = true;
16741686
uc->hooks_count[i]--;
16751687
hook_append(&uc->hooks_to_del, hook);

0 commit comments

Comments
 (0)