mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-01 23:21:08 +00:00
Merge branch 'batch_reg' of https://github.com/lunixbochs/unicorn into lunixbochs-batch_reg
This commit is contained in:
commit
721f17eb74
23
bindings/go/unicorn/uc.c
Normal file
23
bindings/go/unicorn/uc.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <stdlib.h>
|
||||
#include <unicorn/unicorn.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count) {
|
||||
void **val_ref = malloc(sizeof(void *) * count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
val_ref[i] = (void *)&val_out[i];
|
||||
}
|
||||
uc_err ret = uc_reg_read_batch(handle, regs, val_ref, count);
|
||||
free(val_ref);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count) {
|
||||
const void **val_ref = malloc(sizeof(void *) * count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
val_ref[i] = (void *)&val_in[i];
|
||||
}
|
||||
uc_err ret = uc_reg_write_batch(handle, regs, val_ref, count);
|
||||
free(val_ref);
|
||||
return ret;
|
||||
}
|
2
bindings/go/unicorn/uc.h
Normal file
2
bindings/go/unicorn/uc.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count);
|
||||
uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count);
|
|
@ -7,8 +7,10 @@ import (
|
|||
)
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -O3
|
||||
#cgo LDFLAGS: -lunicorn
|
||||
#include <unicorn/unicorn.h>
|
||||
#include "uc.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
|
@ -41,7 +43,9 @@ type Unicorn interface {
|
|||
MemReadInto(dst []byte, addr uint64) error
|
||||
MemWrite(addr uint64, data []byte) error
|
||||
RegRead(reg int) (uint64, error)
|
||||
RegReadBatch(regs []int) ([]uint64, error)
|
||||
RegWrite(reg int, value uint64) error
|
||||
RegWriteBatch(regs []int, vals []uint64) error
|
||||
RegReadMmr(reg int) (*X86Mmr, error)
|
||||
RegWriteMmr(reg int, value *X86Mmr) error
|
||||
Start(begin, until uint64) error
|
||||
|
@ -117,6 +121,38 @@ func (u *uc) RegRead(reg int) (uint64, error) {
|
|||
return uint64(val), errReturn(ucerr)
|
||||
}
|
||||
|
||||
func (u *uc) RegWriteBatch(regs []int, vals []uint64) error {
|
||||
if len(regs) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(vals) < len(regs) {
|
||||
regs = regs[:len(vals)]
|
||||
}
|
||||
cregs := make([]C.int, len(regs))
|
||||
for i, v := range regs {
|
||||
cregs[i] = C.int(v)
|
||||
}
|
||||
cregs2 := (*C.int)(unsafe.Pointer(&cregs[0]))
|
||||
cvals := (*C.uint64_t)(unsafe.Pointer(&vals[0]))
|
||||
ucerr := C.uc_reg_write_batch_helper(u.handle, cregs2, cvals, C.int(len(regs)))
|
||||
return errReturn(ucerr)
|
||||
}
|
||||
|
||||
func (u *uc) RegReadBatch(regs []int) ([]uint64, error) {
|
||||
if len(regs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
cregs := make([]C.int, len(regs))
|
||||
for i, v := range regs {
|
||||
cregs[i] = C.int(v)
|
||||
}
|
||||
cregs2 := (*C.int)(unsafe.Pointer(&cregs[0]))
|
||||
vals := make([]uint64, len(regs))
|
||||
cvals := (*C.uint64_t)(unsafe.Pointer(&vals[0]))
|
||||
ucerr := C.uc_reg_read_batch_helper(u.handle, cregs2, cvals, C.int(len(regs)))
|
||||
return vals, errReturn(ucerr)
|
||||
}
|
||||
|
||||
func (u *uc) MemRegions() ([]*MemRegion, error) {
|
||||
var regions *C.struct_uc_mem_region
|
||||
var count C.uint32_t
|
||||
|
|
|
@ -46,8 +46,8 @@ typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
|
|||
typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result);
|
||||
|
||||
// return 0 on success, -1 on failure
|
||||
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 int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
typedef void (*reg_reset_t)(struct uc_struct *uc);
|
||||
|
||||
|
|
|
@ -386,6 +386,34 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
|
|||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value);
|
||||
|
||||
/*
|
||||
Write multiple register values.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@rges: array of register IDs to store
|
||||
@value: pointer to array of register values
|
||||
@count: length of both *regs and *vals
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, int count);
|
||||
|
||||
/*
|
||||
Read multiple register values.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@rges: array of register IDs to retrieve
|
||||
@value: pointer to array of values to hold registers
|
||||
@count: length of both *regs and *vals
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count);
|
||||
|
||||
/*
|
||||
Write to a range of bytes in memory.
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#define UC_QEMU_TARGET_ARM_H
|
||||
|
||||
// functions to read & write registers
|
||||
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);
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
void arm_reg_reset(struct uc_struct *uc);
|
||||
void arm64_reg_reset(struct uc_struct *uc);
|
||||
|
|
|
@ -23,57 +23,67 @@ void arm64_reg_reset(struct uc_struct *uc)
|
|||
env->pc = 0;
|
||||
}
|
||||
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
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];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_ARM64_REG_X29:
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[29];
|
||||
break;
|
||||
case UC_ARM64_REG_X30:
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[30];
|
||||
break;
|
||||
case UC_ARM64_REG_PC:
|
||||
*(uint64_t *)value = ARM_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
case UC_ARM64_REG_SP:
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[31];
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
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];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_ARM64_REG_X29:
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[29];
|
||||
break;
|
||||
case UC_ARM64_REG_X30:
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[30];
|
||||
break;
|
||||
case UC_ARM64_REG_PC:
|
||||
*(uint64_t *)value = ARM_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
case UC_ARM64_REG_SP:
|
||||
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[31];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
|
||||
ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_ARM64_REG_X29:
|
||||
ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_X30:
|
||||
ARM_CPU(uc, mycpu)->env.xregs[30] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_PC:
|
||||
ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
case UC_ARM64_REG_SP:
|
||||
ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value;
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
|
||||
ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_ARM64_REG_X29:
|
||||
ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_X30:
|
||||
ARM_CPU(uc, mycpu)->env.xregs[30] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_PC:
|
||||
ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
case UC_ARM64_REG_SP:
|
||||
ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,62 +27,72 @@ void arm_reg_reset(struct uc_struct *uc)
|
|||
env->pc = 0;
|
||||
}
|
||||
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu;
|
||||
int i;
|
||||
|
||||
mycpu = first_cpu;
|
||||
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12)
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0];
|
||||
else {
|
||||
switch(regid) {
|
||||
case UC_ARM_REG_CPSR:
|
||||
*(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env);
|
||||
break;
|
||||
//case UC_ARM_REG_SP:
|
||||
case UC_ARM_REG_R13:
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13];
|
||||
break;
|
||||
//case UC_ARM_REG_LR:
|
||||
case UC_ARM_REG_R14:
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14];
|
||||
break;
|
||||
//case UC_ARM_REG_PC:
|
||||
case UC_ARM_REG_R15:
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15];
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12)
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0];
|
||||
else {
|
||||
switch(regid) {
|
||||
case UC_ARM_REG_CPSR:
|
||||
*(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env);
|
||||
break;
|
||||
//case UC_ARM_REG_SP:
|
||||
case UC_ARM_REG_R13:
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13];
|
||||
break;
|
||||
//case UC_ARM_REG_LR:
|
||||
case UC_ARM_REG_R14:
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14];
|
||||
break;
|
||||
//case UC_ARM_REG_PC:
|
||||
case UC_ARM_REG_R15:
|
||||
*(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12)
|
||||
ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
//case UC_ARM_REG_SP:
|
||||
case UC_ARM_REG_R13:
|
||||
ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value;
|
||||
break;
|
||||
//case UC_ARM_REG_LR:
|
||||
case UC_ARM_REG_R14:
|
||||
ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value;
|
||||
break;
|
||||
//case UC_ARM_REG_PC:
|
||||
case UC_ARM_REG_R15:
|
||||
ARM_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
|
||||
ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12)
|
||||
ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
//case UC_ARM_REG_SP:
|
||||
case UC_ARM_REG_R13:
|
||||
ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value;
|
||||
break;
|
||||
//case UC_ARM_REG_LR:
|
||||
case UC_ARM_REG_R14:
|
||||
ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value;
|
||||
break;
|
||||
//case UC_ARM_REG_PC:
|
||||
case UC_ARM_REG_R15:
|
||||
ARM_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
|
||||
ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,8 +5,8 @@
|
|||
#define UC_QEMU_TARGET_I386_H
|
||||
|
||||
// functions to read & write registers
|
||||
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);
|
||||
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
void x86_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
|
|
@ -25,47 +25,56 @@ void m68k_reg_reset(struct uc_struct *uc)
|
|||
env->pc = 0;
|
||||
}
|
||||
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
*(int32_t *)value = M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0];
|
||||
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
|
||||
*(int32_t *)value = M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_M68K_REG_PC:
|
||||
*(int32_t *)value = M68K_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
*(int32_t *)value = M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0];
|
||||
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
|
||||
*(int32_t *)value = M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_M68K_REG_PC:
|
||||
*(int32_t *)value = M68K_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
|
||||
M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_M68K_REG_PC:
|
||||
M68K_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
|
||||
M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_M68K_REG_PC:
|
||||
M68K_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#define UC_QEMU_TARGET_M68K_H
|
||||
|
||||
// functions to read & write registers
|
||||
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);
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
void m68k_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
|
|
@ -39,43 +39,52 @@ void mips_reg_reset(struct uc_struct *uc)
|
|||
env->active_tc.PC = 0;
|
||||
}
|
||||
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
*(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_MIPS_REG_PC:
|
||||
*(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC;
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
*(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_MIPS_REG_PC:
|
||||
*(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_MIPS_REG_PC:
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_MIPS_REG_PC:
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#define UC_QEMU_TARGET_MIPS_H
|
||||
|
||||
// functions to read & write registers
|
||||
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);
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
void mips_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
|
|
@ -39,52 +39,62 @@ void sparc_reg_reset(struct uc_struct *uc)
|
|||
env->regwptr = env->regbase;
|
||||
}
|
||||
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0];
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0];
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0];
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0];
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
*(int32_t *)value = SPARC_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
|
||||
SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
|
||||
SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#define UC_QEMU_TARGET_SPARC_H
|
||||
|
||||
// functions to read & write registers
|
||||
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);
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
void sparc_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
|
|
@ -39,53 +39,62 @@ void sparc_reg_reset(struct uc_struct *uc)
|
|||
env->regwptr = env->regbase;
|
||||
}
|
||||
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0];
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0];
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0];
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0];
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
*(int64_t *)value = SPARC_CPU(uc, mycpu)->env.pc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count)
|
||||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
int i;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
SPARC_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
|
||||
SPARC_CPU(uc, mycpu)->env.npc = *(uint64_t *)value + 4;
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
SPARC_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
|
||||
SPARC_CPU(uc, mycpu)->env.npc = *(uint64_t *)value + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ SOURCES += sample_x86.c
|
|||
SOURCES += shellcode.c
|
||||
SOURCES += mem_apis.c
|
||||
SOURCES += sample_x86_32_gdt_and_seg_regs.c
|
||||
SOURCES += sample_batch_reg.c
|
||||
endif
|
||||
ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_m68k.c
|
||||
|
@ -114,7 +115,7 @@ all: clean_bins $(BINARY)
|
|||
|
||||
clean_bins:
|
||||
rm -rf *.o $(OBJS_ELF) $(BINARY) $(SAMPLEDIR)/*.exe $(SAMPLEDIR)/*.static $(OBJDIR)/lib$(LIBNAME)* $(OBJDIR)/$(LIBNAME)*
|
||||
rm -rf sample_x86 sample_arm sample_arm64 sample_mips sample_sparc sample_ppc sample_m68k shellcode mem_apis sample_x86_32_gdt_and_seg_regs
|
||||
rm -rf sample_x86 sample_arm sample_arm64 sample_mips sample_sparc sample_ppc sample_m68k shellcode mem_apis sample_x86_32_gdt_and_seg_regs sample_batch_reg
|
||||
|
||||
clean_libs:
|
||||
rm -rf libunicorn*.so libunicorn*.lib libunicorn*.dylib unicorn*.dll unicorn*.lib
|
||||
|
|
90
samples/sample_batch_reg.c
Normal file
90
samples/sample_batch_reg.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
int syscall_abi[] = {UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9};
|
||||
uint64_t vals[7] = {200, 10, 11, 12, 13, 14, 15};
|
||||
// This part of the API is less... clean... because Unicorn supports arbitrary register types.
|
||||
// So the least intrusive solution is passing individual pointers.
|
||||
// On the plus side, you only need to make this pointer array once.
|
||||
void *ptrs[7];
|
||||
|
||||
void uc_perror(const char *func, uc_err err) {
|
||||
fprintf(stderr, "Error in %s(): %s\n", func, uc_strerror(err));
|
||||
}
|
||||
|
||||
#define BASE 0x10000
|
||||
|
||||
// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov r9, 6; syscall
|
||||
#define CODE "\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05"
|
||||
|
||||
void hook_syscall(uc_engine *uc, void *user_data) {
|
||||
int i;
|
||||
uc_reg_read_batch(uc, syscall_abi, ptrs, 7);
|
||||
printf("syscall: {");
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (i != 0) printf(", ");
|
||||
printf("%llu", vals[i]);
|
||||
}
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data) {
|
||||
printf("HOOK_CODE: 0x%llx, 0x%x\n", addr, size);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
// set up register pointers
|
||||
for (i = 0; i < 7; i++) {
|
||||
ptrs[i] = &vals[i];
|
||||
}
|
||||
|
||||
uc_err err;
|
||||
uc_engine *uc;
|
||||
if ((err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc))) {
|
||||
uc_perror("uc_open", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// reg_write_batch
|
||||
printf("reg_write_batch({200, 10, 11, 12, 13, 14, 15})\n");
|
||||
if ((err = uc_reg_write_batch(uc, syscall_abi, ptrs, 7))) {
|
||||
uc_perror("uc_reg_write_batch", err);
|
||||
return 1;
|
||||
}
|
||||
// reg_read_batch
|
||||
memset(vals, 0, sizeof(vals));
|
||||
if ((err = uc_reg_read_batch(uc, syscall_abi, ptrs, 7))) {
|
||||
uc_perror("uc_reg_read_batch", err);
|
||||
return 1;
|
||||
}
|
||||
printf("reg_read_batch = {");
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (i != 0) printf(", ");
|
||||
printf("%llu", vals[i]);
|
||||
}
|
||||
printf("}\n");
|
||||
|
||||
// syscall
|
||||
printf("\n");
|
||||
printf("running syscall shellcode\n");
|
||||
uc_hook sys_hook;
|
||||
if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL))) {
|
||||
uc_perror("uc_hook_add", err);
|
||||
return 1;
|
||||
}
|
||||
if ((err = uc_mem_map(uc, BASE, 0x1000, UC_PROT_ALL))) {
|
||||
uc_perror("uc_mem_map", err);
|
||||
return 1;
|
||||
}
|
||||
if ((err = uc_mem_write(uc, BASE, CODE, sizeof(CODE) - 1))) {
|
||||
uc_perror("uc_mem_write", err);
|
||||
return 1;
|
||||
}
|
||||
if ((err = uc_emu_start(uc, BASE, BASE + sizeof(CODE) - 1, 0, 0))) {
|
||||
uc_perror("uc_emu_start", err);
|
||||
return 1;
|
||||
}
|
||||
}
|
22
uc.c
22
uc.c
|
@ -332,10 +332,10 @@ uc_err uc_close(uc_engine *uc)
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
||||
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
|
||||
{
|
||||
if (uc->reg_read)
|
||||
uc->reg_read(uc, regid, value);
|
||||
uc->reg_read(uc, (unsigned int *)ids, vals, count);
|
||||
else
|
||||
return -1; // FIXME: need a proper uc_err
|
||||
|
||||
|
@ -344,10 +344,10 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
|||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
||||
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
|
||||
{
|
||||
if (uc->reg_write)
|
||||
uc->reg_write(uc, regid, value);
|
||||
uc->reg_write(uc, (unsigned int *)ids, vals, count);
|
||||
else
|
||||
return -1; // FIXME: need a proper uc_err
|
||||
|
||||
|
@ -355,6 +355,20 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
|||
}
|
||||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
||||
{
|
||||
return uc_reg_read_batch(uc, ®id, &value, 1);
|
||||
}
|
||||
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
||||
{
|
||||
return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1);
|
||||
}
|
||||
|
||||
|
||||
// check if a memory area is mapped
|
||||
// this is complicated because an area can overlap adjacent blocks
|
||||
static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)
|
||||
|
|
Loading…
Reference in a new issue