Merge branch 'master' of github.com:unicorn-engine/unicorn into fpip_update

This commit is contained in:
mothran 2015-08-28 23:40:25 -07:00
commit 79184ff23d
52 changed files with 3570 additions and 2964 deletions

3
.gitignore vendored
View File

@ -84,3 +84,6 @@ regress/map_crash
regress/sigill
regress/sigill2
regress/block_test
regress/map_write
regress/ro_mem_test
regress/nr_mem_test

View File

@ -15,6 +15,7 @@ SAMPLE_X86 = $(TMPDIR)/sample_x86
all:
cd python && $(MAKE) gen_const
cd go && $(MAKE) gen_const
samples: expected python

View File

@ -5,7 +5,7 @@ import sys, re
INCL_DIR = '../include/unicorn/'
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h' ]
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'unicorn.h' ]
template = {
'python': {
@ -20,13 +20,14 @@ template = {
'x86.h': 'x86',
'sparc.h': 'sparc',
'm68k.h': 'm68k',
'unicorn.h': 'unicorn',
'comment_open': '#',
'comment_close': '',
},
'go': {
'header': "package unicorn\n// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.go]\nconst (",
'header': "package unicorn\n// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.go]\nconst (\n",
'footer': ")",
'line_format': '%s = %s\n',
'line_format': '\t%s = %s\n',
'out_file': './go/unicorn/%s_const.go',
# prefixes for constant filenames of all archs - case sensitive
'arm.h': 'arm',
@ -35,6 +36,7 @@ template = {
'x86.h': 'x86',
'sparc.h': 'sparc',
'm68k.h': 'm68k',
'unicorn.h': 'unicorn',
'comment_open': '//',
'comment_close': '',
},
@ -50,9 +52,11 @@ def gen(lang):
prefix = templ[target]
outfile = open(templ['out_file'] %(prefix), 'w')
outfile.write(templ['header'] % (prefix))
if target == 'unicorn.h':
prefix = ''
lines = open(INCL_DIR + target).readlines()
previous = {}
count = 0
for line in lines:
line = line.strip()
@ -65,17 +69,21 @@ def gen(lang):
if line == '' or line.startswith('//'):
continue
if not line.startswith("UC_" + prefix.upper()):
continue
tmp = line.strip().split(',')
for t in tmp:
t = t.strip()
if not t or t.startswith('//'): continue
f = re.split('\s+', t)
# parse #define UC_TARGET (num)
define = False
if f[0] == '#define' and len(f) >= 3 and f[2].isdigit():
define = True
f.pop(0)
f.insert(1, '=')
if f[0].startswith("UC_" + prefix.upper()):
if len(f) > 1 and f[1] not in '//=':
if len(f) > 1 and f[1] not in ('//', '='):
print("Error: Unable to convert %s" % f)
continue
elif len(f) > 1 and f[1] == '=':
@ -84,29 +92,31 @@ def gen(lang):
rhs = str(count)
count += 1
try:
count = int(rhs) + 1
if (count == 1):
outfile.write("\n")
except ValueError:
if lang == 'ocaml':
# ocaml uses lsl for '<<', lor for '|'
rhs = rhs.replace('<<', ' lsl ')
rhs = rhs.replace('|', ' lor ')
# ocaml variable has _ as prefix
if rhs[0].isalpha():
rhs = '_' + rhs
lhs = f[0].strip()
# evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1"
match = re.match(r'(?P<rhs>\s*\d+\s*<<\s*\d+\s*)', rhs)
if match:
rhs = eval(match.group(1))
else:
# evaluate references to other constants e.g. "UC_ARM_REG_X = UC_ARM_REG_SP"
match = re.match(r'^([^\d]\w+)$', rhs)
if match:
rhs = previous[match.group(1)]
outfile.write(templ['line_format'] %(f[0].strip(), rhs))
count = int(rhs) + 1
if (count == 1):
outfile.write("\n")
outfile.write(templ['line_format'] % (lhs, rhs))
previous[lhs] = rhs
outfile.write(templ['footer'])
outfile.close()
def main():
try:
gen(sys.argv[1])
except:
raise RuntimeError("Unsupported binding %s" % sys.argv[1])
lang = sys.argv[1]
if not lang in template:
raise RuntimeError("Unsupported binding %s" % lang)
gen(sys.argv[1])
if __name__ == "__main__":
if len(sys.argv) < 2:

View File

@ -2,9 +2,13 @@
.PHONY: gen_const test
all:
$(MAKE) gen_const
cd unicorn && go build
$(MAKE) test
gen_const:
cd .. && python const_generator.py go
cd unicorn && go build
test:
cd unicorn && go test

View File

@ -1,276 +1,277 @@
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
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
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
UC_ARM64_REG_IP1 = 215
UC_ARM64_REG_IP0 = 216
UC_ARM64_REG_FP = 1
UC_ARM64_REG_LR = 2
)

View File

@ -1,127 +1,128 @@
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
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
UC_ARM_REG_R13 = 12
UC_ARM_REG_R14 = 10
UC_ARM_REG_R15 = 11
UC_ARM_REG_SB = 75
UC_ARM_REG_SL = 76
UC_ARM_REG_FP = 77
UC_ARM_REG_IP = 78
)

View File

@ -1,22 +0,0 @@
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

@ -1,26 +1,27 @@
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
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

@ -1,197 +1,198 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.go]
const (
// MIPS registers
UC_MIPS_REG_INVALID = 0
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
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
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
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
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
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
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 = 2
UC_MIPS_REG_AT = 3
UC_MIPS_REG_V0 = 4
UC_MIPS_REG_V1 = 5
UC_MIPS_REG_A0 = 6
UC_MIPS_REG_A1 = 7
UC_MIPS_REG_A2 = 8
UC_MIPS_REG_A3 = 9
UC_MIPS_REG_T0 = 10
UC_MIPS_REG_T1 = 11
UC_MIPS_REG_T2 = 12
UC_MIPS_REG_T3 = 13
UC_MIPS_REG_T4 = 14
UC_MIPS_REG_T5 = 15
UC_MIPS_REG_T6 = 16
UC_MIPS_REG_T7 = 17
UC_MIPS_REG_S0 = 18
UC_MIPS_REG_S1 = 19
UC_MIPS_REG_S2 = 20
UC_MIPS_REG_S3 = 21
UC_MIPS_REG_S4 = 22
UC_MIPS_REG_S5 = 23
UC_MIPS_REG_S6 = 24
UC_MIPS_REG_S7 = 25
UC_MIPS_REG_T8 = 26
UC_MIPS_REG_T9 = 27
UC_MIPS_REG_K0 = 28
UC_MIPS_REG_K1 = 29
UC_MIPS_REG_GP = 30
UC_MIPS_REG_SP = 31
UC_MIPS_REG_FP = 32
UC_MIPS_REG_S8 = 32
UC_MIPS_REG_RA = 33
UC_MIPS_REG_HI0 = 45
UC_MIPS_REG_HI1 = 46
UC_MIPS_REG_HI2 = 47
UC_MIPS_REG_HI3 = 48
UC_MIPS_REG_LO0 = 45
UC_MIPS_REG_LO1 = 46
UC_MIPS_REG_LO2 = 47
UC_MIPS_REG_LO3 = 48
)

View File

@ -1,98 +1,99 @@
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
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 = 85
UC_SPARC_REG_I6 = 53
)

View File

@ -17,7 +17,7 @@ func (u UcError) Error() string {
}
func errReturn(err C.uc_err) error {
if err != C.UC_ERR_OK {
if err != UC_ERR_OK {
return UcError(err)
}
return nil
@ -36,10 +36,10 @@ 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)
return nil, UcError(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 {
if ucerr := C.uc_open(C.uc_arch(arch), C.uc_mode(mode), &handle); ucerr != UC_ERR_OK {
return nil, UcError(ucerr)
}
uc := &Uc{handle, arch, mode}

View File

@ -0,0 +1,69 @@
package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go]
const (
UC_API_MAJOR = 0
UC_API_MINOR = 9
UC_SECOND_SCALE = 1000000
UC_MILISECOND_SCALE = 1000
UC_ARCH_ARM = 1
UC_ARCH_ARM64 = 2
UC_ARCH_MIPS = 3
UC_ARCH_X86 = 4
UC_ARCH_PPC = 5
UC_ARCH_SPARC = 6
UC_ARCH_M68K = 7
UC_ARCH_MAX = 8
UC_MODE_LITTLE_ENDIAN = 0
UC_MODE_ARM = 0
UC_MODE_16 = 2
UC_MODE_32 = 4
UC_MODE_64 = 8
UC_MODE_THUMB = 16
UC_MODE_MCLASS = 32
UC_MODE_V8 = 64
UC_MODE_MICRO = 16
UC_MODE_MIPS3 = 32
UC_MODE_MIPS32R6 = 64
UC_MODE_V9 = 16
UC_MODE_QPX = 16
UC_MODE_BIG_ENDIAN = 2147483648
UC_MODE_MIPS32 = 4
UC_MODE_MIPS64 = 8
UC_ERR_OK = 0
UC_ERR_OOM = 1
UC_ERR_ARCH = 2
UC_ERR_HANDLE = 3
UC_ERR_UCH = 4
UC_ERR_MODE = 5
UC_ERR_VERSION = 6
UC_ERR_MEM_READ = 7
UC_ERR_MEM_WRITE = 8
UC_ERR_CODE_INVALID = 9
UC_ERR_HOOK = 10
UC_ERR_INSN_INVALID = 11
UC_ERR_MAP = 12
UC_ERR_MEM_WRITE_NW = 13
UC_ERR_MEM_READ_NR = 14
UC_MEM_READ = 16
UC_MEM_WRITE = 17
UC_MEM_READ_WRITE = 18
UC_MEM_WRITE_NW = 19
UC_MEM_READ_NR = 20
UC_HOOK_INTR = 32
UC_HOOK_INSN = 33
UC_HOOK_CODE = 34
UC_HOOK_BLOCK = 35
UC_HOOK_MEM_INVALID = 36
UC_HOOK_MEM_READ = 37
UC_HOOK_MEM_WRITE = 38
UC_HOOK_MEM_READ_WRITE = 39
UC_PROT_NONE = 0
UC_PROT_READ = 1
UC_PROT_WRITE = 2
UC_PROT_ALL = 3
)

File diff suppressed because it is too large Load Diff

View File

@ -624,7 +624,7 @@ public class Unicorn implements UnicornArchs, UnicornModes, UnicornHooks,
* @param address Base address of the memory range
* @param size Size of the memory block.
*/
public native void mem_map(long address, long size) throws UnicornException;
public native void mem_map(long address, long size, int perms) throws UnicornException;
}

View File

@ -502,13 +502,13 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del
/*
* Class: unicorn_Unicorn
* Method: mem_map
* Signature: (JJ)V
* Signature: (JJI)V
*/
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
(JNIEnv *env, jobject self, jlong address, jlong size) {
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms) {
uch handle = getHandle(env, self);
uc_err err = uc_mem_map(handle, (uint64_t)address, (size_t)size);
uc_err err = uc_mem_map(handle, (uint64_t)address, (size_t)size, (uint32_t)perms);
if (err != UC_ERR_OK) {
throwException(env, err);
}

15
bindings/python/sample_all.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
./sample_x86.py
echo "=========================="
./shellcode.py
echo "=========================="
./sample_arm.py
echo "=========================="
./sample_arm64.py
echo "=========================="
./sample_mips.py
echo "=========================="
./sample_sparc.py
echo "=========================="
./sample_m68k.py

View File

@ -1,464 +1,4 @@
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
import sys
_python2 = sys.version_info[0] < 3
if _python2:
range = xrange
from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const
__all__ = [
'Uc',
'uc_version',
'uc_arch_supported',
'version_bind',
'debug',
'UC_API_MAJOR',
'UC_API_MINOR',
'UC_ARCH_ARM',
'UC_ARCH_ARM64',
'UC_ARCH_MIPS',
'UC_ARCH_X86',
'UC_ARCH_SPARC',
'UC_ARCH_M68K',
'UC_ARCH_ALL',
'UC_MODE_LITTLE_ENDIAN',
'UC_MODE_BIG_ENDIAN',
'UC_MODE_16',
'UC_MODE_32',
'UC_MODE_64',
'UC_MODE_ARM',
'UC_MODE_THUMB',
'UC_MODE_MCLASS',
'UC_MODE_MICRO',
'UC_MODE_MIPS3',
'UC_MODE_MIPS32R6',
'UC_MODE_MIPSGP64',
'UC_MODE_V8',
'UC_MODE_V9',
'UC_MODE_MIPS32',
'UC_MODE_MIPS64',
'UC_ERR_OK',
'UC_ERR_OOM',
'UC_ERR_ARCH',
'UC_ERR_HANDLE',
'UC_ERR_UCH',
'UC_ERR_MODE',
'UC_ERR_VERSION',
'UC_ERR_MEM_READ',
'UC_ERR_MEM_WRITE',
'UC_ERR_CODE_INVALID',
'UC_ERR_HOOK',
'UC_ERR_INSN_INVALID',
'UC_ERR_MAP',
'UC_HOOK_INTR',
'UC_HOOK_INSN',
'UC_HOOK_CODE',
'UC_HOOK_BLOCK',
'UC_HOOK_MEM_INVALID',
'UC_HOOK_MEM_READ',
'UC_HOOK_MEM_WRITE',
'UC_HOOK_MEM_READ_WRITE',
'UC_MEM_READ',
'UC_MEM_WRITE',
'UC_MEM_READ_WRITE',
'UC_SECOND_SCALE',
'UC_MILISECOND_SCALE',
'UcError',
]
# Unicorn C interface
# API version
UC_API_MAJOR = 0
UC_API_MINOR = 9
# Architectures
UC_ARCH_ARM = 1
UC_ARCH_ARM64 = 2
UC_ARCH_MIPS = 3
UC_ARCH_X86 = 4
UC_ARCH_PPC = 5
UC_ARCH_SPARC = 6
UC_ARCH_M68K = 7
UC_ARCH_MAX = 8
UC_ARCH_ALL = 0xFFFF
# Hardware modes
UC_MODE_LITTLE_ENDIAN = 0 # little-endian mode (default mode)
UC_MODE_ARM = 0 # ARM mode
UC_MODE_16 = (1 << 1) # 16-bit mode (for X86)
UC_MODE_32 = (1 << 2) # 32-bit mode (for X86)
UC_MODE_64 = (1 << 3) # 64-bit mode (for X86, PPC)
UC_MODE_THUMB = (1 << 4) # ARM's Thumb mode, including Thumb-2
UC_MODE_MCLASS = (1 << 5) # ARM's Cortex-M series
UC_MODE_V8 = (1 << 6) # ARMv8 A32 encodings for ARM
UC_MODE_MICRO = (1 << 4) # MicroMips mode (MIPS architecture)
UC_MODE_MIPS3 = (1 << 5) # Mips III ISA
UC_MODE_MIPS32R6 = (1 << 6) # Mips32r6 ISA
UC_MODE_MIPSGP64 = (1 << 7) # General Purpose Registers are 64-bit wide (MIPS arch)
UC_MODE_V9 = (1 << 4) # Sparc V9 mode (for Sparc)
UC_MODE_BIG_ENDIAN = (1 << 31) # big-endian mode
UC_MODE_MIPS32 = UC_MODE_32 # Mips32 ISA
UC_MODE_MIPS64 = UC_MODE_64 # Mips64 ISA
# Unicorn error type
UC_ERR_OK = 0 # No error: everything was fine
UC_ERR_OOM = 1 # Out-Of-Memory error: uc_open(), uc_emulate()
UC_ERR_ARCH = 2 # Unsupported architecture: uc_open()
UC_ERR_HANDLE = 3 # Invalid handle
UC_ERR_UCH = 4 # Invalid handle (uch)
UC_ERR_MODE = 5 # Invalid/unsupported mode: uc_open()
UC_ERR_VERSION = 6 # Unsupported version (bindings)
UC_ERR_MEM_READ = 7 # Quit emulation due to invalid memory READ: uc_emu_start()
UC_ERR_MEM_WRITE = 8 # Quit emulation due to invalid memory WRITE: uc_emu_start()
UC_ERR_CODE_INVALID = 9 # Quit emulation due to invalid code address: uc_emu_start()
UC_ERR_HOOK = 10 # Invalid hook type: uc_hook_add()
UC_ERR_INSN_INVALID = 11 # Invalid instruction
UC_ERR_MAP = 12 # Invalid memory mapping
# All type of hooks for uc_hook_add() API.
UC_HOOK_INTR = 32 # Hook all interrupt events
UC_HOOK_INSN = 33 # Hook a particular instruction
UC_HOOK_CODE = 34 # Hook a range of code
UC_HOOK_BLOCK = 35 # Hook basic blocks
UC_HOOK_MEM_INVALID = 36 # Hook for all invalid memory access events
UC_HOOK_MEM_READ = 37 # Hook all memory read events.
UC_HOOK_MEM_WRITE = 38 # Hook all memory write events.
UC_HOOK_MEM_READ_WRITE = 39 # Hook all memory accesses (either READ or WRITE).
# All type of memory accesses for UC_HOOK_MEM_*
UC_MEM_READ = 16 # Memory is read from
UC_MEM_WRITE = 17 # Memory is written to
UC_MEM_READ_WRITE = 18 # Memory is accessed (either READ or WRITE)
# Time scales to calculate timeout on microsecond unit
# This is for Uc.emu_start()
UC_SECOND_SCALE = 1000000 # 1 second = 1000,000 microseconds
UC_MILISECOND_SCALE = 1000 # 1 milisecond = 1000 nanoseconds
import ctypes, ctypes.util, sys
from os.path import split, join, dirname
import distutils.sysconfig
import inspect
if not hasattr(sys.modules[__name__], '__file__'):
__file__ = inspect.getfile(inspect.currentframe())
_lib_path = split(__file__)[0]
_all_libs = ['unicorn.dll', 'libunicorn.so', 'libunicorn.dylib']
_found = False
for _lib in _all_libs:
try:
_lib_file = join(_lib_path, _lib)
# print "Trying to load:", _lib_file
_uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True
break
except OSError:
pass
if _found == False:
# try loading from default paths
for _lib in _all_libs:
try:
_uc = ctypes.cdll.LoadLibrary(_lib)
_found = True
break
except OSError:
pass
if _found == False:
# last try: loading from python lib directory
_lib_path = distutils.sysconfig.get_python_lib()
for _lib in _all_libs:
try:
_lib_file = join(_lib_path, 'unicorn', _lib)
# print "Trying to load:", _lib_file
_uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True
break
except OSError:
pass
if _found == False:
raise ImportError("ERROR: fail to load the dynamic library.")
# setup all the function prototype
def _setup_prototype(lib, fname, restype, *argtypes):
getattr(lib, fname).restype = restype
getattr(lib, fname).argtypes = argtypes
_setup_prototype(_uc, "uc_version", ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
_setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int)
_setup_prototype(_uc, "uc_open", ctypes.c_int, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_close", ctypes.c_int, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_strerror", ctypes.c_char_p, ctypes.c_int)
_setup_prototype(_uc, "uc_errno", ctypes.c_int, ctypes.c_size_t)
_setup_prototype(_uc, "uc_reg_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
_setup_prototype(_uc, "uc_reg_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
_setup_prototype(_uc, "uc_mem_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
_setup_prototype(_uc, "uc_emu_start", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
_setup_prototype(_uc, "uc_emu_stop", ctypes.c_int, ctypes.c_size_t)
_setup_prototype(_uc, "uc_hook_del", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_mem_map", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t)
# uc_hook_add is special due to variable number of arguments
_uc.uc_hook_add = getattr(_uc, "uc_hook_add")
_uc.uc_hook_add.restype = ctypes.c_int
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_size_t, ctypes.c_int, \
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p)
UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_int, \
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p)
UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \
ctypes.c_void_p)
UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_size_t, ctypes.c_uint32, \
ctypes.c_int, ctypes.c_void_p)
UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p)
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_void_p)
# access to error code via @errno of UcError
class UcError(Exception):
def __init__(self, errno):
self.errno = errno
def __str__(self):
return _uc.uc_strerror(self.errno)
# return the core's version
def uc_version():
major = ctypes.c_int()
minor = ctypes.c_int()
combined = _uc.uc_version(ctypes.byref(major), ctypes.byref(minor))
return (major.value, minor.value, combined)
# return the binding's version
def version_bind():
return (UC_API_MAJOR, UC_API_MINOR, (UC_API_MAJOR << 8) + UC_API_MINOR)
# check to see if this engine supports a particular arch
def uc_arch_supported(query):
return _uc.uc_arch_supported(query)
class Uc(object):
def __init__(self, arch, mode):
# verify version compatibility with the core before doing anything
(major, minor, _combined) = uc_version()
if major != UC_API_MAJOR or minor != UC_API_MINOR:
self._uch = None
# our binding version is different from the core's API version
raise UcError(UC_ERR_VERSION)
self._arch, self._mode = arch, mode
self._uch = ctypes.c_size_t()
status = _uc.uc_open(arch, mode, ctypes.byref(self._uch))
if status != UC_ERR_OK:
self._uch = None
raise UcError(status)
# internal mapping table to save callback & userdata
self._callbacks = {}
self._callback_count = 0
# destructor to be called automatically when object is destroyed.
def __del__(self):
if self._uch:
try:
status = _uc.uc_close(ctypes.byref(self._uch))
if status != UC_ERR_OK:
raise UcError(status)
except: # _uc might be pulled from under our feet
pass
# emulate from @begin, and stop when reaching address @until
def emu_start(self, begin, until, timeout=0, count=0):
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
if status != UC_ERR_OK:
raise UcError(status)
# stop emulation
def emu_stop(self):
status = _uc.uc_emu_stop(self._uch)
if status != UC_ERR_OK:
raise UcError(status)
# return the value of a register
def reg_read(self, reg_id):
# read to 64bit number to be safe
reg = ctypes.c_int64(0)
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK:
raise UcError(status)
return reg.value
# write to a register
def reg_write(self, reg_id, value):
# convert to 64bit number to be safe
reg = ctypes.c_int64(value)
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK:
raise UcError(status)
# read data from memory
def mem_read(self, address, size):
data = ctypes.create_string_buffer(size)
status = _uc.uc_mem_read(self._uch, address, data, size)
if status != UC_ERR_OK:
raise UcError(status)
return bytearray(data)
# write to memory
def mem_write(self, address, data):
status = _uc.uc_mem_write(self._uch, address, data, len(data))
if status != UC_ERR_OK:
raise UcError(status)
# map a range of memory
def mem_map(self, address, size):
status = _uc.uc_mem_map(self._uch, address, size)
if status != UC_ERR_OK:
raise UcError(status)
def _hookcode_cb(self, handle, address, size, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, address, size, data)
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
return cb(self, access, address, size, value, data)
def _hook_mem_access_cb(self, handle, access, address, size, value, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, access, address, size, value, data)
def _hook_intr_cb(self, handle, intno, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, intno, data)
def _hook_insn_in_cb(self, handle, port, size, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
return cb(self, port, size, data)
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, port, size, value, data)
def _hook_insn_syscall_cb(self, handle, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, data)
# add a hook
def hook_add(self, htype, callback, user_data=None, arg1=1, arg2=0):
_h2 = ctypes.c_size_t()
# save callback & user_data
self._callback_count += 1
self._callbacks[self._callback_count] = (callback, user_data)
if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE):
begin = ctypes.c_uint64(arg1)
end = ctypes.c_uint64(arg2)
# set callback with wrapper, so it can be called
# with this object as param
cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \
ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end)
elif htype == UC_HOOK_MEM_INVALID:
cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE):
cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
elif htype == UC_HOOK_INSN:
insn = ctypes.c_int(arg1)
if arg1 == x86_const.UC_X86_INS_IN: # IN instruction
cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB)
if arg1 == x86_const.UC_X86_INS_OUT: # OUT instruction
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction
cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), insn)
elif htype == UC_HOOK_INTR:
cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
if status != UC_ERR_OK:
raise UcError(status)
return _h2.value
# delete a hook
def hook_del(self, h):
_h = ctypes.c_size_t(h)
status = _uc.uc_hook_del(self._uch, ctypes.byref(_h))
if status != UC_ERR_OK:
raise UcError(status)
h = 0
# print out debugging info
def debug():
archs = { "arm": UC_ARCH_ARM, "arm64": UC_ARCH_ARM64, \
"mips": UC_ARCH_MIPS, "sparc": UC_ARCH_SPARC, \
"m68k": UC_ARCH_M68K, "x86": UC_ARCH_X86 }
all_archs = ""
keys = archs.keys()
keys.sort()
for k in keys:
if uc_arch_supported(archs[k]):
all_archs += "-%s" % k
(major, minor, _combined) = uc_version()
return "python-%s-c%u.%u-b%u.%u" % (all_archs, major, minor, UC_API_MAJOR, UC_API_MINOR)
from unicorn_const import *
from unicorn import Uc, uc_version, uc_arch_supported, version_bind, debug, UcError

View File

@ -268,7 +268,7 @@ 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
UC_ARM64_REG_IP1 = 215
UC_ARM64_REG_IP0 = 216
UC_ARM64_REG_FP = 1
UC_ARM64_REG_LR = 2

View File

@ -116,10 +116,10 @@ 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
UC_ARM_REG_R13 = 12
UC_ARM_REG_R14 = 10
UC_ARM_REG_R15 = 11
UC_ARM_REG_SB = 75
UC_ARM_REG_SL = 76
UC_ARM_REG_FP = 77
UC_ARM_REG_IP = 78

View File

@ -152,44 +152,44 @@ 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
UC_MIPS_REG_ZERO = 2
UC_MIPS_REG_AT = 3
UC_MIPS_REG_V0 = 4
UC_MIPS_REG_V1 = 5
UC_MIPS_REG_A0 = 6
UC_MIPS_REG_A1 = 7
UC_MIPS_REG_A2 = 8
UC_MIPS_REG_A3 = 9
UC_MIPS_REG_T0 = 10
UC_MIPS_REG_T1 = 11
UC_MIPS_REG_T2 = 12
UC_MIPS_REG_T3 = 13
UC_MIPS_REG_T4 = 14
UC_MIPS_REG_T5 = 15
UC_MIPS_REG_T6 = 16
UC_MIPS_REG_T7 = 17
UC_MIPS_REG_S0 = 18
UC_MIPS_REG_S1 = 19
UC_MIPS_REG_S2 = 20
UC_MIPS_REG_S3 = 21
UC_MIPS_REG_S4 = 22
UC_MIPS_REG_S5 = 23
UC_MIPS_REG_S6 = 24
UC_MIPS_REG_S7 = 25
UC_MIPS_REG_T8 = 26
UC_MIPS_REG_T9 = 27
UC_MIPS_REG_K0 = 28
UC_MIPS_REG_K1 = 29
UC_MIPS_REG_GP = 30
UC_MIPS_REG_SP = 31
UC_MIPS_REG_FP = 32
UC_MIPS_REG_S8 = 32
UC_MIPS_REG_RA = 33
UC_MIPS_REG_HI0 = 45
UC_MIPS_REG_HI1 = 46
UC_MIPS_REG_HI2 = 47
UC_MIPS_REG_HI3 = 48
UC_MIPS_REG_LO0 = 45
UC_MIPS_REG_LO1 = 46
UC_MIPS_REG_LO2 = 47
UC_MIPS_REG_LO3 = 48

View File

@ -92,5 +92,5 @@ 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
UC_SPARC_REG_O6 = 85
UC_SPARC_REG_I6 = 53

View File

@ -0,0 +1,321 @@
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
import sys
_python2 = sys.version_info[0] < 3
if _python2:
range = xrange
from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const
from unicorn_const import *
import ctypes, ctypes.util, sys
from os.path import split, join, dirname
import distutils.sysconfig
import inspect
if not hasattr(sys.modules[__name__], '__file__'):
__file__ = inspect.getfile(inspect.currentframe())
_lib_path = split(__file__)[0]
_all_libs = ['unicorn.dll', 'libunicorn.so', 'libunicorn.dylib']
_found = False
for _lib in _all_libs:
try:
_lib_file = join(_lib_path, _lib)
# print "Trying to load:", _lib_file
_uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True
break
except OSError:
pass
if _found == False:
# try loading from default paths
for _lib in _all_libs:
try:
_uc = ctypes.cdll.LoadLibrary(_lib)
_found = True
break
except OSError:
pass
if _found == False:
# last try: loading from python lib directory
_lib_path = distutils.sysconfig.get_python_lib()
for _lib in _all_libs:
try:
_lib_file = join(_lib_path, 'unicorn', _lib)
# print "Trying to load:", _lib_file
_uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True
break
except OSError:
pass
if _found == False:
raise ImportError("ERROR: fail to load the dynamic library.")
# setup all the function prototype
def _setup_prototype(lib, fname, restype, *argtypes):
getattr(lib, fname).restype = restype
getattr(lib, fname).argtypes = argtypes
_setup_prototype(_uc, "uc_version", ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
_setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int)
_setup_prototype(_uc, "uc_open", ctypes.c_int, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_close", ctypes.c_int, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_strerror", ctypes.c_char_p, ctypes.c_int)
_setup_prototype(_uc, "uc_errno", ctypes.c_int, ctypes.c_size_t)
_setup_prototype(_uc, "uc_reg_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
_setup_prototype(_uc, "uc_reg_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
_setup_prototype(_uc, "uc_mem_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
_setup_prototype(_uc, "uc_emu_start", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
_setup_prototype(_uc, "uc_emu_stop", ctypes.c_int, ctypes.c_size_t)
_setup_prototype(_uc, "uc_hook_del", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_mem_map", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
# uc_hook_add is special due to variable number of arguments
_uc.uc_hook_add = getattr(_uc, "uc_hook_add")
_uc.uc_hook_add.restype = ctypes.c_int
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_size_t, ctypes.c_int, \
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p)
UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_int, \
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p)
UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \
ctypes.c_void_p)
UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_size_t, ctypes.c_uint32, \
ctypes.c_int, ctypes.c_void_p)
UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p)
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_void_p)
# access to error code via @errno of UcError
class UcError(Exception):
def __init__(self, errno):
self.errno = errno
def __str__(self):
return _uc.uc_strerror(self.errno)
# return the core's version
def uc_version():
major = ctypes.c_int()
minor = ctypes.c_int()
combined = _uc.uc_version(ctypes.byref(major), ctypes.byref(minor))
return (major.value, minor.value, combined)
# return the binding's version
def version_bind():
return (UC_API_MAJOR, UC_API_MINOR, (UC_API_MAJOR << 8) + UC_API_MINOR)
# check to see if this engine supports a particular arch
def uc_arch_supported(query):
return _uc.uc_arch_supported(query)
class Uc(object):
def __init__(self, arch, mode):
# verify version compatibility with the core before doing anything
(major, minor, _combined) = uc_version()
if major != UC_API_MAJOR or minor != UC_API_MINOR:
self._uch = None
# our binding version is different from the core's API version
raise UcError(UC_ERR_VERSION)
self._arch, self._mode = arch, mode
self._uch = ctypes.c_size_t()
status = _uc.uc_open(arch, mode, ctypes.byref(self._uch))
if status != UC_ERR_OK:
self._uch = None
raise UcError(status)
# internal mapping table to save callback & userdata
self._callbacks = {}
self._callback_count = 0
# destructor to be called automatically when object is destroyed.
def __del__(self):
if self._uch:
try:
status = _uc.uc_close(ctypes.byref(self._uch))
if status != UC_ERR_OK:
raise UcError(status)
except: # _uc might be pulled from under our feet
pass
# emulate from @begin, and stop when reaching address @until
def emu_start(self, begin, until, timeout=0, count=0):
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
if status != UC_ERR_OK:
raise UcError(status)
# stop emulation
def emu_stop(self):
status = _uc.uc_emu_stop(self._uch)
if status != UC_ERR_OK:
raise UcError(status)
# return the value of a register
def reg_read(self, reg_id):
# read to 64bit number to be safe
reg = ctypes.c_int64(0)
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK:
raise UcError(status)
return reg.value
# write to a register
def reg_write(self, reg_id, value):
# convert to 64bit number to be safe
reg = ctypes.c_int64(value)
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK:
raise UcError(status)
# read data from memory
def mem_read(self, address, size):
data = ctypes.create_string_buffer(size)
status = _uc.uc_mem_read(self._uch, address, data, size)
if status != UC_ERR_OK:
raise UcError(status)
return bytearray(data)
# write to memory
def mem_write(self, address, data):
status = _uc.uc_mem_write(self._uch, address, data, len(data))
if status != UC_ERR_OK:
raise UcError(status)
# map a range of memory
def mem_map(self, address, size, perms=UC_PROT_ALL):
status = _uc.uc_mem_map(self._uch, address, size, perms)
if status != UC_ERR_OK:
raise UcError(status)
def _hookcode_cb(self, handle, address, size, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, address, size, data)
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
return cb(self, access, address, size, value, data)
def _hook_mem_access_cb(self, handle, access, address, size, value, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, access, address, size, value, data)
def _hook_intr_cb(self, handle, intno, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, intno, data)
def _hook_insn_in_cb(self, handle, port, size, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
return cb(self, port, size, data)
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, port, size, value, data)
def _hook_insn_syscall_cb(self, handle, user_data):
# call user's callback with self object
(cb, data) = self._callbacks[user_data]
cb(self, data)
# add a hook
def hook_add(self, htype, callback, user_data=None, arg1=1, arg2=0):
_h2 = ctypes.c_size_t()
# save callback & user_data
self._callback_count += 1
self._callbacks[self._callback_count] = (callback, user_data)
if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE):
begin = ctypes.c_uint64(arg1)
end = ctypes.c_uint64(arg2)
# set callback with wrapper, so it can be called
# with this object as param
cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \
ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end)
elif htype == UC_HOOK_MEM_INVALID:
cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE):
cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
elif htype == UC_HOOK_INSN:
insn = ctypes.c_int(arg1)
if arg1 == x86_const.UC_X86_INS_IN: # IN instruction
cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB)
if arg1 == x86_const.UC_X86_INS_OUT: # OUT instruction
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction
cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), insn)
elif htype == UC_HOOK_INTR:
cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
if status != UC_ERR_OK:
raise UcError(status)
return _h2.value
# delete a hook
def hook_del(self, h):
_h = ctypes.c_size_t(h)
status = _uc.uc_hook_del(self._uch, ctypes.byref(_h))
if status != UC_ERR_OK:
raise UcError(status)
h = 0
# print out debugging info
def debug():
archs = { "arm": UC_ARCH_ARM, "arm64": UC_ARCH_ARM64, \
"mips": UC_ARCH_MIPS, "sparc": UC_ARCH_SPARC, \
"m68k": UC_ARCH_M68K, "x86": UC_ARCH_X86 }
all_archs = ""
keys = archs.keys()
keys.sort()
for k in keys:
if uc_arch_supported(archs[k]):
all_archs += "-%s" % k
(major, minor, _combined) = uc_version()
return "python-%s-c%u.%u-b%u.%u" % (all_archs, major, minor, UC_API_MAJOR, UC_API_MINOR)

View File

@ -0,0 +1,66 @@
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py]
UC_API_MAJOR = 0
UC_API_MINOR = 9
UC_SECOND_SCALE = 1000000
UC_MILISECOND_SCALE = 1000
UC_ARCH_ARM = 1
UC_ARCH_ARM64 = 2
UC_ARCH_MIPS = 3
UC_ARCH_X86 = 4
UC_ARCH_PPC = 5
UC_ARCH_SPARC = 6
UC_ARCH_M68K = 7
UC_ARCH_MAX = 8
UC_MODE_LITTLE_ENDIAN = 0
UC_MODE_ARM = 0
UC_MODE_16 = 2
UC_MODE_32 = 4
UC_MODE_64 = 8
UC_MODE_THUMB = 16
UC_MODE_MCLASS = 32
UC_MODE_V8 = 64
UC_MODE_MICRO = 16
UC_MODE_MIPS3 = 32
UC_MODE_MIPS32R6 = 64
UC_MODE_V9 = 16
UC_MODE_QPX = 16
UC_MODE_BIG_ENDIAN = 2147483648
UC_MODE_MIPS32 = 4
UC_MODE_MIPS64 = 8
UC_ERR_OK = 0
UC_ERR_OOM = 1
UC_ERR_ARCH = 2
UC_ERR_HANDLE = 3
UC_ERR_UCH = 4
UC_ERR_MODE = 5
UC_ERR_VERSION = 6
UC_ERR_MEM_READ = 7
UC_ERR_MEM_WRITE = 8
UC_ERR_CODE_INVALID = 9
UC_ERR_HOOK = 10
UC_ERR_INSN_INVALID = 11
UC_ERR_MAP = 12
UC_ERR_MEM_WRITE_NW = 13
UC_ERR_MEM_READ_NR = 14
UC_MEM_READ = 16
UC_MEM_WRITE = 17
UC_MEM_READ_WRITE = 18
UC_MEM_WRITE_NW = 19
UC_MEM_READ_NR = 20
UC_HOOK_INTR = 32
UC_HOOK_INSN = 33
UC_HOOK_CODE = 34
UC_HOOK_BLOCK = 35
UC_HOOK_MEM_INVALID = 36
UC_HOOK_MEM_READ = 37
UC_HOOK_MEM_WRITE = 38
UC_HOOK_MEM_READ_WRITE = 39
UC_PROT_NONE = 0
UC_PROT_READ = 1
UC_PROT_WRITE = 2
UC_PROT_ALL = 3

15
include/uc_priv.h Executable file → Normal file
View File

@ -15,12 +15,6 @@
QTAILQ_HEAD(CPUTailQ, CPUState);
typedef struct MemoryBlock {
uint64_t begin; //inclusive
uint64_t end; //exclusive
uint32_t perms;
} MemoryBlock;
typedef struct ModuleEntry {
void (*init)(void);
QTAILQ_ENTRY(ModuleEntry) node;
@ -51,7 +45,9 @@ typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long);
typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr);
typedef int (*uc_args_uc_ram_size_t)(struct uc_struct*, ram_addr_t begin, size_t size);
typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, ram_addr_t begin, size_t size, uint32_t perms);
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
// which interrupt should make emulation stop?
typedef bool (*uc_args_int_t)(int intno);
@ -94,6 +90,7 @@ struct uc_struct {
uc_args_tcg_enable_t tcg_enabled;
uc_args_uc_long_t tcg_exec_init;
uc_args_uc_ram_size_t memory_map;
uc_readonly_mem_t readonly_mem;
// list of cpu
void* cpu;
@ -174,13 +171,13 @@ struct uc_struct {
int thumb; // thumb mode for ARM
// full TCG cache leads to middle-block break in the last translation?
bool block_full;
MemoryBlock *mapped_blocks;
MemoryRegion **mapped_blocks;
uint32_t mapped_block_count;
};
#include "qemu_macro.h"
// check if this address is mapped in (via uc_mem_map())
bool memory_mapping(struct uc_struct* uc, uint64_t address);
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address);
#endif

12
include/unicorn/unicorn.h Executable file → Normal file
View File

@ -116,6 +116,8 @@ typedef enum uc_err {
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
UC_ERR_MEM_WRITE_NW, // Quit emulation due to write to non-writable: uc_emu_start()
UC_ERR_MEM_READ_NR, // Quit emulation due to read from non-readable: uc_emu_start()
} uc_err;
@ -147,6 +149,8 @@ typedef enum uc_mem_type {
UC_MEM_READ = 16, // Memory is read from
UC_MEM_WRITE, // Memory is written to
UC_MEM_READ_WRITE, // Memory is accessed (either READ or WRITE)
UC_MEM_WRITE_NW, // write to non-writable
UC_MEM_READ_NR, // read from non-readable
} uc_mem_type;
// All type of hooks for uc_hook_add() API.
@ -385,9 +389,10 @@ UNICORN_EXPORT
uc_err uc_hook_del(uch handle, uch *h2);
typedef enum uc_prot {
UC_PROT_NONE = 0,
UC_PROT_READ = 1,
UC_PROT_WRITE = 2,
UC_PROT_EXEC = 4
UC_PROT_ALL = 3,
} uc_prot;
/*
@ -399,12 +404,15 @@ typedef enum uc_prot {
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.
This size must be multiple of 4KB, or this will return with UC_ERR_MAP error.
@perms: Permissions for the newly mapped region.
This must be some combination of UC_PROT_READ & UC_PROT_WRITE,
or this will return with UC_ERR_MAP error. See uc_prot type above.
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
*/
UNICORN_EXPORT
uc_err uc_mem_map(uch handle, uint64_t address, size_t size);
uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms);
#ifdef __cplusplus
}

View File

@ -117,13 +117,6 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
(uc->arch == UC_ARCH_M68K && cpu->exception_index == 0x2f) /* M68K's EXCP_TRAP15 */
) {
cpu->halted = 1;
//cpu->exception_index = EXCP_HLT;
//no_shutdown = 0;
//printf(">>> calling shutdown-request...\n");
//printf(">>> ** current EIP = %x\n", X86_CPU(cpu)->env.eip);
//qemu_system_shutdown_request();
//pause_all_vcpus();
//cpu_loop_exit(cpu);
ret = EXCP_HLT;
break;
}

0
qemu/header_gen.py Executable file → Normal file
View File

View File

@ -170,6 +170,8 @@ struct MemoryRegion {
MemoryRegionIoeventfd *ioeventfds;
NotifierList iommu_notify;
struct uc_struct *uc;
uint32_t perms; //all perms, partially redundant with readonly
uint64_t end;
};
/**
@ -315,12 +317,14 @@ void memory_region_init_io(struct uc_struct *uc, MemoryRegion *mr,
* @owner: the object that tracks the region's reference count
* @name: the name of the region.
* @size: size of the region.
* @perms: permissions on the region (UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC).
* @errp: pointer to Error*, to store an error if it happens.
*/
void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
struct Object *owner,
const char *name,
uint64_t size,
uint32_t perms,
Error **errp);
/**
@ -934,7 +938,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
void memory_register_types(struct uc_struct *uc);
int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size);
MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms);
int memory_free(struct uc_struct *uc);
#endif

View File

@ -31,27 +31,28 @@
// Unicorn engine
int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size)
MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms)
{
uc->ram = g_new(MemoryRegion, 1);
memory_region_init_ram(uc, uc->ram, NULL, "pc.ram", size, &error_abort);
memory_region_init_ram(uc, uc->ram, NULL, "pc.ram", size, perms, &error_abort);
memory_region_add_subregion(get_system_memory(uc), begin, uc->ram);
if (uc->current_cpu)
tlb_flush(uc->current_cpu, 1);
return 0;
return uc->ram;
}
int memory_free(struct uc_struct *uc)
{
int i;
get_system_memory(uc)->enabled = false;
if (uc->ram) {
uc->ram->enabled = false;
memory_region_del_subregion(get_system_memory(uc), uc->ram);
g_free(uc->ram);
for (i = 0; i < uc->mapped_block_count; i++) {
uc->mapped_blocks[i]->enabled = false;
memory_region_del_subregion(get_system_memory(uc), uc->mapped_blocks[i]);
g_free(uc->mapped_blocks[i]);
}
return 0;
}
@ -1151,10 +1152,15 @@ void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
Object *owner,
const char *name,
uint64_t size,
uint32_t perms,
Error **errp)
{
memory_region_init(uc, mr, owner, name, size);
mr->ram = true;
if (!(perms & UC_PROT_WRITE)) {
mr->readonly = true;
}
mr->perms = perms;
mr->terminates = true;
mr->destructor = memory_region_destructor_ram;
mr->ram_addr = qemu_ram_alloc(size, mr, errp);
@ -1309,6 +1315,12 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
if (mr->readonly != readonly) {
memory_region_transaction_begin(mr->uc);
mr->readonly = readonly;
if (readonly) {
mr->perms &= ~UC_PROT_WRITE;
}
else {
mr->perms |= UC_PROT_WRITE;
}
mr->uc->memory_region_update_pending |= mr->enabled;
memory_region_transaction_commit(mr->uc);
}
@ -1528,6 +1540,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
assert(!subregion->container);
subregion->container = mr;
subregion->addr = offset;
subregion->end = offset + int128_get64(subregion->size);
memory_region_update_container_subregions(subregion);
}

0
qemu/scripts/make_device_config.sh Normal file → Executable file
View File

131
qemu/softmmu_template.h Executable file → Normal file
View File

@ -178,6 +178,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
uintptr_t haddr;
DATA_TYPE res;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// 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_MEM_READ, addr);
@ -188,7 +191,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 && !memory_mapping(env->uc, addr)) {
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->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
@ -203,6 +206,26 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
}
}
// Unicorn: callback on read only memory
if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
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->hook_callbacks[uc->hook_mem_idx].user_data);
}
if (result) {
env->invalid_error = UC_ERR_OK;
}
else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_READ_NR;
// printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return 0;
}
}
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@ -300,6 +323,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
uintptr_t haddr;
DATA_TYPE res;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// 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_MEM_READ, addr);
@ -310,7 +336,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 && !memory_mapping(env->uc, addr)) {
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->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
@ -325,6 +351,26 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
}
}
// Unicorn: callback on read only memory
if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
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->hook_callbacks[uc->hook_mem_idx].user_data);
}
if (result) {
env->invalid_error = UC_ERR_OK;
}
else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_READ_NR;
// printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return 0;
}
}
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@ -460,31 +506,53 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
uintptr_t haddr;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// Unicorn: callback on memory write
if (env->uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_WRITE, addr);
if (uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)uc, UC_MEM_WRITE, addr);
if (trace) {
((uc_cb_hookmem_t)trace->callback)((uch)env->uc, UC_MEM_WRITE,
((uc_cb_hookmem_t)trace->callback)((uch)uc, UC_MEM_WRITE,
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
}
}
// Unicorn: callback on invalid memory
if (env->uc->hook_mem_idx && !memory_mapping(env->uc, addr)) {
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
(uch)env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
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->hook_callbacks[uc->hook_mem_idx].user_data)) {
// save error & quit
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE;
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
cpu_exit(env->uc->current_cpu);
cpu_exit(uc->current_cpu);
return;
} else {
env->invalid_error = UC_ERR_OK;
}
}
// Unicorn: callback on read only memory
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //read only memory
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->hook_callbacks[uc->hook_mem_idx].user_data);
}
if (result) {
env->invalid_error = UC_ERR_OK;
}
else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE_NW;
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return;
}
}
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@ -546,6 +614,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
mmu_idx, retaddr + GETPC_ADJ);
if (env->invalid_error != UC_ERR_OK)
break;
}
return;
}
@ -574,31 +644,54 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
uintptr_t haddr;
struct uc_struct *uc = env->uc;
MemoryRegion *mr = memory_mapping(uc, addr);
// Unicorn: callback on memory write
if (env->uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)env->uc, UC_MEM_WRITE, addr);
if (uc->hook_mem_write) {
struct hook_struct *trace = hook_find((uch)uc, UC_MEM_WRITE, addr);
if (trace) {
((uc_cb_hookmem_t)trace->callback)((uch)env->uc, UC_MEM_WRITE,
((uc_cb_hookmem_t)trace->callback)((uch)uc, UC_MEM_WRITE,
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
}
}
// Unicorn: callback on invalid memory
if (env->uc->hook_mem_idx && !memory_mapping(env->uc, addr)) {
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
(uch)env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
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->hook_callbacks[uc->hook_mem_idx].user_data)) {
// save error & quit
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE;
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
cpu_exit(env->uc->current_cpu);
cpu_exit(uc->current_cpu);
return;
} else {
env->invalid_error = UC_ERR_OK;
}
}
// Unicorn: callback on read only memory
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //read only memory
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->hook_callbacks[uc->hook_mem_idx].user_data);
}
if (result) {
env->invalid_error = UC_ERR_OK;
}
else {
env->invalid_addr = addr;
env->invalid_error = UC_ERR_MEM_WRITE_NW;
// printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr);
cpu_exit(uc->current_cpu);
return;
}
}
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@ -659,6 +752,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
Undo that for the recursion. */
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
mmu_idx, retaddr + GETPC_ADJ);
if (env->invalid_error != UC_ERR_OK)
break;
}
return;
}

View File

@ -8268,7 +8268,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
uint64_t flags;
target_ulong pc_start;
target_ulong cs_base;
int num_insns;
int num_insns = 0;
int max_insns;
bool block_full = false;
@ -8353,12 +8353,18 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
// done with initializing TCG variables
env->uc->init_tcg = true;
// early check to see if the address of this block is the until address
if (tb->pc == env->uc->addr_end) {
gen_tb_start(tcg_ctx);
gen_interrupt(dc, 0x99, tb->pc - tb->cs_base, tb->pc - tb->cs_base);
goto done_generating;
}
gen_opc_end = tcg_ctx->gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT;
pc_ptr = pc_start;
lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0)
max_insns = CF_COUNT_MASK;

View File

@ -73,6 +73,7 @@ static inline void uc_common_init(struct uc_struct* uc)
uc->pause_all_vcpus = pause_all_vcpus;
uc->vm_start = vm_start;
uc->memory_map = memory_map;
uc->readonly_mem = memory_region_set_readonly;
if (!uc->release)
uc->release = release_common;

View File

@ -4,6 +4,7 @@ LDFLAGS = -L.. -lunicorn
TESTS = map_crash map_write
TESTS += sigill sigill2
TESTS += block_test
TESTS += ro_mem_test nr_mem_test
all: $(TESTS)

View File

@ -39,7 +39,7 @@ int main() {
}
fprintf(stderr, "ok %d - uc_open\n", count++);
err = uc_mem_map(u, 0x1000000, 4096);
err = uc_mem_map(u, 0x1000000, 4096, UC_PROT_ALL);
if (err != UC_ERR_OK) {
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
exit(0);

13
regress/emu_stop_segfault.py Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/python
"""See https://github.com/unicorn-engine/unicorn/issues/65"""
import unicorn
ADDR = 0x10101000
mu = unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_32)
mu.mem_map(ADDR, 1024 * 4)
mu.mem_write(ADDR, b'\x41')
mu.emu_start(ADDR, ADDR + 1, count=1)
# The following should not trigger a null pointer dereference
mu.emu_stop()

View File

@ -4,9 +4,10 @@
#include <stdlib.h>
#define UC_BUG_WRITE_SIZE 13000
#define UC_BUG_WRITE_ADDR 0x1000 // fix this by change this to 0x2000
#define UC_BUG_WRITE_ADDR 0x1000
int main() {
int main()
{
int size;
uint8_t *buf;
uch uh;
@ -22,7 +23,7 @@ int main() {
return 1;
}
memset (buf, 0, size);
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size)) {
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
uc_mem_write (uh, UC_BUG_WRITE_ADDR, buf, size);
}
uc_close (&uh);

View File

@ -6,44 +6,45 @@
#define SIZE 1024*64
#define OVERFLOW 1
int main() {
uch uh;
char *buf, *buf2;
int i;
uc_err err;
int main()
{
uch uh;
uint8_t *buf, *buf2;
int i;
uc_err err;
err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh);
if (err) {
printf ("uc_open %d\n", err);
return 1;
}
err = uc_mem_map (uh, ADDR, SIZE);
if (err) {
printf ("uc_mem_map %d\n", err);
return 1;
}
buf = calloc (SIZE*2, 1);
buf2 = calloc (SIZE, 1);
for (i=0;i<SIZE; i++) {
buf[i] = i & 0xff;
}
/* crash here */
err = uc_mem_write (uh, ADDR, buf, SIZE+OVERFLOW);
if (err) {
printf ("uc_mem_map %d\n", err);
return 1;
}
err = uc_mem_read (uh, ADDR+10, buf2, 4);
if (err) {
printf ("uc_mem_map %d\n", err);
return 1;
}
if (buf2[0] != 0xa) {
printf ("mem contents are wrong\n");
return 1;
}
printf ("OK\n");
free (buf);
free (buf2);
return 0;
err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh);
if (err) {
printf ("uc_open %d\n", err);
return 1;
}
err = uc_mem_map (uh, ADDR, SIZE, UC_PROT_ALL);
if (err) {
printf ("uc_mem_map %d\n", err);
return 1;
}
buf = calloc (SIZE*2, 1);
buf2 = calloc (SIZE, 1);
for (i=0;i<SIZE; i++) {
buf[i] = i & 0xff;
}
/* crash here */
err = uc_mem_write (uh, ADDR, buf, SIZE+OVERFLOW);
if (err) {
printf ("uc_mem_map %d\n", err);
return 1;
}
err = uc_mem_read (uh, ADDR+10, buf2, 4);
if (err) {
printf ("uc_mem_map %d\n", err);
return 1;
}
if (buf2[0] != 0xa) {
printf ("mem contents are wrong\n");
return 1;
}
printf ("OK\n");
free (buf);
free (buf2);
return 0;
}

View File

@ -5,4 +5,4 @@ uc = Uc(UC_ARCH_X86, UC_MODE_32)
uc.mem_map(0x0000, 0x2000)
uc.mem_map(0x2000, 0x4000)
uc.mem_write(0x1000, 0x1004 * ' ')
print 'Not reached on x86_64 Linux.'
print 'If not reached, then we have BUG (crash on x86_64 Linux).'

109
regress/nr_mem_test.c Normal file
View File

@ -0,0 +1,109 @@
/*
Non-readable memory test case
Copyright(c) 2015 Chris Eagle
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <unicorn/unicorn.h>
const uint8_t PROGRAM[] =
"\x8b\x1d\x00\x00\x30\x00\xa1\x00\x00\x40\x00";
// total size: 11 bytes
/*
bits 32
mov ebx, [0x300000]
mov eax, [0x400000]
*/
// callback for tracing memory access (READ or WRITE)
static bool hook_mem_invalid(uch handle, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data)
{
switch(type) {
default:
// return false to indicate we want to stop emulation
return false;
case UC_MEM_READ_NR:
printf(">>> non-readable memory is being read at 0x%"PRIx64 ", data size = %u\n",
address, size);
return false;
}
}
int main(int argc, char **argv, char **envp)
{
uch handle, 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);
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);
// write machine code to be emulated to memory
if (uc_mem_write(handle, 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_hook_add(handle, &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);
// emulate machine code in infinite time
printf("BEGIN execution\n");
err = uc_emu_start(handle, 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));
} else {
printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n");
}
printf("END execution\n");
uc_reg_read(handle, UC_X86_REG_EAX, &eax);
printf("Final eax = 0x%x\n", eax);
uc_reg_read(handle, UC_X86_REG_EBX, &ebx);
printf("Final ebx = 0x%x\n", ebx);
uc_close(&handle);
return 0;
}

207
regress/ro_mem_test.c Normal file
View File

@ -0,0 +1,207 @@
/*
Non-writable memory test case
Copyright(c) 2015 Chris Eagle
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <unicorn/unicorn.h>
const uint8_t PROGRAM[] =
"\xeb\x1a\x58\x83\xc0\x04\x83\xe0\xfc\x83\xc0\x01\xc7\x00\x78\x56"
"\x34\x12\x83\xc0\x07\xc7\x00\x21\x43\x65\x87\x90\xe8\xe1\xff\xff"
"\xff" "xxxxAAAAxxxBBBB";
// total size: 33 bytes
/*
jmp short bottom
top:
pop eax
add eax, 4
and eax, 0xfffffffc
add eax, 1 ; unaligned
mov dword [eax], 0x12345678 ; try to write into code section
add eax, 7 ; aligned
mov dword [eax], 0x87654321 ; try to write into code section
nop
bottom:
call top
*/
// callback for tracing instruction
static void hook_code(uch handle, 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);
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,
uint64_t address, int size, int64_t value, void *user_data)
{
uint32_t esp;
uc_reg_read(handle, UC_X86_REG_ESP, &esp);
switch(type) {
default:
// return false to indicate we want to stop emulation
return false;
case UC_MEM_WRITE:
//if this is a push, esp has not been adjusted yet
if (esp == (address + size)) {
uint32_t upper;
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);
// return true to indicate we want to continue
return true;
}
printf(">>> Missing memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
address, size, value);
return false;
case UC_MEM_WRITE_NW:
printf(">>> RO memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
address, size, value);
return false;
}
}
#define STACK 0x500000
#define STACK_SIZE 0x5000
int main(int argc, char **argv, char **envp)
{
uch handle, trace1, trace2;
uc_err err;
uint8_t bytes[8];
uint32_t esp;
int result;
int map_stack = 0;
if (argc == 2 && strcmp(argv[1], "--map-stack") == 0) {
map_stack = 1;
}
printf("Memory mapping test\n");
// Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
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);
if (map_stack) {
printf("Pre-mapping stack\n");
uc_mem_map(handle, 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);
// write machine code to be emulated to memory
if (uc_mem_write(handle, 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);
// intercept invalid memory events
uc_hook_add(handle, &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);
if (err) {
printf("Expected failue on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
} else {
printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n");
}
printf("END execution - 1\n");
// 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);
if (err) {
printf("Expected failure on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
} else {
printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n");
}
printf("END execution - 2\n");
printf("Verifying content at 0x400025 is unchanged\n");
if (!uc_mem_read(handle, 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");
} else {
printf("SUCCESS content in read only memory unchanged\n");
}
} else {
printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4));
return 4;
}
printf("Verifying content at 0x40002C is unchanged\n");
if (!uc_mem_read(handle, 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");
} else {
printf("SUCCESS content in read only memory unchanged\n");
}
} else {
printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4));
return 4;
}
printf("Verifying content at bottom of stack is readable and correct\n");
if (!uc_mem_read(handle, 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);
return 0;
}

View File

@ -8,14 +8,16 @@
int got_sigill = 0;
void _interrupt(uch handle, uint32_t intno, void *user_data) {
void _interrupt(uch handle, uint32_t intno, void *user_data)
{
if (intno == 6) {
uc_emu_stop (handle);
got_sigill = 1;
got_sigill = 1;
}
}
int main() {
int main()
{
int size;
uint8_t *buf;
uch uh;
@ -32,9 +34,9 @@ int main() {
return 1;
}
memset (buf, 0, size);
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size)) {
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
uc_mem_write (uh, UC_BUG_WRITE_ADDR,
(const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);
(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);

View File

@ -18,9 +18,9 @@ int main()
return 1;
}
size = UC_BUG_WRITE_SIZE;
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size)) {
if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) {
uc_mem_write (uh, UC_BUG_WRITE_ADDR,
(const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);
(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);

View File

@ -17,6 +17,8 @@ if test -e $DIR/sample_x86; then
$DIR/sample_x86 -64
echo "=========================="
$DIR/sample_x86 -16
echo "=========================="
$DIR/shellcode -32
fi
if test -e $DIR/sample_arm; then
echo "=========================="

View File

@ -47,7 +47,7 @@ static void test_arm(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);
@ -100,7 +100,7 @@ static void test_thumb(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);

View File

@ -45,7 +45,7 @@ static void test_arm64(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);

View File

@ -60,7 +60,7 @@ static void test_m68k(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);

View File

@ -44,7 +44,7 @@ static void test_mips_eb(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);
@ -94,7 +94,7 @@ static void test_mips_el(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);

View File

@ -46,7 +46,7 @@ static void test_sparc(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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);

View File

@ -26,6 +26,7 @@
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59"
#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al
#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL
// memory address where emulation starts
#define ADDRESS 0x1000000
@ -76,7 +77,7 @@ 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_mem_map(handle, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL);
// return true to indicate we want to continue
return true;
}
@ -152,6 +153,19 @@ static void hook_out(uch handle, uint32_t port, int size, uint32_t value, void *
printf("--- register value = 0x%x\n", tmp);
}
// callback for SYSCALL instruction (X86).
static void hook_syscall(uch handle, void *user_data)
{
uint64_t rax;
uc_reg_read(handle, UC_X86_REG_RAX, &rax);
if (rax == 0x100) {
rax = 0x200;
uc_reg_write(handle, 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;
@ -172,7 +186,7 @@ static void test_i386(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -231,7 +245,7 @@ static void test_i386_jump(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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,
@ -278,7 +292,7 @@ static void test_i386_loop(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -330,7 +344,7 @@ static void test_i386_invalid_mem_read(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -388,7 +402,7 @@ static void test_i386_invalid_mem_write(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -459,7 +473,7 @@ static void test_i386_jump_invalid(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -516,7 +530,7 @@ static void test_i386_inout(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -591,7 +605,7 @@ static void test_x86_64(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {
@ -673,6 +687,57 @@ static void test_x86_64(void)
uc_close(&handle);
}
static void test_x86_64_syscall(void)
{
uch handle;
uch trace1;
uc_err err;
int64_t rax = 0x100;
printf("===================================\n");
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);
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);
// write machine code to be emulated to memory
if (uc_mem_write(handle, 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);
// initialize machine registers
uc_reg_write(handle, 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);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
}
// now print out some registers
printf(">>> Emulation done. Below is the CPU context\n");
uc_reg_read(handle, UC_X86_REG_RAX, &rax);
printf(">>> RAX = 0x%" PRIx64 "\n", rax);
uc_close(&handle);
}
static void test_x86_16(void)
{
uch handle;
@ -693,7 +758,7 @@ static void test_x86_16(void)
}
// map 8KB memory for this emulation
uc_mem_map(handle, 0, 8 * 1024);
uc_mem_map(handle, 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)) {
@ -741,6 +806,7 @@ int main(int argc, char **argv, char **envp)
if (!strcmp(argv[1], "-64")) {
test_x86_64();
test_x86_64_syscall();
}
if (!strcmp(argv[1], "-16")) {

View File

@ -104,7 +104,7 @@ static void test_i386(void)
}
// map 2MB memory for this emulation
uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024);
uc_mem_map(handle, 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)) {

114
uc.c Executable file → Normal file
View File

@ -89,6 +89,10 @@ const char *uc_strerror(uc_err code)
return "Invalid hook type (UC_ERR_HOOK)";
case UC_ERR_MAP:
return "Invalid memory mapping (UC_ERR_MAP)";
case UC_ERR_MEM_WRITE_NW:
return "Write to non-writable (UC_ERR_MEM_WRITE_NW)";
case UC_ERR_MEM_READ_NR:
return "Read from non-readable (UC_ERR_MEM_READ_NR)";
}
}
@ -336,6 +340,26 @@ 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)
{
size_t count = 0, len;
while(count < size) {
MemoryRegion *mr = memory_mapping(uc, address);
if (mr) {
len = MIN(size - count, mr->end - address);
count += len;
address += len;
} else // this address is not mapped in yet
break;
}
return (count == size);
}
UNICORN_EXPORT
uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
{
@ -345,12 +369,30 @@ uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
// invalid handle
return UC_ERR_UCH;
if (uc->read_mem(&uc->as, address, bytes, size) == false)
if (!check_mem_area(uc, address, size))
return UC_ERR_MEM_READ;
return UC_ERR_OK;
}
size_t count = 0, len;
// memory area can overlap adjacent memory blocks
while(count < size) {
MemoryRegion *mr = memory_mapping(uc, address);
if (mr) {
len = MIN(size - count, mr->end - address);
if (uc->read_mem(&uc->as, address, bytes, len) == false)
break;
count += len;
address += len;
bytes += len;
} else // this address is not mapped in yet
break;
}
if (count == size)
return UC_ERR_OK;
else
return UC_ERR_MEM_READ;
}
UNICORN_EXPORT
uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size)
@ -361,10 +403,39 @@ uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t s
// invalid handle
return UC_ERR_UCH;
if (uc->write_mem(&uc->as, address, bytes, size) == false)
if (!check_mem_area(uc, address, size))
return UC_ERR_MEM_WRITE;
return UC_ERR_OK;
size_t count = 0, len;
// memory area can overlap adjacent memory blocks
while(count < size) {
MemoryRegion *mr = memory_mapping(uc, address);
if (mr) {
uint32_t operms = mr->perms;
if (!(operms & UC_PROT_WRITE)) // write protected
// but this is not the program accessing memory, so temporarily mark writable
uc->readonly_mem(mr, false);
len = MIN(size - count, mr->end - address);
if (uc->write_mem(&uc->as, address, bytes, len) == false)
break;
if (!(operms & UC_PROT_WRITE)) // write protected
// now write protect it again
uc->readonly_mem(mr, true);
count += len;
address += len;
bytes += len;
} else // this address is not mapped in yet
break;
}
if (count == size)
return UC_ERR_OK;
else
return UC_ERR_MEM_WRITE;
}
#define TIMEOUT_STEP 2 // microseconds
@ -412,6 +483,7 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout
uc->stop_request = false;
uc->invalid_error = UC_ERR_OK;
uc->block_full = false;
uc->emulation_done = false;
switch(uc->arch) {
default:
@ -490,6 +562,9 @@ uc_err uc_emu_stop(uch handle)
// invalid handle
return UC_ERR_UCH;
if (uc->emulation_done)
return UC_ERR_OK;
uc->stop_request = true;
// exit the current TB
cpu_exit(uc->current_cpu);
@ -529,9 +604,9 @@ static uc_err _hook_mem_access(uch handle, uc_mem_type type,
}
UNICORN_EXPORT
uc_err uc_mem_map(uch handle, uint64_t address, size_t size)
uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms)
{
MemoryBlock *blocks;
MemoryRegion **regions;
struct uc_struct* uc = (struct uc_struct *)handle;
if (handle == 0)
@ -550,34 +625,34 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size)
if ((size & (4*1024 - 1)) != 0)
return UC_ERR_MAP;
// check for only valid permissions
if ((perms & ~(UC_PROT_READ | UC_PROT_WRITE)) != 0)
return UC_ERR_MAP;
if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow
blocks = realloc(uc->mapped_blocks, sizeof(MemoryBlock) * (uc->mapped_block_count + MEM_BLOCK_INCR));
if (blocks == NULL) {
regions = (MemoryRegion**)realloc(uc->mapped_blocks, sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR));
if (regions == NULL) {
return UC_ERR_OOM;
}
uc->mapped_blocks = blocks;
uc->mapped_blocks = regions;
}
uc->mapped_blocks[uc->mapped_block_count].begin = address;
uc->mapped_blocks[uc->mapped_block_count].end = address + size;
//TODO extend uc_mem_map to accept permissions, figure out how to pass this down to qemu
uc->mapped_blocks[uc->mapped_block_count].perms = UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC;
uc->memory_map(uc, address, size);
uc->mapped_blocks[uc->mapped_block_count] = uc->memory_map(uc, address, size, perms);
uc->mapped_block_count++;
return UC_ERR_OK;
}
bool memory_mapping(struct uc_struct* uc, uint64_t address)
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
{
unsigned int i;
for(i = 0; i < uc->mapped_block_count; i++) {
if (address >= uc->mapped_blocks[i].begin && address < uc->mapped_blocks[i].end)
return true;
if (address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end)
return uc->mapped_blocks[i];
}
// not found
return false;
return NULL;
}
static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
@ -744,4 +819,3 @@ uc_err uc_hook_del(uch handle, uch *h2)
return hook_del(handle, h2);
}