From 4083b870324a6256242ce266844ff6e7e5bbd7f7 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 22 Oct 2016 11:19:55 +0800 Subject: [PATCH] add new hook type UC_HOOK_MEM_READ_AFTER, adapted from PR #399 by @farmdve. updated all bindings, except Ruby & Haskell --- .../dotnet/UnicornManaged/Const/Common.fs | 2 + bindings/go/unicorn/unicorn_const.go | 2 + bindings/java/unicorn/UnicornConst.java | 2 + bindings/python/unicorn/unicorn_const.py | 2 + include/uc_priv.h | 1 + include/unicorn/unicorn.h | 57 ++++++++++++------- qemu/softmmu_template.h | 38 +++++++++++-- 7 files changed, 80 insertions(+), 24 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 899ab8b0..4fe0be48 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -73,6 +73,7 @@ module Common = let UC_MEM_WRITE_PROT = 22 let UC_MEM_READ_PROT = 23 let UC_MEM_FETCH_PROT = 24 + let UC_MEM_READ_AFTER = 25 let UC_HOOK_INTR = 1 let UC_HOOK_INSN = 2 let UC_HOOK_CODE = 4 @@ -86,6 +87,7 @@ module Common = let UC_HOOK_MEM_READ = 1024 let UC_HOOK_MEM_WRITE = 2048 let UC_HOOK_MEM_FETCH = 4096 + let UC_HOOK_MEM_READ_AFTER = 8192 let UC_HOOK_MEM_UNMAPPED = 112 let UC_HOOK_MEM_PROT = 896 let UC_HOOK_MEM_READ_INVALID = 144 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index c1a4f063..f6d2bf79 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -68,6 +68,7 @@ const ( MEM_WRITE_PROT = 22 MEM_READ_PROT = 23 MEM_FETCH_PROT = 24 + MEM_READ_AFTER = 25 HOOK_INTR = 1 HOOK_INSN = 2 HOOK_CODE = 4 @@ -81,6 +82,7 @@ const ( HOOK_MEM_READ = 1024 HOOK_MEM_WRITE = 2048 HOOK_MEM_FETCH = 4096 + HOOK_MEM_READ_AFTER = 8192 HOOK_MEM_UNMAPPED = 112 HOOK_MEM_PROT = 896 HOOK_MEM_READ_INVALID = 144 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index aec3bf9c..577ffd87 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -70,6 +70,7 @@ public interface UnicornConst { public static final int UC_MEM_WRITE_PROT = 22; public static final int UC_MEM_READ_PROT = 23; public static final int UC_MEM_FETCH_PROT = 24; + public static final int UC_MEM_READ_AFTER = 25; public static final int UC_HOOK_INTR = 1; public static final int UC_HOOK_INSN = 2; public static final int UC_HOOK_CODE = 4; @@ -83,6 +84,7 @@ public interface UnicornConst { public static final int UC_HOOK_MEM_READ = 1024; public static final int UC_HOOK_MEM_WRITE = 2048; public static final int UC_HOOK_MEM_FETCH = 4096; + public static final int UC_HOOK_MEM_READ_AFTER = 8192; public static final int UC_HOOK_MEM_UNMAPPED = 112; public static final int UC_HOOK_MEM_PROT = 896; public static final int UC_HOOK_MEM_READ_INVALID = 144; diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 34d43210..8c1c14b1 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -66,6 +66,7 @@ UC_MEM_FETCH_UNMAPPED = 21 UC_MEM_WRITE_PROT = 22 UC_MEM_READ_PROT = 23 UC_MEM_FETCH_PROT = 24 +UC_MEM_READ_AFTER = 25 UC_HOOK_INTR = 1 UC_HOOK_INSN = 2 UC_HOOK_CODE = 4 @@ -79,6 +80,7 @@ UC_HOOK_MEM_FETCH_PROT = 512 UC_HOOK_MEM_READ = 1024 UC_HOOK_MEM_WRITE = 2048 UC_HOOK_MEM_FETCH = 4096 +UC_HOOK_MEM_READ_AFTER = 8192 UC_HOOK_MEM_UNMAPPED = 112 UC_HOOK_MEM_PROT = 896 UC_HOOK_MEM_READ_INVALID = 144 diff --git a/include/uc_priv.h b/include/uc_priv.h index 30992570..df22a50c 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -105,6 +105,7 @@ enum uc_hook_idx { UC_HOOK_MEM_READ_IDX, UC_HOOK_MEM_WRITE_IDX, UC_HOOK_MEM_FETCH_IDX, + UC_HOOK_MEM_READ_AFTER_IDX, UC_HOOK_MAX, }; diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index d531c44c..65ee8ae2 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -195,38 +195,55 @@ typedef enum uc_mem_type { UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory UC_MEM_READ_PROT, // Read from read protected, but mapped, memory UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory + UC_MEM_READ_AFTER, // Memory is read from (successful access) } uc_mem_type; // All type of hooks for uc_hook_add() API. typedef enum uc_hook_type { - UC_HOOK_INTR = 1 << 0, // Hook all interrupt/syscall events - UC_HOOK_INSN = 1 << 1, // Hook a particular instruction - UC_HOOK_CODE = 1 << 2, // Hook a range of code - UC_HOOK_BLOCK = 1 << 3, // Hook basic blocks - UC_HOOK_MEM_READ_UNMAPPED = 1 << 4, // Hook for memory read on unmapped memory - UC_HOOK_MEM_WRITE_UNMAPPED = 1 << 5, // Hook for invalid memory write events - UC_HOOK_MEM_FETCH_UNMAPPED = 1 << 6, // Hook for invalid memory fetch for execution events - UC_HOOK_MEM_READ_PROT = 1 << 7, // Hook for memory read on read-protected memory - UC_HOOK_MEM_WRITE_PROT = 1 << 8, // Hook for memory write on write-protected memory - UC_HOOK_MEM_FETCH_PROT = 1 << 9, // Hook for memory fetch on non-executable memory - UC_HOOK_MEM_READ = 1 << 10, // Hook memory read events. - UC_HOOK_MEM_WRITE = 1 << 11, // Hook memory write events. - UC_HOOK_MEM_FETCH = 1 << 12, // Hook memory fetch for execution events + // Hook all interrupt/syscall events + UC_HOOK_INTR = 1 << 0, + // Hook a particular instruction + UC_HOOK_INSN = 1 << 1, + // Hook a range of code + UC_HOOK_CODE = 1 << 2, + // Hook basic blocks + UC_HOOK_BLOCK = 1 << 3, + // Hook for memory read on unmapped memory + UC_HOOK_MEM_READ_UNMAPPED = 1 << 4, + // Hook for invalid memory write events + UC_HOOK_MEM_WRITE_UNMAPPED = 1 << 5, + // Hook for invalid memory fetch for execution events + UC_HOOK_MEM_FETCH_UNMAPPED = 1 << 6, + // Hook for memory read on read-protected memory + UC_HOOK_MEM_READ_PROT = 1 << 7, + // Hook for memory write on write-protected memory + UC_HOOK_MEM_WRITE_PROT = 1 << 8, + // Hook for memory fetch on non-executable memory + UC_HOOK_MEM_FETCH_PROT = 1 << 9, + // Hook memory read events. + UC_HOOK_MEM_READ = 1 << 10, + // Hook memory write events. + UC_HOOK_MEM_WRITE = 1 << 11, + // Hook memory fetch for execution events + UC_HOOK_MEM_FETCH = 1 << 12, + // Hook memory read events, but only successful access. + // The callback will be triggered after successful read. + UC_HOOK_MEM_READ_AFTER = 1 << 13, } uc_hook_type; -// hook type for all events of unmapped memory access +// Hook type for all events of unmapped memory access #define UC_HOOK_MEM_UNMAPPED (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + UC_HOOK_MEM_FETCH_UNMAPPED) -// hook type for all events of illegal protected memory access +// Hook type for all events of illegal protected memory access #define UC_HOOK_MEM_PROT (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT) -// hook type for all events of illegal read memory access +// Hook type for all events of illegal read memory access #define UC_HOOK_MEM_READ_INVALID (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED) -// hook type for all events of illegal write memory access +// Hook type for all events of illegal write memory access #define UC_HOOK_MEM_WRITE_INVALID (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED) -// hook type for all events of illegal fetch memory access +// Hook type for all events of illegal fetch memory access #define UC_HOOK_MEM_FETCH_INVALID (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED) -// hook type for all events of illegal memory access +// Hook type for all events of illegal memory access #define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT) -// hook type for all events of valid memory access +// Hook type for all events of valid memory access #define UC_HOOK_MEM_VALID (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH) /* diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index f58065b9..1f0adefb 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -240,6 +240,10 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #endif // Unicorn: callback on memory read + // NOTE: this happens before the actual read, so we cannot tell + // the callback if read access is succesful, or not. + // See UC_HOOK_MEM_READ_AFTER & UC_MEM_READ_AFTER if you only care + // about successful read if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { if (!HOOK_BOUND_CHECK(hook, addr)) @@ -317,7 +321,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, byte ordering. We should push the LE/BE request down into io. */ res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); res = TGT_LE(res); - return res; + goto _out; } /* Handle slow unaligned access (it spans two pages or IO). */ @@ -350,7 +354,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, /* Little-endian combine. */ res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift)); - return res; + goto _out; } /* Handle aligned access or unaligned access in the same page. */ @@ -375,6 +379,17 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #else res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr); #endif + +_out: + // Unicorn: callback on successful read + if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) { + if (!HOOK_BOUND_CHECK(hook, addr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data); + } + } + return res; } @@ -452,6 +467,10 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #endif // Unicorn: callback on memory read + // NOTE: this happens before the actual read, so we cannot tell + // the callback if read access is succesful, or not. + // See UC_HOOK_MEM_READ_AFTER & UC_MEM_READ_AFTER if you only care + // about successful read if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { if (!HOOK_BOUND_CHECK(hook, addr)) @@ -528,7 +547,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, byte ordering. We should push the LE/BE request down into io. */ res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); res = TGT_BE(res); - return res; + goto _out; } /* Handle slow unaligned access (it spans two pages or IO). */ @@ -561,7 +580,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, /* Big-endian combine. */ res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift)); - return res; + goto _out; } /* Handle aligned access or unaligned access in the same page. */ @@ -582,6 +601,17 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, haddr = addr + env->tlb_table[mmu_idx][index].addend; res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr); + +_out: + // Unicorn: callback on successful read + if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) { + if (!HOOK_BOUND_CHECK(hook, addr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, DATA_SIZE, res, hook->user_data); + } + } + return res; } #endif /* DATA_SIZE > 1 */