diff --git a/bindings/go/unicorn/hook.go b/bindings/go/unicorn/hook.go index e1fe6079..bfa72c80 100644 --- a/bindings/go/unicorn/hook.go +++ b/bindings/go/unicorn/hook.go @@ -12,55 +12,57 @@ import ( import "C" type HookData struct { - Uc *Uc + Uc Unicorn Callback interface{} } +type Hook uint64 + //export hookCode func hookCode(handle *C.uc_engine, addr uint64, size uint32, user unsafe.Pointer) { hook := (*HookData)(user) - hook.Callback.(func(*Uc, uint64, uint32))(hook.Uc, uint64(addr), uint32(size)) + hook.Callback.(func(Unicorn, uint64, uint32))(hook.Uc, uint64(addr), uint32(size)) } //export hookMemInvalid func hookMemInvalid(handle *C.uc_engine, typ C.uc_mem_type, addr uint64, size int, value int64, user unsafe.Pointer) bool { hook := (*HookData)(user) - return hook.Callback.(func(*Uc, int, uint64, int, int64) bool)(hook.Uc, int(typ), addr, size, value) + return hook.Callback.(func(Unicorn, int, uint64, int, int64) bool)(hook.Uc, int(typ), addr, size, value) } //export hookMemAccess func hookMemAccess(handle *C.uc_engine, typ C.uc_mem_type, addr uint64, size int, value int64, user unsafe.Pointer) { hook := (*HookData)(user) - hook.Callback.(func(*Uc, int, uint64, int, int64))(hook.Uc, int(typ), addr, size, value) + hook.Callback.(func(Unicorn, int, uint64, int, int64))(hook.Uc, int(typ), addr, size, value) } //export hookInterrupt func hookInterrupt(handle *C.uc_engine, intno uint32, user unsafe.Pointer) { hook := (*HookData)(user) - hook.Callback.(func(*Uc, uint32))(hook.Uc, intno) + hook.Callback.(func(Unicorn, uint32))(hook.Uc, intno) } //export hookX86In func hookX86In(handle *C.uc_engine, port, size uint32, user unsafe.Pointer) uint32 { hook := (*HookData)(user) - return hook.Callback.(func(*Uc, uint32, uint32) uint32)(hook.Uc, port, size) + return hook.Callback.(func(Unicorn, uint32, uint32) uint32)(hook.Uc, port, size) } //export hookX86Out func hookX86Out(handle *C.uc_engine, port, size, value uint32, user unsafe.Pointer) { hook := (*HookData)(user) - hook.Callback.(func(*Uc, uint32, uint32, uint32))(hook.Uc, port, size, value) + hook.Callback.(func(Unicorn, uint32, uint32, uint32))(hook.Uc, port, size, value) } //export hookX86Syscall func hookX86Syscall(handle *C.uc_engine, user unsafe.Pointer) { hook := (*HookData)(user) - hook.Callback.(func(*Uc))(hook.Uc) + hook.Callback.(func(Unicorn))(hook.Uc) } -var hookRetain = make(map[C.uc_hook]*HookData) +var hookRetain = make(map[Hook]*HookData) -func (u *Uc) HookAdd(htype int, cb interface{}, extra ...uint64) (C.uc_hook, error) { +func (u *uc) HookAdd(htype int, cb interface{}, extra ...uint64) (Hook, error) { var callback unsafe.Pointer var iarg1 C.int var uarg1, uarg2 C.uint64_t @@ -101,15 +103,15 @@ func (u *Uc) HookAdd(htype int, cb interface{}, extra ...uint64) (C.uc_hook, err } else { uarg1, uarg2 = 1, 0 } - C.uc_hook_add_u2(u.Handle, &h2, C.uc_hook_type(htype), callback, unsafe.Pointer(data), uarg1, uarg2) + C.uc_hook_add_u2(u.handle, &h2, C.uc_hook_type(htype), callback, unsafe.Pointer(data), uarg1, uarg2) } else { - C.uc_hook_add_i1(u.Handle, &h2, C.uc_hook_type(htype), callback, unsafe.Pointer(data), iarg1) + C.uc_hook_add_i1(u.handle, &h2, C.uc_hook_type(htype), callback, unsafe.Pointer(data), iarg1) } - hookRetain[h2] = data - return h2, nil + hookRetain[Hook(h2)] = data + return Hook(h2), nil } -func (u *Uc) HookDel(hook C.uc_hook) error { +func (u *uc) HookDel(hook Hook) error { delete(hookRetain, hook) - return errReturn(C.uc_hook_del(u.Handle, hook)) + return errReturn(C.uc_hook_del(u.handle, C.uc_hook(hook))) } diff --git a/bindings/go/unicorn/unicorn.go b/bindings/go/unicorn/unicorn.go index c90dd141..1de2c95f 100644 --- a/bindings/go/unicorn/unicorn.go +++ b/bindings/go/unicorn/unicorn.go @@ -23,16 +23,30 @@ func errReturn(err C.uc_err) error { return nil } -type Uc struct { - Handle *C.uc_engine - Arch, Mode int +type Unicorn interface { + MemMap(addr, size uint64) error + MemMapProt(addr, size uint64, prot int) error + MemRead(addr, size uint64) ([]byte, error) + MemReadInto(dst []byte, addr uint64) error + MemWrite(addr uint64, data []byte) error + RegRead(reg int) (uint64, error) + RegWrite(reg int, value uint64) error + Start(begin, until uint64) error + StartWithOptions(begin, until uint64, options *UcOptions) error + Stop() error + HookAdd(htype int, cb interface{}, extra ...uint64) (Hook, error) + HookDel(hook Hook) error +} + +type uc struct { + handle *C.uc_engine } type UcOptions struct { Timeout, Count uint64 } -func NewUc(arch, mode int) (*Uc, error) { +func NewUnicorn(arch, mode int) (Unicorn, error) { var major, minor C.uint C.uc_version(&major, &minor) if major != C.UC_API_MAJOR || minor != C.UC_API_MINOR { @@ -42,58 +56,58 @@ func NewUc(arch, mode int) (*Uc, error) { if ucerr := C.uc_open(C.uc_arch(arch), C.uc_mode(mode), &handle); ucerr != ERR_OK { return nil, UcError(ucerr) } - uc := &Uc{handle, arch, mode} + uc := &uc{handle} return uc, nil } -func (u *Uc) StartWithOptions(begin, until uint64, options *UcOptions) error { - ucerr := C.uc_emu_start(u.Handle, C.uint64_t(begin), C.uint64_t(until), C.uint64_t(options.Timeout), C.size_t(options.Count)) +func (u *uc) StartWithOptions(begin, until uint64, options *UcOptions) error { + ucerr := C.uc_emu_start(u.handle, C.uint64_t(begin), C.uint64_t(until), C.uint64_t(options.Timeout), C.size_t(options.Count)) return errReturn(ucerr) } -func (u *Uc) Start(begin, until uint64) error { +func (u *uc) Start(begin, until uint64) error { return u.StartWithOptions(begin, until, &UcOptions{}) } -func (u *Uc) Stop() error { - return errReturn(C.uc_emu_stop(u.Handle)) +func (u *uc) Stop() error { + return errReturn(C.uc_emu_stop(u.handle)) } -func (u *Uc) RegWrite(reg int, value uint64) error { +func (u *uc) RegWrite(reg int, value uint64) error { var val C.uint64_t = C.uint64_t(value) - ucerr := C.uc_reg_write(u.Handle, C.int(reg), unsafe.Pointer(&val)) + ucerr := C.uc_reg_write(u.handle, C.int(reg), unsafe.Pointer(&val)) return errReturn(ucerr) } -func (u *Uc) RegRead(reg int) (uint64, error) { +func (u *uc) RegRead(reg int) (uint64, error) { var val C.uint64_t - ucerr := C.uc_reg_read(u.Handle, C.int(reg), unsafe.Pointer(&val)) + ucerr := C.uc_reg_read(u.handle, C.int(reg), unsafe.Pointer(&val)) return uint64(val), errReturn(ucerr) } -func (u *Uc) MemWrite(addr uint64, data []byte) error { +func (u *uc) MemWrite(addr uint64, data []byte) error { if len(data) == 0 { return nil } - return errReturn(C.uc_mem_write(u.Handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.size_t(len(data)))) + return errReturn(C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.size_t(len(data)))) } -func (u *Uc) MemReadInto(dst []byte, addr uint64) error { +func (u *uc) MemReadInto(dst []byte, addr uint64) error { if len(dst) == 0 { return nil } - return errReturn(C.uc_mem_read(u.Handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.size_t(len(dst)))) + return errReturn(C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.size_t(len(dst)))) } -func (u *Uc) MemRead(addr, size uint64) ([]byte, error) { +func (u *uc) MemRead(addr, size uint64) ([]byte, error) { dst := make([]byte, size) return dst, u.MemReadInto(dst, addr) } -func (u *Uc) MemMapProt(addr, size uint64, prot int) error { - return errReturn(C.uc_mem_map(u.Handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot))) +func (u *uc) MemMapProt(addr, size uint64, prot int) error { + return errReturn(C.uc_mem_map(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot))) } -func (u *Uc) MemMap(addr, size uint64) error { +func (u *uc) MemMap(addr, size uint64) error { return u.MemMapProt(addr, size, PROT_ALL) } diff --git a/bindings/go/unicorn/x86_test.go b/bindings/go/unicorn/x86_test.go index 8dc5ea7d..302a105d 100644 --- a/bindings/go/unicorn/x86_test.go +++ b/bindings/go/unicorn/x86_test.go @@ -6,8 +6,8 @@ import ( var ADDRESS uint64 = 0x1000000 -func MakeUc(mode int, code string) (*Uc, error) { - mu, err := NewUc(ARCH_X86, mode) +func MakeUc(mode int, code string) (Unicorn, error) { + mu, err := NewUnicorn(ARCH_X86, mode) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func TestX86InOut(t *testing.T) { } var outVal uint64 var inCalled, outCalled bool - mu.HookAdd(HOOK_INSN, func(mu *Uc, port, size uint32) uint32 { + mu.HookAdd(HOOK_INSN, func(_ Unicorn, port, size uint32) uint32 { inCalled = true switch size { case 1: @@ -97,7 +97,7 @@ func TestX86InOut(t *testing.T) { return 0 } }, X86_INS_IN) - mu.HookAdd(HOOK_INSN, func(uc *Uc, port, size, value uint32) { + mu.HookAdd(HOOK_INSN, func(_ Unicorn, port, size, value uint32) { outCalled = true var err error switch size { @@ -129,7 +129,7 @@ func TestX86Syscall(t *testing.T) { if err != nil { t.Fatal(err) } - mu.HookAdd(HOOK_INSN, func(mu *Uc) { + mu.HookAdd(HOOK_INSN, func(_ Unicorn) { rax, _ := mu.RegRead(X86_REG_RAX) mu.RegWrite(X86_REG_RAX, rax+1) }, X86_INS_SYSCALL)