mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-23 06:25:12 +00:00
Merge branch 'change-handle-based-api' of https://github.com/JonathonReinhart/unicorn into JonathonReinhart-change-handle-based-api
This commit is contained in:
commit
dd13d821af
59
hook.c
59
hook.c
|
@ -38,13 +38,9 @@ size_t hook_find_new(struct uc_struct *uc)
|
|||
}
|
||||
|
||||
// return -1 on failure, index to hook_callbacks[] on success.
|
||||
size_t hook_add(uch handle, int type, uint64_t begin, uint64_t end, void *callback, void *user_data)
|
||||
size_t hook_add(struct uc_struct *uc, int type, uint64_t begin, uint64_t end, void *callback, void *user_data)
|
||||
{
|
||||
int i;
|
||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
if (handle == 0)
|
||||
return -1;
|
||||
|
||||
// find the first free slot. skip slot 0, so index > 0
|
||||
i = hook_find_new(uc);
|
||||
|
@ -95,52 +91,45 @@ size_t hook_add(uch handle, int type, uint64_t begin, uint64_t end, void *callba
|
|||
}
|
||||
|
||||
// return 0 on success, -1 on failure
|
||||
uc_err hook_del(uch handle, uch *h2)
|
||||
uc_err hook_del(struct uc_struct *uc, uc_hook_h hh)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
if (handle == 0)
|
||||
return UC_ERR_UCH;
|
||||
|
||||
if (*h2 == uc->hook_block_idx) {
|
||||
if (hh == uc->hook_block_idx) {
|
||||
uc->hook_block_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_insn_idx) {
|
||||
if (hh == uc->hook_insn_idx) {
|
||||
uc->hook_insn_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_read_idx) {
|
||||
if (hh == uc->hook_read_idx) {
|
||||
uc->hook_read_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_write_idx) {
|
||||
if (hh == uc->hook_write_idx) {
|
||||
uc->hook_write_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_mem_idx) {
|
||||
if (hh == uc->hook_mem_idx) {
|
||||
uc->hook_mem_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_intr_idx) {
|
||||
if (hh == uc->hook_intr_idx) {
|
||||
uc->hook_intr_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_out_idx) {
|
||||
if (hh == uc->hook_out_idx) {
|
||||
uc->hook_out_idx = 0;
|
||||
}
|
||||
|
||||
if (*h2 == uc->hook_in_idx) {
|
||||
if (hh == uc->hook_in_idx) {
|
||||
uc->hook_in_idx = 0;
|
||||
}
|
||||
|
||||
uc->hook_callbacks[*h2].callback = NULL;
|
||||
uc->hook_callbacks[*h2].user_data = NULL;
|
||||
uc->hook_callbacks[*h2].hook_type = 0;
|
||||
uc->hook_callbacks[*h2].begin = 0;
|
||||
uc->hook_callbacks[*h2].end = 0;
|
||||
|
||||
*h2 = 0;
|
||||
uc->hook_callbacks[hh].callback = NULL;
|
||||
uc->hook_callbacks[hh].user_data = NULL;
|
||||
uc->hook_callbacks[hh].hook_type = 0;
|
||||
uc->hook_callbacks[hh].begin = 0;
|
||||
uc->hook_callbacks[hh].end = 0;
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
@ -206,26 +195,19 @@ static struct hook_struct *_hook_find(struct uc_struct *uc, int type, uint64_t a
|
|||
}
|
||||
|
||||
|
||||
static void hook_count_cb(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
// count this instruction
|
||||
uc->emu_counter++;
|
||||
|
||||
if (uc->emu_counter > uc->emu_count)
|
||||
uc_emu_stop(handle);
|
||||
uc_emu_stop(uc);
|
||||
else if (uc->hook_count_callback)
|
||||
uc->hook_count_callback(handle, address, size, user_data);
|
||||
uc->hook_count_callback(uc, address, size, user_data);
|
||||
}
|
||||
|
||||
struct hook_struct *hook_find(uch handle, int type, uint64_t address)
|
||||
struct hook_struct *hook_find(struct uc_struct *uc, int type, uint64_t address)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
if (handle == 0)
|
||||
return NULL;
|
||||
|
||||
// stop executing callbacks if we already got stop request
|
||||
if (uc->stop_request)
|
||||
return NULL;
|
||||
|
@ -270,6 +252,5 @@ void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t add
|
|||
uc->set_pc(uc, address);
|
||||
}
|
||||
|
||||
((uc_cb_hookcode_t)callback)((uch)handle, address, size, user_data);
|
||||
((uc_cb_hookcode_t)callback)(uc, address, size, user_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#define UC_HOOK_H
|
||||
|
||||
// return -1 on failure, index to traces[] on success.
|
||||
size_t hook_add(uch handle, int type, uint64_t begin, uint64_t end, void *callback, void *user_data);
|
||||
size_t hook_add(struct uc_struct *uc, int type, uint64_t begin, uint64_t end, void *callback, void *user_data);
|
||||
|
||||
// return 0 on success, -1 on failure
|
||||
uc_err hook_del(uch handle, uch *traceh);
|
||||
uc_err hook_del(struct uc_struct *uc, uc_hook_h hh);
|
||||
|
||||
// return NULL on failure
|
||||
struct hook_struct *hook_find(uch handle, int type, uint64_t address);
|
||||
struct hook_struct *hook_find(struct uc_struct *uc, int type, uint64_t address);
|
||||
|
||||
// return index of an free hook entry in hook_callbacks[] array.
|
||||
// this realloc memory if needed.
|
||||
|
|
|
@ -24,10 +24,10 @@ typedef struct ModuleEntry {
|
|||
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
|
||||
|
||||
// return 0 on success, -1 on failure
|
||||
typedef int (*reg_read_t)(uch handle, unsigned int regid, void *value);
|
||||
typedef int (*reg_write_t)(uch handle, unsigned int regid, const void *value);
|
||||
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
|
||||
typedef void (*reg_reset_t)(uch handle);
|
||||
typedef void (*reg_reset_t)(struct uc_struct *uc);
|
||||
|
||||
typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len);
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ extern "C" {
|
|||
|
||||
#include "platform.h"
|
||||
|
||||
// Handle to use with all APIs
|
||||
typedef size_t uch;
|
||||
struct uc_struct;
|
||||
typedef struct uc_struct ucengine;
|
||||
|
||||
typedef size_t uc_hook_h;
|
||||
|
||||
#include "m68k.h"
|
||||
#include "x86.h"
|
||||
|
@ -107,7 +109,6 @@ typedef enum uc_err {
|
|||
UC_ERR_OOM, // Out-Of-Memory error: uc_open(), uc_emulate()
|
||||
UC_ERR_ARCH, // Unsupported architecture: uc_open()
|
||||
UC_ERR_HANDLE, // Invalid handle
|
||||
UC_ERR_UCH, // Invalid handle (uch)
|
||||
UC_ERR_MODE, // Invalid/unsupported mode: uc_open()
|
||||
UC_ERR_VERSION, // Unsupported version (bindings)
|
||||
UC_ERR_MEM_READ, // Quit emulation due to invalid memory READ: uc_emu_start()
|
||||
|
@ -125,24 +126,24 @@ typedef enum uc_err {
|
|||
// @address: address where the code is being executed
|
||||
// @size: size of machine instruction(s) being executed, or 0 when size is unknown
|
||||
// @user_data: user data passed to tracing APIs.
|
||||
typedef void (*uc_cb_hookcode_t)(uch handle, uint64_t address, uint32_t size, void *user_data);
|
||||
typedef void (*uc_cb_hookcode_t)(ucengine *uc, uint64_t address, uint32_t size, void *user_data);
|
||||
|
||||
// Callback function for tracing interrupts (for uc_hook_intr())
|
||||
// @intno: interrupt number
|
||||
// @user_data: user data passed to tracing APIs.
|
||||
typedef void (*uc_cb_hookintr_t)(uch handle, uint32_t intno, void *user_data);
|
||||
typedef void (*uc_cb_hookintr_t)(ucengine *uc, uint32_t intno, void *user_data);
|
||||
|
||||
// Callback function for tracing IN instruction of X86
|
||||
// @port: port number
|
||||
// @size: data size (1/2/4) to be read from this port
|
||||
// @user_data: user data passed to tracing APIs.
|
||||
typedef uint32_t (*uc_cb_insn_in_t)(uch handle, uint32_t port, int size, void *user_data);
|
||||
typedef uint32_t (*uc_cb_insn_in_t)(ucengine *uc, uint32_t port, int size, void *user_data);
|
||||
|
||||
// x86's handler for OUT
|
||||
// @port: port number
|
||||
// @size: data size (1/2/4) to be written to this port
|
||||
// @value: data value to be written to this port
|
||||
typedef void (*uc_cb_insn_out_t)(uch handle, uint32_t port, int size, uint32_t value, void *user_data);
|
||||
typedef void (*uc_cb_insn_out_t)(ucengine *uc, uint32_t port, int size, uint32_t value, void *user_data);
|
||||
|
||||
// All type of memory accesses for UC_HOOK_MEM_*
|
||||
typedef enum uc_mem_type {
|
||||
|
@ -171,7 +172,7 @@ typedef enum uc_hook_t {
|
|||
// @size: size of data being read or written
|
||||
// @value: value of data being written to memory, or irrelevant if type = READ.
|
||||
// @user_data: user data passed to tracing APIs
|
||||
typedef void (*uc_cb_hookmem_t)(uch handle, uc_mem_type type,
|
||||
typedef void (*uc_cb_hookmem_t)(ucengine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data);
|
||||
|
||||
// Callback function for handling memory events (for UC_HOOK_MEM_INVALID)
|
||||
|
@ -181,7 +182,7 @@ typedef void (*uc_cb_hookmem_t)(uch handle, uc_mem_type type,
|
|||
// @value: value of data being written to memory, or irrelevant if type = READ.
|
||||
// @user_data: user data passed to tracing APIs
|
||||
// @return: return true to continue, or false to stop program (due to invalid memory).
|
||||
typedef bool (*uc_cb_eventmem_t)(uch handle, uc_mem_type type,
|
||||
typedef bool (*uc_cb_eventmem_t)(ucengine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data);
|
||||
|
||||
|
||||
|
@ -218,43 +219,43 @@ bool uc_arch_supported(uc_arch arch);
|
|||
|
||||
|
||||
/*
|
||||
Initialize UC handle: this must be done before any usage of UC.
|
||||
Create new instance of unicorn engine.
|
||||
|
||||
@arch: architecture type (UC_ARCH_*)
|
||||
@mode: hardware mode. This is combined of UC_MODE_*
|
||||
@handle: pointer to handle, which will be updated at return time
|
||||
@uc: pointer to ucengine, which will be updated at return time
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_open(uc_arch arch, uc_mode mode, uch *handle);
|
||||
uc_err uc_open(uc_arch arch, uc_mode mode, ucengine **uc);
|
||||
|
||||
/*
|
||||
Close UC handle: MUST do to release the handle when it is not used anymore.
|
||||
Close UC instance: MUST do to release the handle when it is not used anymore.
|
||||
NOTE: this must be called only when there is no longer usage of Unicorn.
|
||||
The reason is the this API releases some cached memory, thus access to any
|
||||
Unicorn API after uc_close() might crash your application.
|
||||
After this, @handle is invalid, and nolonger usable.
|
||||
After this, @uc is invalid, and nolonger usable.
|
||||
|
||||
@handle: pointer to a handle returned by uc_open()
|
||||
@uc: pointer to a handle returned by uc_open()
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_close(uch *handle);
|
||||
uc_err uc_close(ucengine *uc);
|
||||
|
||||
/*
|
||||
Report the last error number when some API function fail.
|
||||
Like glibc's errno, uc_errno might not retain its old value once accessed.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
|
||||
@return: error code of uc_err enum type (UC_ERR_*, see above)
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_errno(uch handle);
|
||||
uc_err uc_errno(ucengine *uc);
|
||||
|
||||
/*
|
||||
Return a string describing given error code.
|
||||
|
@ -270,7 +271,7 @@ const char *uc_strerror(uc_err code);
|
|||
/*
|
||||
Write to register.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
@regid: register ID that is to be modified.
|
||||
@value: pointer to the value that will set to register @regid
|
||||
|
||||
|
@ -278,12 +279,12 @@ const char *uc_strerror(uc_err code);
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write(uch handle, int regid, const void *value);
|
||||
uc_err uc_reg_write(ucengine *uc, int regid, const void *value);
|
||||
|
||||
/*
|
||||
Read register value.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
@regid: register ID that is to be retrieved.
|
||||
@value: pointer to a variable storing the register value.
|
||||
|
||||
|
@ -291,12 +292,12 @@ uc_err uc_reg_write(uch handle, int regid, const void *value);
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uch handle, int regid, void *value);
|
||||
uc_err uc_reg_read(ucengine *uc, int regid, void *value);
|
||||
|
||||
/*
|
||||
Write to a range of bytes in memory.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
@address: starting memory address of bytes to set.
|
||||
@bytes: pointer to a variable containing data to be written to memory.
|
||||
@size: size of memory to write to.
|
||||
|
@ -307,12 +308,12 @@ uc_err uc_reg_read(uch handle, int regid, void *value);
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size);
|
||||
uc_err uc_mem_write(ucengine *uc, uint64_t address, const uint8_t *bytes, size_t size);
|
||||
|
||||
/*
|
||||
Read a range of bytes in memory.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
@address: starting memory address of bytes to get.
|
||||
@bytes: pointer to a variable containing data copied from memory.
|
||||
@size: size of memory to read.
|
||||
|
@ -323,12 +324,12 @@ uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t s
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size);
|
||||
uc_err uc_mem_read(ucengine *uc, uint64_t address, uint8_t *bytes, size_t size);
|
||||
|
||||
/*
|
||||
Emulate machine code in a specific duration of time.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
@begin: address where emulation starts
|
||||
@until: address where emulation stops (i.e when this address is hit)
|
||||
@timeout: duration to emulate the code (in microseconds). When this value is 0,
|
||||
|
@ -340,27 +341,27 @@ uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size);
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout, size_t count);
|
||||
uc_err uc_emu_start(ucengine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count);
|
||||
|
||||
/*
|
||||
Stop emulation (which was started by uc_emu_start() API.
|
||||
This is typically called from callback functions registered via tracing APIs.
|
||||
NOTE: for now, this will stop the execution only after the current block.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_emu_stop(uch handle);
|
||||
uc_err uc_emu_stop(ucengine *uc);
|
||||
|
||||
/*
|
||||
Register callback for a hook event.
|
||||
The callback will be run when the hook event is hit.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@h2: hook handle returned from this registration. To be used in uc_hook_del() API
|
||||
@uc: handle returned by uc_open()
|
||||
@hh: hook handle returned from this registration. To be used in uc_hook_del() API
|
||||
@type: hook type
|
||||
@callback: callback to be run when instruction is hit
|
||||
@user_data: user-defined data. This will be passed to callback function in its
|
||||
|
@ -371,22 +372,22 @@ uc_err uc_emu_stop(uch handle);
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_hook_add(uch handle, uch *h2, uc_hook_t type, void *callback, void *user_data, ...);
|
||||
uc_err uc_hook_add(ucengine *uc, uc_hook_h *hh, uc_hook_t type, void *callback, void *user_data, ...);
|
||||
|
||||
/*
|
||||
Unregister (remove) a hook callback.
|
||||
This API removes the hook callback registered by uc_hook_add().
|
||||
NOTE: this should be called only when you no longer want to trace.
|
||||
After this, @hhandle is invalid, and nolonger usable.
|
||||
After this, @hh is invalid, and nolonger usable.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@h2: handle returned by uc_hook_add()
|
||||
@uc: handle returned by uc_open()
|
||||
@hh: handle returned by uc_hook_add()
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_hook_del(uch handle, uch *h2);
|
||||
uc_err uc_hook_del(ucengine *uc, uc_hook_h hh);
|
||||
|
||||
typedef enum uc_prot {
|
||||
UC_PROT_NONE = 0,
|
||||
|
@ -399,7 +400,7 @@ typedef enum uc_prot {
|
|||
Map memory in for emulation.
|
||||
This API adds a memory region that can be used by emulation.
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@uc: handle returned by uc_open()
|
||||
@address: starting address of the new memory region to be mapped in.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_MAP error.
|
||||
@size: size of the new memory region to be mapped in.
|
||||
|
@ -412,7 +413,7 @@ typedef enum uc_prot {
|
|||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms);
|
||||
uc_err uc_mem_map(ucengine *uc, uint64_t address, size_t size, uint32_t perms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ extern "C" {
|
|||
|
||||
// Callback function for tracing SYSCALL/SYSENTER (for uc_hook_intr())
|
||||
// @user_data: user data passed to tracing APIs.
|
||||
typedef void (*uc_cb_insn_syscall_t)(uch handle, void *user_data);
|
||||
typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data);
|
||||
|
||||
//> X86 registers
|
||||
typedef enum uc_x86_reg {
|
||||
|
|
|
@ -141,7 +141,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
|||
// Unicorn: call interrupt callback if registered
|
||||
if (uc->hook_intr_idx)
|
||||
((uc_cb_hookintr_t)uc->hook_callbacks[uc->hook_intr_idx].callback)(
|
||||
(uch)uc, cpu->exception_index,
|
||||
uc, cpu->exception_index,
|
||||
uc->hook_callbacks[uc->hook_intr_idx].user_data);
|
||||
cpu->exception_index = -1;
|
||||
#endif
|
||||
|
|
|
@ -69,7 +69,7 @@ void cpu_outb(struct uc_struct *uc, pio_addr_t addr, uint8_t val)
|
|||
// Unicorn: call interrupt callback if registered
|
||||
if (uc->hook_out_idx)
|
||||
((uc_cb_insn_out_t)uc->hook_callbacks[uc->hook_out_idx].callback)(
|
||||
(uch)uc, addr, 1, val,
|
||||
uc, addr, 1, val,
|
||||
uc->hook_callbacks[uc->hook_out_idx].user_data);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ void cpu_outw(struct uc_struct *uc, pio_addr_t addr, uint16_t val)
|
|||
// Unicorn: call interrupt callback if registered
|
||||
if (uc->hook_out_idx)
|
||||
((uc_cb_insn_out_t)uc->hook_callbacks[uc->hook_out_idx].callback)(
|
||||
(uch)uc, addr, 2, val,
|
||||
uc, addr, 2, val,
|
||||
uc->hook_callbacks[uc->hook_out_idx].user_data);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ void cpu_outl(struct uc_struct *uc, pio_addr_t addr, uint32_t val)
|
|||
//LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
|
||||
if (uc->hook_out_idx)
|
||||
((uc_cb_insn_out_t)uc->hook_callbacks[uc->hook_out_idx].callback)(
|
||||
(uch)uc, addr, 4, val,
|
||||
uc, addr, 4, val,
|
||||
uc->hook_callbacks[uc->hook_out_idx].user_data);
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ uint8_t cpu_inb(struct uc_struct *uc, pio_addr_t addr)
|
|||
//LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
|
||||
if (uc->hook_in_idx)
|
||||
return ((uc_cb_insn_in_t)uc->hook_callbacks[uc->hook_in_idx].callback)(
|
||||
(uch)uc, addr, 1,
|
||||
uc, addr, 1,
|
||||
uc->hook_callbacks[uc->hook_in_idx].user_data);
|
||||
|
||||
return 0;
|
||||
|
@ -108,7 +108,7 @@ uint16_t cpu_inw(struct uc_struct *uc, pio_addr_t addr)
|
|||
//LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
|
||||
if (uc->hook_in_idx)
|
||||
return ((uc_cb_insn_in_t)uc->hook_callbacks[uc->hook_in_idx].callback)(
|
||||
(uch)uc, addr, 2,
|
||||
uc, addr, 2,
|
||||
uc->hook_callbacks[uc->hook_in_idx].user_data);
|
||||
|
||||
return 0;
|
||||
|
@ -119,7 +119,7 @@ uint32_t cpu_inl(struct uc_struct *uc, pio_addr_t addr)
|
|||
//LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
|
||||
if (uc->hook_in_idx)
|
||||
return ((uc_cb_insn_in_t)uc->hook_callbacks[uc->hook_in_idx].callback)(
|
||||
(uch)uc, addr, 4,
|
||||
uc, addr, 4,
|
||||
uc->hook_callbacks[uc->hook_in_idx].user_data);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -183,9 +183,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||
|
||||
// Unicorn: callback on memory read
|
||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_MEM_READ, addr);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr);
|
||||
if (trace) {
|
||||
((uc_cb_hookmem_t)trace->callback)((uch)env->uc, UC_MEM_READ,
|
||||
((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ,
|
||||
(uint64_t)addr, (int)DATA_SIZE, (int64_t)0, trace->user_data);
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||
// Unicorn: callback on invalid memory
|
||||
if (env->uc->hook_mem_idx && mr == NULL) {
|
||||
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
||||
(uch)env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||
env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
|
@ -211,7 +211,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||
bool result = false;
|
||||
if (uc->hook_mem_idx) {
|
||||
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
(uch)uc, UC_MEM_READ_NR, addr, DATA_SIZE, 0,
|
||||
uc, UC_MEM_READ_NR, addr, DATA_SIZE, 0,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
||||
}
|
||||
if (result) {
|
||||
|
@ -328,9 +328,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||
|
||||
// Unicorn: callback on memory read
|
||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_MEM_READ, addr);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr);
|
||||
if (trace) {
|
||||
((uc_cb_hookmem_t)trace->callback)((uch)env->uc, UC_MEM_READ,
|
||||
((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ,
|
||||
(uint64_t)addr, (int)DATA_SIZE, (int64_t)0, trace->user_data);
|
||||
}
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||
// Unicorn: callback on invalid memory
|
||||
if (env->uc->hook_mem_idx && mr == NULL) {
|
||||
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
||||
(uch)env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||
env->uc, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
|
@ -356,7 +356,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||
bool result = false;
|
||||
if (uc->hook_mem_idx) {
|
||||
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
(uch)uc, UC_MEM_READ_NR, addr, DATA_SIZE, 0,
|
||||
uc, UC_MEM_READ_NR, addr, DATA_SIZE, 0,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
||||
}
|
||||
if (result) {
|
||||
|
@ -511,9 +511,9 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||
|
||||
// Unicorn: callback on memory write
|
||||
if (uc->hook_mem_write) {
|
||||
struct hook_struct *trace = hook_find((uch)uc, UC_HOOK_MEM_WRITE, addr);
|
||||
struct hook_struct *trace = hook_find(uc, UC_HOOK_MEM_WRITE, addr);
|
||||
if (trace) {
|
||||
((uc_cb_hookmem_t)trace->callback)((uch)uc, UC_MEM_WRITE,
|
||||
((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE,
|
||||
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||
// Unicorn: callback on invalid memory
|
||||
if (uc->hook_mem_idx && mr == NULL) {
|
||||
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
(uch)uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
||||
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
|
@ -539,7 +539,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||
bool result = false;
|
||||
if (uc->hook_mem_idx) {
|
||||
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
(uch)uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val,
|
||||
uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
||||
}
|
||||
if (result) {
|
||||
|
@ -649,9 +649,9 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||
|
||||
// Unicorn: callback on memory write
|
||||
if (uc->hook_mem_write) {
|
||||
struct hook_struct *trace = hook_find((uch)uc, UC_HOOK_MEM_WRITE, addr);
|
||||
struct hook_struct *trace = hook_find(uc, UC_HOOK_MEM_WRITE, addr);
|
||||
if (trace) {
|
||||
((uc_cb_hookmem_t)trace->callback)((uch)uc, UC_MEM_WRITE,
|
||||
((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE,
|
||||
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
|
||||
}
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||
// Unicorn: callback on invalid memory
|
||||
if (uc->hook_mem_idx && mr == NULL) {
|
||||
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
(uch)uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
||||
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||
// save error & quit
|
||||
env->invalid_addr = addr;
|
||||
|
@ -677,7 +677,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||
bool result = false;
|
||||
if (uc->hook_mem_idx) {
|
||||
result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||
(uch)uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val,
|
||||
uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val,
|
||||
uc->hook_callbacks[uc->hook_mem_idx].user_data);
|
||||
}
|
||||
if (result) {
|
||||
|
|
|
@ -10984,7 +10984,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)s->uc, UC_HOOK_CODE, s->pc - 4);
|
||||
struct hook_struct *trace = hook_find(s->uc, UC_HOOK_CODE, s->pc - 4);
|
||||
if (trace)
|
||||
gen_uc_tracecode(tcg_ctx, 4, trace->callback, env->uc, s->pc - 4, trace->user_data);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -11109,7 +11109,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
|
|||
// Only hook this block if it is not broken from previous translation due to
|
||||
// full translation cache
|
||||
if (env->uc->hook_block && !env->uc->block_full) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
if (trace) {
|
||||
// save block address to see if we need to patch block size later
|
||||
env->uc->block_addr = pc_start;
|
||||
|
|
|
@ -7688,7 +7688,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (s->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)s->uc, UC_HOOK_CODE, s->pc - 4);
|
||||
struct hook_struct *trace = hook_find(s->uc, UC_HOOK_CODE, s->pc - 4);
|
||||
if (trace)
|
||||
gen_uc_tracecode(tcg_ctx, 4, trace->callback, s->uc, s->pc - 4, trace->user_data);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -10411,7 +10411,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)s->uc, UC_HOOK_CODE, s->pc);
|
||||
struct hook_struct *trace = hook_find(s->uc, UC_HOOK_CODE, s->pc);
|
||||
if (trace)
|
||||
gen_uc_tracecode(tcg_ctx, 2, trace->callback, env->uc, s->pc, trace->user_data);
|
||||
// if requested to emulate only some instructions, check to see
|
||||
|
@ -11232,7 +11232,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
|
|||
// Only hook this block if it is not broken from previous translation due to
|
||||
// full translation cache
|
||||
if (env->uc->hook_block && !env->uc->block_full) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
if (trace) {
|
||||
// save block address to see if we need to patch block size later
|
||||
env->uc->block_addr = pc_start;
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#define UC_QEMU_TARGET_ARM_H
|
||||
|
||||
// functions to read & write registers
|
||||
int arm_reg_read(uch handle, unsigned int regid, void *value);
|
||||
int arm_reg_write(uch handle, unsigned int regid, const void *value);
|
||||
int arm64_reg_read(uch handle, unsigned int regid, void *value);
|
||||
int arm64_reg_write(uch handle, unsigned int regid, const void *value);
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
|
||||
void arm_reg_reset(uch handle);
|
||||
void arm64_reg_reset(uch handle);
|
||||
void arm_reg_reset(struct uc_struct *uc);
|
||||
void arm64_reg_reset(struct uc_struct *uc);
|
||||
|
||||
__attribute__ ((visibility ("default")))
|
||||
void arm_uc_init(struct uc_struct* uc);
|
||||
|
|
|
@ -25,23 +25,17 @@ static void arm64_set_pc(struct uc_struct *uc, uint64_t address)
|
|||
((CPUARMState *)uc->current_cpu->env_ptr)->pc = address;
|
||||
}
|
||||
|
||||
void arm64_reg_reset(uch handle)
|
||||
void arm64_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUArchState *env;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
CPUArchState *env = first_cpu->env_ptr;
|
||||
memset(env->xregs, 0, sizeof(env->xregs));
|
||||
|
||||
env->pc = 0;
|
||||
}
|
||||
|
||||
int arm64_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
|
||||
mycpu = first_cpu;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0];
|
||||
|
@ -68,12 +62,9 @@ int arm64_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int arm64_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
|
||||
mycpu = first_cpu;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
|
||||
ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(int64_t *)value;
|
||||
|
|
|
@ -25,9 +25,9 @@ static void arm_set_pc(struct uc_struct *uc, uint64_t address)
|
|||
((CPUARMState *)uc->current_cpu->env_ptr)->regs[15] = address;
|
||||
}
|
||||
|
||||
void arm_reg_reset(uch handle)
|
||||
void arm_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
(void)uc;
|
||||
CPUArchState *env;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
|
@ -36,10 +36,9 @@ void arm_reg_reset(uch handle)
|
|||
env->pc = 0;
|
||||
}
|
||||
|
||||
int arm_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
|
||||
mycpu = first_cpu;
|
||||
|
||||
|
@ -78,12 +77,9 @@ int arm_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int arm_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
|
||||
mycpu = first_cpu;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
switch(uc->mode) {
|
||||
default:
|
||||
|
|
|
@ -949,7 +949,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
|
|||
struct uc_struct *uc = env->uc;
|
||||
if (uc->hook_syscall_idx) {
|
||||
((uc_cb_insn_syscall_t)uc->hook_callbacks[uc->hook_syscall_idx].callback)(
|
||||
(uch)uc, uc->hook_callbacks[uc->hook_syscall_idx].user_data);
|
||||
uc, uc->hook_callbacks[uc->hook_syscall_idx].user_data);
|
||||
env->eip += next_eip_addend;
|
||||
}
|
||||
|
||||
|
|
|
@ -4761,7 +4761,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
trace = hook_find((uch)env->uc, UC_HOOK_CODE, pc_start);
|
||||
trace = hook_find(env->uc, UC_HOOK_CODE, pc_start);
|
||||
if (trace) {
|
||||
if (s->last_cc_op != s->cc_op) {
|
||||
sync_eflags(s, tcg_ctx);
|
||||
|
@ -8379,7 +8379,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
|
|||
// Only hook this block if it is not broken from previous translation due to
|
||||
// full translation cache
|
||||
if (env->uc->hook_block && !env->uc->block_full) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
if (trace) {
|
||||
env->uc->block_addr = pc_start;
|
||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data);
|
||||
|
|
|
@ -48,12 +48,10 @@ void x86_release(void *ctx)
|
|||
g_free(s->tb_ctx.tbs);
|
||||
}
|
||||
|
||||
void x86_reg_reset(uch handle)
|
||||
void x86_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUArchState *env;
|
||||
CPUArchState *env = first_cpu->env_ptr;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH;
|
||||
env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_AES;
|
||||
env->features[FEAT_8000_0001_EDX] = CPUID_EXT2_3DNOW | CPUID_EXT2_RDTSCP;
|
||||
|
@ -143,12 +141,9 @@ void x86_reg_reset(uch handle)
|
|||
}
|
||||
}
|
||||
|
||||
int x86_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
|
||||
mycpu = first_cpu;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
switch(uc->mode) {
|
||||
default:
|
||||
|
@ -545,12 +540,9 @@ int x86_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int x86_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
|
||||
mycpu = first_cpu;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
switch(uc->mode) {
|
||||
default:
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#define UC_QEMU_TARGET_I386_H
|
||||
|
||||
// functions to read & write registers
|
||||
int x86_reg_read(uch handle, unsigned int regid, void *value);
|
||||
int x86_reg_write(uch handle, unsigned int regid, const void *value);
|
||||
int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
|
||||
void x86_reg_reset(uch handle);
|
||||
void x86_reg_reset(struct uc_struct *uc);
|
||||
|
||||
void x86_uc_init(struct uc_struct* uc);
|
||||
int x86_uc_machine_init(struct uc_struct *uc);
|
||||
|
|
|
@ -3044,7 +3044,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_CODE, s->pc);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, s->pc);
|
||||
if (trace)
|
||||
gen_uc_tracecode(tcg_ctx, 2, trace->callback, env->uc, s->pc, trace->user_data);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -3105,7 +3105,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
|
|||
// Only hook this block if it is not broken from previous translation due to
|
||||
// full translation cache
|
||||
if (env->uc->hook_block && !env->uc->block_full) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
if (trace) {
|
||||
// save block address to see if we need to patch block size later
|
||||
env->uc->block_addr = pc_start;
|
||||
|
|
|
@ -21,21 +21,18 @@ static void m68k_set_pc(struct uc_struct *uc, uint64_t address)
|
|||
((CPUM68KState *)uc->current_cpu->env_ptr)->pc = address;
|
||||
}
|
||||
|
||||
void m68k_reg_reset(uch handle)
|
||||
void m68k_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUArchState *env;
|
||||
CPUArchState *env = first_cpu->env_ptr;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
memset(env->aregs, 0, sizeof(env->aregs));
|
||||
memset(env->dregs, 0, sizeof(env->dregs));
|
||||
|
||||
env->pc = 0;
|
||||
}
|
||||
|
||||
int m68k_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
|
@ -60,9 +57,8 @@ int m68k_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int m68k_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#define UC_QEMU_TARGET_M68K_H
|
||||
|
||||
// functions to read & write registers
|
||||
int m68k_reg_read(uch handle, unsigned int regid, void *value);
|
||||
int m68k_reg_write(uch handle, unsigned int regid, const void *value);
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
|
||||
void m68k_reg_reset(uch handle);
|
||||
void m68k_reg_reset(struct uc_struct *uc);
|
||||
|
||||
void m68k_uc_init(struct uc_struct* uc);
|
||||
|
||||
|
|
|
@ -11344,7 +11344,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_CODE, ctx->pc);
|
||||
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);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -13944,7 +13944,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_CODE, ctx->pc);
|
||||
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);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -18523,7 +18523,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (env->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_CODE, ctx->pc);
|
||||
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);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -19211,7 +19211,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
|||
// Only hook this block if it is not broken from previous translation due to
|
||||
// full translation cache
|
||||
if (env->uc->hook_block && !env->uc->block_full) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
if (trace) {
|
||||
// save block address to see if we need to patch block size later
|
||||
env->uc->block_addr = pc_start;
|
||||
|
|
|
@ -22,19 +22,17 @@ static void mips_set_pc(struct uc_struct *uc, uint64_t address)
|
|||
((CPUMIPSState *)uc->current_cpu->env_ptr)->active_tc.PC = address;
|
||||
}
|
||||
|
||||
void mips_reg_reset(uch handle)
|
||||
void mips_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUArchState *env;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
(void)uc;
|
||||
CPUArchState *env = first_cpu->env_ptr;
|
||||
memset(env->active_tc.gpr, 0, sizeof(env->active_tc.gpr));
|
||||
|
||||
env->active_tc.PC = 0; }
|
||||
env->active_tc.PC = 0;
|
||||
}
|
||||
|
||||
int mips_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
|
@ -57,9 +55,8 @@ int mips_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int mips_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#define UC_QEMU_TARGET_MIPS_H
|
||||
|
||||
// functions to read & write registers
|
||||
int mips_reg_read(uch handle, unsigned int regid, void *value);
|
||||
int mips_reg_write(uch handle, unsigned int regid, const void *value);
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
|
||||
void mips_reg_reset(uch handle);
|
||||
void mips_reg_reset(struct uc_struct *uc);
|
||||
|
||||
void mips_uc_init(struct uc_struct* uc);
|
||||
void mipsel_uc_init(struct uc_struct* uc);
|
||||
|
|
|
@ -2632,7 +2632,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
|||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (dc->uc->hook_insn) {
|
||||
struct hook_struct *trace = hook_find((uch)dc->uc, UC_HOOK_CODE, dc->pc);
|
||||
struct hook_struct *trace = hook_find(dc->uc, UC_HOOK_CODE, dc->pc);
|
||||
if (trace)
|
||||
gen_uc_tracecode(tcg_ctx, 4, trace->callback, dc->uc, dc->pc, trace->user_data);
|
||||
// if requested to emulate only some instructions, check if
|
||||
|
@ -5409,7 +5409,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
|
|||
// Only hook this block if it is not broken from previous translation due to
|
||||
// full translation cache
|
||||
if (env->uc->hook_block && !env->uc->block_full) {
|
||||
struct hook_struct *trace = hook_find((uch)env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||
if (trace) {
|
||||
// save block address to see if we need to patch block size later
|
||||
env->uc->block_addr = pc_start;
|
||||
|
|
|
@ -32,12 +32,10 @@ static void sparc_set_pc(struct uc_struct *uc, uint64_t address)
|
|||
((CPUSPARCState *)uc->current_cpu->env_ptr)->npc = address + 4;
|
||||
}
|
||||
|
||||
void sparc_reg_reset(uch handle)
|
||||
void sparc_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUArchState *env;
|
||||
CPUArchState *env = first_cpu->env_ptr;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
memset(env->gregs, 0, sizeof(env->gregs));
|
||||
memset(env->fpr, 0, sizeof(env->fpr));
|
||||
memset(env->regbase, 0, sizeof(env->regbase));
|
||||
|
@ -46,9 +44,8 @@ void sparc_reg_reset(uch handle)
|
|||
env->npc = 0;
|
||||
}
|
||||
|
||||
int sparc_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
|
@ -71,9 +68,8 @@ int sparc_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int sparc_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#define UC_QEMU_TARGET_SPARC_H
|
||||
|
||||
// functions to read & write registers
|
||||
int sparc_reg_read(uch handle, unsigned int regid, void *value);
|
||||
int sparc_reg_write(uch handle, unsigned int regid, const void *value);
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value);
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value);
|
||||
|
||||
void sparc_reg_reset(uch handle);
|
||||
void sparc_reg_reset(struct uc_struct *uc);
|
||||
|
||||
void sparc_uc_init(struct uc_struct* uc);
|
||||
void sparc64_uc_init(struct uc_struct* uc);
|
||||
|
|
|
@ -15,12 +15,10 @@
|
|||
#define READ_BYTE_L(x) (x & 0xff)
|
||||
|
||||
|
||||
void sparc_reg_reset(uch handle)
|
||||
void sparc_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUArchState *env;
|
||||
CPUArchState *env = first_cpu->env_ptr;
|
||||
|
||||
env = first_cpu->env_ptr;
|
||||
memset(env->gregs, 0, sizeof(env->gregs));
|
||||
memset(env->fpr, 0, sizeof(env->fpr));
|
||||
memset(env->regbase, 0, sizeof(env->regbase));
|
||||
|
@ -29,9 +27,8 @@ void sparc_reg_reset(uch handle)
|
|||
env->npc = 0;
|
||||
}
|
||||
|
||||
int sparc_reg_read(uch handle, unsigned int regid, void *value)
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
|
@ -54,9 +51,8 @@ int sparc_reg_read(uch handle, unsigned int regid, void *value)
|
|||
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | (b & 0xff))
|
||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||
|
||||
int sparc_reg_write(uch handle, unsigned int regid, const void *value)
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *) handle;
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
|
|
|
@ -12,7 +12,7 @@ static int count = 1;
|
|||
// @address: address where the code is being executed
|
||||
// @size: size of machine instruction being executed
|
||||
// @user_data: user data passed to tracing APIs.
|
||||
void cb_hookblock(uch handle, uint64_t address, uint32_t size, void *user_data) {
|
||||
void cb_hookblock(ucengine *uc, uint64_t address, uint32_t size, void *user_data) {
|
||||
fprintf(stderr, "# >>> Tracing basic block at 0x%llx, block size = 0x%x\n", address, size);
|
||||
if (address != 0x1000000 && address != 0x1000200) {
|
||||
fprintf(stderr, "not ok %d - address != 0x1000000 && address != 0x1000200\n", count++);
|
||||
|
@ -27,19 +27,19 @@ void cb_hookblock(uch handle, uint64_t address, uint32_t size, void *user_data)
|
|||
}
|
||||
|
||||
int main() {
|
||||
uch u;
|
||||
ucengine *uc;
|
||||
|
||||
fprintf(stderr, "# basic block callback test\n");
|
||||
fprintf(stderr, "# there are only two basic blocks 0x1000000-0x10001ff and 0x1000200-0x10003ff\n");
|
||||
|
||||
uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &u);
|
||||
uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err != UC_ERR_OK) {
|
||||
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
||||
exit(0);
|
||||
}
|
||||
fprintf(stderr, "ok %d - uc_open\n", count++);
|
||||
|
||||
err = uc_mem_map(u, 0x1000000, 4096, UC_PROT_ALL);
|
||||
err = uc_mem_map(uc, 0x1000000, 4096, UC_PROT_ALL);
|
||||
if (err != UC_ERR_OK) {
|
||||
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
||||
exit(0);
|
||||
|
@ -55,23 +55,23 @@ int main() {
|
|||
memset(code, 0x90, sizeof(code));
|
||||
memcpy(code + 1024 - 5, "\xe9\x00\xfe\xff\xff", 5);
|
||||
|
||||
err = uc_mem_write(u, 0x1000000, code, sizeof(code));
|
||||
err = uc_mem_write(uc, 0x1000000, code, sizeof(code));
|
||||
if (err != UC_ERR_OK) {
|
||||
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
||||
exit(0);
|
||||
}
|
||||
fprintf(stderr, "ok %d - uc_mem_write\n", count++);
|
||||
|
||||
uch h1, h2;
|
||||
uc_hook_h h1, h2;
|
||||
|
||||
err = uc_hook_add(u, &h1, UC_HOOK_BLOCK, cb_hookblock, NULL, (uint64_t)1, (uint64_t)0);
|
||||
err = uc_hook_add(uc, &h1, UC_HOOK_BLOCK, cb_hookblock, NULL, (uint64_t)1, (uint64_t)0);
|
||||
if (err != UC_ERR_OK) {
|
||||
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
||||
exit(0);
|
||||
}
|
||||
fprintf(stderr, "ok %d - uc_hook_add\n", count++);
|
||||
|
||||
err = uc_emu_start(u, 0x1000000, 0x1000000 + sizeof(code), 0, 1030);
|
||||
err = uc_emu_start(uc, 0x1000000, 0x1000000 + sizeof(code), 0, 1030);
|
||||
if (err != UC_ERR_OK) {
|
||||
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
||||
exit(0);
|
||||
|
|
|
@ -10,8 +10,8 @@ int main()
|
|||
{
|
||||
int size;
|
||||
uint8_t *buf;
|
||||
uch uh;
|
||||
uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh);
|
||||
ucengine *uc;
|
||||
uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
fprintf (stderr, "Cannot initialize unicorn\n");
|
||||
return 1;
|
||||
|
@ -23,9 +23,9 @@ int main()
|
|||
return 1;
|
||||
}
|
||||
memset (buf, 0, size);
|
||||
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
|
||||
uc_mem_write (uh, UC_BUG_WRITE_ADDR, buf, size);
|
||||
if (!uc_mem_map (uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
|
||||
uc_mem_write (uc, UC_BUG_WRITE_ADDR, buf, size);
|
||||
}
|
||||
uc_close (&uh);
|
||||
uc_close(uc);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,17 +8,17 @@
|
|||
|
||||
int main()
|
||||
{
|
||||
uch uh;
|
||||
ucengine *uc;
|
||||
uint8_t *buf, *buf2;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh);
|
||||
err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
printf ("uc_open %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
err = uc_mem_map (uh, ADDR, SIZE, UC_PROT_ALL);
|
||||
err = uc_mem_map (uc, ADDR, SIZE, UC_PROT_ALL);
|
||||
if (err) {
|
||||
printf ("uc_mem_map %d\n", err);
|
||||
return 1;
|
||||
|
@ -29,12 +29,12 @@ int main()
|
|||
buf[i] = i & 0xff;
|
||||
}
|
||||
/* crash here */
|
||||
err = uc_mem_write (uh, ADDR, buf, SIZE+OVERFLOW);
|
||||
err = uc_mem_write (uc, ADDR, buf, SIZE+OVERFLOW);
|
||||
if (err) {
|
||||
printf ("uc_mem_map %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
err = uc_mem_read (uh, ADDR+10, buf2, 4);
|
||||
err = uc_mem_read (uc, ADDR+10, buf2, 4);
|
||||
if (err) {
|
||||
printf ("uc_mem_map %d\n", err);
|
||||
return 1;
|
||||
|
|
|
@ -36,7 +36,7 @@ bits 32
|
|||
*/
|
||||
|
||||
// callback for tracing memory access (READ or WRITE)
|
||||
static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
||||
static bool hook_mem_invalid(ucengine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
|
||||
|
@ -54,42 +54,43 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
|||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uch handle, trace1, trace2;
|
||||
ucengine *uc;
|
||||
uc_hook_h trace1, trace2;
|
||||
uc_err err;
|
||||
uint32_t eax, ebx;
|
||||
|
||||
printf("Memory protections test\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ);
|
||||
uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(handle, 0x400000, 0x1000, UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x100000, 0x1000, UC_PROT_READ);
|
||||
uc_mem_map(uc, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x400000, 0x1000, UC_PROT_WRITE);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) {
|
||||
if (uc_mem_write(uc, 0x100000, PROGRAM, sizeof(PROGRAM))) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return 2;
|
||||
} else {
|
||||
printf("Allowed to write to read only memory via uc_mem_write\n");
|
||||
}
|
||||
|
||||
uc_mem_write(handle, 0x300000, (const uint8_t*)"\x41\x41\x41\x41", 4);
|
||||
uc_mem_write(handle, 0x400000, (const uint8_t*)"\x42\x42\x42\x42", 4);
|
||||
uc_mem_write(uc, 0x300000, (const uint8_t*)"\x41\x41\x41\x41", 4);
|
||||
uc_mem_write(uc, 0x400000, (const uint8_t*)"\x42\x42\x42\x42", 4);
|
||||
|
||||
//uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
||||
//uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
||||
|
||||
// intercept invalid memory events
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
printf("BEGIN execution\n");
|
||||
err = uc_emu_start(handle, 0x100000, 0x100000 + sizeof(PROGRAM), 0, 2);
|
||||
err = uc_emu_start(uc, 0x100000, 0x100000 + sizeof(PROGRAM), 0, 2);
|
||||
if (err) {
|
||||
printf("Expected failure on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -98,12 +99,12 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
printf("END execution\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EAX, &eax);
|
||||
uc_reg_read(uc, UC_X86_REG_EAX, &eax);
|
||||
printf("Final eax = 0x%x\n", eax);
|
||||
uc_reg_read(handle, UC_X86_REG_EBX, &ebx);
|
||||
uc_reg_read(uc, UC_X86_REG_EBX, &ebx);
|
||||
printf("Final ebx = 0x%x\n", ebx);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -50,17 +50,17 @@ hlt
|
|||
static int log_num = 1;
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t addr, uint32_t size, void *user_data)
|
||||
{
|
||||
uint8_t opcode;
|
||||
if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) {
|
||||
if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
_exit(-1);
|
||||
}
|
||||
switch (opcode) {
|
||||
case 0xf4: //hlt
|
||||
printf("# Handling HLT\n");
|
||||
if (uc_emu_stop(handle) != UC_ERR_OK) {
|
||||
if (uc_emu_stop(uc) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
_exit(-1);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data)
|
|||
}
|
||||
|
||||
// callback for tracing memory access (READ or WRITE)
|
||||
static void hook_mem_write(uch handle, uc_mem_type type,
|
||||
static void hook_mem_write(ucengine *uc, uc_mem_type type,
|
||||
uint64_t addr, int size, int64_t value, void *user_data)
|
||||
{
|
||||
printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
||||
|
@ -89,7 +89,8 @@ static void hook_mem_write(uch handle, uc_mem_type type,
|
|||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uch handle, trace1, trace2;
|
||||
ucengine *uc;
|
||||
uc_hook_h trace1, trace2;
|
||||
uc_err err;
|
||||
uint8_t buf1[100], readbuf[100];
|
||||
|
||||
|
@ -98,7 +99,7 @@ int main(int argc, char **argv, char **envp)
|
|||
memset(buf1, 'A', 20);
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
|
||||
return 1;
|
||||
|
@ -107,11 +108,11 @@ int main(int argc, char **argv, char **envp)
|
|||
printf("ok %d - uc_open() success\n", log_num++);
|
||||
}
|
||||
|
||||
uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ);
|
||||
uc_mem_map(handle, 0x200000, 0x2000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x100000, 0x1000, UC_PROT_READ);
|
||||
uc_mem_map(uc, 0x200000, 0x2000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
|
||||
// fill in the data that we want to copy
|
||||
if (uc_mem_write(handle, 0x200000, (uint8_t*)buf1, 20)) {
|
||||
if (uc_mem_write(uc, 0x200000, (uint8_t*)buf1, 20)) {
|
||||
printf("not ok %d - Failed to write read buffer to memory, quit!\n", log_num++);
|
||||
return 2;
|
||||
}
|
||||
|
@ -120,7 +121,7 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) {
|
||||
if (uc_mem_write(uc, 0x100000, PROGRAM, sizeof(PROGRAM))) {
|
||||
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
|
||||
return 4;
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ int main(int argc, char **argv, char **envp)
|
|||
printf("ok %d - Program written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) {
|
||||
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
|
||||
return 5;
|
||||
}
|
||||
|
@ -137,7 +138,7 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
|
||||
// intercept memory write events only, NOT read events
|
||||
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) {
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
|
||||
return 6;
|
||||
}
|
||||
|
@ -147,7 +148,7 @@ int main(int argc, char **argv, char **envp)
|
|||
|
||||
// emulate machine code until told to stop by hook_code
|
||||
printf("# BEGIN execution\n");
|
||||
err = uc_emu_start(handle, 0x100000, 0x101000, 0, 0);
|
||||
err = uc_emu_start(uc, 0x100000, 0x101000, 0, 0);
|
||||
if (err != UC_ERR_OK) {
|
||||
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
|
||||
return 8;
|
||||
|
@ -159,7 +160,7 @@ int main(int argc, char **argv, char **envp)
|
|||
|
||||
//make sure that data got copied
|
||||
// fill in sections that shouldn't get touched
|
||||
if (uc_mem_read(handle, 0x201000, (uint8_t*)readbuf, 20)) {
|
||||
if (uc_mem_read(uc, 0x201000, (uint8_t*)readbuf, 20)) {
|
||||
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
|
||||
}
|
||||
else {
|
||||
|
@ -172,7 +173,7 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
}
|
||||
|
||||
if (uc_close(&handle) == UC_ERR_OK) {
|
||||
if (uc_close(uc) == UC_ERR_OK) {
|
||||
printf("ok %d - uc_close complete\n", log_num++);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -46,22 +46,22 @@ bottom:
|
|||
*/
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
uint32_t esp;
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_ESP, &esp);
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
printf(">>> --- ESP is 0x%x\n", esp);
|
||||
|
||||
}
|
||||
|
||||
// callback for tracing memory access (READ or WRITE)
|
||||
static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
||||
static bool hook_mem_invalid(ucengine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
uint32_t esp;
|
||||
uc_reg_read(handle, UC_X86_REG_ESP, &esp);
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
|
@ -74,7 +74,7 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
|||
upper = (esp + 0xfff) & ~0xfff;
|
||||
printf(">>> Stack appears to be missing at 0x%"PRIx64 ", allocating now\n", address);
|
||||
// map this memory in with 2MB in size
|
||||
uc_mem_map(handle, upper - 0x8000, 0x8000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, upper - 0x8000, 0x8000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
// return true to indicate we want to continue
|
||||
return true;
|
||||
}
|
||||
|
@ -94,7 +94,8 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
|||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uch handle, trace1, trace2;
|
||||
ucengine *uc;
|
||||
uc_hook_h trace1, trace2;
|
||||
uc_err err;
|
||||
uint8_t bytes[8];
|
||||
uint32_t esp;
|
||||
|
@ -108,44 +109,44 @@ int main(int argc, char **argv, char **envp)
|
|||
printf("Memory mapping test\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_ALL);
|
||||
uc_mem_map(handle, 0x200000, 0x2000, UC_PROT_ALL);
|
||||
uc_mem_map(handle, 0x300000, 0x3000, UC_PROT_ALL);
|
||||
uc_mem_map(handle, 0x400000, 0x4000, UC_PROT_READ);
|
||||
uc_mem_map(uc, 0x100000, 0x1000, UC_PROT_ALL);
|
||||
uc_mem_map(uc, 0x200000, 0x2000, UC_PROT_ALL);
|
||||
uc_mem_map(uc, 0x300000, 0x3000, UC_PROT_ALL);
|
||||
uc_mem_map(uc, 0x400000, 0x4000, UC_PROT_READ);
|
||||
|
||||
if (map_stack) {
|
||||
printf("Pre-mapping stack\n");
|
||||
uc_mem_map(handle, STACK, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, STACK, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE);
|
||||
} else {
|
||||
printf("Mapping stack on first invalid memory access\n");
|
||||
}
|
||||
|
||||
esp = STACK + STACK_SIZE;
|
||||
|
||||
uc_reg_write(handle, UC_X86_REG_ESP, &esp);
|
||||
uc_reg_write(uc, UC_X86_REG_ESP, &esp);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, 0x400000, PROGRAM, sizeof(PROGRAM))) {
|
||||
if (uc_mem_write(uc, 0x400000, PROGRAM, sizeof(PROGRAM))) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return 2;
|
||||
} else {
|
||||
printf("Allowed to write to read only memory via uc_mem_write\n");
|
||||
}
|
||||
|
||||
//uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
||||
//uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
||||
|
||||
// intercept invalid memory events
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
printf("BEGIN execution - 1\n");
|
||||
err = uc_emu_start(handle, 0x400000, 0x400000 + sizeof(PROGRAM), 0, 10);
|
||||
err = uc_emu_start(uc, 0x400000, 0x400000 + sizeof(PROGRAM), 0, 10);
|
||||
if (err) {
|
||||
printf("Expected failue on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -157,8 +158,8 @@ int main(int argc, char **argv, char **envp)
|
|||
// emulate machine code in infinite time
|
||||
printf("BEGIN execution - 2\n");
|
||||
uint32_t eax = 0x40002C;
|
||||
uc_reg_write(handle, UC_X86_REG_EAX, &eax);
|
||||
err = uc_emu_start(handle, 0x400015, 0x400000 + sizeof(PROGRAM), 0, 2);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &eax);
|
||||
err = uc_emu_start(uc, 0x400015, 0x400000 + sizeof(PROGRAM), 0, 2);
|
||||
if (err) {
|
||||
printf("Expected failure on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -168,7 +169,7 @@ int main(int argc, char **argv, char **envp)
|
|||
printf("END execution - 2\n");
|
||||
|
||||
printf("Verifying content at 0x400025 is unchanged\n");
|
||||
if (!uc_mem_read(handle, 0x400025, bytes, 4)) {
|
||||
if (!uc_mem_read(uc, 0x400025, bytes, 4)) {
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)0x400025, *(uint32_t*) bytes);
|
||||
if (0x41414141 != *(uint32_t*) bytes) {
|
||||
printf("ERROR content in read only memory changed\n");
|
||||
|
@ -181,7 +182,7 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
|
||||
printf("Verifying content at 0x40002C is unchanged\n");
|
||||
if (!uc_mem_read(handle, 0x40002C, bytes, 4)) {
|
||||
if (!uc_mem_read(uc, 0x40002C, bytes, 4)) {
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)0x40002C, *(uint32_t*) bytes);
|
||||
if (0x42424242 != *(uint32_t*) bytes) {
|
||||
printf("ERROR content in read only memory changed\n");
|
||||
|
@ -194,14 +195,14 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
|
||||
printf("Verifying content at bottom of stack is readable and correct\n");
|
||||
if (!uc_mem_read(handle, esp - 4, bytes, 4)) {
|
||||
if (!uc_mem_read(uc, esp - 4, bytes, 4)) {
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)(esp - 4), *(uint32_t*) bytes);
|
||||
} else {
|
||||
printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4));
|
||||
return 4;
|
||||
}
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
int got_sigill = 0;
|
||||
|
||||
void _interrupt(uch handle, uint32_t intno, void *user_data)
|
||||
void _interrupt(ucengine *uc, uint32_t intno, void *user_data)
|
||||
{
|
||||
if (intno == 6) {
|
||||
uc_emu_stop (handle);
|
||||
uc_emu_stop(uc);
|
||||
got_sigill = 1;
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ int main()
|
|||
{
|
||||
int size;
|
||||
uint8_t *buf;
|
||||
uch uh;
|
||||
uch uh_trap;
|
||||
uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh);
|
||||
ucengine *uc;
|
||||
uc_hook_h uh_trap;
|
||||
uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
fprintf (stderr, "Cannot initialize unicorn\n");
|
||||
return 1;
|
||||
|
@ -34,13 +34,13 @@ int main()
|
|||
return 1;
|
||||
}
|
||||
memset (buf, 0, size);
|
||||
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
|
||||
uc_mem_write (uh, UC_BUG_WRITE_ADDR,
|
||||
if (!uc_mem_map(uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
|
||||
uc_mem_write(uc, UC_BUG_WRITE_ADDR,
|
||||
(const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);
|
||||
}
|
||||
uc_hook_add (uh, &uh_trap, UC_HOOK_INTR, _interrupt, NULL);
|
||||
uc_emu_start (uh, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
||||
uc_close (&uh);
|
||||
uc_hook_add(uc, &uh_trap, UC_HOOK_INTR, _interrupt, NULL);
|
||||
uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
||||
uc_close(uc);
|
||||
printf ("Correct: %s\n", got_sigill? "YES": "NO");
|
||||
return got_sigill? 0: 1;
|
||||
}
|
||||
|
|
|
@ -10,20 +10,20 @@ int main()
|
|||
{
|
||||
int size;
|
||||
uint8_t *buf;
|
||||
uch uh;
|
||||
uch uh_trap;
|
||||
uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh);
|
||||
ucengine *uc;
|
||||
|
||||
uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
fprintf (stderr, "Cannot initialize unicorn\n");
|
||||
return 1;
|
||||
}
|
||||
size = UC_BUG_WRITE_SIZE;
|
||||
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
|
||||
uc_mem_write (uh, UC_BUG_WRITE_ADDR,
|
||||
if (!uc_mem_map (uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
|
||||
uc_mem_write (uc, UC_BUG_WRITE_ADDR,
|
||||
(const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);
|
||||
}
|
||||
err = uc_emu_start (uh, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
||||
uc_close (&uh);
|
||||
err = uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
||||
uc_close(uc);
|
||||
printf ("Error = %u (%s)\n", err, uc_strerror(err));
|
||||
return err? -1: 0;
|
||||
}
|
||||
|
|
|
@ -24,21 +24,21 @@ https://github.com/unicorn-engine/unicorn/issues/78
|
|||
// number of seconds to wait before timeout
|
||||
#define TIMEOUT 5
|
||||
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_arm(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r0 = 0x1234; // R0 register
|
||||
int r2 = 0x6789; // R1 register
|
||||
|
@ -48,7 +48,7 @@ static void test_arm(void)
|
|||
printf("Emulate ARM code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &handle);
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -56,25 +56,25 @@ static void test_arm(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_write(handle, UC_ARM_REG_R2, &r2);
|
||||
uc_reg_write(handle, UC_ARM_REG_R3, &r3);
|
||||
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_write(uc, UC_ARM_REG_R2, &r2);
|
||||
uc_reg_write(uc, UC_ARM_REG_R3, &r3);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, UC_SECOND_SCALE * TIMEOUT, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, UC_SECOND_SCALE * TIMEOUT, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
@ -82,26 +82,26 @@ static void test_arm(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_read(handle, UC_ARM_REG_R1, &r1);
|
||||
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_read(uc, UC_ARM_REG_R1, &r1);
|
||||
printf(">>> R0 = 0x%x\n", r0);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_thumb(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int sp = 0x1234; // R0 register
|
||||
|
||||
printf("Emulate THUMB code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &handle);
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -109,23 +109,23 @@ static void test_thumb(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_ARM_REG_SP, &sp);
|
||||
uc_reg_write(uc, UC_ARM_REG_SP, &sp);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, UC_SECOND_SCALE * TIMEOUT, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, UC_SECOND_SCALE * TIMEOUT, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
@ -133,10 +133,10 @@ static void test_thumb(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_ARM_REG_SP, &sp);
|
||||
uc_reg_read(uc, UC_ARM_REG_SP, &sp);
|
||||
printf(">>> SP = 0x%x\n", sp);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -15,21 +15,21 @@
|
|||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_arm(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r0 = 0x1234; // R0 register
|
||||
int r2 = 0x6789; // R1 register
|
||||
|
@ -39,7 +39,7 @@ static void test_arm(void)
|
|||
printf("Emulate ARM code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &handle);
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -47,25 +47,25 @@ static void test_arm(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_write(handle, UC_ARM_REG_R2, &r2);
|
||||
uc_reg_write(handle, UC_ARM_REG_R3, &r3);
|
||||
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_write(uc, UC_ARM_REG_R2, &r2);
|
||||
uc_reg_write(uc, UC_ARM_REG_R3, &r3);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
@ -73,26 +73,26 @@ static void test_arm(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_read(handle, UC_ARM_REG_R1, &r1);
|
||||
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_read(uc, UC_ARM_REG_R1, &r1);
|
||||
printf(">>> R0 = 0x%x\n", r0);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_thumb(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int sp = 0x1234; // R0 register
|
||||
|
||||
printf("Emulate THUMB code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &handle);
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -100,23 +100,23 @@ static void test_thumb(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_ARM_REG_SP, &sp);
|
||||
uc_reg_write(uc, UC_ARM_REG_SP, &sp);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
@ -124,10 +124,10 @@ static void test_thumb(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_ARM_REG_SP, &sp);
|
||||
uc_reg_read(uc, UC_ARM_REG_SP, &sp);
|
||||
printf(">>> SP = 0x%x\n", sp);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_arm64(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int64_t x11 = 0x1234; // X11 register
|
||||
int64_t x13 = 0x6789; // X13 register
|
||||
|
@ -37,7 +37,7 @@ static void test_arm64(void)
|
|||
printf("Emulate ARM64 code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &handle);
|
||||
err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -45,25 +45,25 @@ static void test_arm64(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_ARM64_REG_X11, &x11);
|
||||
uc_reg_write(handle, UC_ARM64_REG_X13, &x13);
|
||||
uc_reg_write(handle, UC_ARM64_REG_X15, &x15);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X11, &x11);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X13, &x13);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X15, &x15);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
@ -71,10 +71,10 @@ static void test_arm64(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_ARM64_REG_X11, &x11);
|
||||
uc_reg_read(uc, UC_ARM64_REG_X11, &x11);
|
||||
printf(">>> X11 = 0x%" PRIx64 "\n", x11);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -12,20 +12,20 @@
|
|||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_m68k(void)
|
||||
{
|
||||
uch handle;
|
||||
uch trace1, trace2;
|
||||
ucengine *uc;
|
||||
uc_hook_h trace1, trace2;
|
||||
uc_err err;
|
||||
|
||||
int d0 = 0x0000; // d0 data register
|
||||
|
@ -52,7 +52,7 @@ static void test_m68k(void)
|
|||
printf("Emulate M68K code\n");
|
||||
|
||||
// Initialize emulator in M68K mode
|
||||
err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &handle);
|
||||
err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -60,42 +60,42 @@ static void test_m68k(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)M68K_CODE, sizeof(M68K_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)M68K_CODE, sizeof(M68K_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_M68K_REG_D0, &d0);
|
||||
uc_reg_write(handle, UC_M68K_REG_D1, &d1);
|
||||
uc_reg_write(handle, UC_M68K_REG_D2, &d2);
|
||||
uc_reg_write(handle, UC_M68K_REG_D3, &d3);
|
||||
uc_reg_write(handle, UC_M68K_REG_D4, &d4);
|
||||
uc_reg_write(handle, UC_M68K_REG_D5, &d5);
|
||||
uc_reg_write(handle, UC_M68K_REG_D6, &d6);
|
||||
uc_reg_write(handle, UC_M68K_REG_D7, &d7);
|
||||
uc_reg_write(uc, UC_M68K_REG_D0, &d0);
|
||||
uc_reg_write(uc, UC_M68K_REG_D1, &d1);
|
||||
uc_reg_write(uc, UC_M68K_REG_D2, &d2);
|
||||
uc_reg_write(uc, UC_M68K_REG_D3, &d3);
|
||||
uc_reg_write(uc, UC_M68K_REG_D4, &d4);
|
||||
uc_reg_write(uc, UC_M68K_REG_D5, &d5);
|
||||
uc_reg_write(uc, UC_M68K_REG_D6, &d6);
|
||||
uc_reg_write(uc, UC_M68K_REG_D7, &d7);
|
||||
|
||||
uc_reg_write(handle, UC_M68K_REG_A0, &a0);
|
||||
uc_reg_write(handle, UC_M68K_REG_A1, &a1);
|
||||
uc_reg_write(handle, UC_M68K_REG_A2, &a2);
|
||||
uc_reg_write(handle, UC_M68K_REG_A3, &a3);
|
||||
uc_reg_write(handle, UC_M68K_REG_A4, &a4);
|
||||
uc_reg_write(handle, UC_M68K_REG_A5, &a5);
|
||||
uc_reg_write(handle, UC_M68K_REG_A6, &a6);
|
||||
uc_reg_write(handle, UC_M68K_REG_A7, &a7);
|
||||
uc_reg_write(uc, UC_M68K_REG_A0, &a0);
|
||||
uc_reg_write(uc, UC_M68K_REG_A1, &a1);
|
||||
uc_reg_write(uc, UC_M68K_REG_A2, &a2);
|
||||
uc_reg_write(uc, UC_M68K_REG_A3, &a3);
|
||||
uc_reg_write(uc, UC_M68K_REG_A4, &a4);
|
||||
uc_reg_write(uc, UC_M68K_REG_A5, &a5);
|
||||
uc_reg_write(uc, UC_M68K_REG_A6, &a6);
|
||||
uc_reg_write(uc, UC_M68K_REG_A7, &a7);
|
||||
|
||||
uc_reg_write(handle, UC_M68K_REG_PC, &pc);
|
||||
uc_reg_write(handle, UC_M68K_REG_SR, &sr);
|
||||
uc_reg_write(uc, UC_M68K_REG_PC, &pc);
|
||||
uc_reg_write(uc, UC_M68K_REG_SR, &sr);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instruction
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
@ -103,26 +103,26 @@ static void test_m68k(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_M68K_REG_D0, &d0);
|
||||
uc_reg_read(handle, UC_M68K_REG_D1, &d1);
|
||||
uc_reg_read(handle, UC_M68K_REG_D2, &d2);
|
||||
uc_reg_read(handle, UC_M68K_REG_D3, &d3);
|
||||
uc_reg_read(handle, UC_M68K_REG_D4, &d4);
|
||||
uc_reg_read(handle, UC_M68K_REG_D5, &d5);
|
||||
uc_reg_read(handle, UC_M68K_REG_D6, &d6);
|
||||
uc_reg_read(handle, UC_M68K_REG_D7, &d7);
|
||||
uc_reg_read(uc, UC_M68K_REG_D0, &d0);
|
||||
uc_reg_read(uc, UC_M68K_REG_D1, &d1);
|
||||
uc_reg_read(uc, UC_M68K_REG_D2, &d2);
|
||||
uc_reg_read(uc, UC_M68K_REG_D3, &d3);
|
||||
uc_reg_read(uc, UC_M68K_REG_D4, &d4);
|
||||
uc_reg_read(uc, UC_M68K_REG_D5, &d5);
|
||||
uc_reg_read(uc, UC_M68K_REG_D6, &d6);
|
||||
uc_reg_read(uc, UC_M68K_REG_D7, &d7);
|
||||
|
||||
uc_reg_read(handle, UC_M68K_REG_A0, &a0);
|
||||
uc_reg_read(handle, UC_M68K_REG_A1, &a1);
|
||||
uc_reg_read(handle, UC_M68K_REG_A2, &a2);
|
||||
uc_reg_read(handle, UC_M68K_REG_A3, &a3);
|
||||
uc_reg_read(handle, UC_M68K_REG_A4, &a4);
|
||||
uc_reg_read(handle, UC_M68K_REG_A5, &a5);
|
||||
uc_reg_read(handle, UC_M68K_REG_A6, &a6);
|
||||
uc_reg_read(handle, UC_M68K_REG_A7, &a7);
|
||||
uc_reg_read(uc, UC_M68K_REG_A0, &a0);
|
||||
uc_reg_read(uc, UC_M68K_REG_A1, &a1);
|
||||
uc_reg_read(uc, UC_M68K_REG_A2, &a2);
|
||||
uc_reg_read(uc, UC_M68K_REG_A3, &a3);
|
||||
uc_reg_read(uc, UC_M68K_REG_A4, &a4);
|
||||
uc_reg_read(uc, UC_M68K_REG_A5, &a5);
|
||||
uc_reg_read(uc, UC_M68K_REG_A6, &a6);
|
||||
uc_reg_read(uc, UC_M68K_REG_A7, &a7);
|
||||
|
||||
uc_reg_read(handle, UC_M68K_REG_PC, &pc);
|
||||
uc_reg_read(handle, UC_M68K_REG_SR, &sr);
|
||||
uc_reg_read(uc, UC_M68K_REG_PC, &pc);
|
||||
uc_reg_read(uc, UC_M68K_REG_SR, &sr);
|
||||
|
||||
printf(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n", a0, d0);
|
||||
printf(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n", a1, d1);
|
||||
|
@ -135,7 +135,7 @@ static void test_m68k(void)
|
|||
printf(">>> PC = 0x%x\n", pc);
|
||||
printf(">>> SR = 0x%x\n", sr);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -15,28 +15,28 @@
|
|||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_mips_eb(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r1 = 0x6789; // R1 register
|
||||
|
||||
printf("Emulate MIPS code (big-endian)\n");
|
||||
|
||||
// Initialize emulator in MIPS mode
|
||||
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &handle);
|
||||
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -44,23 +44,23 @@ static void test_mips_eb(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_MIPS_REG_1, &r1);
|
||||
uc_reg_write(uc, UC_MIPS_REG_1, &r1);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err));
|
||||
}
|
||||
|
@ -68,17 +68,17 @@ static void test_mips_eb(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_MIPS_REG_1, &r1);
|
||||
uc_reg_read(uc, UC_MIPS_REG_1, &r1);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_mips_el(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r1 = 0x6789; // R1 register
|
||||
|
||||
|
@ -86,7 +86,7 @@ static void test_mips_el(void)
|
|||
printf("Emulate MIPS code (little-endian)\n");
|
||||
|
||||
// Initialize emulator in MIPS mode
|
||||
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &handle);
|
||||
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -94,23 +94,23 @@ static void test_mips_el(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_MIPS_REG_1, &r1);
|
||||
uc_reg_write(uc, UC_MIPS_REG_1, &r1);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err));
|
||||
}
|
||||
|
@ -118,10 +118,10 @@ static void test_mips_el(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_MIPS_REG_1, &r1);
|
||||
uc_reg_read(uc, UC_MIPS_REG_1, &r1);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -15,21 +15,21 @@
|
|||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_sparc(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int g1 = 0x1230; // G1 register
|
||||
int g2 = 0x6789; // G2 register
|
||||
|
@ -38,7 +38,7 @@ static void test_sparc(void)
|
|||
printf("Emulate SPARC code\n");
|
||||
|
||||
// Initialize emulator in Sparc mode
|
||||
err = uc_open(UC_ARCH_SPARC, UC_MODE_BIG_ENDIAN, &handle);
|
||||
err = uc_open(UC_ARCH_SPARC, UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -46,25 +46,25 @@ static void test_sparc(void)
|
|||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(handle, ADDRESS, (uint8_t *)SPARC_CODE, sizeof(SPARC_CODE) - 1);
|
||||
uc_mem_write(uc, ADDRESS, (uint8_t *)SPARC_CODE, sizeof(SPARC_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_SPARC_REG_G1, &g1);
|
||||
uc_reg_write(handle, UC_SPARC_REG_G2, &g2);
|
||||
uc_reg_write(handle, UC_SPARC_REG_G3, &g3);
|
||||
uc_reg_write(uc, UC_SPARC_REG_G1, &g1);
|
||||
uc_reg_write(uc, UC_SPARC_REG_G2, &g2);
|
||||
uc_reg_write(uc, UC_SPARC_REG_G3, &g3);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
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(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(SPARC_CODE) -1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -73,10 +73,10 @@ static void test_sparc(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_SPARC_REG_G3, &g3);
|
||||
uc_reg_read(uc, UC_SPARC_REG_G3, &g3);
|
||||
printf(">>> G3 = 0x%x\n", g3);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -32,41 +32,41 @@
|
|||
#define ADDRESS 0x1000000
|
||||
|
||||
// callback for tracing basic blocks
|
||||
static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_block(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
int eflags;
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EFLAGS, &eflags);
|
||||
uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
|
||||
printf(">>> --- EFLAGS is 0x%x\n", eflags);
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// uc_emu_stop(handle);
|
||||
// uc_emu_stop(uc);
|
||||
}
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code64(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code64(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
uint64_t rip;
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_RIP, &rip);
|
||||
uc_reg_read(uc, UC_X86_REG_RIP, &rip);
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
printf(">>> RIP is 0x%"PRIx64 "\n", rip);
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// uc_emu_stop(handle);
|
||||
// uc_emu_stop(uc);
|
||||
}
|
||||
|
||||
// callback for tracing memory access (READ or WRITE)
|
||||
static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
||||
static bool hook_mem_invalid(ucengine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
switch(type) {
|
||||
|
@ -77,13 +77,13 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type,
|
|||
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
|
||||
uc_mem_map(handle, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL);
|
||||
// return true to indicate we want to continue
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void hook_mem64(uch handle, uc_mem_type type,
|
||||
static void hook_mem64(ucengine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
switch(type) {
|
||||
|
@ -101,11 +101,11 @@ static void hook_mem64(uch handle, uc_mem_type type,
|
|||
|
||||
// callback for IN instruction (X86).
|
||||
// this returns the data read from the port
|
||||
static uint32_t hook_in(uch handle, uint32_t port, int size, void *user_data)
|
||||
static uint32_t hook_in(ucengine *uc, uint32_t port, int size, void *user_data)
|
||||
{
|
||||
uint32_t eip;
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EIP, &eip);
|
||||
uc_reg_read(uc, UC_X86_REG_EIP, &eip);
|
||||
|
||||
printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size, eip);
|
||||
|
||||
|
@ -126,12 +126,12 @@ static uint32_t hook_in(uch handle, uint32_t port, int size, void *user_data)
|
|||
}
|
||||
|
||||
// callback for OUT instruction (X86).
|
||||
static void hook_out(uch handle, uint32_t port, int size, uint32_t value, void *user_data)
|
||||
static void hook_out(ucengine *uc, uint32_t port, int size, uint32_t value, void *user_data)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t eip;
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EIP, &eip);
|
||||
uc_reg_read(uc, UC_X86_REG_EIP, &eip);
|
||||
|
||||
printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n", port, size, value, eip);
|
||||
|
||||
|
@ -140,13 +140,13 @@ static void hook_out(uch handle, uint32_t port, int size, uint32_t value, void *
|
|||
default:
|
||||
return; // should never reach this
|
||||
case 1:
|
||||
uc_reg_read(handle, UC_X86_REG_AL, &tmp);
|
||||
uc_reg_read(uc, UC_X86_REG_AL, &tmp);
|
||||
break;
|
||||
case 2:
|
||||
uc_reg_read(handle, UC_X86_REG_AX, &tmp);
|
||||
uc_reg_read(uc, UC_X86_REG_AX, &tmp);
|
||||
break;
|
||||
case 4:
|
||||
uc_reg_read(handle, UC_X86_REG_EAX, &tmp);
|
||||
uc_reg_read(uc, UC_X86_REG_EAX, &tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -154,24 +154,24 @@ static void hook_out(uch handle, uint32_t port, int size, uint32_t value, void *
|
|||
}
|
||||
|
||||
// callback for SYSCALL instruction (X86).
|
||||
static void hook_syscall(uch handle, void *user_data)
|
||||
static void hook_syscall(ucengine *uc, void *user_data)
|
||||
{
|
||||
uint64_t rax;
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_read(uc, UC_X86_REG_RAX, &rax);
|
||||
if (rax == 0x100) {
|
||||
rax = 0x200;
|
||||
uc_reg_write(handle, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
|
||||
} else
|
||||
printf("ERROR: was not expecting rax=0x%"PRIx64 " in syscall\n", rax);
|
||||
}
|
||||
|
||||
static void test_i386(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uint32_t tmp;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
int r_edx = 0x7890; // EDX register
|
||||
|
@ -179,33 +179,33 @@ static void test_i386(void)
|
|||
printf("Emulate i386 code\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32, sizeof(X86_CODE32) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32, sizeof(X86_CODE32) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instruction by having @begin > @end
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -214,54 +214,54 @@ static void test_i386(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
|
||||
// read from memory
|
||||
if (!uc_mem_read(handle, ADDRESS, (uint8_t *)&tmp, 4))
|
||||
if (!uc_mem_read(uc, ADDRESS, (uint8_t *)&tmp, 4))
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp);
|
||||
else
|
||||
printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_i386_jump(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
printf("===================================\n");
|
||||
printf("Emulate i386 code with jump\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_JUMP,
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_JUMP,
|
||||
sizeof(X86_CODE32_JUMP) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// tracing 1 basic block with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// tracing 1 instruction at ADDRESS
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -269,13 +269,13 @@ static void test_i386_jump(void)
|
|||
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
// emulate code that loop forever
|
||||
static void test_i386_loop(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
|
@ -285,28 +285,28 @@ static void test_i386_loop(void)
|
|||
printf("Emulate i386 code that loop forever\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// emulate machine code in 2 seconds, so we can quit even
|
||||
// if the code loops
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, 2 * UC_SECOND_SCALE, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, 2 * UC_SECOND_SCALE, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -315,20 +315,20 @@ static void test_i386_loop(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
// emulate code that read invalid memory
|
||||
static void test_i386_invalid_mem_read(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
int r_edx = 0x7890; // EDX register
|
||||
|
@ -337,33 +337,33 @@ static void test_i386_invalid_mem_read(void)
|
|||
printf("Emulate i386 code that read from invalid memory\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_MEM_READ, sizeof(X86_CODE32_MEM_READ) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_MEM_READ, sizeof(X86_CODE32_MEM_READ) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instruction by having @begin > @end
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -372,20 +372,20 @@ static void test_i386_invalid_mem_read(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
// emulate code that read invalid memory
|
||||
static void test_i386_invalid_mem_write(void)
|
||||
{
|
||||
uch handle, evh;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2; //, trace3;
|
||||
uc_hook_h trace1, trace2, trace3;
|
||||
uint32_t tmp;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
|
@ -395,36 +395,36 @@ static void test_i386_invalid_mem_write(void)
|
|||
printf("Emulate i386 code that write to invalid memory\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instruction by having @begin > @end
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// intercept invalid memory events
|
||||
uc_hook_add(handle, &evh, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
||||
uc_hook_add(uc, &trace3, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -433,31 +433,31 @@ static void test_i386_invalid_mem_write(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
|
||||
// read from memory
|
||||
if (!uc_mem_read(handle, 0xaaaaaaaa, (uint8_t *)&tmp, 4))
|
||||
if (!uc_mem_read(uc, 0xaaaaaaaa, (uint8_t *)&tmp, 4))
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xaaaaaaaa, tmp);
|
||||
else
|
||||
printf(">>> Failed to read 4 bytes from [0x%x]\n", 0xffffffaa);
|
||||
|
||||
if (!uc_mem_read(handle, 0xffffffaa, (uint8_t *)&tmp, 4))
|
||||
if (!uc_mem_read(uc, 0xffffffaa, (uint8_t *)&tmp, 4))
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xffffffaa, tmp);
|
||||
else
|
||||
printf(">>> Failed to read 4 bytes from [0x%x]\n", 0xffffffaa);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
// emulate code that jump to invalid memory
|
||||
static void test_i386_jump_invalid(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
int r_edx = 0x7890; // EDX register
|
||||
|
@ -466,33 +466,33 @@ static void test_i386_jump_invalid(void)
|
|||
printf("Emulate i386 code that jumps to invalid memory\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_JMP_INVALID, sizeof(X86_CODE32_JMP_INVALID) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_JMP_INVALID, sizeof(X86_CODE32_JMP_INVALID) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instructions by having @begin > @end
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -501,20 +501,19 @@ static void test_i386_jump_invalid(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_i386_inout(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2;
|
||||
uch trace3, trace4;
|
||||
uc_hook_h trace1, trace2, trace3, trace4;
|
||||
|
||||
int r_eax = 0x1234; // EAX register
|
||||
int r_ecx = 0x6789; // ECX register
|
||||
|
@ -523,38 +522,38 @@ static void test_i386_inout(void)
|
|||
printf("Emulate i386 code with IN/OUT instructions\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_EAX, &r_eax);
|
||||
uc_reg_write(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &r_eax);
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instructions
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// handle IN instruction
|
||||
uc_hook_add(handle, &trace3, UC_HOOK_INSN, hook_in, NULL, UC_X86_INS_IN);
|
||||
// handle OUT instruction
|
||||
uc_hook_add(handle, &trace4, UC_HOOK_INSN, hook_out, NULL, UC_X86_INS_OUT);
|
||||
// uc IN instruction
|
||||
uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, UC_X86_INS_IN);
|
||||
// uc OUT instruction
|
||||
uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, UC_X86_INS_OUT);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -563,19 +562,19 @@ static void test_i386_inout(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EAX, &r_eax);
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
printf(">>> EAX = 0x%x\n", r_eax);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_x86_64(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1, trace2, trace3, trace4;
|
||||
uc_hook_h trace1, trace2, trace3, trace4;
|
||||
|
||||
int64_t rax = 0x71f3029efd49d41d;
|
||||
int64_t rbx = 0xd87b45277f133ddb;
|
||||
|
@ -598,54 +597,54 @@ static void test_x86_64(void)
|
|||
printf("Emulate x86_64 code\n");
|
||||
|
||||
// Initialize emulator in X86-64bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE64, sizeof(X86_CODE64) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE64, sizeof(X86_CODE64) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_RSP, &rsp);
|
||||
uc_reg_write(uc, UC_X86_REG_RSP, &rsp);
|
||||
|
||||
uc_reg_write(handle, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_write(handle, UC_X86_REG_RBX, &rbx);
|
||||
uc_reg_write(handle, UC_X86_REG_RCX, &rcx);
|
||||
uc_reg_write(handle, UC_X86_REG_RDX, &rdx);
|
||||
uc_reg_write(handle, UC_X86_REG_RSI, &rsi);
|
||||
uc_reg_write(handle, UC_X86_REG_RDI, &rdi);
|
||||
uc_reg_write(handle, UC_X86_REG_R8, &r8);
|
||||
uc_reg_write(handle, UC_X86_REG_R9, &r9);
|
||||
uc_reg_write(handle, UC_X86_REG_R10, &r10);
|
||||
uc_reg_write(handle, UC_X86_REG_R11, &r11);
|
||||
uc_reg_write(handle, UC_X86_REG_R12, &r12);
|
||||
uc_reg_write(handle, UC_X86_REG_R13, &r13);
|
||||
uc_reg_write(handle, UC_X86_REG_R14, &r14);
|
||||
uc_reg_write(handle, UC_X86_REG_R15, &r15);
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_write(uc, UC_X86_REG_RBX, &rbx);
|
||||
uc_reg_write(uc, UC_X86_REG_RCX, &rcx);
|
||||
uc_reg_write(uc, UC_X86_REG_RDX, &rdx);
|
||||
uc_reg_write(uc, UC_X86_REG_RSI, &rsi);
|
||||
uc_reg_write(uc, UC_X86_REG_RDI, &rdi);
|
||||
uc_reg_write(uc, UC_X86_REG_R8, &r8);
|
||||
uc_reg_write(uc, UC_X86_REG_R9, &r9);
|
||||
uc_reg_write(uc, UC_X86_REG_R10, &r10);
|
||||
uc_reg_write(uc, UC_X86_REG_R11, &r11);
|
||||
uc_reg_write(uc, UC_X86_REG_R12, &r12);
|
||||
uc_reg_write(uc, UC_X86_REG_R13, &r13);
|
||||
uc_reg_write(uc, UC_X86_REG_R14, &r14);
|
||||
uc_reg_write(uc, UC_X86_REG_R15, &r15);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instructions in the range [ADDRESS, ADDRESS+20]
|
||||
uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)ADDRESS, (uint64_t)(ADDRESS+20));
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)ADDRESS, (uint64_t)(ADDRESS+20));
|
||||
|
||||
// tracing all memory WRITE access (with @begin > @end)
|
||||
uc_hook_add(handle, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all memory READ access (with @begin > @end)
|
||||
uc_hook_add(handle, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0);
|
||||
uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -654,20 +653,20 @@ static void test_x86_64(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_read(handle, UC_X86_REG_RBX, &rbx);
|
||||
uc_reg_read(handle, UC_X86_REG_RCX, &rcx);
|
||||
uc_reg_read(handle, UC_X86_REG_RDX, &rdx);
|
||||
uc_reg_read(handle, UC_X86_REG_RSI, &rsi);
|
||||
uc_reg_read(handle, UC_X86_REG_RDI, &rdi);
|
||||
uc_reg_read(handle, UC_X86_REG_R8, &r8);
|
||||
uc_reg_read(handle, UC_X86_REG_R9, &r9);
|
||||
uc_reg_read(handle, UC_X86_REG_R10, &r10);
|
||||
uc_reg_read(handle, UC_X86_REG_R11, &r11);
|
||||
uc_reg_read(handle, UC_X86_REG_R12, &r12);
|
||||
uc_reg_read(handle, UC_X86_REG_R13, &r13);
|
||||
uc_reg_read(handle, UC_X86_REG_R14, &r14);
|
||||
uc_reg_read(handle, UC_X86_REG_R15, &r15);
|
||||
uc_reg_read(uc, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_read(uc, UC_X86_REG_RBX, &rbx);
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &rdx);
|
||||
uc_reg_read(uc, UC_X86_REG_RSI, &rsi);
|
||||
uc_reg_read(uc, UC_X86_REG_RDI, &rdi);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &r8);
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &r9);
|
||||
uc_reg_read(uc, UC_X86_REG_R10, &r10);
|
||||
uc_reg_read(uc, UC_X86_REG_R11, &r11);
|
||||
uc_reg_read(uc, UC_X86_REG_R12, &r12);
|
||||
uc_reg_read(uc, UC_X86_REG_R13, &r13);
|
||||
uc_reg_read(uc, UC_X86_REG_R14, &r14);
|
||||
uc_reg_read(uc, UC_X86_REG_R15, &r15);
|
||||
|
||||
printf(">>> RAX = 0x%" PRIx64 "\n", rax);
|
||||
printf(">>> RBX = 0x%" PRIx64 "\n", rbx);
|
||||
|
@ -684,13 +683,13 @@ static void test_x86_64(void)
|
|||
printf(">>> R14 = 0x%" PRIx64 "\n", r14);
|
||||
printf(">>> R15 = 0x%" PRIx64 "\n", r15);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_x86_64_syscall(void)
|
||||
{
|
||||
uch handle;
|
||||
uch trace1;
|
||||
ucengine *uc;
|
||||
uc_hook_h trace1;
|
||||
uc_err err;
|
||||
|
||||
int64_t rax = 0x100;
|
||||
|
@ -699,30 +698,30 @@ static void test_x86_64_syscall(void)
|
|||
printf("Emulate x86_64 code with 'syscall' instruction\n");
|
||||
|
||||
// Initialize emulator in X86-64bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE64_SYSCALL, sizeof(X86_CODE64_SYSCALL) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE64_SYSCALL, sizeof(X86_CODE64_SYSCALL) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// hook interrupts for syscall
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_INSN, hook_syscall, NULL, UC_X86_INS_SYSCALL);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, UC_X86_INS_SYSCALL);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -731,16 +730,16 @@ static void test_x86_64_syscall(void)
|
|||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_read(uc, UC_X86_REG_RAX, &rax);
|
||||
|
||||
printf(">>> RAX = 0x%" PRIx64 "\n", rax);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_x86_16(void)
|
||||
{
|
||||
uch handle;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uint8_t tmp;
|
||||
|
||||
|
@ -751,29 +750,29 @@ static void test_x86_16(void)
|
|||
printf("Emulate x86 16-bit code\n");
|
||||
|
||||
// Initialize emulator in X86-16bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_16, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 8KB memory for this emulation
|
||||
uc_mem_map(handle, 0, 8 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, 0, 8 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) {
|
||||
if (uc_mem_write(uc, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_EAX, &eax);
|
||||
uc_reg_write(handle, UC_X86_REG_EBX, &ebx);
|
||||
uc_reg_write(handle, UC_X86_REG_ESI, &esi);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &eax);
|
||||
uc_reg_write(uc, UC_X86_REG_EBX, &ebx);
|
||||
uc_reg_write(uc, UC_X86_REG_ESI, &esi);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, 0, sizeof(X86_CODE16) - 1, 0, 0);
|
||||
err = uc_emu_start(uc, 0, sizeof(X86_CODE16) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -783,12 +782,12 @@ static void test_x86_16(void)
|
|||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
// read from memory
|
||||
if (!uc_mem_read(handle, 11, &tmp, 1))
|
||||
if (!uc_mem_read(uc, 11, &tmp, 1))
|
||||
printf(">>> Read 1 bytes from [0x%x] = 0x%x\n", 11, tmp);
|
||||
else
|
||||
printf(">>> Failed to read 1 bytes from [0x%x]\n", 11);
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
|
@ -20,18 +20,18 @@
|
|||
|
||||
#define MIN(a, b) (a < b? a : b)
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data)
|
||||
static void hook_code(ucengine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
int r_eip;
|
||||
char tmp[16];
|
||||
|
||||
printf("Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EIP, &r_eip);
|
||||
uc_reg_read(uc, UC_X86_REG_EIP, &r_eip);
|
||||
printf("*** EIP = %x ***: ", r_eip);
|
||||
|
||||
size = MIN(sizeof(tmp), size);
|
||||
if (!uc_mem_read(handle, address, (uint8_t *)tmp, size)) {
|
||||
if (!uc_mem_read(uc, address, (uint8_t *)tmp, size)) {
|
||||
int i;
|
||||
for (i=0; i<size; i++) {
|
||||
printf("%x ", ((uint8_t*)tmp)[i]);
|
||||
|
@ -43,7 +43,7 @@ static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_da
|
|||
#define MIN(a, b) (a < b? a : b)
|
||||
// callback for handling interrupt
|
||||
// ref: http://syscalls.kernelgrok.com/
|
||||
static void hook_intr(uch handle, uint32_t intno, void *user_data)
|
||||
static void hook_intr(ucengine *uc, uint32_t intno, void *user_data)
|
||||
{
|
||||
int32_t r_eax, r_ecx, r_eip;
|
||||
uint32_t r_edx, size;
|
||||
|
@ -53,8 +53,8 @@ static void hook_intr(uch handle, uint32_t intno, void *user_data)
|
|||
if (intno != 0x80)
|
||||
return;
|
||||
|
||||
uc_reg_read(handle, UC_X86_REG_EAX, &r_eax);
|
||||
uc_reg_read(handle, UC_X86_REG_EIP, &r_eip);
|
||||
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
|
||||
uc_reg_read(uc, UC_X86_REG_EIP, &r_eip);
|
||||
|
||||
switch(r_eax) {
|
||||
default:
|
||||
|
@ -62,19 +62,19 @@ static void hook_intr(uch handle, uint32_t intno, void *user_data)
|
|||
break;
|
||||
case 1: // sys_exit
|
||||
printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno);
|
||||
uc_emu_stop(handle);
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
case 4: // sys_write
|
||||
// ECX = buffer address
|
||||
uc_reg_read(handle, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
|
||||
// EDX = buffer size
|
||||
uc_reg_read(handle, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// read the buffer in
|
||||
size = MIN(sizeof(buffer)-1, r_edx);
|
||||
|
||||
if (!uc_mem_read(handle, r_ecx, buffer, size)) {
|
||||
if (!uc_mem_read(uc, r_ecx, buffer, size)) {
|
||||
buffer[size] = '\0';
|
||||
printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n",
|
||||
r_eip, intno, r_ecx, r_edx, buffer);
|
||||
|
@ -88,44 +88,44 @@ static void hook_intr(uch handle, uint32_t intno, void *user_data)
|
|||
|
||||
static void test_i386(void)
|
||||
{
|
||||
uch handle, evh;
|
||||
ucengine *uc;
|
||||
uc_err err;
|
||||
uch trace1;
|
||||
uc_hook_h trace1, trace2;
|
||||
|
||||
int r_esp = ADDRESS + 0x200000; // ESP register
|
||||
|
||||
printf("Emulate i386 code\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, ADDRESS, (uint8_t *)X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) {
|
||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_ESP, &r_esp);
|
||||
uc_reg_write(uc, UC_X86_REG_ESP, &r_esp);
|
||||
|
||||
// tracing all instructions by having @begin > @end
|
||||
uc_hook_add(handle, &trace1, UC_HOOK_CODE, hook_code, NULL, 1, 0);
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_CODE, hook_code, NULL, 1, 0);
|
||||
|
||||
// handle interrupt ourself
|
||||
uc_hook_add(handle, &evh, UC_HOOK_INTR, hook_intr, NULL);
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_INTR, hook_intr, NULL);
|
||||
|
||||
printf("\n>>> Start tracing this Linux code\n");
|
||||
|
||||
// emulate machine code in infinite time
|
||||
// err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, 12); <--- emulate only 12 instructions
|
||||
err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0);
|
||||
// err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, 12); <--- emulate only 12 instructions
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
|
@ -133,7 +133,7 @@ static void test_i386(void)
|
|||
|
||||
printf("\n>>> Emulation done.\n");
|
||||
|
||||
uc_close(&handle);
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
|
|
183
uc.c
183
uc.c
|
@ -44,15 +44,8 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor)
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_errno(uch handle)
|
||||
uc_err uc_errno(ucengine *uc)
|
||||
{
|
||||
struct uc_struct *uc;
|
||||
|
||||
if (!handle)
|
||||
return UC_ERR_UCH;
|
||||
|
||||
uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
return uc->errnum;
|
||||
}
|
||||
|
||||
|
@ -71,8 +64,6 @@ const char *uc_strerror(uc_err code)
|
|||
return "Invalid/unsupported architecture(UC_ERR_ARCH)";
|
||||
case UC_ERR_HANDLE:
|
||||
return "Invalid handle (UC_ERR_HANDLE)";
|
||||
case UC_ERR_UCH:
|
||||
return "Invalid uch (UC_ERR_UCH)";
|
||||
case UC_ERR_MODE:
|
||||
return "Invalid mode (UC_ERR_MODE)";
|
||||
case UC_ERR_VERSION:
|
||||
|
@ -130,7 +121,7 @@ bool uc_arch_supported(uc_arch arch)
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_open(uc_arch arch, uc_mode mode, uch *handle)
|
||||
uc_err uc_open(uc_arch arch, uc_mode mode, ucengine **result)
|
||||
{
|
||||
struct uc_struct *uc;
|
||||
|
||||
|
@ -179,7 +170,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uch *handle)
|
|||
|
||||
// verify mode
|
||||
if (mode != UC_MODE_ARM && mode != UC_MODE_THUMB) {
|
||||
*handle = 0;
|
||||
free(uc);
|
||||
return UC_ERR_MODE;
|
||||
}
|
||||
|
@ -229,38 +219,29 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uch *handle)
|
|||
}
|
||||
|
||||
if (uc->init_arch == NULL) {
|
||||
*handle = 0;
|
||||
return UC_ERR_ARCH;
|
||||
}
|
||||
|
||||
machine_initialize(uc);
|
||||
|
||||
*handle = (uintptr_t)uc;
|
||||
*result = uc;
|
||||
|
||||
if (uc->reg_reset)
|
||||
uc->reg_reset(*handle);
|
||||
uc->reg_reset(uc);
|
||||
|
||||
uc->hook_size = HOOK_SIZE;
|
||||
uc->hook_callbacks = calloc(1, sizeof(uc->hook_callbacks[0]) * HOOK_SIZE);
|
||||
|
||||
return UC_ERR_OK;
|
||||
} else {
|
||||
*handle = 0;
|
||||
return UC_ERR_ARCH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_close(uch *handle)
|
||||
uc_err uc_close(ucengine *uc)
|
||||
{
|
||||
struct uc_struct *uc;
|
||||
|
||||
// invalid handle ?
|
||||
if (*handle == 0)
|
||||
return UC_ERR_UCH;
|
||||
|
||||
uc = (struct uc_struct *)(*handle);
|
||||
if (uc->release)
|
||||
uc->release(uc->tcg_ctx);
|
||||
|
||||
|
@ -294,26 +275,15 @@ uc_err uc_close(uch *handle)
|
|||
memset(uc, 0, sizeof(*uc));
|
||||
free(uc);
|
||||
|
||||
// invalidate this handle by ZERO out its value.
|
||||
// this is to make sure it is unusable after uc_close()
|
||||
*handle = 0;
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uch handle, int regid, void *value)
|
||||
uc_err uc_reg_read(ucengine *uc, int regid, void *value)
|
||||
{
|
||||
struct uc_struct *uc;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
uc = (struct uc_struct *)handle;
|
||||
if (uc->reg_read)
|
||||
uc->reg_read(handle, regid, value);
|
||||
uc->reg_read(uc, regid, value);
|
||||
else
|
||||
return -1; // FIXME: need a proper uc_err
|
||||
|
||||
|
@ -322,17 +292,10 @@ uc_err uc_reg_read(uch handle, int regid, void *value)
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write(uch handle, int regid, const void *value)
|
||||
uc_err uc_reg_write(ucengine *uc, int regid, const void *value)
|
||||
{
|
||||
struct uc_struct *uc;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
uc = (struct uc_struct *)handle;
|
||||
if (uc->reg_write)
|
||||
uc->reg_write(handle, regid, value);
|
||||
uc->reg_write(uc, regid, value);
|
||||
else
|
||||
return -1; // FIXME: need a proper uc_err
|
||||
|
||||
|
@ -342,7 +305,7 @@ uc_err uc_reg_write(uch handle, int regid, const void *value)
|
|||
|
||||
// check if a memory area is mapped
|
||||
// this is complicated because an area can overlap adjacent blocks
|
||||
static bool check_mem_area(struct uc_struct *uc, uint64_t address, size_t size)
|
||||
static bool check_mem_area(ucengine *uc, uint64_t address, size_t size)
|
||||
{
|
||||
size_t count = 0, len;
|
||||
|
||||
|
@ -361,14 +324,8 @@ static bool check_mem_area(struct uc_struct *uc, uint64_t address, size_t size)
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
|
||||
uc_err uc_mem_read(ucengine *uc, uint64_t address, uint8_t *bytes, size_t size)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
if (!check_mem_area(uc, address, size))
|
||||
return UC_ERR_MEM_READ;
|
||||
|
||||
|
@ -395,14 +352,8 @@ uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
|
|||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size)
|
||||
uc_err uc_mem_write(ucengine *uc, uint64_t address, const uint8_t *bytes, size_t size)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
if (!check_mem_area(uc, address, size))
|
||||
return UC_ERR_MEM_WRITE;
|
||||
|
||||
|
@ -441,7 +392,7 @@ uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t s
|
|||
#define TIMEOUT_STEP 2 // microseconds
|
||||
static void *_timeout_fn(void *arg)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)arg;
|
||||
struct uc_struct *uc = arg;
|
||||
int64_t current_time = get_clock();
|
||||
|
||||
do {
|
||||
|
@ -454,30 +405,22 @@ static void *_timeout_fn(void *arg)
|
|||
// timeout before emulation is done?
|
||||
if (!uc->emulation_done) {
|
||||
// force emulation to stop
|
||||
uc_emu_stop((uch)uc);
|
||||
uc_emu_stop(uc);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void enable_emu_timer(uch handle, uint64_t timeout)
|
||||
static void enable_emu_timer(ucengine *uc, uint64_t timeout)
|
||||
{
|
||||
struct uc_struct *uc = (struct uc_struct *)handle;
|
||||
|
||||
uc->timeout = timeout;
|
||||
qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn,
|
||||
uc, QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout, size_t count)
|
||||
uc_err uc_emu_start(ucengine* uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count)
|
||||
{
|
||||
struct uc_struct* uc = (struct uc_struct *)handle;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
// reset the counter
|
||||
uc->emu_counter = 0;
|
||||
uc->stop_request = false;
|
||||
|
@ -490,7 +433,7 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout
|
|||
break;
|
||||
|
||||
case UC_ARCH_M68K:
|
||||
uc_reg_write(handle, UC_M68K_REG_PC, &begin);
|
||||
uc_reg_write(uc, UC_M68K_REG_PC, &begin);
|
||||
break;
|
||||
|
||||
case UC_ARCH_X86:
|
||||
|
@ -498,13 +441,13 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout
|
|||
default:
|
||||
break;
|
||||
case UC_MODE_16:
|
||||
uc_reg_write(handle, UC_X86_REG_IP, &begin);
|
||||
uc_reg_write(uc, UC_X86_REG_IP, &begin);
|
||||
break;
|
||||
case UC_MODE_32:
|
||||
uc_reg_write(handle, UC_X86_REG_EIP, &begin);
|
||||
uc_reg_write(uc, UC_X86_REG_EIP, &begin);
|
||||
break;
|
||||
case UC_MODE_64:
|
||||
uc_reg_write(handle, UC_X86_REG_RIP, &begin);
|
||||
uc_reg_write(uc, UC_X86_REG_RIP, &begin);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -515,23 +458,23 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout
|
|||
break;
|
||||
case UC_MODE_THUMB:
|
||||
case UC_MODE_ARM:
|
||||
uc_reg_write(handle, UC_ARM_REG_R15, &begin);
|
||||
uc_reg_write(uc, UC_ARM_REG_R15, &begin);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case UC_ARCH_ARM64:
|
||||
uc_reg_write(handle, UC_ARM64_REG_PC, &begin);
|
||||
uc_reg_write(uc, UC_ARM64_REG_PC, &begin);
|
||||
break;
|
||||
|
||||
case UC_ARCH_MIPS:
|
||||
// TODO: MIPS32/MIPS64/BIGENDIAN etc
|
||||
uc_reg_write(handle, UC_MIPS_REG_PC, &begin);
|
||||
uc_reg_write(uc, UC_MIPS_REG_PC, &begin);
|
||||
break;
|
||||
|
||||
case UC_ARCH_SPARC:
|
||||
// TODO: Sparc/Sparc64
|
||||
uc_reg_write(handle, UC_SPARC_REG_PC, &begin);
|
||||
uc_reg_write(uc, UC_SPARC_REG_PC, &begin);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -544,7 +487,7 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout
|
|||
|
||||
uc->vm_start(uc);
|
||||
if (timeout)
|
||||
enable_emu_timer(handle, timeout * 1000); // microseconds -> nanoseconds
|
||||
enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds
|
||||
uc->pause_all_vcpus(uc);
|
||||
// emulation is done
|
||||
uc->emulation_done = true;
|
||||
|
@ -559,14 +502,8 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_emu_stop(uch handle)
|
||||
uc_err uc_emu_stop(ucengine *uc)
|
||||
{
|
||||
struct uc_struct* uc = (struct uc_struct *)handle;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
if (uc->emulation_done)
|
||||
return UC_ERR_OK;
|
||||
|
||||
|
@ -578,45 +515,40 @@ uc_err uc_emu_stop(uch handle)
|
|||
}
|
||||
|
||||
|
||||
static int _hook_code(uch handle, int type, uint64_t begin, uint64_t end,
|
||||
void *callback, void *user_data, uch *h2)
|
||||
static int _hook_code(ucengine *uc, int type, uint64_t begin, uint64_t end,
|
||||
void *callback, void *user_data, uc_hook_h *hh)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = hook_add(handle, type, begin, end, callback, user_data);
|
||||
i = hook_add(uc, type, begin, end, callback, user_data);
|
||||
if (i == 0)
|
||||
return UC_ERR_OOM; // FIXME
|
||||
|
||||
*h2 = i;
|
||||
*hh = i;
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
static uc_err _hook_mem_access(uch handle, uc_hook_t type,
|
||||
static uc_err _hook_mem_access(ucengine *uc, uc_hook_t type,
|
||||
uint64_t begin, uint64_t end,
|
||||
void *callback, void *user_data, uch *h2)
|
||||
void *callback, void *user_data, uc_hook_h *hh)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = hook_add(handle, type, begin, end, callback, user_data);
|
||||
i = hook_add(uc, type, begin, end, callback, user_data);
|
||||
if (i == 0)
|
||||
return UC_ERR_OOM; // FIXME
|
||||
|
||||
*h2 = i;
|
||||
*hh = i;
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms)
|
||||
uc_err uc_mem_map(ucengine *uc, uint64_t address, size_t size, uint32_t perms)
|
||||
{
|
||||
MemoryRegion **regions;
|
||||
struct uc_struct* uc = (struct uc_struct *)handle;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
if (size == 0)
|
||||
// invalid memory mapping
|
||||
|
@ -647,7 +579,7 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms)
|
|||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
|
||||
MemoryRegion *memory_mapping(ucengine* uc, uint64_t address)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -661,7 +593,7 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
|
|||
}
|
||||
|
||||
static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
|
||||
void *user_data, uch *evh)
|
||||
void *user_data, uc_hook_h *evh)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -680,7 +612,7 @@ static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
|
|||
|
||||
|
||||
static uc_err _hook_intr(struct uc_struct* uc, void *callback,
|
||||
void *user_data, uch *evh)
|
||||
void *user_data, uc_hook_h *evh)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -699,7 +631,7 @@ static uc_err _hook_intr(struct uc_struct* uc, void *callback,
|
|||
|
||||
|
||||
static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callback,
|
||||
void *user_data, uch *evh)
|
||||
void *user_data, uc_hook_h *evh)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -750,18 +682,13 @@ static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callb
|
|||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_hook_add(uch handle, uch *h2, uc_hook_t type, void *callback, void *user_data, ...)
|
||||
uc_err uc_hook_add(ucengine *uc, uc_hook_h *hh, uc_hook_t type, void *callback, void *user_data, ...)
|
||||
{
|
||||
struct uc_struct* uc = (struct uc_struct *)handle;
|
||||
va_list valist;
|
||||
int ret = UC_ERR_OK;
|
||||
int id;
|
||||
uint64_t begin, end;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
va_start(valist, user_data);
|
||||
|
||||
switch(type) {
|
||||
|
@ -769,39 +696,39 @@ uc_err uc_hook_add(uch handle, uch *h2, uc_hook_t type, void *callback, void *us
|
|||
ret = UC_ERR_HOOK;
|
||||
break;
|
||||
case UC_HOOK_INTR:
|
||||
ret = _hook_intr(uc, callback, user_data, h2);
|
||||
ret = _hook_intr(uc, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_INSN:
|
||||
id = va_arg(valist, int);
|
||||
ret = _hook_insn(uc, id, callback, user_data, h2);
|
||||
ret = _hook_insn(uc, id, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_CODE:
|
||||
begin = va_arg(valist, uint64_t);
|
||||
end = va_arg(valist, uint64_t);
|
||||
ret = _hook_code(handle, UC_HOOK_CODE, begin, end, callback, user_data, h2);
|
||||
ret = _hook_code(uc, UC_HOOK_CODE, begin, end, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_BLOCK:
|
||||
begin = va_arg(valist, uint64_t);
|
||||
end = va_arg(valist, uint64_t);
|
||||
ret = _hook_code(handle, UC_HOOK_BLOCK, begin, end, callback, user_data, h2);
|
||||
ret = _hook_code(uc, UC_HOOK_BLOCK, begin, end, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_MEM_INVALID:
|
||||
ret = _hook_mem_invalid(uc, callback, user_data, h2);
|
||||
ret = _hook_mem_invalid(uc, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_MEM_READ:
|
||||
begin = va_arg(valist, uint64_t);
|
||||
end = va_arg(valist, uint64_t);
|
||||
ret = _hook_mem_access(handle, UC_HOOK_MEM_READ, begin, end, callback, user_data, h2);
|
||||
ret = _hook_mem_access(uc, UC_HOOK_MEM_READ, begin, end, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_MEM_WRITE:
|
||||
begin = va_arg(valist, uint64_t);
|
||||
end = va_arg(valist, uint64_t);
|
||||
ret = _hook_mem_access(handle, UC_HOOK_MEM_WRITE, begin, end, callback, user_data, h2);
|
||||
ret = _hook_mem_access(uc, UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh);
|
||||
break;
|
||||
case UC_HOOK_MEM_READ_WRITE:
|
||||
begin = va_arg(valist, uint64_t);
|
||||
end = va_arg(valist, uint64_t);
|
||||
ret = _hook_mem_access(handle, UC_HOOK_MEM_READ_WRITE, begin, end, callback, user_data, h2);
|
||||
ret = _hook_mem_access(uc, UC_HOOK_MEM_READ_WRITE, begin, end, callback, user_data, hh);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -811,17 +738,7 @@ uc_err uc_hook_add(uch handle, uch *h2, uc_hook_t type, void *callback, void *us
|
|||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_hook_del(uch handle, uch *h2)
|
||||
uc_err uc_hook_del(ucengine *uc, uc_hook_h hh)
|
||||
{
|
||||
//struct uc_struct* uc = (struct uc_struct *)handle;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
if (*h2 == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_HANDLE;
|
||||
|
||||
return hook_del(handle, h2);
|
||||
return hook_del(uc, hh);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue