Merge pull request #64 from lunixbochs/go-bindings

add Go bindings
This commit is contained in:
Nguyen Anh Quynh 2015-08-28 12:22:46 +08:00
commit adec227dad
14 changed files with 2720 additions and 0 deletions

View File

@ -23,6 +23,21 @@ template = {
'comment_open': '#',
'comment_close': '',
},
'go': {
'header': "package unicorn\n// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.go]\nconst (",
'footer': ")",
'line_format': '%s = %s\n',
'out_file': './go/unicorn/%s_const.go',
# prefixes for constant filenames of all archs - case sensitive
'arm.h': 'arm',
'arm64.h': 'arm64',
'mips.h': 'mips',
'x86.h': 'x86',
'sparc.h': 'sparc',
'm68k.h': 'm68k',
'comment_open': '//',
'comment_close': '',
},
}
# markup for comments to be added to autogen files

10
bindings/go/Makefile Normal file
View File

@ -0,0 +1,10 @@
# Go binding for Unicorn engine. Ryan Hileman <lunixbochs@gmail.com>
.PHONY: gen_const test
gen_const:
cd .. && python const_generator.py go
cd unicorn && go build
test:
cd unicorn && go test

View File

@ -0,0 +1,276 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.go]
const (
// ARM64 registers
UC_ARM64_REG_INVALID = 0
UC_ARM64_REG_X29 = 1
UC_ARM64_REG_X30 = 2
UC_ARM64_REG_NZCV = 3
UC_ARM64_REG_SP = 4
UC_ARM64_REG_WSP = 5
UC_ARM64_REG_WZR = 6
UC_ARM64_REG_XZR = 7
UC_ARM64_REG_B0 = 8
UC_ARM64_REG_B1 = 9
UC_ARM64_REG_B2 = 10
UC_ARM64_REG_B3 = 11
UC_ARM64_REG_B4 = 12
UC_ARM64_REG_B5 = 13
UC_ARM64_REG_B6 = 14
UC_ARM64_REG_B7 = 15
UC_ARM64_REG_B8 = 16
UC_ARM64_REG_B9 = 17
UC_ARM64_REG_B10 = 18
UC_ARM64_REG_B11 = 19
UC_ARM64_REG_B12 = 20
UC_ARM64_REG_B13 = 21
UC_ARM64_REG_B14 = 22
UC_ARM64_REG_B15 = 23
UC_ARM64_REG_B16 = 24
UC_ARM64_REG_B17 = 25
UC_ARM64_REG_B18 = 26
UC_ARM64_REG_B19 = 27
UC_ARM64_REG_B20 = 28
UC_ARM64_REG_B21 = 29
UC_ARM64_REG_B22 = 30
UC_ARM64_REG_B23 = 31
UC_ARM64_REG_B24 = 32
UC_ARM64_REG_B25 = 33
UC_ARM64_REG_B26 = 34
UC_ARM64_REG_B27 = 35
UC_ARM64_REG_B28 = 36
UC_ARM64_REG_B29 = 37
UC_ARM64_REG_B30 = 38
UC_ARM64_REG_B31 = 39
UC_ARM64_REG_D0 = 40
UC_ARM64_REG_D1 = 41
UC_ARM64_REG_D2 = 42
UC_ARM64_REG_D3 = 43
UC_ARM64_REG_D4 = 44
UC_ARM64_REG_D5 = 45
UC_ARM64_REG_D6 = 46
UC_ARM64_REG_D7 = 47
UC_ARM64_REG_D8 = 48
UC_ARM64_REG_D9 = 49
UC_ARM64_REG_D10 = 50
UC_ARM64_REG_D11 = 51
UC_ARM64_REG_D12 = 52
UC_ARM64_REG_D13 = 53
UC_ARM64_REG_D14 = 54
UC_ARM64_REG_D15 = 55
UC_ARM64_REG_D16 = 56
UC_ARM64_REG_D17 = 57
UC_ARM64_REG_D18 = 58
UC_ARM64_REG_D19 = 59
UC_ARM64_REG_D20 = 60
UC_ARM64_REG_D21 = 61
UC_ARM64_REG_D22 = 62
UC_ARM64_REG_D23 = 63
UC_ARM64_REG_D24 = 64
UC_ARM64_REG_D25 = 65
UC_ARM64_REG_D26 = 66
UC_ARM64_REG_D27 = 67
UC_ARM64_REG_D28 = 68
UC_ARM64_REG_D29 = 69
UC_ARM64_REG_D30 = 70
UC_ARM64_REG_D31 = 71
UC_ARM64_REG_H0 = 72
UC_ARM64_REG_H1 = 73
UC_ARM64_REG_H2 = 74
UC_ARM64_REG_H3 = 75
UC_ARM64_REG_H4 = 76
UC_ARM64_REG_H5 = 77
UC_ARM64_REG_H6 = 78
UC_ARM64_REG_H7 = 79
UC_ARM64_REG_H8 = 80
UC_ARM64_REG_H9 = 81
UC_ARM64_REG_H10 = 82
UC_ARM64_REG_H11 = 83
UC_ARM64_REG_H12 = 84
UC_ARM64_REG_H13 = 85
UC_ARM64_REG_H14 = 86
UC_ARM64_REG_H15 = 87
UC_ARM64_REG_H16 = 88
UC_ARM64_REG_H17 = 89
UC_ARM64_REG_H18 = 90
UC_ARM64_REG_H19 = 91
UC_ARM64_REG_H20 = 92
UC_ARM64_REG_H21 = 93
UC_ARM64_REG_H22 = 94
UC_ARM64_REG_H23 = 95
UC_ARM64_REG_H24 = 96
UC_ARM64_REG_H25 = 97
UC_ARM64_REG_H26 = 98
UC_ARM64_REG_H27 = 99
UC_ARM64_REG_H28 = 100
UC_ARM64_REG_H29 = 101
UC_ARM64_REG_H30 = 102
UC_ARM64_REG_H31 = 103
UC_ARM64_REG_Q0 = 104
UC_ARM64_REG_Q1 = 105
UC_ARM64_REG_Q2 = 106
UC_ARM64_REG_Q3 = 107
UC_ARM64_REG_Q4 = 108
UC_ARM64_REG_Q5 = 109
UC_ARM64_REG_Q6 = 110
UC_ARM64_REG_Q7 = 111
UC_ARM64_REG_Q8 = 112
UC_ARM64_REG_Q9 = 113
UC_ARM64_REG_Q10 = 114
UC_ARM64_REG_Q11 = 115
UC_ARM64_REG_Q12 = 116
UC_ARM64_REG_Q13 = 117
UC_ARM64_REG_Q14 = 118
UC_ARM64_REG_Q15 = 119
UC_ARM64_REG_Q16 = 120
UC_ARM64_REG_Q17 = 121
UC_ARM64_REG_Q18 = 122
UC_ARM64_REG_Q19 = 123
UC_ARM64_REG_Q20 = 124
UC_ARM64_REG_Q21 = 125
UC_ARM64_REG_Q22 = 126
UC_ARM64_REG_Q23 = 127
UC_ARM64_REG_Q24 = 128
UC_ARM64_REG_Q25 = 129
UC_ARM64_REG_Q26 = 130
UC_ARM64_REG_Q27 = 131
UC_ARM64_REG_Q28 = 132
UC_ARM64_REG_Q29 = 133
UC_ARM64_REG_Q30 = 134
UC_ARM64_REG_Q31 = 135
UC_ARM64_REG_S0 = 136
UC_ARM64_REG_S1 = 137
UC_ARM64_REG_S2 = 138
UC_ARM64_REG_S3 = 139
UC_ARM64_REG_S4 = 140
UC_ARM64_REG_S5 = 141
UC_ARM64_REG_S6 = 142
UC_ARM64_REG_S7 = 143
UC_ARM64_REG_S8 = 144
UC_ARM64_REG_S9 = 145
UC_ARM64_REG_S10 = 146
UC_ARM64_REG_S11 = 147
UC_ARM64_REG_S12 = 148
UC_ARM64_REG_S13 = 149
UC_ARM64_REG_S14 = 150
UC_ARM64_REG_S15 = 151
UC_ARM64_REG_S16 = 152
UC_ARM64_REG_S17 = 153
UC_ARM64_REG_S18 = 154
UC_ARM64_REG_S19 = 155
UC_ARM64_REG_S20 = 156
UC_ARM64_REG_S21 = 157
UC_ARM64_REG_S22 = 158
UC_ARM64_REG_S23 = 159
UC_ARM64_REG_S24 = 160
UC_ARM64_REG_S25 = 161
UC_ARM64_REG_S26 = 162
UC_ARM64_REG_S27 = 163
UC_ARM64_REG_S28 = 164
UC_ARM64_REG_S29 = 165
UC_ARM64_REG_S30 = 166
UC_ARM64_REG_S31 = 167
UC_ARM64_REG_W0 = 168
UC_ARM64_REG_W1 = 169
UC_ARM64_REG_W2 = 170
UC_ARM64_REG_W3 = 171
UC_ARM64_REG_W4 = 172
UC_ARM64_REG_W5 = 173
UC_ARM64_REG_W6 = 174
UC_ARM64_REG_W7 = 175
UC_ARM64_REG_W8 = 176
UC_ARM64_REG_W9 = 177
UC_ARM64_REG_W10 = 178
UC_ARM64_REG_W11 = 179
UC_ARM64_REG_W12 = 180
UC_ARM64_REG_W13 = 181
UC_ARM64_REG_W14 = 182
UC_ARM64_REG_W15 = 183
UC_ARM64_REG_W16 = 184
UC_ARM64_REG_W17 = 185
UC_ARM64_REG_W18 = 186
UC_ARM64_REG_W19 = 187
UC_ARM64_REG_W20 = 188
UC_ARM64_REG_W21 = 189
UC_ARM64_REG_W22 = 190
UC_ARM64_REG_W23 = 191
UC_ARM64_REG_W24 = 192
UC_ARM64_REG_W25 = 193
UC_ARM64_REG_W26 = 194
UC_ARM64_REG_W27 = 195
UC_ARM64_REG_W28 = 196
UC_ARM64_REG_W29 = 197
UC_ARM64_REG_W30 = 198
UC_ARM64_REG_X0 = 199
UC_ARM64_REG_X1 = 200
UC_ARM64_REG_X2 = 201
UC_ARM64_REG_X3 = 202
UC_ARM64_REG_X4 = 203
UC_ARM64_REG_X5 = 204
UC_ARM64_REG_X6 = 205
UC_ARM64_REG_X7 = 206
UC_ARM64_REG_X8 = 207
UC_ARM64_REG_X9 = 208
UC_ARM64_REG_X10 = 209
UC_ARM64_REG_X11 = 210
UC_ARM64_REG_X12 = 211
UC_ARM64_REG_X13 = 212
UC_ARM64_REG_X14 = 213
UC_ARM64_REG_X15 = 214
UC_ARM64_REG_X16 = 215
UC_ARM64_REG_X17 = 216
UC_ARM64_REG_X18 = 217
UC_ARM64_REG_X19 = 218
UC_ARM64_REG_X20 = 219
UC_ARM64_REG_X21 = 220
UC_ARM64_REG_X22 = 221
UC_ARM64_REG_X23 = 222
UC_ARM64_REG_X24 = 223
UC_ARM64_REG_X25 = 224
UC_ARM64_REG_X26 = 225
UC_ARM64_REG_X27 = 226
UC_ARM64_REG_X28 = 227
UC_ARM64_REG_V0 = 228
UC_ARM64_REG_V1 = 229
UC_ARM64_REG_V2 = 230
UC_ARM64_REG_V3 = 231
UC_ARM64_REG_V4 = 232
UC_ARM64_REG_V5 = 233
UC_ARM64_REG_V6 = 234
UC_ARM64_REG_V7 = 235
UC_ARM64_REG_V8 = 236
UC_ARM64_REG_V9 = 237
UC_ARM64_REG_V10 = 238
UC_ARM64_REG_V11 = 239
UC_ARM64_REG_V12 = 240
UC_ARM64_REG_V13 = 241
UC_ARM64_REG_V14 = 242
UC_ARM64_REG_V15 = 243
UC_ARM64_REG_V16 = 244
UC_ARM64_REG_V17 = 245
UC_ARM64_REG_V18 = 246
UC_ARM64_REG_V19 = 247
UC_ARM64_REG_V20 = 248
UC_ARM64_REG_V21 = 249
UC_ARM64_REG_V22 = 250
UC_ARM64_REG_V23 = 251
UC_ARM64_REG_V24 = 252
UC_ARM64_REG_V25 = 253
UC_ARM64_REG_V26 = 254
UC_ARM64_REG_V27 = 255
UC_ARM64_REG_V28 = 256
UC_ARM64_REG_V29 = 257
UC_ARM64_REG_V30 = 258
UC_ARM64_REG_V31 = 259
// pseudo registers
UC_ARM64_REG_PC = 260
UC_ARM64_REG_ENDING = 261
// alias registers
UC_ARM64_REG_IP1 = UC_ARM64_REG_X16
UC_ARM64_REG_IP0 = UC_ARM64_REG_X17
UC_ARM64_REG_FP = UC_ARM64_REG_X29
UC_ARM64_REG_LR = UC_ARM64_REG_X30
)

View File

@ -0,0 +1,127 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.go]
const (
// ARM registers
UC_ARM_REG_INVALID = 0
UC_ARM_REG_APSR = 1
UC_ARM_REG_APSR_NZCV = 2
UC_ARM_REG_CPSR = 3
UC_ARM_REG_FPEXC = 4
UC_ARM_REG_FPINST = 5
UC_ARM_REG_FPSCR = 6
UC_ARM_REG_FPSCR_NZCV = 7
UC_ARM_REG_FPSID = 8
UC_ARM_REG_ITSTATE = 9
UC_ARM_REG_LR = 10
UC_ARM_REG_PC = 11
UC_ARM_REG_SP = 12
UC_ARM_REG_SPSR = 13
UC_ARM_REG_D0 = 14
UC_ARM_REG_D1 = 15
UC_ARM_REG_D2 = 16
UC_ARM_REG_D3 = 17
UC_ARM_REG_D4 = 18
UC_ARM_REG_D5 = 19
UC_ARM_REG_D6 = 20
UC_ARM_REG_D7 = 21
UC_ARM_REG_D8 = 22
UC_ARM_REG_D9 = 23
UC_ARM_REG_D10 = 24
UC_ARM_REG_D11 = 25
UC_ARM_REG_D12 = 26
UC_ARM_REG_D13 = 27
UC_ARM_REG_D14 = 28
UC_ARM_REG_D15 = 29
UC_ARM_REG_D16 = 30
UC_ARM_REG_D17 = 31
UC_ARM_REG_D18 = 32
UC_ARM_REG_D19 = 33
UC_ARM_REG_D20 = 34
UC_ARM_REG_D21 = 35
UC_ARM_REG_D22 = 36
UC_ARM_REG_D23 = 37
UC_ARM_REG_D24 = 38
UC_ARM_REG_D25 = 39
UC_ARM_REG_D26 = 40
UC_ARM_REG_D27 = 41
UC_ARM_REG_D28 = 42
UC_ARM_REG_D29 = 43
UC_ARM_REG_D30 = 44
UC_ARM_REG_D31 = 45
UC_ARM_REG_FPINST2 = 46
UC_ARM_REG_MVFR0 = 47
UC_ARM_REG_MVFR1 = 48
UC_ARM_REG_MVFR2 = 49
UC_ARM_REG_Q0 = 50
UC_ARM_REG_Q1 = 51
UC_ARM_REG_Q2 = 52
UC_ARM_REG_Q3 = 53
UC_ARM_REG_Q4 = 54
UC_ARM_REG_Q5 = 55
UC_ARM_REG_Q6 = 56
UC_ARM_REG_Q7 = 57
UC_ARM_REG_Q8 = 58
UC_ARM_REG_Q9 = 59
UC_ARM_REG_Q10 = 60
UC_ARM_REG_Q11 = 61
UC_ARM_REG_Q12 = 62
UC_ARM_REG_Q13 = 63
UC_ARM_REG_Q14 = 64
UC_ARM_REG_Q15 = 65
UC_ARM_REG_R0 = 66
UC_ARM_REG_R1 = 67
UC_ARM_REG_R2 = 68
UC_ARM_REG_R3 = 69
UC_ARM_REG_R4 = 70
UC_ARM_REG_R5 = 71
UC_ARM_REG_R6 = 72
UC_ARM_REG_R7 = 73
UC_ARM_REG_R8 = 74
UC_ARM_REG_R9 = 75
UC_ARM_REG_R10 = 76
UC_ARM_REG_R11 = 77
UC_ARM_REG_R12 = 78
UC_ARM_REG_S0 = 79
UC_ARM_REG_S1 = 80
UC_ARM_REG_S2 = 81
UC_ARM_REG_S3 = 82
UC_ARM_REG_S4 = 83
UC_ARM_REG_S5 = 84
UC_ARM_REG_S6 = 85
UC_ARM_REG_S7 = 86
UC_ARM_REG_S8 = 87
UC_ARM_REG_S9 = 88
UC_ARM_REG_S10 = 89
UC_ARM_REG_S11 = 90
UC_ARM_REG_S12 = 91
UC_ARM_REG_S13 = 92
UC_ARM_REG_S14 = 93
UC_ARM_REG_S15 = 94
UC_ARM_REG_S16 = 95
UC_ARM_REG_S17 = 96
UC_ARM_REG_S18 = 97
UC_ARM_REG_S19 = 98
UC_ARM_REG_S20 = 99
UC_ARM_REG_S21 = 100
UC_ARM_REG_S22 = 101
UC_ARM_REG_S23 = 102
UC_ARM_REG_S24 = 103
UC_ARM_REG_S25 = 104
UC_ARM_REG_S26 = 105
UC_ARM_REG_S27 = 106
UC_ARM_REG_S28 = 107
UC_ARM_REG_S29 = 108
UC_ARM_REG_S30 = 109
UC_ARM_REG_S31 = 110
UC_ARM_REG_ENDING = 111
// alias registers
UC_ARM_REG_R13 = UC_ARM_REG_SP
UC_ARM_REG_R14 = UC_ARM_REG_LR
UC_ARM_REG_R15 = UC_ARM_REG_PC
UC_ARM_REG_SB = UC_ARM_REG_R9
UC_ARM_REG_SL = UC_ARM_REG_R10
UC_ARM_REG_FP = UC_ARM_REG_R11
UC_ARM_REG_IP = UC_ARM_REG_R12
)

View File

@ -0,0 +1,22 @@
package unicorn
// #include <unicorn/unicorn.h>
import "C"
// TODO: update const script to generate these?
const (
UC_HOOK_BLOCK = C.UC_HOOK_BLOCK
UC_HOOK_CODE = C.UC_HOOK_CODE
UC_HOOK_MEM_INVALID = C.UC_HOOK_MEM_INVALID
UC_HOOK_MEM_READ = C.UC_HOOK_MEM_READ
UC_HOOK_MEM_WRITE = C.UC_HOOK_MEM_WRITE
UC_HOOK_MEM_READ_WRITE = C.UC_HOOK_MEM_READ_WRITE
UC_HOOK_INSN = C.UC_HOOK_INSN
UC_ARCH_X86 = C.UC_ARCH_X86
UC_MODE_32 = C.UC_MODE_32
UC_MODE_64 = C.UC_MODE_64
UC_ERR_MEM_READ = C.UC_ERR_MEM_READ
UC_ERR_MEM_WRITE = C.UC_ERR_MEM_WRITE
)

View File

@ -0,0 +1,30 @@
#include <unicorn/unicorn.h>
#include "_cgo_export.h"
uc_err uc_hook_add2(uch handle, uch *h2, uc_hook_t type, void *callback, void *user_data, int extra) {
return uc_hook_add(handle, h2, type, callback, user_data, extra);
}
void hookCode_cgo(uch handle, uint64_t addr, uint32_t size, void *user) {
hookCode(handle, addr, size, user);
}
bool hookMemInvalid_cgo(uch handle, uc_mem_type type, uint64_t addr, int64_t value, void *user) {
return hookMemInvalid(handle, type, addr, value, user);
}
void hookMemAccess_cgo(uch handle, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user) {
hookMemAccess(handle, type, addr, size, value, user);
}
uint32_t hookX86In_cgo(uch handle, uint32_t port, uint32_t size, void *user) {
return hookX86In(handle, port, size, user);
}
void hookX86Out_cgo(uch handle, uint32_t port, uint32_t size, uint32_t value, void *user) {
hookX86Out(handle, port, size, value, user);
}
void hookX86Syscall_cgo(uch handle, void *user) {
hookX86Syscall(handle, user);
}

View File

@ -0,0 +1,87 @@
package unicorn
import (
"errors"
"unsafe"
)
/*
#include <unicorn/unicorn.h>
#include "hook.h"
*/
import "C"
type HookData struct {
Uc *Uc
Callback interface{}
}
//export hookCode
func hookCode(handle C.uch, addr C.uint64_t, size C.uint32_t, user unsafe.Pointer) {
hook := (*HookData)(user)
hook.Callback.(func(*Uc, uint64, uint32))(hook.Uc, uint64(addr), uint32(size))
}
//export hookMemInvalid
func hookMemInvalid(handle C.uch, typ C.uc_mem_type, addr C.uint64_t, value C.int64_t, user unsafe.Pointer) C.bool {
hook := (*HookData)(user)
return C.bool(hook.Callback.(func(*Uc, int, uint64, int64) bool)(hook.Uc, int(typ), uint64(addr), int64(value)))
}
//export hookMemAccess
func hookMemAccess(handle C.uch, typ C.uc_mem_type, addr C.uint64_t, size int, value C.int64_t, user unsafe.Pointer) {
hook := (*HookData)(user)
hook.Callback.(func(*Uc, int, uint64, uint32, int64))(hook.Uc, int(typ), uint64(addr), uint32(size), int64(value))
}
//export hookX86In
func hookX86In(handle C.uch, port, size uint32, user unsafe.Pointer) C.uint32_t {
hook := (*HookData)(user)
return C.uint32_t(hook.Callback.(func(*Uc, uint32, uint32) uint32)(hook.Uc, port, size))
}
//export hookX86Out
func hookX86Out(handle C.uch, port, size, value uint32, user unsafe.Pointer) {
hook := (*HookData)(user)
hook.Callback.(func(*Uc, uint32, uint32, uint32))(hook.Uc, uint32(port), uint32(size), uint32(value))
}
//export hookX86Syscall
func hookX86Syscall(handle C.uch, user unsafe.Pointer) {
hook := (*HookData)(user)
hook.Callback.(func(*Uc))(hook.Uc)
}
func (u *Uc) HookAdd(htype int, cb interface{}, insn ...int) (C.uch, error) {
var callback unsafe.Pointer
var extra C.int
switch htype {
case UC_HOOK_BLOCK, UC_HOOK_CODE:
callback = C.hookCode_cgo
case UC_HOOK_MEM_INVALID:
callback = C.hookMemInvalid_cgo
case UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE:
callback = C.hookMemAccess_cgo
case UC_HOOK_INSN:
extra = C.int(insn[0])
switch extra {
case UC_X86_INS_IN:
callback = C.hookX86In_cgo
case UC_X86_INS_OUT:
callback = C.hookX86Out_cgo
case UC_X86_INS_SYSCALL, UC_X86_INS_SYSENTER:
callback = C.hookX86Syscall_cgo
default:
return 0, errors.New("Unknown instruction type.")
}
default:
return 0, errors.New("Unknown hook type.")
}
var h2 C.uch
C.uc_hook_add2(u.Handle, &h2, C.uc_hook_t(htype), callback, unsafe.Pointer(&HookData{u, cb}), extra)
return h2, nil
}
func (u *Uc) HookDel(hook *C.uch) error {
return errReturn(C.uc_hook_del(u.Handle, hook))
}

View File

@ -0,0 +1,7 @@
uc_err uc_hook_add2(uch handle, uch *h2, uc_hook_t type, void *callback, void *user_data, int extra);
void hookCode_cgo(uch handle, uint64_t addr, uint32_t size, void *user);
bool hookMemInvalid_cgo(uch handle, uc_mem_type type, uint64_t addr, int64_t value, void *user);
void hookMemAccess_cgo(uch handle, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user);
uint32_t hookX86In_cgo(uch handle, uint32_t port, uint32_t size, void *user);
void hookX86Out_cgo(uch handle, uint32_t port, uint32_t size, uint32_t value, void *user);
void hookX86Syscall_cgo(uch handle, void *user);

View File

@ -0,0 +1,26 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.go]
const (
// M68K registers
UC_M68K_REG_INVALID = 0
UC_M68K_REG_A0 = 1
UC_M68K_REG_A1 = 2
UC_M68K_REG_A2 = 3
UC_M68K_REG_A3 = 4
UC_M68K_REG_A4 = 5
UC_M68K_REG_A5 = 6
UC_M68K_REG_A6 = 7
UC_M68K_REG_A7 = 8
UC_M68K_REG_D0 = 9
UC_M68K_REG_D1 = 10
UC_M68K_REG_D2 = 11
UC_M68K_REG_D3 = 12
UC_M68K_REG_D4 = 13
UC_M68K_REG_D5 = 14
UC_M68K_REG_D6 = 15
UC_M68K_REG_D7 = 16
UC_M68K_REG_SR = 17
UC_M68K_REG_PC = 18
UC_M68K_REG_ENDING = 19
)

View File

@ -0,0 +1,197 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.go]
const (
// MIPS registers
UC_MIPS_REG_INVALID = 0
// General purpose registers
UC_MIPS_REG_PC = 1
UC_MIPS_REG_0 = 2
UC_MIPS_REG_1 = 3
UC_MIPS_REG_2 = 4
UC_MIPS_REG_3 = 5
UC_MIPS_REG_4 = 6
UC_MIPS_REG_5 = 7
UC_MIPS_REG_6 = 8
UC_MIPS_REG_7 = 9
UC_MIPS_REG_8 = 10
UC_MIPS_REG_9 = 11
UC_MIPS_REG_10 = 12
UC_MIPS_REG_11 = 13
UC_MIPS_REG_12 = 14
UC_MIPS_REG_13 = 15
UC_MIPS_REG_14 = 16
UC_MIPS_REG_15 = 17
UC_MIPS_REG_16 = 18
UC_MIPS_REG_17 = 19
UC_MIPS_REG_18 = 20
UC_MIPS_REG_19 = 21
UC_MIPS_REG_20 = 22
UC_MIPS_REG_21 = 23
UC_MIPS_REG_22 = 24
UC_MIPS_REG_23 = 25
UC_MIPS_REG_24 = 26
UC_MIPS_REG_25 = 27
UC_MIPS_REG_26 = 28
UC_MIPS_REG_27 = 29
UC_MIPS_REG_28 = 30
UC_MIPS_REG_29 = 31
UC_MIPS_REG_30 = 32
UC_MIPS_REG_31 = 33
// DSP registers
UC_MIPS_REG_DSPCCOND = 34
UC_MIPS_REG_DSPCARRY = 35
UC_MIPS_REG_DSPEFI = 36
UC_MIPS_REG_DSPOUTFLAG = 37
UC_MIPS_REG_DSPOUTFLAG16_19 = 38
UC_MIPS_REG_DSPOUTFLAG20 = 39
UC_MIPS_REG_DSPOUTFLAG21 = 40
UC_MIPS_REG_DSPOUTFLAG22 = 41
UC_MIPS_REG_DSPOUTFLAG23 = 42
UC_MIPS_REG_DSPPOS = 43
UC_MIPS_REG_DSPSCOUNT = 44
// ACC registers
UC_MIPS_REG_AC0 = 45
UC_MIPS_REG_AC1 = 46
UC_MIPS_REG_AC2 = 47
UC_MIPS_REG_AC3 = 48
// COP registers
UC_MIPS_REG_CC0 = 49
UC_MIPS_REG_CC1 = 50
UC_MIPS_REG_CC2 = 51
UC_MIPS_REG_CC3 = 52
UC_MIPS_REG_CC4 = 53
UC_MIPS_REG_CC5 = 54
UC_MIPS_REG_CC6 = 55
UC_MIPS_REG_CC7 = 56
// FPU registers
UC_MIPS_REG_F0 = 57
UC_MIPS_REG_F1 = 58
UC_MIPS_REG_F2 = 59
UC_MIPS_REG_F3 = 60
UC_MIPS_REG_F4 = 61
UC_MIPS_REG_F5 = 62
UC_MIPS_REG_F6 = 63
UC_MIPS_REG_F7 = 64
UC_MIPS_REG_F8 = 65
UC_MIPS_REG_F9 = 66
UC_MIPS_REG_F10 = 67
UC_MIPS_REG_F11 = 68
UC_MIPS_REG_F12 = 69
UC_MIPS_REG_F13 = 70
UC_MIPS_REG_F14 = 71
UC_MIPS_REG_F15 = 72
UC_MIPS_REG_F16 = 73
UC_MIPS_REG_F17 = 74
UC_MIPS_REG_F18 = 75
UC_MIPS_REG_F19 = 76
UC_MIPS_REG_F20 = 77
UC_MIPS_REG_F21 = 78
UC_MIPS_REG_F22 = 79
UC_MIPS_REG_F23 = 80
UC_MIPS_REG_F24 = 81
UC_MIPS_REG_F25 = 82
UC_MIPS_REG_F26 = 83
UC_MIPS_REG_F27 = 84
UC_MIPS_REG_F28 = 85
UC_MIPS_REG_F29 = 86
UC_MIPS_REG_F30 = 87
UC_MIPS_REG_F31 = 88
UC_MIPS_REG_FCC0 = 89
UC_MIPS_REG_FCC1 = 90
UC_MIPS_REG_FCC2 = 91
UC_MIPS_REG_FCC3 = 92
UC_MIPS_REG_FCC4 = 93
UC_MIPS_REG_FCC5 = 94
UC_MIPS_REG_FCC6 = 95
UC_MIPS_REG_FCC7 = 96
// AFPR128
UC_MIPS_REG_W0 = 97
UC_MIPS_REG_W1 = 98
UC_MIPS_REG_W2 = 99
UC_MIPS_REG_W3 = 100
UC_MIPS_REG_W4 = 101
UC_MIPS_REG_W5 = 102
UC_MIPS_REG_W6 = 103
UC_MIPS_REG_W7 = 104
UC_MIPS_REG_W8 = 105
UC_MIPS_REG_W9 = 106
UC_MIPS_REG_W10 = 107
UC_MIPS_REG_W11 = 108
UC_MIPS_REG_W12 = 109
UC_MIPS_REG_W13 = 110
UC_MIPS_REG_W14 = 111
UC_MIPS_REG_W15 = 112
UC_MIPS_REG_W16 = 113
UC_MIPS_REG_W17 = 114
UC_MIPS_REG_W18 = 115
UC_MIPS_REG_W19 = 116
UC_MIPS_REG_W20 = 117
UC_MIPS_REG_W21 = 118
UC_MIPS_REG_W22 = 119
UC_MIPS_REG_W23 = 120
UC_MIPS_REG_W24 = 121
UC_MIPS_REG_W25 = 122
UC_MIPS_REG_W26 = 123
UC_MIPS_REG_W27 = 124
UC_MIPS_REG_W28 = 125
UC_MIPS_REG_W29 = 126
UC_MIPS_REG_W30 = 127
UC_MIPS_REG_W31 = 128
UC_MIPS_REG_HI = 129
UC_MIPS_REG_LO = 130
UC_MIPS_REG_P0 = 131
UC_MIPS_REG_P1 = 132
UC_MIPS_REG_P2 = 133
UC_MIPS_REG_MPL0 = 134
UC_MIPS_REG_MPL1 = 135
UC_MIPS_REG_MPL2 = 136
UC_MIPS_REG_ENDING = 137
UC_MIPS_REG_ZERO = UC_MIPS_REG_0
UC_MIPS_REG_AT = UC_MIPS_REG_1
UC_MIPS_REG_V0 = UC_MIPS_REG_2
UC_MIPS_REG_V1 = UC_MIPS_REG_3
UC_MIPS_REG_A0 = UC_MIPS_REG_4
UC_MIPS_REG_A1 = UC_MIPS_REG_5
UC_MIPS_REG_A2 = UC_MIPS_REG_6
UC_MIPS_REG_A3 = UC_MIPS_REG_7
UC_MIPS_REG_T0 = UC_MIPS_REG_8
UC_MIPS_REG_T1 = UC_MIPS_REG_9
UC_MIPS_REG_T2 = UC_MIPS_REG_10
UC_MIPS_REG_T3 = UC_MIPS_REG_11
UC_MIPS_REG_T4 = UC_MIPS_REG_12
UC_MIPS_REG_T5 = UC_MIPS_REG_13
UC_MIPS_REG_T6 = UC_MIPS_REG_14
UC_MIPS_REG_T7 = UC_MIPS_REG_15
UC_MIPS_REG_S0 = UC_MIPS_REG_16
UC_MIPS_REG_S1 = UC_MIPS_REG_17
UC_MIPS_REG_S2 = UC_MIPS_REG_18
UC_MIPS_REG_S3 = UC_MIPS_REG_19
UC_MIPS_REG_S4 = UC_MIPS_REG_20
UC_MIPS_REG_S5 = UC_MIPS_REG_21
UC_MIPS_REG_S6 = UC_MIPS_REG_22
UC_MIPS_REG_S7 = UC_MIPS_REG_23
UC_MIPS_REG_T8 = UC_MIPS_REG_24
UC_MIPS_REG_T9 = UC_MIPS_REG_25
UC_MIPS_REG_K0 = UC_MIPS_REG_26
UC_MIPS_REG_K1 = UC_MIPS_REG_27
UC_MIPS_REG_GP = UC_MIPS_REG_28
UC_MIPS_REG_SP = UC_MIPS_REG_29
UC_MIPS_REG_FP = UC_MIPS_REG_30
UC_MIPS_REG_S8 = UC_MIPS_REG_30
UC_MIPS_REG_RA = UC_MIPS_REG_31
UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0
UC_MIPS_REG_HI1 = UC_MIPS_REG_AC1
UC_MIPS_REG_HI2 = UC_MIPS_REG_AC2
UC_MIPS_REG_HI3 = UC_MIPS_REG_AC3
UC_MIPS_REG_LO0 = UC_MIPS_REG_HI0
UC_MIPS_REG_LO1 = UC_MIPS_REG_HI1
UC_MIPS_REG_LO2 = UC_MIPS_REG_HI2
UC_MIPS_REG_LO3 = UC_MIPS_REG_HI3
)

View File

@ -0,0 +1,98 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.go]
const (
// SPARC registers
UC_SPARC_REG_INVALID = 0
UC_SPARC_REG_F0 = 1
UC_SPARC_REG_F1 = 2
UC_SPARC_REG_F2 = 3
UC_SPARC_REG_F3 = 4
UC_SPARC_REG_F4 = 5
UC_SPARC_REG_F5 = 6
UC_SPARC_REG_F6 = 7
UC_SPARC_REG_F7 = 8
UC_SPARC_REG_F8 = 9
UC_SPARC_REG_F9 = 10
UC_SPARC_REG_F10 = 11
UC_SPARC_REG_F11 = 12
UC_SPARC_REG_F12 = 13
UC_SPARC_REG_F13 = 14
UC_SPARC_REG_F14 = 15
UC_SPARC_REG_F15 = 16
UC_SPARC_REG_F16 = 17
UC_SPARC_REG_F17 = 18
UC_SPARC_REG_F18 = 19
UC_SPARC_REG_F19 = 20
UC_SPARC_REG_F20 = 21
UC_SPARC_REG_F21 = 22
UC_SPARC_REG_F22 = 23
UC_SPARC_REG_F23 = 24
UC_SPARC_REG_F24 = 25
UC_SPARC_REG_F25 = 26
UC_SPARC_REG_F26 = 27
UC_SPARC_REG_F27 = 28
UC_SPARC_REG_F28 = 29
UC_SPARC_REG_F29 = 30
UC_SPARC_REG_F30 = 31
UC_SPARC_REG_F31 = 32
UC_SPARC_REG_F32 = 33
UC_SPARC_REG_F34 = 34
UC_SPARC_REG_F36 = 35
UC_SPARC_REG_F38 = 36
UC_SPARC_REG_F40 = 37
UC_SPARC_REG_F42 = 38
UC_SPARC_REG_F44 = 39
UC_SPARC_REG_F46 = 40
UC_SPARC_REG_F48 = 41
UC_SPARC_REG_F50 = 42
UC_SPARC_REG_F52 = 43
UC_SPARC_REG_F54 = 44
UC_SPARC_REG_F56 = 45
UC_SPARC_REG_F58 = 46
UC_SPARC_REG_F60 = 47
UC_SPARC_REG_F62 = 48
UC_SPARC_REG_FCC0 = 49
UC_SPARC_REG_FCC1 = 50
UC_SPARC_REG_FCC2 = 51
UC_SPARC_REG_FCC3 = 52
UC_SPARC_REG_FP = 53
UC_SPARC_REG_G0 = 54
UC_SPARC_REG_G1 = 55
UC_SPARC_REG_G2 = 56
UC_SPARC_REG_G3 = 57
UC_SPARC_REG_G4 = 58
UC_SPARC_REG_G5 = 59
UC_SPARC_REG_G6 = 60
UC_SPARC_REG_G7 = 61
UC_SPARC_REG_I0 = 62
UC_SPARC_REG_I1 = 63
UC_SPARC_REG_I2 = 64
UC_SPARC_REG_I3 = 65
UC_SPARC_REG_I4 = 66
UC_SPARC_REG_I5 = 67
UC_SPARC_REG_I7 = 68
UC_SPARC_REG_ICC = 69
UC_SPARC_REG_L0 = 70
UC_SPARC_REG_L1 = 71
UC_SPARC_REG_L2 = 72
UC_SPARC_REG_L3 = 73
UC_SPARC_REG_L4 = 74
UC_SPARC_REG_L5 = 75
UC_SPARC_REG_L6 = 76
UC_SPARC_REG_L7 = 77
UC_SPARC_REG_O0 = 78
UC_SPARC_REG_O1 = 79
UC_SPARC_REG_O2 = 80
UC_SPARC_REG_O3 = 81
UC_SPARC_REG_O4 = 82
UC_SPARC_REG_O5 = 83
UC_SPARC_REG_O7 = 84
UC_SPARC_REG_SP = 85
UC_SPARC_REG_Y = 86
UC_SPARC_REG_XCC = 87
UC_SPARC_REG_PC = 88
UC_SPARC_REG_ENDING = 89
UC_SPARC_REG_O6 = UC_SPARC_REG_SP
UC_SPARC_REG_I6 = UC_SPARC_REG_FP
)

View File

@ -0,0 +1,89 @@
package unicorn
import (
"unsafe"
)
/*
#cgo LDFLAGS: -lunicorn
#include <unicorn/unicorn.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 != C.UC_ERR_OK {
return UcError(err)
}
return nil
}
type Uc struct {
Handle C.uch
Arch, Mode int
}
type UcOptions struct {
Timeout, Count uint64
}
func NewUc(arch, mode int) (*Uc, error) {
var major, minor C.uint
C.uc_version(&major, &minor)
if major != C.UC_API_MAJOR || minor != C.UC_API_MINOR {
return nil, UcError(C.UC_ERR_VERSION)
}
var handle C.uch
if ucerr := C.uc_open(C.uc_arch(arch), C.uc_mode(mode), &handle); ucerr != C.UC_ERR_OK {
return nil, UcError(ucerr)
}
uc := &Uc{handle, arch, mode}
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))
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) MemWrite(addr uint64, data []byte) error {
return errReturn(C.uc_mem_write(u.Handle, C.uint64_t(addr), (*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data))))
}
func (u *Uc) MemReadInto(dst []byte, addr uint64) error {
return errReturn(C.uc_mem_read(u.Handle, C.uint64_t(addr), (*C.uint8_t)(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) MemMap(addr, size uint64) error {
return errReturn(C.uc_mem_map(u.Handle, C.uint64_t(addr), C.size_t(size)))
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,145 @@
package unicorn
import (
"testing"
)
var ADDRESS uint64 = 0x1000000
func MakeUc(mode int, code string) (*Uc, error) {
mu, err := NewUc(UC_ARCH_X86, mode)
if err != nil {
return nil, err
}
if err := mu.MemMap(ADDRESS, 2*1024*1024); err != nil {
return nil, err
}
if err := mu.MemWrite(ADDRESS, []byte(code)); err != nil {
return nil, err
}
if err := mu.RegWrite(UC_X86_REG_ECX, 0x1234); err != nil {
return nil, err
}
if err := mu.RegWrite(UC_X86_REG_EDX, 0x7890); err != nil {
return nil, err
}
return mu, nil
}
func TestX86(t *testing.T) {
code := "\x41\x4a"
mu, err := MakeUc(UC_MODE_32, code)
if err != nil {
t.Fatal(err)
}
if err := mu.Start(ADDRESS, ADDRESS+uint64(len(code))); err != nil {
t.Fatal(err)
}
ecx, _ := mu.RegRead(UC_X86_REG_ECX)
edx, _ := mu.RegRead(UC_X86_REG_EDX)
if ecx != 0x1235 || edx != 0x788f {
t.Fatal("Bad register values.")
}
}
func TestX86InvalidRead(t *testing.T) {
code := "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a"
mu, err := MakeUc(UC_MODE_32, code)
if err != nil {
t.Fatal(err)
}
err = mu.Start(ADDRESS, ADDRESS+uint64(len(code)))
if err.(UcError) != UC_ERR_MEM_READ {
t.Fatal("Expected UC_ERR_MEM_READ")
}
ecx, _ := mu.RegRead(UC_X86_REG_ECX)
edx, _ := mu.RegRead(UC_X86_REG_EDX)
if ecx != 0x1234 || edx != 0x7890 {
t.Fatal("Bad register values.")
}
}
func TestX86InvalidWrite(t *testing.T) {
code := "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a"
mu, err := MakeUc(UC_MODE_32, code)
if err != nil {
t.Fatal(err)
}
err = mu.Start(ADDRESS, ADDRESS+uint64(len(code)))
if err.(UcError) != UC_ERR_MEM_WRITE {
t.Fatal("Expected UC_ERR_MEM_WRITE")
}
ecx, _ := mu.RegRead(UC_X86_REG_ECX)
edx, _ := mu.RegRead(UC_X86_REG_EDX)
if ecx != 0x1234 || edx != 0x7890 {
t.Fatal("Bad register values.")
}
}
func TestX86InOut(t *testing.T) {
code := "\x41\xE4\x3F\x4a\xE6\x46\x43"
mu, err := MakeUc(UC_MODE_32, code)
if err != nil {
t.Fatal(err)
}
var outVal uint64
var inCalled, outCalled bool
mu.HookAdd(UC_HOOK_INSN, func(mu *Uc, port, size uint32) uint32 {
inCalled = true
switch size {
case 1:
return 0xf1
case 2:
return 0xf2
case 4:
return 0xf4
default:
return 0
}
}, UC_X86_INS_IN)
mu.HookAdd(UC_HOOK_INSN, func(uc *Uc, port, size, value uint32) {
outCalled = true
var err error
switch size {
case 1:
outVal, err = mu.RegRead(UC_X86_REG_AL)
case 2:
outVal, err = mu.RegRead(UC_X86_REG_AX)
case 4:
outVal, err = mu.RegRead(UC_X86_REG_EAX)
}
if err != nil {
t.Fatal(err)
}
}, UC_X86_INS_OUT)
if err := mu.Start(ADDRESS, ADDRESS+uint64(len(code))); err != nil {
t.Fatal(err)
}
if !inCalled || !outCalled {
t.Fatal("Ports not accessed.")
}
if outVal != 0xf1 {
t.Fatal("Incorrect OUT value.")
}
}
func TestX86Syscall(t *testing.T) {
code := "\x0f\x05"
mu, err := MakeUc(UC_MODE_64, code)
if err != nil {
t.Fatal(err)
}
mu.HookAdd(UC_HOOK_INSN, func(mu *Uc) {
rax, _ := mu.RegRead(UC_X86_REG_RAX)
mu.RegWrite(UC_X86_REG_RAX, rax+1)
}, UC_X86_INS_SYSCALL)
mu.RegWrite(UC_X86_REG_RAX, 0x100)
err = mu.Start(ADDRESS, ADDRESS+uint64(len(code)))
if err != nil {
t.Fatal(err)
}
v, _ := mu.RegRead(UC_X86_REG_RAX)
if v != 0x101 {
t.Fatal("Incorrect syscall return value.")
}
}