Files
favicon-trap/bindings/go/unicorn/unicorn.go
Stephen 75d90aff52 Make cleanup (#666)
* make cleanup

* Update .travis.yml
Update eflags_nosync.c
Update sigill2.c
Update ro_mem_test.c
Update ro_mem_test.c
Update nr_mem_test.c
Update mem_fuzz.c
Update mem_double_unmap.c
Update emu_stop_in_hook_overrun.c
Update eflags_nosync.c
remove unused
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update mem_64_c.c
Update mem_64_c.c
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update Makefile
Update .travis.yml
try android ndk build
Update unicorn.py
Update unicorn.py
Update Makefile
Update unicorn.py
Update unicorn.py
remove an untrue comment

if a dll/so/dylib gets loaded at runtime is dependent on many different factors, primarily the LD/DYLD paths. Those do not always include the current working directory
Update Makefile
Update .appveyor.yml
Update .travis.yml
Update Makefile
Update .appveyor.yml
Fix bad sample

* Update Makefile

* Update Makefile

* Update install-cmocka-linux.sh

* remove verbose option from tar

* add upgrade to pacman for cmake

* pacman double update, needed to get new packages

* enable cmocka unit testing

* rejigger commands to fail on any step

should get fails in msys builds for cmocka

* fix quote

* make cmocka in cygwin only

* add msys cache
2016-11-19 17:17:48 +08:00

227 lines
5.9 KiB
Go

package unicorn
import (
"runtime"
"sync"
"unsafe"
)
/*
#cgo CFLAGS: -O3 -Wall -Werror -I../../../include
#cgo LDFLAGS: -L../../../ -lunicorn -lglib-2.0
#include <unicorn/unicorn.h>
#include "uc.h"
*/
import "C"
type UcError C.uc_err
func (u UcError) Error() string {
return C.GoString(C.uc_strerror(C.uc_err(u)))
}
func errReturn(err C.uc_err) error {
if err != ERR_OK {
return UcError(err)
}
return nil
}
type MemRegion struct {
Begin, End uint64
Prot int
}
type Unicorn interface {
MemMap(addr, size uint64) error
MemMapProt(addr, size uint64, prot int) error
MemMapPtr(addr, size uint64, prot int, ptr unsafe.Pointer) error
MemProtect(addr, size uint64, prot int) error
MemUnmap(addr, size uint64) error
MemRegions() ([]*MemRegion, error)
MemRead(addr, size uint64) ([]byte, error)
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
StartWithOptions(begin, until uint64, options *UcOptions) error
Stop() error
HookAdd(htype int, cb interface{}, begin, end uint64, extra ...int) (Hook, error)
HookDel(hook Hook) error
Query(queryType int) (uint64, error)
Close() error
ContextSave(reuse Context) (Context, error)
ContextRestore(Context) error
}
type uc struct {
handle *C.uc_engine
final sync.Once
hooks map[Hook]uintptr
}
type UcOptions struct {
Timeout, Count uint64
}
func Version() (int, int) {
var major, minor C.uint
C.uc_version(&major, &minor)
return int(major), int(minor)
}
func NewUnicorn(arch, mode int) (Unicorn, error) {
major, minor := Version()
if major != C.UC_API_MAJOR || minor != C.UC_API_MINOR {
return nil, UcError(ERR_VERSION)
}
var handle *C.uc_engine
if ucerr := C.uc_open(C.uc_arch(arch), C.uc_mode(mode), &handle); ucerr != ERR_OK {
return nil, UcError(ucerr)
}
u := &uc{handle: handle, hooks: make(map[Hook]uintptr)}
runtime.SetFinalizer(u, func(u *uc) { u.Close() })
return u, nil
}
func (u *uc) Close() (err error) {
u.final.Do(func() {
if u.handle != nil {
for _, uptr := range u.hooks {
delete(hookDataMap, uptr)
}
u.hooks = nil
err = errReturn(C.uc_close(u.handle))
u.handle = nil
}
})
return err
}
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 {
return u.StartWithOptions(begin, until, &UcOptions{})
}
func (u *uc) Stop() error {
return errReturn(C.uc_emu_stop(u.handle))
}
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))
return errReturn(ucerr)
}
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))
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.uc_mem_region
var count C.uint32_t
ucerr := C.uc_mem_regions(u.handle, &regions, &count)
if ucerr != C.UC_ERR_OK {
return nil, errReturn(ucerr)
}
ret := make([]*MemRegion, count)
tmp := (*[1 << 24]C.struct_uc_mem_region)(unsafe.Pointer(regions))[:count]
for i, v := range tmp {
ret[i] = &MemRegion{
Begin: uint64(v.begin),
End: uint64(v.end),
Prot: int(v.perms),
}
}
return ret, nil
}
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))))
}
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))))
}
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) MemMap(addr, size uint64) error {
return u.MemMapProt(addr, size, PROT_ALL)
}
func (u *uc) MemMapPtr(addr, size uint64, prot int, ptr unsafe.Pointer) error {
return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot), ptr))
}
func (u *uc) MemProtect(addr, size uint64, prot int) error {
return errReturn(C.uc_mem_protect(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot)))
}
func (u *uc) MemUnmap(addr, size uint64) error {
return errReturn(C.uc_mem_unmap(u.handle, C.uint64_t(addr), C.size_t(size)))
}
func (u *uc) Query(queryType int) (uint64, error) {
var ret C.size_t
ucerr := C.uc_query(u.handle, C.uc_query_type(queryType), &ret)
return uint64(ret), errReturn(ucerr)
}