diff --git a/bindings/go/unicorn/hook.go b/bindings/go/unicorn/hook.go index c286f08f..3176df9f 100644 --- a/bindings/go/unicorn/hook.go +++ b/bindings/go/unicorn/hook.go @@ -90,7 +90,7 @@ func (u *uc) HookAdd(htype int, cb interface{}, extra ...uint64) (Hook, error) { } default: // special case for mask - if htype&(HOOK_MEM_READ_INVALID|HOOK_MEM_WRITE_INVALID|HOOK_MEM_FETCH_INVALID| + if htype&(HOOK_MEM_READ_UNMAPPED|HOOK_MEM_WRITE_UNMAPPED|HOOK_MEM_FETCH_UNMAPPED| HOOK_MEM_READ_PROT|HOOK_MEM_WRITE_PROT|HOOK_MEM_FETCH_PROT) != 0 { rangeMode = true callback = C.hookMemInvalid_cgo diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 8bd35349..5afeec46 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -39,26 +39,25 @@ const ( ERR_HANDLE = 3 ERR_MODE = 4 ERR_VERSION = 5 - ERR_READ_INVALID = 6 - ERR_WRITE_INVALID = 7 - ERR_FETCH_INVALID = 8 - ERR_CODE_INVALID = 9 - ERR_HOOK = 10 - ERR_INSN_INVALID = 11 - ERR_MAP = 12 - ERR_WRITE_PROT = 13 - ERR_READ_PROT = 14 - ERR_FETCH_PROT = 15 - ERR_ARG = 16 - ERR_READ_UNALIGNED = 17 - ERR_WRITE_UNALIGNED = 18 - ERR_FETCH_UNALIGNED = 19 + ERR_READ_UNMAPPED = 6 + ERR_WRITE_UNMAPPED = 7 + ERR_FETCH_UNMAPPED = 8 + ERR_HOOK = 9 + ERR_INSN_INVALID = 10 + ERR_MAP = 11 + ERR_WRITE_PROT = 12 + ERR_READ_PROT = 13 + ERR_FETCH_PROT = 14 + ERR_ARG = 15 + ERR_READ_UNALIGNED = 16 + ERR_WRITE_UNALIGNED = 17 + ERR_FETCH_UNALIGNED = 18 MEM_READ = 16 MEM_WRITE = 17 MEM_FETCH = 18 - MEM_READ_INVALID = 19 - MEM_WRITE_INVALID = 20 - MEM_FETCH_INVALID = 21 + MEM_READ_UNMAPPED = 19 + MEM_WRITE_UNMAPPED = 20 + MEM_FETCH_UNMAPPED = 21 MEM_WRITE_PROT = 22 MEM_READ_PROT = 23 MEM_FETCH_PROT = 24 @@ -66,9 +65,9 @@ const ( HOOK_INSN = 2 HOOK_CODE = 4 HOOK_BLOCK = 8 - HOOK_MEM_READ_INVALID = 16 - HOOK_MEM_WRITE_INVALID = 32 - HOOK_MEM_FETCH_INVALID = 64 + HOOK_MEM_READ_UNMAPPED = 16 + HOOK_MEM_WRITE_UNMAPPED = 32 + HOOK_MEM_FETCH_UNMAPPED = 64 HOOK_MEM_READ_PROT = 128 HOOK_MEM_WRITE_PROT = 256 HOOK_MEM_FETCH_PROT = 512 diff --git a/bindings/java/samples/Sample_x86.java b/bindings/java/samples/Sample_x86.java index edda0e97..91ca2698 100644 --- a/bindings/java/samples/Sample_x86.java +++ b/bindings/java/samples/Sample_x86.java @@ -419,7 +419,7 @@ public class Sample_x86 { u.hook_add(new MyCodeHook(), 1, 0, null); // intercept invalid memory events - u.hook_add(new MyWriteInvalidHook(), Unicorn.UC_HOOK_MEM_WRITE_INVALID, null); + u.hook_add(new MyWriteInvalidHook(), Unicorn.UC_HOOK_MEM_WRITE_UNMAPPED, null); // emulate machine code in infinite time try { diff --git a/bindings/java/unicorn/Unicorn.java b/bindings/java/unicorn/Unicorn.java index 9abfeb60..5a28c267 100644 --- a/bindings/java/unicorn/Unicorn.java +++ b/bindings/java/unicorn/Unicorn.java @@ -72,9 +72,9 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S //required to load native method implementations static { System.loadLibrary("unicorn_java"); //loads unicorn.dll or libunicorn.so - eventMemMap.put(UC_HOOK_MEM_READ_INVALID, UC_MEM_READ_INVALID); - eventMemMap.put(UC_HOOK_MEM_WRITE_INVALID, UC_MEM_WRITE_INVALID); - eventMemMap.put(UC_HOOK_MEM_FETCH_INVALID, UC_MEM_FETCH_INVALID); + eventMemMap.put(UC_HOOK_MEM_READ_UNMAPPED, UC_MEM_READ_UNMAPPED); + eventMemMap.put(UC_HOOK_MEM_WRITE_UNMAPPED, UC_MEM_WRITE_UNMAPPED); + eventMemMap.put(UC_HOOK_MEM_FETCH_UNMAPPED, UC_MEM_FETCH_UNMAPPED); eventMemMap.put(UC_HOOK_MEM_READ_PROT, UC_MEM_READ_PROT); eventMemMap.put(UC_HOOK_MEM_WRITE_PROT, UC_MEM_WRITE_PROT); eventMemMap.put(UC_HOOK_MEM_FETCH_PROT, UC_MEM_FETCH_PROT); @@ -140,10 +140,10 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S } /** - * Invoke all UC_HOOK_MEM_XXX_INVALID andor UC_HOOK_MEM_XXX_PROT callbacks registered + * Invoke all UC_HOOK_MEM_XXX_UNMAPPED andor UC_HOOK_MEM_XXX_PROT callbacks registered * for a specific Unicorn. * This function gets invoked from the native C callback registered for - * for UC_HOOK_MEM_XXX_INVALID or UC_HOOK_MEM_XXX_PROT + * for UC_HOOK_MEM_XXX_UNMAPPED or UC_HOOK_MEM_XXX_PROT * * @param eng A Unicorn uc_engine* eng returned by uc_open * @param type The type of event that is taking place @@ -535,12 +535,12 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S } /** - * Hook registration for UC_HOOK_MEM_XXX_INVALID and UC_HOOK_MEM_XXX_PROT hooks. + * Hook registration for UC_HOOK_MEM_XXX_UNMAPPED and UC_HOOK_MEM_XXX_PROT hooks. * The registered callback function will be invoked whenever a read or write is * attempted from an invalid or protected memory address. * * @param callback Implementation of a EventMemHook interface - * @param type Type of memory event being hooked such as UC_HOOK_MEM_READ_INVALID or UC_HOOK_MEM_WRITE_PROT + * @param type Type of memory event being hooked such as UC_HOOK_MEM_READ_UNMAPPED or UC_HOOK_MEM_WRITE_PROT * @param user_data User data to be passed to the callback function each time the event is triggered */ public void hook_add(EventMemHook callback, int type, Object user_data) throws UnicornException { diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 615a6906..7cff4e63 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -41,26 +41,25 @@ public interface UnicornConst { public static final int UC_ERR_HANDLE = 3; public static final int UC_ERR_MODE = 4; public static final int UC_ERR_VERSION = 5; - public static final int UC_ERR_READ_INVALID = 6; - public static final int UC_ERR_WRITE_INVALID = 7; - public static final int UC_ERR_FETCH_INVALID = 8; - public static final int UC_ERR_CODE_INVALID = 9; - public static final int UC_ERR_HOOK = 10; - public static final int UC_ERR_INSN_INVALID = 11; - public static final int UC_ERR_MAP = 12; - public static final int UC_ERR_WRITE_PROT = 13; - public static final int UC_ERR_READ_PROT = 14; - public static final int UC_ERR_FETCH_PROT = 15; - public static final int UC_ERR_ARG = 16; - public static final int UC_ERR_READ_UNALIGNED = 17; - public static final int UC_ERR_WRITE_UNALIGNED = 18; - public static final int UC_ERR_FETCH_UNALIGNED = 19; + public static final int UC_ERR_READ_UNMAPPED = 6; + public static final int UC_ERR_WRITE_UNMAPPED = 7; + public static final int UC_ERR_FETCH_UNMAPPED = 8; + public static final int UC_ERR_HOOK = 9; + public static final int UC_ERR_INSN_INVALID = 10; + public static final int UC_ERR_MAP = 11; + public static final int UC_ERR_WRITE_PROT = 12; + public static final int UC_ERR_READ_PROT = 13; + public static final int UC_ERR_FETCH_PROT = 14; + public static final int UC_ERR_ARG = 15; + public static final int UC_ERR_READ_UNALIGNED = 16; + public static final int UC_ERR_WRITE_UNALIGNED = 17; + public static final int UC_ERR_FETCH_UNALIGNED = 18; public static final int UC_MEM_READ = 16; public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_FETCH = 18; - public static final int UC_MEM_READ_INVALID = 19; - public static final int UC_MEM_WRITE_INVALID = 20; - public static final int UC_MEM_FETCH_INVALID = 21; + public static final int UC_MEM_READ_UNMAPPED = 19; + public static final int UC_MEM_WRITE_UNMAPPED = 20; + public static final int UC_MEM_FETCH_UNMAPPED = 21; 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; @@ -68,9 +67,9 @@ public interface UnicornConst { public static final int UC_HOOK_INSN = 2; public static final int UC_HOOK_CODE = 4; public static final int UC_HOOK_BLOCK = 8; - public static final int UC_HOOK_MEM_READ_INVALID = 16; - public static final int UC_HOOK_MEM_WRITE_INVALID = 32; - public static final int UC_HOOK_MEM_FETCH_INVALID = 64; + public static final int UC_HOOK_MEM_READ_UNMAPPED = 16; + public static final int UC_HOOK_MEM_WRITE_UNMAPPED = 32; + public static final int UC_HOOK_MEM_FETCH_UNMAPPED = 64; public static final int UC_HOOK_MEM_READ_PROT = 128; public static final int UC_HOOK_MEM_WRITE_PROT = 256; public static final int UC_HOOK_MEM_FETCH_PROT = 512; diff --git a/bindings/java/unicorn/UnicornErrors.java b/bindings/java/unicorn/UnicornErrors.java index 3d74aa3d..d3f376f5 100644 --- a/bindings/java/unicorn/UnicornErrors.java +++ b/bindings/java/unicorn/UnicornErrors.java @@ -31,9 +31,8 @@ public interface UnicornErrors { public static final int UC_ERR_VERSION = 6; // Unsupported version (bindings) public static final int UC_ERR_MEM_READ = 7; // Quit emulation due to invalid memory READ: uc_emu_start() public static final int UC_ERR_MEM_WRITE = 8; // Quit emulation due to invalid memory WRITE: uc_emu_start() - public static final int UC_ERR_CODE_INVALID = 9; // Quit emulation due to invalid code address: uc_emu_start() - public static final int UC_ERR_HOOK = 10; // Invalid hook type: uc_hook_add() - public static final int UC_ERR_INSN_INVALID = 11; // Quit emulation due to invalid instruction: uc_emu_start() - public static final int UC_ERR_MAP = 12; // Invalid memory mapping: uc_mem_map() + public static final int UC_ERR_HOOK = 9; // Invalid hook type: uc_hook_add() + public static final int UC_ERR_INSN_INVALID = 10; // Quit emulation due to invalid instruction: uc_emu_start() + public static final int UC_ERR_MAP = 11; // Invalid memory mapping: uc_mem_map() } diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c index 470c6340..a14bd9e4 100644 --- a/bindings/java/unicorn_Unicorn.c +++ b/bindings/java/unicorn_Unicorn.c @@ -160,7 +160,7 @@ static void cb_hookmem(uc_engine *eng, uc_mem_type type, (*cachedJVM)->DetachCurrentThread(cachedJVM); } -// Callback function for handling memory events (for UC_HOOK_MEM_INVALID) +// Callback function for handling memory events (for UC_HOOK_MEM_UNMAPPED) // @type: this memory is being READ, or WRITE // @address: address where the code is being executed // @size: size of data being read or written @@ -389,9 +389,9 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI } err = uc_hook_add((uc_engine*)eng, &hh, (uc_hook_type)type, cb_hookintr, env); break; - case UC_HOOK_MEM_FETCH_INVALID: // Hook for all invalid memory access events - case UC_HOOK_MEM_READ_INVALID: // Hook for all invalid memory access events - case UC_HOOK_MEM_WRITE_INVALID: // Hook for all invalid memory access events + case UC_HOOK_MEM_FETCH_UNMAPPED: // Hook for all invalid memory access events + case UC_HOOK_MEM_READ_UNMAPPED: // Hook for all invalid memory access events + case UC_HOOK_MEM_WRITE_UNMAPPED: // Hook for all invalid memory access events case UC_HOOK_MEM_FETCH_PROT: // Hook for all invalid memory access events case UC_HOOK_MEM_READ_PROT: // Hook for all invalid memory access events case UC_HOOK_MEM_WRITE_PROT: // Hook for all invalid memory access events diff --git a/bindings/python/sample_x86.py b/bindings/python/sample_x86.py index 151ed73c..f4a98b22 100755 --- a/bindings/python/sample_x86.py +++ b/bindings/python/sample_x86.py @@ -33,7 +33,7 @@ def hook_code(uc, address, size, user_data): # callback for tracing invalid memory access (READ or WRITE) def hook_mem_invalid(uc, access, address, size, value, user_data): - if access == UC_MEM_WRITE_INVALID: + if access == UC_MEM_WRITE_UNMAPPED: print(">>> Missing memory is being WRITE at 0x%x, data size = %u, data value = 0x%x" \ %(address, size, value)) # map this memory in with 2MB in size @@ -231,7 +231,7 @@ def test_i386_invalid_mem_write(): #mu.hook_add(UC_HOOK_CODE, hook_code) # intercept invalid memory events - mu.hook_add(UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID, hook_mem_invalid) + mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid) try: # emulate machine code in infinite time diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index dd67306a..d8fc62b0 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -272,8 +272,8 @@ class Uc(object): cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB) status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \ ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end) - elif htype & UC_HOOK_MEM_READ_INVALID or htype & UC_HOOK_MEM_WRITE_INVALID or \ - htype & UC_HOOK_MEM_FETCH_INVALID or htype & UC_HOOK_MEM_READ_PROT or \ + elif htype & UC_HOOK_MEM_READ_UNMAPPED or htype & UC_HOOK_MEM_WRITE_UNMAPPED or \ + htype & UC_HOOK_MEM_FETCH_UNMAPPED or htype & UC_HOOK_MEM_READ_PROT or \ htype & UC_HOOK_MEM_WRITE_PROT or htype & UC_HOOK_MEM_FETCH_PROT: cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB) status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 467cdd29..a401c83a 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -37,26 +37,25 @@ UC_ERR_ARCH = 2 UC_ERR_HANDLE = 3 UC_ERR_MODE = 4 UC_ERR_VERSION = 5 -UC_ERR_READ_INVALID = 6 -UC_ERR_WRITE_INVALID = 7 -UC_ERR_FETCH_INVALID = 8 -UC_ERR_CODE_INVALID = 9 -UC_ERR_HOOK = 10 -UC_ERR_INSN_INVALID = 11 -UC_ERR_MAP = 12 -UC_ERR_WRITE_PROT = 13 -UC_ERR_READ_PROT = 14 -UC_ERR_FETCH_PROT = 15 -UC_ERR_ARG = 16 -UC_ERR_READ_UNALIGNED = 17 -UC_ERR_WRITE_UNALIGNED = 18 -UC_ERR_FETCH_UNALIGNED = 19 +UC_ERR_READ_UNMAPPED = 6 +UC_ERR_WRITE_UNMAPPED = 7 +UC_ERR_FETCH_UNMAPPED = 8 +UC_ERR_HOOK = 9 +UC_ERR_INSN_INVALID = 10 +UC_ERR_MAP = 11 +UC_ERR_WRITE_PROT = 12 +UC_ERR_READ_PROT = 13 +UC_ERR_FETCH_PROT = 14 +UC_ERR_ARG = 15 +UC_ERR_READ_UNALIGNED = 16 +UC_ERR_WRITE_UNALIGNED = 17 +UC_ERR_FETCH_UNALIGNED = 18 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 -UC_MEM_READ_INVALID = 19 -UC_MEM_WRITE_INVALID = 20 -UC_MEM_FETCH_INVALID = 21 +UC_MEM_READ_UNMAPPED = 19 +UC_MEM_WRITE_UNMAPPED = 20 +UC_MEM_FETCH_UNMAPPED = 21 UC_MEM_WRITE_PROT = 22 UC_MEM_READ_PROT = 23 UC_MEM_FETCH_PROT = 24 @@ -64,9 +63,9 @@ UC_HOOK_INTR = 1 UC_HOOK_INSN = 2 UC_HOOK_CODE = 4 UC_HOOK_BLOCK = 8 -UC_HOOK_MEM_READ_INVALID = 16 -UC_HOOK_MEM_WRITE_INVALID = 32 -UC_HOOK_MEM_FETCH_INVALID = 64 +UC_HOOK_MEM_READ_UNMAPPED = 16 +UC_HOOK_MEM_WRITE_UNMAPPED = 32 +UC_HOOK_MEM_FETCH_UNMAPPED = 64 UC_HOOK_MEM_READ_PROT = 128 UC_HOOK_MEM_WRITE_PROT = 256 UC_HOOK_MEM_FETCH_PROT = 512 diff --git a/include/uc_priv.h b/include/uc_priv.h index 1f19a58a..de2e457f 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -185,6 +185,7 @@ struct uc_struct { void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c) uint32_t target_page_size; uint32_t target_page_align; + uint64_t next_pc; // save next PC for some special cases }; #include "qemu_macro.h" diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 75f47064..bc4edd40 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -111,10 +111,9 @@ typedef enum uc_err { UC_ERR_HANDLE, // Invalid handle UC_ERR_MODE, // Invalid/unsupported mode: uc_open() UC_ERR_VERSION, // Unsupported version (bindings) - UC_ERR_READ_INVALID, // Quit emulation due to invalid memory READ: uc_emu_start() - UC_ERR_WRITE_INVALID, // Quit emulation due to invalid memory WRITE: uc_emu_start() - UC_ERR_FETCH_INVALID, // Quit emulation due to invalid memory FETCH: uc_emu_start() - UC_ERR_CODE_INVALID, // Quit emulation due to invalid code address: uc_emu_start() + UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: uc_emu_start() + UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: uc_emu_start() + UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: uc_emu_start() UC_ERR_HOOK, // Invalid hook type: uc_hook_add() UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start() UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() @@ -156,9 +155,9 @@ typedef enum uc_mem_type { UC_MEM_READ = 16, // Memory is read from UC_MEM_WRITE, // Memory is written to UC_MEM_FETCH, // Memory is fetched - UC_MEM_READ_INVALID, // Unmapped memory is read from - UC_MEM_WRITE_INVALID, // Unmapped memory is written to - UC_MEM_FETCH_INVALID, // Unmapped memory is fetched + UC_MEM_READ_UNMAPPED, // Unmapped memory is read from + UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to + UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched 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 @@ -166,13 +165,13 @@ typedef enum 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 events + 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_INVALID = 1 << 4, // Hook for invalid memory read events - UC_HOOK_MEM_WRITE_INVALID = 1 << 5, // Hook for invalid memory write events - UC_HOOK_MEM_FETCH_INVALID = 1 << 6, // Hook for invalid memory fetch for execution events + 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 @@ -182,17 +181,17 @@ typedef enum uc_hook_type { } uc_hook_type; // hook type for all events of unmapped memory access -#define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_READ_INVALID + UC_HOOK_MEM_WRITE_INVALID + UC_HOOK_MEM_FETCH_INVALID) +#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 #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 -#define UC_HOOK_MEM_READ_ERR (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_INVALID) +#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 -#define UC_HOOK_MEM_WRITE_ERR (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_INVALID) +#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 -#define UC_HOOK_MEM_FETCH_ERR (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_INVALID) +#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 -#define UC_HOOK_MEM_ERR (UC_HOOK_MEM_INVALID + UC_HOOK_MEM_PROT) +#define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT) // Callback function for hooking memory (UC_MEM_READ, UC_MEM_WRITE & UC_MEM_FETCH) // @type: this memory is being READ, or WRITE @@ -203,7 +202,7 @@ typedef enum uc_hook_type { typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data); -// Callback function for handling invalid memory access events (UC_MEM_*_INVALID and +// Callback function for handling invalid memory access events (UC_MEM_*_UNMAPPED and // UC_MEM_*PROT events) // @type: this memory is being READ, or WRITE // @address: address where the code is being executed diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 77de1644..b888e1cd 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_AARCH64_H #define UNICORN_AUTOGEN_AARCH64_H +#define helper_power_down helper_power_down_aarch64 #define check_exit_request check_exit_request_aarch64 #define address_space_unregister address_space_unregister_aarch64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index 3d405fac..5f70b6bf 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_ARM_H #define UNICORN_AUTOGEN_ARM_H +#define helper_power_down helper_power_down_arm #define check_exit_request check_exit_request_arm #define address_space_unregister address_space_unregister_arm #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_arm diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index c83485c3..b74e8e87 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -108,18 +108,6 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq break; } - if ((uc->arch == UC_ARCH_X86 && cpu->exception_index == 0x99) || // X86's Int 0x99 - (uc->arch == UC_ARCH_ARM && cpu->exception_index == 2) || /* ARM's EXCP_SWI */ - (uc->arch == UC_ARCH_ARM64 && cpu->exception_index == 2) || /* ARM's EXCP_SWI */ - (uc->arch == UC_ARCH_MIPS && cpu->exception_index == 17) || /* Mips's EXCP_SYSCALL */ - (uc->arch == UC_ARCH_SPARC && cpu->exception_index == 0x80) || /* Sparc's TT_TRAP */ - (uc->arch == UC_ARCH_SPARC && cpu->exception_index == 0x100) || /* Sparc64's TT_TRAP */ - (uc->arch == UC_ARCH_M68K && cpu->exception_index == 0x2f) /* M68K's EXCP_TRAP15 */ - ) { - cpu->halted = 1; - ret = EXCP_HLT; - break; - } if (cpu->exception_index >= EXCP_INTERRUPT) { /* exit request from the cpu execution loop */ ret = cpu->exception_index; @@ -148,6 +136,9 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq // point EIP to the next instruction after INT env->eip = env->exception_next_eip; #endif +#if defined(TARGET_MIPS) || defined(TARGET_MIPS64) + env->active_tc.PC = uc->next_pc; +#endif #endif } } @@ -209,7 +200,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq have_tb_lock = true; tb = tb_find_fast(env); // qq if (!tb) { // invalid TB due to invalid code? - uc->invalid_error = UC_ERR_CODE_INVALID; + uc->invalid_error = UC_ERR_FETCH_UNMAPPED; ret = EXCP_HLT; break; } diff --git a/qemu/cputlb.c b/qemu/cputlb.c index b9b16e30..468219ae 100644 --- a/qemu/cputlb.c +++ b/qemu/cputlb.c @@ -39,7 +39,7 @@ static void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr); static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe); -static ram_addr_t qemu_ram_addr_from_host_nofail(struct uc_struct *uc, void *ptr); +static bool qemu_ram_addr_from_host_nofail(struct uc_struct *uc, void *ptr, ram_addr_t *addr); static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr, target_ulong size); static void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr); @@ -292,6 +292,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) int mmu_idx, page_index, pd; void *p; MemoryRegion *mr; + ram_addr_t ram_addr; CPUState *cpu = ENV_GET_CPU(env1); page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); @@ -301,7 +302,6 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) cpu_ldub_code(env1, addr); //check for NX related error from softmmu if (env1->invalid_error == UC_ERR_FETCH_PROT) { - env1->invalid_error = UC_ERR_CODE_INVALID; return -1; } } @@ -316,23 +316,27 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) //cpu_abort(cpu, "Trying to execute code outside RAM or ROM at 0x" // TARGET_FMT_lx "\n", addr); // qq env1->invalid_addr = addr; - env1->invalid_error = UC_ERR_CODE_INVALID; - return -1; // qq FIXME + env1->invalid_error = UC_ERR_FETCH_UNMAPPED; + return -1; } } p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend); - return qemu_ram_addr_from_host_nofail(cpu->uc, p); + if (!qemu_ram_addr_from_host_nofail(cpu->uc, p, &ram_addr)) { + env1->invalid_addr = addr; + env1->invalid_error = UC_ERR_FETCH_UNMAPPED; + return -1; + } else + return ram_addr; } -static ram_addr_t qemu_ram_addr_from_host_nofail(struct uc_struct *uc, void *ptr) +static bool qemu_ram_addr_from_host_nofail(struct uc_struct *uc, void *ptr, ram_addr_t *ram_addr) { - ram_addr_t ram_addr; - - if (qemu_ram_addr_from_host(uc, ptr, &ram_addr) == NULL) { - fprintf(stderr, "Bad ram pointer %p\n", ptr); - abort(); + if (qemu_ram_addr_from_host(uc, ptr, ram_addr) == NULL) { + // fprintf(stderr, "Bad ram pointer %p\n", ptr); + return false; } - return ram_addr; + + return true; } static void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 67982502..c5133381 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -7,6 +7,7 @@ import sys symbols = ( + 'helper_power_down', 'check_exit_request', 'address_space_unregister', 'tb_invalidate_phys_page_fast', diff --git a/qemu/include/sysemu/os-win32.h b/qemu/include/sysemu/os-win32.h index b683d767..3049cd6a 100644 --- a/qemu/include/sysemu/os-win32.h +++ b/qemu/include/sysemu/os-win32.h @@ -28,6 +28,7 @@ #include #include +#include /* Workaround for older versions of MinGW. */ #ifndef ECONNREFUSED diff --git a/qemu/m68k.h b/qemu/m68k.h index 4be757ba..8a344cbb 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_M68K_H #define UNICORN_AUTOGEN_M68K_H +#define helper_power_down helper_power_down_m68k #define check_exit_request check_exit_request_m68k #define address_space_unregister address_space_unregister_m68k #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 7a3e308a..21258098 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS_H #define UNICORN_AUTOGEN_MIPS_H +#define helper_power_down helper_power_down_mips #define check_exit_request check_exit_request_mips #define address_space_unregister address_space_unregister_mips #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9870cb15..d6863cc3 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64_H #define UNICORN_AUTOGEN_MIPS64_H +#define helper_power_down helper_power_down_mips64 #define check_exit_request check_exit_request_mips64 #define address_space_unregister address_space_unregister_mips64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 5fde9e53..07118619 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64EL_H #define UNICORN_AUTOGEN_MIPS64EL_H +#define helper_power_down helper_power_down_mips64el #define check_exit_request check_exit_request_mips64el #define address_space_unregister address_space_unregister_mips64el #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index caf1fe4d..901fb181 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPSEL_H #define UNICORN_AUTOGEN_MIPSEL_H +#define helper_power_down helper_power_down_mipsel #define check_exit_request check_exit_request_mipsel #define address_space_unregister address_space_unregister_mipsel #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 92e614e1..35bf7578 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_POWERPC_H #define UNICORN_AUTOGEN_POWERPC_H +#define helper_power_down helper_power_down_powerpc #define check_exit_request check_exit_request_powerpc #define address_space_unregister address_space_unregister_powerpc #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_powerpc diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index 9730c840..2818bde0 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -185,14 +185,14 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // memory can be unmapped while reading or fetching if (mr == NULL) { #if defined(SOFTMMU_CODE_ACCESS) - error_code = UC_ERR_FETCH_INVALID; + error_code = UC_ERR_FETCH_UNMAPPED; if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)( - uc, UC_MEM_FETCH_INVALID, addr, DATA_SIZE, 0, + uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) { #else - error_code = UC_ERR_READ_INVALID; + error_code = UC_ERR_READ_UNMAPPED; if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)( - uc, UC_MEM_READ_INVALID, addr, DATA_SIZE, 0, + uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) { #endif env->invalid_error = UC_ERR_OK; @@ -284,7 +284,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, ioaddr = env->iotlb[mmu_idx][index]; if (ioaddr == 0) { env->invalid_addr = addr; - env->invalid_error = UC_ERR_READ_INVALID; + env->invalid_error = UC_ERR_READ_UNMAPPED; // printf("Invalid memory read at " TARGET_FMT_lx "\n", addr); cpu_exit(env->uc->current_cpu); return 0; @@ -376,14 +376,14 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // memory can be unmapped while reading or fetching if (mr == NULL) { #if defined(SOFTMMU_CODE_ACCESS) - error_code = UC_ERR_FETCH_INVALID; + error_code = UC_ERR_FETCH_UNMAPPED; if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)( - uc, UC_MEM_FETCH_INVALID, addr, DATA_SIZE, 0, + uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) { #else - error_code = UC_ERR_READ_INVALID; + error_code = UC_ERR_READ_UNMAPPED; if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)( - uc, UC_MEM_READ_INVALID, addr, DATA_SIZE, 0, + uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) { #endif env->invalid_error = UC_ERR_OK; @@ -475,7 +475,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, if (ioaddr == 0) { env->invalid_addr = addr; - env->invalid_error = UC_ERR_READ_INVALID; + env->invalid_error = UC_ERR_READ_UNMAPPED; // printf("Invalid memory read at " TARGET_FMT_lx "\n", addr); cpu_exit(env->uc->current_cpu); return 0; @@ -612,11 +612,11 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on invalid memory if (uc->hook_mem_write_idx && mr == NULL) { if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)( - uc, UC_MEM_WRITE_INVALID, addr, DATA_SIZE, (int64_t)val, + uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, (int64_t)val, uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) { // save error & quit env->invalid_addr = addr; - env->invalid_error = UC_ERR_WRITE_INVALID; + env->invalid_error = UC_ERR_WRITE_UNMAPPED; // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->current_cpu); return; @@ -673,7 +673,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, ioaddr = env->iotlb[mmu_idx][index]; if (ioaddr == 0) { env->invalid_addr = addr; - env->invalid_error = UC_ERR_WRITE_INVALID; + env->invalid_error = UC_ERR_WRITE_UNMAPPED; // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); cpu_exit(env->uc->current_cpu); return; @@ -759,11 +759,11 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on invalid memory if (uc->hook_mem_write_idx && mr == NULL) { if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)( - uc, UC_MEM_WRITE_INVALID, addr, DATA_SIZE, (int64_t)val, + uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, (int64_t)val, uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) { // save error & quit env->invalid_addr = addr; - env->invalid_error = UC_ERR_WRITE_INVALID; + env->invalid_error = UC_ERR_WRITE_UNMAPPED; // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->current_cpu); return; @@ -820,7 +820,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, ioaddr = env->iotlb[mmu_idx][index]; if (ioaddr == 0) { env->invalid_addr = addr; - env->invalid_error = UC_ERR_WRITE_INVALID; + env->invalid_error = UC_ERR_WRITE_UNMAPPED; // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); cpu_exit(env->uc->current_cpu); return; diff --git a/qemu/sparc.h b/qemu/sparc.h index 6aa47aa5..82bab3a2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC_H #define UNICORN_AUTOGEN_SPARC_H +#define helper_power_down helper_power_down_sparc #define check_exit_request check_exit_request_sparc #define address_space_unregister address_space_unregister_sparc #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 6d3d2a1d..ac1b66e6 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC64_H #define UNICORN_AUTOGEN_SPARC64_H +#define helper_power_down helper_power_down_sparc64 #define check_exit_request check_exit_request_sparc64 #define address_space_unregister address_space_unregister_sparc64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_sparc64 diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index d081fc49..8e267f98 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -10974,7 +10974,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_exception_insn(s, 0, EXCP_SWI, 0); + // imitate WFI instruction to halt emulation + s->is_jmp = DISAS_WFI; return; } @@ -11107,8 +11108,9 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { + // imitate WFI instruction to halt emulation gen_tb_start(tcg_ctx); - gen_exception_insn(dc, 0, EXCP_SWI, 0); + dc->is_jmp = DISAS_WFI; goto done_generating; } diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 8875b641..83f8ec02 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -10396,7 +10396,8 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_exception_insn(s, 0, EXCP_SWI, 0); + // imitate WFI instruction to halt emulation + s->is_jmp = DISAS_WFI; return; } @@ -11230,9 +11231,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { + // imitate WFI instruction to halt emulation gen_tb_start(tcg_ctx); - gen_exception_insn(dc, 0, EXCP_SWI, 0); - goto done_generating; + dc->is_jmp = DISAS_WFI; + goto tb_end; } // Unicorn: trace this block on request @@ -11289,6 +11291,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, store_cpu_field(tcg_ctx, tmp, condexec_bits); } do { + //printf(">>> arm pc = %x\n", dc->pc); #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ if (dc->pc >= 0xffff0000) { @@ -11370,7 +11373,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // end address tells us to stop emulation if (dc->pc == dc->uc->addr_end) { - gen_exception_insn(dc, 0, EXCP_SWI, 0); + // imitate WFI instruction to halt emulation + dc->is_jmp = DISAS_WFI; } else { insn = arm_ldl_code(env, dc->pc, dc->bswap_code); dc->pc += 4; @@ -11413,6 +11417,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, block_full = true; } +tb_end: + /* At this stage dc->condjmp will only be set when the skipped instruction was a conditional branch or trap, and the PC has already been written. */ diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 84db6114..a920689c 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -4751,7 +4751,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, // end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_interrupt(s, 0x99, pc_start - s->cs_base, pc_start - s->cs_base); + // imitate the HLT instruction + gen_update_cc_op(s); + gen_jmp_im(s, pc_start - s->cs_base); + gen_helper_hlt(tcg_ctx, cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start)); + s->is_jmp = DISAS_TB_JUMP; return s->pc; } @@ -8361,8 +8365,11 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, // early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { + // imitate the HLT instruction gen_tb_start(tcg_ctx); - gen_interrupt(dc, 0x99, tb->pc - tb->cs_base, tb->pc - tb->cs_base); + gen_jmp_im(dc, tb->pc - tb->cs_base); + gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, 0)); + dc->is_jmp = DISAS_TB_JUMP; goto done_generating; } diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index fedffecc..109c7f1f 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3038,7 +3038,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { - gen_exception(s, s->pc, EXCP_TRAP15); + gen_exception(s, s->pc, EXCP_HLT); return; } @@ -3104,7 +3104,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { gen_tb_start(tcg_ctx); - gen_exception(dc, dc->pc, EXCP_TRAP15); + gen_exception(dc, dc->pc, EXCP_HLT); goto done_generating; } diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index e1ff51a7..c1941505 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -11322,7 +11322,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) return 4; } -static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) +static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool is_bc_slot) { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; @@ -11343,7 +11343,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) n_bytes = 2; // Unicorn: trace this instruction on request - if (!is_slot && env->uc->hook_insn) { + if (!is_bc_slot && env->uc->hook_insn) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); if (trace) gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); @@ -13928,7 +13928,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, } } -static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) +static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool is_bc_slot) { TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; @@ -13943,7 +13943,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int is_sl } // Unicorn: trace this instruction on request - if (!is_slot && env->uc->hook_insn) { + if (!is_bc_slot && env->uc->hook_insn) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); if (trace) gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); @@ -18503,7 +18503,7 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) } } -static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) +static void decode_opc (CPUMIPSState *env, DisasContext *ctx, bool is_bc_slot) { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; #if defined(TARGET_MIPS64) @@ -18523,7 +18523,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) } // Unicorn: trace this instruction on request - if (!is_slot && env->uc->hook_insn) { + if (!is_bc_slot && env->uc->hook_insn) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); if (trace) gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); @@ -19171,6 +19171,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, int max_insns; int insn_bytes; int is_slot = 0; + bool is_bc_slot = false; TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGArg *save_opparam_ptr = NULL; bool block_full = false; @@ -19211,7 +19212,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: early check to see if the address of this block is the until address if (tb->pc == env->uc->addr_end) { gen_tb_start(tcg_ctx); - generate_exception(&ctx, EXCP_SYSCALL); + gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); + ctx.bstate = BS_EXCP; goto done_generating; } @@ -19229,6 +19231,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, gen_tb_start(tcg_ctx); while (ctx.bstate == BS_NONE) { + // printf(">>> mips pc = %x\n", ctx.pc); if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { if (bp->pc == ctx.pc) { @@ -19261,7 +19264,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: end address tells us to stop emulation if (ctx.pc == ctx.uc->addr_end) { - generate_exception(&ctx, EXCP_SYSCALL); + gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); + ctx.bstate = BS_EXCP; break; } else { // Unicorn: save param buffer @@ -19269,16 +19273,18 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, save_opparam_ptr = tcg_ctx->gen_opparam_ptr; is_slot = ctx.hflags & MIPS_HFLAG_BMASK; + is_bc_slot = (is_slot & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BC; + if (!(ctx.hflags & MIPS_HFLAG_M16)) { ctx.opcode = cpu_ldl_code(env, ctx.pc); insn_bytes = 4; - decode_opc(env, &ctx, is_slot); + decode_opc(env, &ctx, is_bc_slot); } else if (ctx.insn_flags & ASE_MICROMIPS) { ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_micromips_opc(env, &ctx, is_slot); + insn_bytes = decode_micromips_opc(env, &ctx, is_bc_slot); } else if (ctx.insn_flags & ASE_MIPS16) { ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_mips16_opc(env, &ctx, is_slot); + insn_bytes = decode_mips16_opc(env, &ctx, is_bc_slot); } else { generate_exception(&ctx, EXCP_RI); ctx.bstate = BS_STOP; @@ -19286,18 +19292,19 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, } // Unicorn: patch the callback for the instruction size - if (env->uc->hook_insn) + if (!is_bc_slot && env->uc->hook_insn) *(save_opparam_ptr + 1) = insn_bytes; } if (ctx.hflags & MIPS_HFLAG_BMASK) { if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 | - MIPS_HFLAG_FBNSLOT))) { + MIPS_HFLAG_FBNSLOT))) { /* force to generate branch as there is neither delay nor forbidden slot */ is_slot = 1; } } + if (is_slot) { gen_branch(&ctx, insn_bytes); } @@ -19341,6 +19348,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, switch (ctx.bstate) { case BS_STOP: gen_goto_tb(&ctx, 0, ctx.pc); + env->uc->next_pc = ctx.pc; break; case BS_NONE: save_cpu_state(&ctx, 0); diff --git a/qemu/target-sparc/helper.c b/qemu/target-sparc/helper.c index 98a80fe5..8f60d0ae 100644 --- a/qemu/target-sparc/helper.c +++ b/qemu/target-sparc/helper.c @@ -241,7 +241,7 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1, helper_raise_exception(env, TT_TOVF); } -#ifndef TARGET_SPARC64 +//#ifndef TARGET_SPARC64 void helper_power_down(CPUSPARCState *env) { CPUState *cs = CPU(sparc_env_get_cpu(env)); @@ -252,4 +252,4 @@ void helper_power_down(CPUSPARCState *env) env->npc = env->pc + 4; cpu_loop_exit(cs); } -#endif +//#endif diff --git a/qemu/target-sparc/helper.h b/qemu/target-sparc/helper.h index 14c8a335..2557dd08 100644 --- a/qemu/target-sparc/helper.h +++ b/qemu/target-sparc/helper.h @@ -1,10 +1,10 @@ DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_1(power_down, void, env) #ifndef TARGET_SPARC64 DEF_HELPER_1(rett, void, env) DEF_HELPER_2(wrpsr, void, env, tl) DEF_HELPER_1(rdpsr, tl, env) -DEF_HELPER_1(power_down, void, env) #else DEF_HELPER_2(wrpil, void, env, tl) DEF_HELPER_2(wrpstate, void, env, tl) diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index 8d38522a..f076633e 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -5419,6 +5419,14 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, if (max_insns == 0) max_insns = CF_COUNT_MASK; + // Unicorn: early check to see if the address of this block is the until address + if (tb->pc == env->uc->addr_end) { + gen_tb_start(tcg_ctx); + save_state(dc); + gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); + goto done_generating; + } + // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache @@ -5462,7 +5470,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, // gen_io_start(); // Unicorn: end address tells us to stop emulation if (dc->pc == dc->uc->addr_end) { - insn = 0x91d02000; // generate TRAP to end this TB + save_state(dc); + gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); + break; } else { last_pc = dc->pc; insn = cpu_ldl_code(env, dc->pc); @@ -5511,6 +5521,8 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tcg_gen_exit_tb(tcg_ctx, 0); } } + +done_generating: gen_tb_end(tcg_ctx, tb, num_insns); *tcg_ctx->gen_opc_ptr = INDEX_op_end; if (spc) { diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 53460c63..381fde94 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -2586,8 +2586,13 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf) // qq } #endif + //printf("====== before gen code\n"); + //tcg_dump_ops(s); tcg_gen_code_common(s, gen_code_buf, -1); // qq + //printf("====== after gen code\n"); + //tcg_dump_ops(s); + /* flush instruction cache */ flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); diff --git a/qemu/x86_64.h b/qemu/x86_64.h index ac9f34f0..9c133773 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_X86_64_H #define UNICORN_AUTOGEN_X86_64_H +#define helper_power_down helper_power_down_x86_64 #define check_exit_request check_exit_request_x86_64 #define address_space_unregister address_space_unregister_x86_64 #define tb_invalidate_phys_page_fast tb_invalidate_phys_page_fast_x86_64 diff --git a/samples/mem_apis.c b/samples/mem_apis.c index 28f2b60c..db0240d8 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -79,10 +79,10 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, default: printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr); return false; - case UC_MEM_READ_INVALID: + case UC_MEM_READ_UNMAPPED: printf("not ok - Read from invalid memory at 0x%"PRIx64 ", data size = %u\n", addr, size); return false; - case UC_MEM_WRITE_INVALID: + case UC_MEM_WRITE_UNMAPPED: printf("not ok - Write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); return false; case UC_MEM_FETCH_PROT: @@ -147,7 +147,7 @@ static void do_nx_demo(bool cause_fault) // intercept code and invalid memory events if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, UC_HOOK_MEM_ERR, + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; @@ -228,7 +228,7 @@ static void do_perms_demo(bool change_perms) // intercept code and invalid memory events if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || uc_hook_add(uc, &trace1, - UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_FETCH_INVALID | UC_HOOK_MEM_FETCH_PROT | UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_READ_PROT, + UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; @@ -306,7 +306,7 @@ static void do_unmap_demo(bool do_unmap) // intercept code and invalid memory events if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || uc_hook_add(uc, &trace1, - UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_FETCH_INVALID | UC_HOOK_MEM_FETCH_PROT | UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_READ_PROT, + UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 3f253ff1..45c185a5 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -59,8 +59,8 @@ static void test_sparc(void) // tracing all basic blocks with customized callback uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); - // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + // tracing all instructions with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. diff --git a/samples/sample_x86.c b/samples/sample_x86.c index f2a28916..49118e42 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -73,7 +73,7 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, default: // return false to indicate we want to stop emulation return false; - case UC_MEM_WRITE_INVALID: + case UC_MEM_WRITE_UNMAPPED: printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", address, size, value); // map this memory in with 2MB in size @@ -421,7 +421,7 @@ static void test_i386_invalid_mem_write(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); // intercept invalid memory events - uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID, hook_mem_invalid, NULL); + uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0); diff --git a/tests/regress/arm_bxeq_hang.py b/tests/regress/arm_bxeq_hang.py index 12f4a2ae..5040d725 100755 --- a/tests/regress/arm_bxeq_hang.py +++ b/tests/regress/arm_bxeq_hang.py @@ -10,8 +10,9 @@ class BxHang(regress.RegressTest): def runTest(self): uc = Uc(UC_ARCH_ARM, UC_MODE_ARM) uc.mem_map(0x1000, 0x1000) - uc.mem_write(0x1000, '1eff2f010000a0e1'.decode('hex')) + uc.mem_write(0x1000, '1eff2f010000a0e1'.decode('hex')) # bxeq lr; mov r0, r0 uc.count = 0 + def hook_block(uc, addr, *args): print 'enter block 0x%04x' % addr uc.count += 1 diff --git a/tests/regress/bad_ram.py b/tests/regress/bad_ram.py new file mode 100755 index 00000000..a74fa495 --- /dev/null +++ b/tests/regress/bad_ram.py @@ -0,0 +1,30 @@ +#!/usr/bin/python + +from unicorn import * +from unicorn.x86_const import * + +import regress + + +class Hang(regress.RegressTest): + + def runTest(self): + PAGE_SIZE = 0x5000 + CODE_ADDR = 0x400000 + RSP_ADDR = 0x200000 + binary1 = "\xCA\x24\x5D" # retf 0x5d24 + mu = Uc(UC_ARCH_X86, UC_MODE_64) + + mu.mem_map(CODE_ADDR, PAGE_SIZE) + mu.mem_map(RSP_ADDR, PAGE_SIZE) + + mu.mem_write(CODE_ADDR, binary1) + mu.reg_write(UC_X86_REG_RSP, RSP_ADDR) + try: + self.assertEqual(mu.emu_start(CODE_ADDR, CODE_ADDR + PAGE_SIZE, 0), UC_ERR_FETCH_INVALID) + except UcError as e: + print("ERROR: %s" % e) + + +if __name__ == '__main__': + regress.main() diff --git a/tests/regress/ensure_typedef_consts_generated.py b/tests/regress/ensure_typedef_consts_generated.py new file mode 100644 index 00000000..186cbc49 --- /dev/null +++ b/tests/regress/ensure_typedef_consts_generated.py @@ -0,0 +1,13 @@ +"""See https://github.com/unicorn-engine/unicorn/issues/161 + +Ensure that constants which are specified via a typedef, rather than an enum, +are included in the bindings by the script for autogenerating mappings for +constants. +""" + +import unicorn + +try: + unicorn.UC_HOOK_MEM_UNMAPPED +except AttributeError: + assert(False and "Definition for UC_HOOK_MEM_UNMAPPED not generated") diff --git a/tests/regress/jmp_ebx_hang.py b/tests/regress/jmp_ebx_hang.py index 602c594f..221765d9 100755 --- a/tests/regress/jmp_ebx_hang.py +++ b/tests/regress/jmp_ebx_hang.py @@ -22,7 +22,7 @@ class JumEbxHang(regress.RegressTest): with self.assertRaises(UcError) as m: mu.emu_start(CODE_ADDR, CODE_ADDR + 2, count=1) - self.assertEqual(m.exception.errno, unicorn.UC_ERR_CODE_INVALID) + self.assertEqual(m.exception.errno, unicorn.UC_ERR_FETCH_UNMAPPED) print(">>> jmp ebx (ebx = 0xaa96a47f)"); mu = unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_32) @@ -33,7 +33,7 @@ class JumEbxHang(regress.RegressTest): with self.assertRaises(UcError) as m: mu.emu_start(CODE_ADDR, CODE_ADDR + 2, count=1) - self.assertEqual(m.exception.errno, unicorn.UC_ERR_CODE_INVALID) + self.assertEqual(m.exception.errno, unicorn.UC_ERR_FETCH_UNMAPPED) if __name__ == '__main__': regress.main() diff --git a/tests/regress/mem_unmap.c b/tests/regress/mem_unmap.c index 06223bfa..98e209f0 100644 --- a/tests/regress/mem_unmap.c +++ b/tests/regress/mem_unmap.c @@ -224,7 +224,7 @@ int main(int argc, char **argv, char **envp) } // intercept invalid memory events - if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL) != UC_ERR_OK) { printf("not ok %d - Failed to install memory invalid handler\n", log_num++); return 7; } else { diff --git a/tests/regress/mips_except.py b/tests/regress/mips_except.py index 23969e9e..b400efe6 100755 --- a/tests/regress/mips_except.py +++ b/tests/regress/mips_except.py @@ -28,13 +28,13 @@ class MipsExcept(regress.RegressTest): uc.reg_write(UC_MIPS_REG_SP, 0xFFFFFFF0) uc.emu_start(CODE, CODE + len(asm), 200) - self.assertEqual(UC_ERR_READ_INVALID, m.exception.errno) + self.assertEqual(UC_ERR_READ_UNMAPPED, m.exception.errno) with self.assertRaises(UcError) as m: uc.reg_write(UC_MIPS_REG_SP, 0x80000000) uc.emu_start(CODE, CODE + len(asm), 100) - self.assertEqual(UC_ERR_READ_INVALID, m.exception.errno) + self.assertEqual(UC_ERR_READ_UNMAPPED, m.exception.errno) if __name__ == '__main__': regress.main() diff --git a/tests/regress/mips_single_step_sp.py b/tests/regress/mips_single_step_sp.py new file mode 100755 index 00000000..b3c78400 --- /dev/null +++ b/tests/regress/mips_single_step_sp.py @@ -0,0 +1,51 @@ +#!/usr/bin/python + +from unicorn import * +from unicorn.mips_const import * + +import regress + +def code_hook(uc, addr, size, user_data): + print 'code hook: pc=%08x sp=%08x' % (addr, uc.reg_read(UC_MIPS_REG_SP)) + +def run(step=False): + addr = 0x4010dc + + code = ( + 'f8ff0124' # addiu $at, $zero, -8 + '24e8a103' # and $sp, $sp, $at + '09f82003' # jalr $t9 + 'e8ffbd23' # addi $sp, $sp, -0x18 + 'b8ffbd27' # addiu $sp, $sp, -0x48 + '00000000' # nop + ).decode('hex') + + uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN) + if step: + uc.hook_add(UC_HOOK_CODE, code_hook) + + uc.reg_write(UC_MIPS_REG_SP, 0x60800000) + uc.reg_write(UC_MIPS_REG_T9, addr + len(code) - 8) + + print 'sp =', hex(uc.reg_read(UC_MIPS_REG_SP)) + print 'at =', hex(uc.reg_read(UC_MIPS_REG_AT)) + print ' (single step: %s)' % (str(step)) + + uc.mem_map(addr & ~(0x1000 - 1), 0x2000) + uc.mem_write(addr, code) + uc.emu_start(addr, addr + len(code)) + + print 'sp =', hex(uc.reg_read(UC_MIPS_REG_SP)) + print 'at =', hex(uc.reg_read(UC_MIPS_REG_AT)) + print + return uc.reg_read(UC_MIPS_REG_SP) + + +class MipsSingleStep(regress.RegressTest): + def test(self): + sp1 = run(step=False) + sp2 = run(step=True) + self.assertEqual(sp1, sp2) + +if __name__ == '__main__': + regress.main() diff --git a/tests/regress/mips_syscall_pc.py b/tests/regress/mips_syscall_pc.py new file mode 100755 index 00000000..995b154f --- /dev/null +++ b/tests/regress/mips_syscall_pc.py @@ -0,0 +1,27 @@ +#!/usr/bin/python + +from unicorn import * +from unicorn.mips_const import * + +import regress + +def intr_hook(uc, intno, data): + print 'interrupt=%d, v0=%d, pc=0x%08x' % (intno, uc.reg_read(UC_MIPS_REG_V0), uc.reg_read(UC_MIPS_REG_PC)) + +class MipsSyscall(regress.RegressTest): + def test(self): + addr = 0x40000 + code = '0c000000'.decode('hex') # syscall + + uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN) + uc.mem_map(addr, 0x1000) + uc.mem_write(addr, code) + uc.reg_write(UC_MIPS_REG_V0, 100) + uc.hook_add(UC_HOOK_INTR, intr_hook) + + uc.emu_start(addr, addr+len(code)) + self.assertEqual(0x40004, uc.reg_read(UC_MIPS_REG_PC)) + + +if __name__ == '__main__': + regress.main() diff --git a/tests/regress/reg_write_sign_extension.py b/tests/regress/reg_write_sign_extension.py index 34d65506..b7d3be55 100755 --- a/tests/regress/reg_write_sign_extension.py +++ b/tests/regress/reg_write_sign_extension.py @@ -24,7 +24,7 @@ class RegWriteSignExt(regress.RegressTest): # jmp ebx mu.mem_write(0x10000000, b'\xff\xe3') - mu.hook_add(unicorn.UC_HOOK_MEM_FETCH_INVALID | unicorn.UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid) + mu.hook_add(unicorn.UC_HOOK_MEM_FETCH_UNMAPPED | unicorn.UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid) mu.emu_start(0x10000000, 0x10000000 + 2, count=1) if __name__ == '__main__': diff --git a/tests/regress/ro_mem_test.c b/tests/regress/ro_mem_test.c index 1e612033..7b430497 100644 --- a/tests/regress/ro_mem_test.c +++ b/tests/regress/ro_mem_test.c @@ -142,7 +142,7 @@ int main(int argc, char **argv, char **envp) //uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff); // intercept invalid memory events - uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_WRITE_PROT, hook_mem_invalid, NULL); + uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_WRITE_PROT, hook_mem_invalid, NULL); // emulate machine code in infinite time printf("BEGIN execution - 1\n"); diff --git a/tests/regress/sparc_reg.py b/tests/regress/sparc_reg.py index 326d00e4..03832de9 100755 --- a/tests/regress/sparc_reg.py +++ b/tests/regress/sparc_reg.py @@ -164,7 +164,7 @@ def print_registers(mu): print_registers(uc) -assert uc.reg_read(UC_SPARC_REG_PC) == 128 # make sure we executed all instructions +assert uc.reg_read(UC_SPARC_REG_PC) == 132 # make sure we executed all instructions assert uc.reg_read(UC_SPARC_REG_SP) == 101 assert uc.reg_read(UC_SPARC_REG_FP) == 201 diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index e1d6856c..04441123 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -408,7 +408,7 @@ static void test_i386_invalid_mem_read(void **state) // emulate machine code in infinite time err = uc_emu_start(uc, address, address+sizeof(code), 0, 0); - uc_assert_err(UC_ERR_READ_INVALID, err); + uc_assert_err(UC_ERR_READ_UNMAPPED, err); uc_assert_success(uc_close(uc)); } @@ -438,7 +438,7 @@ static void test_i386_invalid_mem_write(void **state) // emulate machine code in infinite time err = uc_emu_start(uc, address, address+sizeof(code), 0, 0); - uc_assert_err(UC_ERR_WRITE_INVALID, err); + uc_assert_err(UC_ERR_WRITE_UNMAPPED, err); uc_assert_success(uc_close(uc)); @@ -469,7 +469,7 @@ static void test_i386_jump_invalid(void **state) // emulate machine code in infinite time err = uc_emu_start(uc, address, address+sizeof(code), 0, 0); - uc_assert_err(UC_ERR_CODE_INVALID, err); + uc_assert_err(UC_ERR_FETCH_UNMAPPED, err); uc_assert_success(uc_close(uc)); diff --git a/uc.c b/uc.c index d5219542..b87d1a63 100644 --- a/uc.c +++ b/uc.c @@ -69,14 +69,12 @@ const char *uc_strerror(uc_err code) return "Invalid mode (UC_ERR_MODE)"; case UC_ERR_VERSION: return "Different API version between core & binding (UC_ERR_VERSION)"; - case UC_ERR_READ_INVALID: - return "Invalid memory read (UC_ERR_READ_INVALID)"; - case UC_ERR_WRITE_INVALID: - return "Invalid memory write (UC_ERR_WRITE_INVALID)"; - case UC_ERR_FETCH_INVALID: - return "Invalid memory fetch (UC_ERR_FETCH_INVALID)"; - case UC_ERR_CODE_INVALID: - return "Invalid code address (UC_ERR_CODE_INVALID)"; + case UC_ERR_READ_UNMAPPED: + return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; + case UC_ERR_WRITE_UNMAPPED: + return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; + case UC_ERR_FETCH_UNMAPPED: + return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; case UC_ERR_HOOK: return "Invalid hook type (UC_ERR_HOOK)"; case UC_ERR_INSN_INVALID: @@ -343,7 +341,7 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) uint8_t *bytes = _bytes; if (!check_mem_area(uc, address, size)) - return UC_ERR_READ_INVALID; + return UC_ERR_READ_UNMAPPED; size_t count = 0, len; @@ -364,7 +362,7 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) if (count == size) return UC_ERR_OK; else - return UC_ERR_READ_INVALID; + return UC_ERR_READ_UNMAPPED; } UNICORN_EXPORT @@ -373,7 +371,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t const uint8_t *bytes = _bytes; if (!check_mem_area(uc, address, size)) - return UC_ERR_WRITE_INVALID; + return UC_ERR_WRITE_UNMAPPED; size_t count = 0, len; @@ -404,7 +402,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t if (count == size) return UC_ERR_OK; else - return UC_ERR_WRITE_INVALID; + return UC_ERR_WRITE_UNMAPPED; } #define TIMEOUT_STEP 2 // microseconds @@ -842,15 +840,15 @@ static uc_err _hook_mem_invalid(struct uc_struct* uc, int type, uc_cb_eventmem_t uc->hook_callbacks[i].callback = callback; uc->hook_callbacks[i].user_data = user_data; *evh = i; - if (type & UC_HOOK_MEM_READ_INVALID) + if (type & UC_HOOK_MEM_READ_UNMAPPED) uc->hook_mem_read_idx = i; if (type & UC_HOOK_MEM_READ_PROT) uc->hook_mem_read_prot_idx = i; - if (type & UC_HOOK_MEM_WRITE_INVALID) + if (type & UC_HOOK_MEM_WRITE_UNMAPPED) uc->hook_mem_write_idx = i; if (type & UC_HOOK_MEM_WRITE_PROT) uc->hook_mem_write_prot_idx = i; - if (type & UC_HOOK_MEM_FETCH_INVALID) + if (type & UC_HOOK_MEM_FETCH_UNMAPPED) uc->hook_mem_fetch_idx = i; if (type & UC_HOOK_MEM_FETCH_PROT) uc->hook_mem_fetch_prot_idx = i; @@ -940,14 +938,14 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *u va_start(valist, user_data); - if (type & UC_HOOK_MEM_READ_INVALID) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_INVALID, callback, user_data, hh); + if (type & UC_HOOK_MEM_READ_UNMAPPED) + ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_UNMAPPED, callback, user_data, hh); - if (type & UC_HOOK_MEM_WRITE_INVALID) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_WRITE_INVALID, callback, user_data, hh); + if (type & UC_HOOK_MEM_WRITE_UNMAPPED) + ret = _hook_mem_invalid(uc, UC_HOOK_MEM_WRITE_UNMAPPED, callback, user_data, hh); - if (type & UC_HOOK_MEM_FETCH_INVALID) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_FETCH_INVALID, callback, user_data, hh); + if (type & UC_HOOK_MEM_FETCH_UNMAPPED) + ret = _hook_mem_invalid(uc, UC_HOOK_MEM_FETCH_UNMAPPED, callback, user_data, hh); if (type & UC_HOOK_MEM_READ_PROT) ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_PROT, callback, user_data, hh);