import Unicorn2
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
This directory contains bindings & test code for Python, Java, Go, .NET and Rust.
|
||||
This directory contains bindings & test code for Python, Java, Go and .NET.
|
||||
See <language>/README or <language>/README.TXT or <language>/README.md for how to install each binding.
|
||||
|
||||
The following bindings are contributed by community.
|
||||
@@ -10,14 +10,13 @@ The following bindings are contributed by community.
|
||||
- Haskell binding: by Adrian Herrera.
|
||||
- VB6 binding: David Zimmer.
|
||||
- FreePascal/Delphi binding: Mohamed Osama.
|
||||
- Rust binding: Lukas Seidel.
|
||||
|
||||
More bindings created & maintained externally by community are available as follows.
|
||||
|
||||
- UnicornPascal: Delphi/Free Pascal binding (by Stievie).
|
||||
https://github.com/stievie/UnicornPascal
|
||||
|
||||
- Unicorn-Rs: Rust binding (by Sébastien Duquette, unmaintained)
|
||||
- Unicorn-Rs: Rust binding (by Sébastien Duquette)
|
||||
https://github.com/ekse/unicorn-rs
|
||||
|
||||
- UnicornEngine: Perl binding (by Vikas Naresh Kumar)
|
||||
@@ -34,6 +33,3 @@ More bindings created & maintained externally by community are available as foll
|
||||
|
||||
- pharo-unicorn: Pharo binding (by Guille Polito)
|
||||
https://github.com/guillep/pharo-unicorn
|
||||
|
||||
- Unicorn.js: JavaScript binding (by Alexandro Sanchez)
|
||||
https://github.com/AlexAltea/unicorn.js
|
||||
|
||||
@@ -6,7 +6,7 @@ import sys, re, os
|
||||
|
||||
INCL_DIR = os.path.join('..', 'include', 'unicorn')
|
||||
|
||||
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'unicorn.h' ]
|
||||
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'ppc.h', 'riscv.h', 'unicorn.h' ]
|
||||
|
||||
template = {
|
||||
'python': {
|
||||
@@ -21,6 +21,8 @@ template = {
|
||||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
@@ -37,6 +39,8 @@ template = {
|
||||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
@@ -53,6 +57,8 @@ template = {
|
||||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
@@ -69,6 +75,8 @@ template = {
|
||||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
@@ -85,6 +93,8 @@ template = {
|
||||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
'unicorn.h': 'Common',
|
||||
'comment_open': ' //',
|
||||
'comment_close': '',
|
||||
@@ -101,6 +111,8 @@ template = {
|
||||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
|
||||
@@ -6,13 +6,14 @@ open System
|
||||
|
||||
[<AutoOpen>]
|
||||
module Common =
|
||||
let UC_API_MAJOR = 1
|
||||
let UC_API_MAJOR = 2
|
||||
|
||||
let UC_API_MINOR = 0
|
||||
let UC_VERSION_MAJOR = 1
|
||||
let UC_VERSION_MAJOR = 2
|
||||
|
||||
let UC_VERSION_MINOR = 0
|
||||
let UC_VERSION_EXTRA = 3
|
||||
|
||||
let UC_VERSION_EXTRA = 0
|
||||
let UC_SECOND_SCALE = 1000000
|
||||
let UC_MILISECOND_SCALE = 1000
|
||||
let UC_ARCH_ARM = 1
|
||||
@@ -22,7 +23,8 @@ module Common =
|
||||
let UC_ARCH_PPC = 5
|
||||
let UC_ARCH_SPARC = 6
|
||||
let UC_ARCH_M68K = 7
|
||||
let UC_ARCH_MAX = 8
|
||||
let UC_ARCH_RISCV = 8
|
||||
let UC_ARCH_MAX = 9
|
||||
|
||||
let UC_MODE_LITTLE_ENDIAN = 0
|
||||
let UC_MODE_BIG_ENDIAN = 1073741824
|
||||
@@ -34,7 +36,6 @@ module Common =
|
||||
let UC_MODE_ARM926 = 128
|
||||
let UC_MODE_ARM946 = 256
|
||||
let UC_MODE_ARM1176 = 512
|
||||
let UC_MODE_ARMBE8 = 1024
|
||||
let UC_MODE_MICRO = 16
|
||||
let UC_MODE_MIPS3 = 32
|
||||
let UC_MODE_MIPS32R6 = 64
|
||||
@@ -49,6 +50,8 @@ module Common =
|
||||
let UC_MODE_SPARC32 = 4
|
||||
let UC_MODE_SPARC64 = 8
|
||||
let UC_MODE_V9 = 16
|
||||
let UC_MODE_RISCV32 = 4
|
||||
let UC_MODE_RISCV64 = 8
|
||||
|
||||
let UC_ERR_OK = 0
|
||||
let UC_ERR_NOMEM = 1
|
||||
|
||||
48
bindings/dotnet/UnicornManaged/Const/Ppc.fs
Normal file
48
bindings/dotnet/UnicornManaged/Const/Ppc.fs
Normal file
@@ -0,0 +1,48 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
|
||||
open System
|
||||
|
||||
[<AutoOpen>]
|
||||
module Ppc =
|
||||
|
||||
// PPC registers
|
||||
|
||||
let UC_PPC_REG_INVALID = 0
|
||||
|
||||
// General purpose registers
|
||||
let UC_PPC_REG_PC = 1
|
||||
let UC_PPC_REG_0 = 2
|
||||
let UC_PPC_REG_1 = 3
|
||||
let UC_PPC_REG_2 = 4
|
||||
let UC_PPC_REG_3 = 5
|
||||
let UC_PPC_REG_4 = 6
|
||||
let UC_PPC_REG_5 = 7
|
||||
let UC_PPC_REG_6 = 8
|
||||
let UC_PPC_REG_7 = 9
|
||||
let UC_PPC_REG_8 = 10
|
||||
let UC_PPC_REG_9 = 11
|
||||
let UC_PPC_REG_10 = 12
|
||||
let UC_PPC_REG_11 = 13
|
||||
let UC_PPC_REG_12 = 14
|
||||
let UC_PPC_REG_13 = 15
|
||||
let UC_PPC_REG_14 = 16
|
||||
let UC_PPC_REG_15 = 17
|
||||
let UC_PPC_REG_16 = 18
|
||||
let UC_PPC_REG_17 = 19
|
||||
let UC_PPC_REG_18 = 20
|
||||
let UC_PPC_REG_19 = 21
|
||||
let UC_PPC_REG_20 = 22
|
||||
let UC_PPC_REG_21 = 23
|
||||
let UC_PPC_REG_22 = 24
|
||||
let UC_PPC_REG_23 = 25
|
||||
let UC_PPC_REG_24 = 26
|
||||
let UC_PPC_REG_25 = 27
|
||||
let UC_PPC_REG_26 = 28
|
||||
let UC_PPC_REG_27 = 29
|
||||
let UC_PPC_REG_28 = 30
|
||||
let UC_PPC_REG_29 = 31
|
||||
let UC_PPC_REG_30 = 32
|
||||
let UC_PPC_REG_31 = 33
|
||||
|
||||
150
bindings/dotnet/UnicornManaged/Const/Riscv.fs
Normal file
150
bindings/dotnet/UnicornManaged/Const/Riscv.fs
Normal file
@@ -0,0 +1,150 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
|
||||
open System
|
||||
|
||||
[<AutoOpen>]
|
||||
module Riscv =
|
||||
|
||||
// RISCV registers
|
||||
|
||||
let UC_RISCV_REG_INVALID = 0
|
||||
|
||||
// General purpose registers
|
||||
let UC_RISCV_REG_X0 = 1
|
||||
let UC_RISCV_REG_X1 = 2
|
||||
let UC_RISCV_REG_X2 = 3
|
||||
let UC_RISCV_REG_X3 = 4
|
||||
let UC_RISCV_REG_X4 = 5
|
||||
let UC_RISCV_REG_X5 = 6
|
||||
let UC_RISCV_REG_X6 = 7
|
||||
let UC_RISCV_REG_X7 = 8
|
||||
let UC_RISCV_REG_X8 = 9
|
||||
let UC_RISCV_REG_X9 = 10
|
||||
let UC_RISCV_REG_X10 = 11
|
||||
let UC_RISCV_REG_X11 = 12
|
||||
let UC_RISCV_REG_X12 = 13
|
||||
let UC_RISCV_REG_X13 = 14
|
||||
let UC_RISCV_REG_X14 = 15
|
||||
let UC_RISCV_REG_X15 = 16
|
||||
let UC_RISCV_REG_X16 = 17
|
||||
let UC_RISCV_REG_X17 = 18
|
||||
let UC_RISCV_REG_X18 = 19
|
||||
let UC_RISCV_REG_X19 = 20
|
||||
let UC_RISCV_REG_X20 = 21
|
||||
let UC_RISCV_REG_X21 = 22
|
||||
let UC_RISCV_REG_X22 = 23
|
||||
let UC_RISCV_REG_X23 = 24
|
||||
let UC_RISCV_REG_X24 = 25
|
||||
let UC_RISCV_REG_X25 = 26
|
||||
let UC_RISCV_REG_X26 = 27
|
||||
let UC_RISCV_REG_X27 = 28
|
||||
let UC_RISCV_REG_X28 = 29
|
||||
let UC_RISCV_REG_X29 = 30
|
||||
let UC_RISCV_REG_X30 = 31
|
||||
let UC_RISCV_REG_X31 = 32
|
||||
|
||||
// Floating-point registers
|
||||
let UC_RISCV_REG_F0 = 33
|
||||
let UC_RISCV_REG_F1 = 34
|
||||
let UC_RISCV_REG_F2 = 35
|
||||
let UC_RISCV_REG_F3 = 36
|
||||
let UC_RISCV_REG_F4 = 37
|
||||
let UC_RISCV_REG_F5 = 38
|
||||
let UC_RISCV_REG_F6 = 39
|
||||
let UC_RISCV_REG_F7 = 40
|
||||
let UC_RISCV_REG_F8 = 41
|
||||
let UC_RISCV_REG_F9 = 42
|
||||
let UC_RISCV_REG_F10 = 43
|
||||
let UC_RISCV_REG_F11 = 44
|
||||
let UC_RISCV_REG_F12 = 45
|
||||
let UC_RISCV_REG_F13 = 46
|
||||
let UC_RISCV_REG_F14 = 47
|
||||
let UC_RISCV_REG_F15 = 48
|
||||
let UC_RISCV_REG_F16 = 49
|
||||
let UC_RISCV_REG_F17 = 50
|
||||
let UC_RISCV_REG_F18 = 51
|
||||
let UC_RISCV_REG_F19 = 52
|
||||
let UC_RISCV_REG_F20 = 53
|
||||
let UC_RISCV_REG_F21 = 54
|
||||
let UC_RISCV_REG_F22 = 55
|
||||
let UC_RISCV_REG_F23 = 56
|
||||
let UC_RISCV_REG_F24 = 57
|
||||
let UC_RISCV_REG_F25 = 58
|
||||
let UC_RISCV_REG_F26 = 59
|
||||
let UC_RISCV_REG_F27 = 60
|
||||
let UC_RISCV_REG_F28 = 61
|
||||
let UC_RISCV_REG_F29 = 62
|
||||
let UC_RISCV_REG_F30 = 63
|
||||
let UC_RISCV_REG_F31 = 64
|
||||
let UC_RISCV_REG_PC = 65
|
||||
let UC_RISCV_REG_ENDING = 66
|
||||
|
||||
// Alias registers
|
||||
let UC_RISCV_REG_ZERO = 1
|
||||
let UC_RISCV_REG_RA = 2
|
||||
let UC_RISCV_REG_SP = 3
|
||||
let UC_RISCV_REG_GP = 4
|
||||
let UC_RISCV_REG_TP = 5
|
||||
let UC_RISCV_REG_T0 = 6
|
||||
let UC_RISCV_REG_T1 = 7
|
||||
let UC_RISCV_REG_T2 = 8
|
||||
let UC_RISCV_REG_S0 = 9
|
||||
let UC_RISCV_REG_FP = 9
|
||||
let UC_RISCV_REG_S1 = 10
|
||||
let UC_RISCV_REG_A0 = 11
|
||||
let UC_RISCV_REG_A1 = 12
|
||||
let UC_RISCV_REG_A2 = 13
|
||||
let UC_RISCV_REG_A3 = 14
|
||||
let UC_RISCV_REG_A4 = 15
|
||||
let UC_RISCV_REG_A5 = 16
|
||||
let UC_RISCV_REG_A6 = 17
|
||||
let UC_RISCV_REG_A7 = 18
|
||||
let UC_RISCV_REG_S2 = 19
|
||||
let UC_RISCV_REG_S3 = 20
|
||||
let UC_RISCV_REG_S4 = 21
|
||||
let UC_RISCV_REG_S5 = 22
|
||||
let UC_RISCV_REG_S6 = 23
|
||||
let UC_RISCV_REG_S7 = 24
|
||||
let UC_RISCV_REG_S8 = 25
|
||||
let UC_RISCV_REG_S9 = 26
|
||||
let UC_RISCV_REG_S10 = 27
|
||||
let UC_RISCV_REG_S11 = 28
|
||||
let UC_RISCV_REG_T3 = 29
|
||||
let UC_RISCV_REG_T4 = 30
|
||||
let UC_RISCV_REG_T5 = 31
|
||||
let UC_RISCV_REG_T6 = 32
|
||||
let UC_RISCV_REG_FT0 = 33
|
||||
let UC_RISCV_REG_FT1 = 34
|
||||
let UC_RISCV_REG_FT2 = 35
|
||||
let UC_RISCV_REG_FT3 = 36
|
||||
let UC_RISCV_REG_FT4 = 37
|
||||
let UC_RISCV_REG_FT5 = 38
|
||||
let UC_RISCV_REG_FT6 = 39
|
||||
let UC_RISCV_REG_FT7 = 40
|
||||
let UC_RISCV_REG_FS0 = 41
|
||||
let UC_RISCV_REG_FS1 = 42
|
||||
let UC_RISCV_REG_FA0 = 43
|
||||
let UC_RISCV_REG_FA1 = 44
|
||||
let UC_RISCV_REG_FA2 = 45
|
||||
let UC_RISCV_REG_FA3 = 46
|
||||
let UC_RISCV_REG_FA4 = 47
|
||||
let UC_RISCV_REG_FA5 = 48
|
||||
let UC_RISCV_REG_FA6 = 49
|
||||
let UC_RISCV_REG_FA7 = 50
|
||||
let UC_RISCV_REG_FS2 = 51
|
||||
let UC_RISCV_REG_FS3 = 52
|
||||
let UC_RISCV_REG_FS4 = 53
|
||||
let UC_RISCV_REG_FS5 = 54
|
||||
let UC_RISCV_REG_FS6 = 55
|
||||
let UC_RISCV_REG_FS7 = 56
|
||||
let UC_RISCV_REG_FS8 = 57
|
||||
let UC_RISCV_REG_FS9 = 58
|
||||
let UC_RISCV_REG_FS10 = 59
|
||||
let UC_RISCV_REG_FS11 = 60
|
||||
let UC_RISCV_REG_FT8 = 61
|
||||
let UC_RISCV_REG_FT9 = 62
|
||||
let UC_RISCV_REG_FT10 = 63
|
||||
let UC_RISCV_REG_FT11 = 64
|
||||
|
||||
Binary file not shown.
Binary file not shown.
43
bindings/go/unicorn/ppc_const.go
Normal file
43
bindings/go/unicorn/ppc_const.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package unicorn
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.go]
|
||||
const (
|
||||
|
||||
// PPC registers
|
||||
|
||||
PPC_REG_INVALID = 0
|
||||
|
||||
// General purpose registers
|
||||
PPC_REG_PC = 1
|
||||
PPC_REG_0 = 2
|
||||
PPC_REG_1 = 3
|
||||
PPC_REG_2 = 4
|
||||
PPC_REG_3 = 5
|
||||
PPC_REG_4 = 6
|
||||
PPC_REG_5 = 7
|
||||
PPC_REG_6 = 8
|
||||
PPC_REG_7 = 9
|
||||
PPC_REG_8 = 10
|
||||
PPC_REG_9 = 11
|
||||
PPC_REG_10 = 12
|
||||
PPC_REG_11 = 13
|
||||
PPC_REG_12 = 14
|
||||
PPC_REG_13 = 15
|
||||
PPC_REG_14 = 16
|
||||
PPC_REG_15 = 17
|
||||
PPC_REG_16 = 18
|
||||
PPC_REG_17 = 19
|
||||
PPC_REG_18 = 20
|
||||
PPC_REG_19 = 21
|
||||
PPC_REG_20 = 22
|
||||
PPC_REG_21 = 23
|
||||
PPC_REG_22 = 24
|
||||
PPC_REG_23 = 25
|
||||
PPC_REG_24 = 26
|
||||
PPC_REG_25 = 27
|
||||
PPC_REG_26 = 28
|
||||
PPC_REG_27 = 29
|
||||
PPC_REG_28 = 30
|
||||
PPC_REG_29 = 31
|
||||
PPC_REG_30 = 32
|
||||
PPC_REG_31 = 33
|
||||
)
|
||||
145
bindings/go/unicorn/riscv_const.go
Normal file
145
bindings/go/unicorn/riscv_const.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package unicorn
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.go]
|
||||
const (
|
||||
|
||||
// RISCV registers
|
||||
|
||||
RISCV_REG_INVALID = 0
|
||||
|
||||
// General purpose registers
|
||||
RISCV_REG_X0 = 1
|
||||
RISCV_REG_X1 = 2
|
||||
RISCV_REG_X2 = 3
|
||||
RISCV_REG_X3 = 4
|
||||
RISCV_REG_X4 = 5
|
||||
RISCV_REG_X5 = 6
|
||||
RISCV_REG_X6 = 7
|
||||
RISCV_REG_X7 = 8
|
||||
RISCV_REG_X8 = 9
|
||||
RISCV_REG_X9 = 10
|
||||
RISCV_REG_X10 = 11
|
||||
RISCV_REG_X11 = 12
|
||||
RISCV_REG_X12 = 13
|
||||
RISCV_REG_X13 = 14
|
||||
RISCV_REG_X14 = 15
|
||||
RISCV_REG_X15 = 16
|
||||
RISCV_REG_X16 = 17
|
||||
RISCV_REG_X17 = 18
|
||||
RISCV_REG_X18 = 19
|
||||
RISCV_REG_X19 = 20
|
||||
RISCV_REG_X20 = 21
|
||||
RISCV_REG_X21 = 22
|
||||
RISCV_REG_X22 = 23
|
||||
RISCV_REG_X23 = 24
|
||||
RISCV_REG_X24 = 25
|
||||
RISCV_REG_X25 = 26
|
||||
RISCV_REG_X26 = 27
|
||||
RISCV_REG_X27 = 28
|
||||
RISCV_REG_X28 = 29
|
||||
RISCV_REG_X29 = 30
|
||||
RISCV_REG_X30 = 31
|
||||
RISCV_REG_X31 = 32
|
||||
|
||||
// Floating-point registers
|
||||
RISCV_REG_F0 = 33
|
||||
RISCV_REG_F1 = 34
|
||||
RISCV_REG_F2 = 35
|
||||
RISCV_REG_F3 = 36
|
||||
RISCV_REG_F4 = 37
|
||||
RISCV_REG_F5 = 38
|
||||
RISCV_REG_F6 = 39
|
||||
RISCV_REG_F7 = 40
|
||||
RISCV_REG_F8 = 41
|
||||
RISCV_REG_F9 = 42
|
||||
RISCV_REG_F10 = 43
|
||||
RISCV_REG_F11 = 44
|
||||
RISCV_REG_F12 = 45
|
||||
RISCV_REG_F13 = 46
|
||||
RISCV_REG_F14 = 47
|
||||
RISCV_REG_F15 = 48
|
||||
RISCV_REG_F16 = 49
|
||||
RISCV_REG_F17 = 50
|
||||
RISCV_REG_F18 = 51
|
||||
RISCV_REG_F19 = 52
|
||||
RISCV_REG_F20 = 53
|
||||
RISCV_REG_F21 = 54
|
||||
RISCV_REG_F22 = 55
|
||||
RISCV_REG_F23 = 56
|
||||
RISCV_REG_F24 = 57
|
||||
RISCV_REG_F25 = 58
|
||||
RISCV_REG_F26 = 59
|
||||
RISCV_REG_F27 = 60
|
||||
RISCV_REG_F28 = 61
|
||||
RISCV_REG_F29 = 62
|
||||
RISCV_REG_F30 = 63
|
||||
RISCV_REG_F31 = 64
|
||||
RISCV_REG_PC = 65
|
||||
RISCV_REG_ENDING = 66
|
||||
|
||||
// Alias registers
|
||||
RISCV_REG_ZERO = 1
|
||||
RISCV_REG_RA = 2
|
||||
RISCV_REG_SP = 3
|
||||
RISCV_REG_GP = 4
|
||||
RISCV_REG_TP = 5
|
||||
RISCV_REG_T0 = 6
|
||||
RISCV_REG_T1 = 7
|
||||
RISCV_REG_T2 = 8
|
||||
RISCV_REG_S0 = 9
|
||||
RISCV_REG_FP = 9
|
||||
RISCV_REG_S1 = 10
|
||||
RISCV_REG_A0 = 11
|
||||
RISCV_REG_A1 = 12
|
||||
RISCV_REG_A2 = 13
|
||||
RISCV_REG_A3 = 14
|
||||
RISCV_REG_A4 = 15
|
||||
RISCV_REG_A5 = 16
|
||||
RISCV_REG_A6 = 17
|
||||
RISCV_REG_A7 = 18
|
||||
RISCV_REG_S2 = 19
|
||||
RISCV_REG_S3 = 20
|
||||
RISCV_REG_S4 = 21
|
||||
RISCV_REG_S5 = 22
|
||||
RISCV_REG_S6 = 23
|
||||
RISCV_REG_S7 = 24
|
||||
RISCV_REG_S8 = 25
|
||||
RISCV_REG_S9 = 26
|
||||
RISCV_REG_S10 = 27
|
||||
RISCV_REG_S11 = 28
|
||||
RISCV_REG_T3 = 29
|
||||
RISCV_REG_T4 = 30
|
||||
RISCV_REG_T5 = 31
|
||||
RISCV_REG_T6 = 32
|
||||
RISCV_REG_FT0 = 33
|
||||
RISCV_REG_FT1 = 34
|
||||
RISCV_REG_FT2 = 35
|
||||
RISCV_REG_FT3 = 36
|
||||
RISCV_REG_FT4 = 37
|
||||
RISCV_REG_FT5 = 38
|
||||
RISCV_REG_FT6 = 39
|
||||
RISCV_REG_FT7 = 40
|
||||
RISCV_REG_FS0 = 41
|
||||
RISCV_REG_FS1 = 42
|
||||
RISCV_REG_FA0 = 43
|
||||
RISCV_REG_FA1 = 44
|
||||
RISCV_REG_FA2 = 45
|
||||
RISCV_REG_FA3 = 46
|
||||
RISCV_REG_FA4 = 47
|
||||
RISCV_REG_FA5 = 48
|
||||
RISCV_REG_FA6 = 49
|
||||
RISCV_REG_FA7 = 50
|
||||
RISCV_REG_FS2 = 51
|
||||
RISCV_REG_FS3 = 52
|
||||
RISCV_REG_FS4 = 53
|
||||
RISCV_REG_FS5 = 54
|
||||
RISCV_REG_FS6 = 55
|
||||
RISCV_REG_FS7 = 56
|
||||
RISCV_REG_FS8 = 57
|
||||
RISCV_REG_FS9 = 58
|
||||
RISCV_REG_FS10 = 59
|
||||
RISCV_REG_FS11 = 60
|
||||
RISCV_REG_FT8 = 61
|
||||
RISCV_REG_FT9 = 62
|
||||
RISCV_REG_FT10 = 63
|
||||
RISCV_REG_FT11 = 64
|
||||
)
|
||||
@@ -1,13 +1,14 @@
|
||||
package unicorn
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go]
|
||||
const (
|
||||
API_MAJOR = 1
|
||||
API_MAJOR = 2
|
||||
|
||||
API_MINOR = 0
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MAJOR = 2
|
||||
|
||||
VERSION_MINOR = 0
|
||||
VERSION_EXTRA = 3
|
||||
|
||||
VERSION_EXTRA = 0
|
||||
SECOND_SCALE = 1000000
|
||||
MILISECOND_SCALE = 1000
|
||||
ARCH_ARM = 1
|
||||
@@ -17,7 +18,8 @@ const (
|
||||
ARCH_PPC = 5
|
||||
ARCH_SPARC = 6
|
||||
ARCH_M68K = 7
|
||||
ARCH_MAX = 8
|
||||
ARCH_RISCV = 8
|
||||
ARCH_MAX = 9
|
||||
|
||||
MODE_LITTLE_ENDIAN = 0
|
||||
MODE_BIG_ENDIAN = 1073741824
|
||||
@@ -29,7 +31,6 @@ const (
|
||||
MODE_ARM926 = 128
|
||||
MODE_ARM946 = 256
|
||||
MODE_ARM1176 = 512
|
||||
MODE_ARMBE8 = 1024
|
||||
MODE_MICRO = 16
|
||||
MODE_MIPS3 = 32
|
||||
MODE_MIPS32R6 = 64
|
||||
@@ -44,6 +45,8 @@ const (
|
||||
MODE_SPARC32 = 4
|
||||
MODE_SPARC64 = 8
|
||||
MODE_V9 = 16
|
||||
MODE_RISCV32 = 4
|
||||
MODE_RISCV64 = 8
|
||||
|
||||
ERR_OK = 0
|
||||
ERR_NOMEM = 1
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
JAVA_HOME := $(shell jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));')
|
||||
|
||||
JAVA_INC := $(shell realpath $(JAVA_HOME)/include)
|
||||
JAVA_INC := $(shell realpath $(JAVA_HOME)/../include)
|
||||
|
||||
JAVA_PLATFORM_INC := $(shell dirname `find $(JAVA_INC) -name jni_md.h`)
|
||||
|
||||
@@ -46,7 +46,7 @@ all: lib jar samples
|
||||
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
||||
|
||||
unicorn_Unicorn.h: unicorn/Unicorn.java
|
||||
javac -h unicorn/ unicorn/*.java
|
||||
javah unicorn.Unicorn
|
||||
|
||||
unicorn_Unicorn.o: unicorn_Unicorn.c unicorn_Unicorn.h
|
||||
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
||||
|
||||
46
bindings/java/unicorn/PpcConst.java
Normal file
46
bindings/java/unicorn/PpcConst.java
Normal file
@@ -0,0 +1,46 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
package unicorn;
|
||||
|
||||
public interface PpcConst {
|
||||
|
||||
// PPC registers
|
||||
|
||||
public static final int UC_PPC_REG_INVALID = 0;
|
||||
|
||||
// General purpose registers
|
||||
public static final int UC_PPC_REG_PC = 1;
|
||||
public static final int UC_PPC_REG_0 = 2;
|
||||
public static final int UC_PPC_REG_1 = 3;
|
||||
public static final int UC_PPC_REG_2 = 4;
|
||||
public static final int UC_PPC_REG_3 = 5;
|
||||
public static final int UC_PPC_REG_4 = 6;
|
||||
public static final int UC_PPC_REG_5 = 7;
|
||||
public static final int UC_PPC_REG_6 = 8;
|
||||
public static final int UC_PPC_REG_7 = 9;
|
||||
public static final int UC_PPC_REG_8 = 10;
|
||||
public static final int UC_PPC_REG_9 = 11;
|
||||
public static final int UC_PPC_REG_10 = 12;
|
||||
public static final int UC_PPC_REG_11 = 13;
|
||||
public static final int UC_PPC_REG_12 = 14;
|
||||
public static final int UC_PPC_REG_13 = 15;
|
||||
public static final int UC_PPC_REG_14 = 16;
|
||||
public static final int UC_PPC_REG_15 = 17;
|
||||
public static final int UC_PPC_REG_16 = 18;
|
||||
public static final int UC_PPC_REG_17 = 19;
|
||||
public static final int UC_PPC_REG_18 = 20;
|
||||
public static final int UC_PPC_REG_19 = 21;
|
||||
public static final int UC_PPC_REG_20 = 22;
|
||||
public static final int UC_PPC_REG_21 = 23;
|
||||
public static final int UC_PPC_REG_22 = 24;
|
||||
public static final int UC_PPC_REG_23 = 25;
|
||||
public static final int UC_PPC_REG_24 = 26;
|
||||
public static final int UC_PPC_REG_25 = 27;
|
||||
public static final int UC_PPC_REG_26 = 28;
|
||||
public static final int UC_PPC_REG_27 = 29;
|
||||
public static final int UC_PPC_REG_28 = 30;
|
||||
public static final int UC_PPC_REG_29 = 31;
|
||||
public static final int UC_PPC_REG_30 = 32;
|
||||
public static final int UC_PPC_REG_31 = 33;
|
||||
|
||||
}
|
||||
148
bindings/java/unicorn/RiscvConst.java
Normal file
148
bindings/java/unicorn/RiscvConst.java
Normal file
@@ -0,0 +1,148 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
package unicorn;
|
||||
|
||||
public interface RiscvConst {
|
||||
|
||||
// RISCV registers
|
||||
|
||||
public static final int UC_RISCV_REG_INVALID = 0;
|
||||
|
||||
// General purpose registers
|
||||
public static final int UC_RISCV_REG_X0 = 1;
|
||||
public static final int UC_RISCV_REG_X1 = 2;
|
||||
public static final int UC_RISCV_REG_X2 = 3;
|
||||
public static final int UC_RISCV_REG_X3 = 4;
|
||||
public static final int UC_RISCV_REG_X4 = 5;
|
||||
public static final int UC_RISCV_REG_X5 = 6;
|
||||
public static final int UC_RISCV_REG_X6 = 7;
|
||||
public static final int UC_RISCV_REG_X7 = 8;
|
||||
public static final int UC_RISCV_REG_X8 = 9;
|
||||
public static final int UC_RISCV_REG_X9 = 10;
|
||||
public static final int UC_RISCV_REG_X10 = 11;
|
||||
public static final int UC_RISCV_REG_X11 = 12;
|
||||
public static final int UC_RISCV_REG_X12 = 13;
|
||||
public static final int UC_RISCV_REG_X13 = 14;
|
||||
public static final int UC_RISCV_REG_X14 = 15;
|
||||
public static final int UC_RISCV_REG_X15 = 16;
|
||||
public static final int UC_RISCV_REG_X16 = 17;
|
||||
public static final int UC_RISCV_REG_X17 = 18;
|
||||
public static final int UC_RISCV_REG_X18 = 19;
|
||||
public static final int UC_RISCV_REG_X19 = 20;
|
||||
public static final int UC_RISCV_REG_X20 = 21;
|
||||
public static final int UC_RISCV_REG_X21 = 22;
|
||||
public static final int UC_RISCV_REG_X22 = 23;
|
||||
public static final int UC_RISCV_REG_X23 = 24;
|
||||
public static final int UC_RISCV_REG_X24 = 25;
|
||||
public static final int UC_RISCV_REG_X25 = 26;
|
||||
public static final int UC_RISCV_REG_X26 = 27;
|
||||
public static final int UC_RISCV_REG_X27 = 28;
|
||||
public static final int UC_RISCV_REG_X28 = 29;
|
||||
public static final int UC_RISCV_REG_X29 = 30;
|
||||
public static final int UC_RISCV_REG_X30 = 31;
|
||||
public static final int UC_RISCV_REG_X31 = 32;
|
||||
|
||||
// Floating-point registers
|
||||
public static final int UC_RISCV_REG_F0 = 33;
|
||||
public static final int UC_RISCV_REG_F1 = 34;
|
||||
public static final int UC_RISCV_REG_F2 = 35;
|
||||
public static final int UC_RISCV_REG_F3 = 36;
|
||||
public static final int UC_RISCV_REG_F4 = 37;
|
||||
public static final int UC_RISCV_REG_F5 = 38;
|
||||
public static final int UC_RISCV_REG_F6 = 39;
|
||||
public static final int UC_RISCV_REG_F7 = 40;
|
||||
public static final int UC_RISCV_REG_F8 = 41;
|
||||
public static final int UC_RISCV_REG_F9 = 42;
|
||||
public static final int UC_RISCV_REG_F10 = 43;
|
||||
public static final int UC_RISCV_REG_F11 = 44;
|
||||
public static final int UC_RISCV_REG_F12 = 45;
|
||||
public static final int UC_RISCV_REG_F13 = 46;
|
||||
public static final int UC_RISCV_REG_F14 = 47;
|
||||
public static final int UC_RISCV_REG_F15 = 48;
|
||||
public static final int UC_RISCV_REG_F16 = 49;
|
||||
public static final int UC_RISCV_REG_F17 = 50;
|
||||
public static final int UC_RISCV_REG_F18 = 51;
|
||||
public static final int UC_RISCV_REG_F19 = 52;
|
||||
public static final int UC_RISCV_REG_F20 = 53;
|
||||
public static final int UC_RISCV_REG_F21 = 54;
|
||||
public static final int UC_RISCV_REG_F22 = 55;
|
||||
public static final int UC_RISCV_REG_F23 = 56;
|
||||
public static final int UC_RISCV_REG_F24 = 57;
|
||||
public static final int UC_RISCV_REG_F25 = 58;
|
||||
public static final int UC_RISCV_REG_F26 = 59;
|
||||
public static final int UC_RISCV_REG_F27 = 60;
|
||||
public static final int UC_RISCV_REG_F28 = 61;
|
||||
public static final int UC_RISCV_REG_F29 = 62;
|
||||
public static final int UC_RISCV_REG_F30 = 63;
|
||||
public static final int UC_RISCV_REG_F31 = 64;
|
||||
public static final int UC_RISCV_REG_PC = 65;
|
||||
public static final int UC_RISCV_REG_ENDING = 66;
|
||||
|
||||
// Alias registers
|
||||
public static final int UC_RISCV_REG_ZERO = 1;
|
||||
public static final int UC_RISCV_REG_RA = 2;
|
||||
public static final int UC_RISCV_REG_SP = 3;
|
||||
public static final int UC_RISCV_REG_GP = 4;
|
||||
public static final int UC_RISCV_REG_TP = 5;
|
||||
public static final int UC_RISCV_REG_T0 = 6;
|
||||
public static final int UC_RISCV_REG_T1 = 7;
|
||||
public static final int UC_RISCV_REG_T2 = 8;
|
||||
public static final int UC_RISCV_REG_S0 = 9;
|
||||
public static final int UC_RISCV_REG_FP = 9;
|
||||
public static final int UC_RISCV_REG_S1 = 10;
|
||||
public static final int UC_RISCV_REG_A0 = 11;
|
||||
public static final int UC_RISCV_REG_A1 = 12;
|
||||
public static final int UC_RISCV_REG_A2 = 13;
|
||||
public static final int UC_RISCV_REG_A3 = 14;
|
||||
public static final int UC_RISCV_REG_A4 = 15;
|
||||
public static final int UC_RISCV_REG_A5 = 16;
|
||||
public static final int UC_RISCV_REG_A6 = 17;
|
||||
public static final int UC_RISCV_REG_A7 = 18;
|
||||
public static final int UC_RISCV_REG_S2 = 19;
|
||||
public static final int UC_RISCV_REG_S3 = 20;
|
||||
public static final int UC_RISCV_REG_S4 = 21;
|
||||
public static final int UC_RISCV_REG_S5 = 22;
|
||||
public static final int UC_RISCV_REG_S6 = 23;
|
||||
public static final int UC_RISCV_REG_S7 = 24;
|
||||
public static final int UC_RISCV_REG_S8 = 25;
|
||||
public static final int UC_RISCV_REG_S9 = 26;
|
||||
public static final int UC_RISCV_REG_S10 = 27;
|
||||
public static final int UC_RISCV_REG_S11 = 28;
|
||||
public static final int UC_RISCV_REG_T3 = 29;
|
||||
public static final int UC_RISCV_REG_T4 = 30;
|
||||
public static final int UC_RISCV_REG_T5 = 31;
|
||||
public static final int UC_RISCV_REG_T6 = 32;
|
||||
public static final int UC_RISCV_REG_FT0 = 33;
|
||||
public static final int UC_RISCV_REG_FT1 = 34;
|
||||
public static final int UC_RISCV_REG_FT2 = 35;
|
||||
public static final int UC_RISCV_REG_FT3 = 36;
|
||||
public static final int UC_RISCV_REG_FT4 = 37;
|
||||
public static final int UC_RISCV_REG_FT5 = 38;
|
||||
public static final int UC_RISCV_REG_FT6 = 39;
|
||||
public static final int UC_RISCV_REG_FT7 = 40;
|
||||
public static final int UC_RISCV_REG_FS0 = 41;
|
||||
public static final int UC_RISCV_REG_FS1 = 42;
|
||||
public static final int UC_RISCV_REG_FA0 = 43;
|
||||
public static final int UC_RISCV_REG_FA1 = 44;
|
||||
public static final int UC_RISCV_REG_FA2 = 45;
|
||||
public static final int UC_RISCV_REG_FA3 = 46;
|
||||
public static final int UC_RISCV_REG_FA4 = 47;
|
||||
public static final int UC_RISCV_REG_FA5 = 48;
|
||||
public static final int UC_RISCV_REG_FA6 = 49;
|
||||
public static final int UC_RISCV_REG_FA7 = 50;
|
||||
public static final int UC_RISCV_REG_FS2 = 51;
|
||||
public static final int UC_RISCV_REG_FS3 = 52;
|
||||
public static final int UC_RISCV_REG_FS4 = 53;
|
||||
public static final int UC_RISCV_REG_FS5 = 54;
|
||||
public static final int UC_RISCV_REG_FS6 = 55;
|
||||
public static final int UC_RISCV_REG_FS7 = 56;
|
||||
public static final int UC_RISCV_REG_FS8 = 57;
|
||||
public static final int UC_RISCV_REG_FS9 = 58;
|
||||
public static final int UC_RISCV_REG_FS10 = 59;
|
||||
public static final int UC_RISCV_REG_FS11 = 60;
|
||||
public static final int UC_RISCV_REG_FT8 = 61;
|
||||
public static final int UC_RISCV_REG_FT9 = 62;
|
||||
public static final int UC_RISCV_REG_FT10 = 63;
|
||||
public static final int UC_RISCV_REG_FT11 = 64;
|
||||
|
||||
}
|
||||
@@ -3,13 +3,14 @@
|
||||
package unicorn;
|
||||
|
||||
public interface UnicornConst {
|
||||
public static final int UC_API_MAJOR = 1;
|
||||
public static final int UC_API_MAJOR = 2;
|
||||
|
||||
public static final int UC_API_MINOR = 0;
|
||||
public static final int UC_VERSION_MAJOR = 1;
|
||||
public static final int UC_VERSION_MAJOR = 2;
|
||||
|
||||
public static final int UC_VERSION_MINOR = 0;
|
||||
public static final int UC_VERSION_EXTRA = 3;
|
||||
|
||||
public static final int UC_VERSION_EXTRA = 0;
|
||||
public static final int UC_SECOND_SCALE = 1000000;
|
||||
public static final int UC_MILISECOND_SCALE = 1000;
|
||||
public static final int UC_ARCH_ARM = 1;
|
||||
@@ -19,7 +20,8 @@ public interface UnicornConst {
|
||||
public static final int UC_ARCH_PPC = 5;
|
||||
public static final int UC_ARCH_SPARC = 6;
|
||||
public static final int UC_ARCH_M68K = 7;
|
||||
public static final int UC_ARCH_MAX = 8;
|
||||
public static final int UC_ARCH_RISCV = 8;
|
||||
public static final int UC_ARCH_MAX = 9;
|
||||
|
||||
public static final int UC_MODE_LITTLE_ENDIAN = 0;
|
||||
public static final int UC_MODE_BIG_ENDIAN = 1073741824;
|
||||
@@ -31,7 +33,6 @@ public interface UnicornConst {
|
||||
public static final int UC_MODE_ARM926 = 128;
|
||||
public static final int UC_MODE_ARM946 = 256;
|
||||
public static final int UC_MODE_ARM1176 = 512;
|
||||
public static final int UC_MODE_ARMBE8 = 1024;
|
||||
public static final int UC_MODE_MICRO = 16;
|
||||
public static final int UC_MODE_MIPS3 = 32;
|
||||
public static final int UC_MODE_MIPS32R6 = 64;
|
||||
@@ -46,6 +47,8 @@ public interface UnicornConst {
|
||||
public static final int UC_MODE_SPARC32 = 4;
|
||||
public static final int UC_MODE_SPARC64 = 8;
|
||||
public static final int UC_MODE_V9 = 16;
|
||||
public static final int UC_MODE_RISCV32 = 4;
|
||||
public static final int UC_MODE_RISCV64 = 8;
|
||||
|
||||
public static final int UC_ERR_OK = 0;
|
||||
public static final int UC_ERR_NOMEM = 1;
|
||||
|
||||
48
bindings/pascal/unicorn/PpcConst.pas
Normal file
48
bindings/pascal/unicorn/PpcConst.pas
Normal file
@@ -0,0 +1,48 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
unit PpcConst;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
// PPC registers
|
||||
|
||||
UC_PPC_REG_INVALID = 0;
|
||||
|
||||
// General purpose registers
|
||||
UC_PPC_REG_PC = 1;
|
||||
UC_PPC_REG_0 = 2;
|
||||
UC_PPC_REG_1 = 3;
|
||||
UC_PPC_REG_2 = 4;
|
||||
UC_PPC_REG_3 = 5;
|
||||
UC_PPC_REG_4 = 6;
|
||||
UC_PPC_REG_5 = 7;
|
||||
UC_PPC_REG_6 = 8;
|
||||
UC_PPC_REG_7 = 9;
|
||||
UC_PPC_REG_8 = 10;
|
||||
UC_PPC_REG_9 = 11;
|
||||
UC_PPC_REG_10 = 12;
|
||||
UC_PPC_REG_11 = 13;
|
||||
UC_PPC_REG_12 = 14;
|
||||
UC_PPC_REG_13 = 15;
|
||||
UC_PPC_REG_14 = 16;
|
||||
UC_PPC_REG_15 = 17;
|
||||
UC_PPC_REG_16 = 18;
|
||||
UC_PPC_REG_17 = 19;
|
||||
UC_PPC_REG_18 = 20;
|
||||
UC_PPC_REG_19 = 21;
|
||||
UC_PPC_REG_20 = 22;
|
||||
UC_PPC_REG_21 = 23;
|
||||
UC_PPC_REG_22 = 24;
|
||||
UC_PPC_REG_23 = 25;
|
||||
UC_PPC_REG_24 = 26;
|
||||
UC_PPC_REG_25 = 27;
|
||||
UC_PPC_REG_26 = 28;
|
||||
UC_PPC_REG_27 = 29;
|
||||
UC_PPC_REG_28 = 30;
|
||||
UC_PPC_REG_29 = 31;
|
||||
UC_PPC_REG_30 = 32;
|
||||
UC_PPC_REG_31 = 33;
|
||||
|
||||
implementation
|
||||
end.
|
||||
150
bindings/pascal/unicorn/RiscvConst.pas
Normal file
150
bindings/pascal/unicorn/RiscvConst.pas
Normal file
@@ -0,0 +1,150 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
unit RiscvConst;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
// RISCV registers
|
||||
|
||||
UC_RISCV_REG_INVALID = 0;
|
||||
|
||||
// General purpose registers
|
||||
UC_RISCV_REG_X0 = 1;
|
||||
UC_RISCV_REG_X1 = 2;
|
||||
UC_RISCV_REG_X2 = 3;
|
||||
UC_RISCV_REG_X3 = 4;
|
||||
UC_RISCV_REG_X4 = 5;
|
||||
UC_RISCV_REG_X5 = 6;
|
||||
UC_RISCV_REG_X6 = 7;
|
||||
UC_RISCV_REG_X7 = 8;
|
||||
UC_RISCV_REG_X8 = 9;
|
||||
UC_RISCV_REG_X9 = 10;
|
||||
UC_RISCV_REG_X10 = 11;
|
||||
UC_RISCV_REG_X11 = 12;
|
||||
UC_RISCV_REG_X12 = 13;
|
||||
UC_RISCV_REG_X13 = 14;
|
||||
UC_RISCV_REG_X14 = 15;
|
||||
UC_RISCV_REG_X15 = 16;
|
||||
UC_RISCV_REG_X16 = 17;
|
||||
UC_RISCV_REG_X17 = 18;
|
||||
UC_RISCV_REG_X18 = 19;
|
||||
UC_RISCV_REG_X19 = 20;
|
||||
UC_RISCV_REG_X20 = 21;
|
||||
UC_RISCV_REG_X21 = 22;
|
||||
UC_RISCV_REG_X22 = 23;
|
||||
UC_RISCV_REG_X23 = 24;
|
||||
UC_RISCV_REG_X24 = 25;
|
||||
UC_RISCV_REG_X25 = 26;
|
||||
UC_RISCV_REG_X26 = 27;
|
||||
UC_RISCV_REG_X27 = 28;
|
||||
UC_RISCV_REG_X28 = 29;
|
||||
UC_RISCV_REG_X29 = 30;
|
||||
UC_RISCV_REG_X30 = 31;
|
||||
UC_RISCV_REG_X31 = 32;
|
||||
|
||||
// Floating-point registers
|
||||
UC_RISCV_REG_F0 = 33;
|
||||
UC_RISCV_REG_F1 = 34;
|
||||
UC_RISCV_REG_F2 = 35;
|
||||
UC_RISCV_REG_F3 = 36;
|
||||
UC_RISCV_REG_F4 = 37;
|
||||
UC_RISCV_REG_F5 = 38;
|
||||
UC_RISCV_REG_F6 = 39;
|
||||
UC_RISCV_REG_F7 = 40;
|
||||
UC_RISCV_REG_F8 = 41;
|
||||
UC_RISCV_REG_F9 = 42;
|
||||
UC_RISCV_REG_F10 = 43;
|
||||
UC_RISCV_REG_F11 = 44;
|
||||
UC_RISCV_REG_F12 = 45;
|
||||
UC_RISCV_REG_F13 = 46;
|
||||
UC_RISCV_REG_F14 = 47;
|
||||
UC_RISCV_REG_F15 = 48;
|
||||
UC_RISCV_REG_F16 = 49;
|
||||
UC_RISCV_REG_F17 = 50;
|
||||
UC_RISCV_REG_F18 = 51;
|
||||
UC_RISCV_REG_F19 = 52;
|
||||
UC_RISCV_REG_F20 = 53;
|
||||
UC_RISCV_REG_F21 = 54;
|
||||
UC_RISCV_REG_F22 = 55;
|
||||
UC_RISCV_REG_F23 = 56;
|
||||
UC_RISCV_REG_F24 = 57;
|
||||
UC_RISCV_REG_F25 = 58;
|
||||
UC_RISCV_REG_F26 = 59;
|
||||
UC_RISCV_REG_F27 = 60;
|
||||
UC_RISCV_REG_F28 = 61;
|
||||
UC_RISCV_REG_F29 = 62;
|
||||
UC_RISCV_REG_F30 = 63;
|
||||
UC_RISCV_REG_F31 = 64;
|
||||
UC_RISCV_REG_PC = 65;
|
||||
UC_RISCV_REG_ENDING = 66;
|
||||
|
||||
// Alias registers
|
||||
UC_RISCV_REG_ZERO = 1;
|
||||
UC_RISCV_REG_RA = 2;
|
||||
UC_RISCV_REG_SP = 3;
|
||||
UC_RISCV_REG_GP = 4;
|
||||
UC_RISCV_REG_TP = 5;
|
||||
UC_RISCV_REG_T0 = 6;
|
||||
UC_RISCV_REG_T1 = 7;
|
||||
UC_RISCV_REG_T2 = 8;
|
||||
UC_RISCV_REG_S0 = 9;
|
||||
UC_RISCV_REG_FP = 9;
|
||||
UC_RISCV_REG_S1 = 10;
|
||||
UC_RISCV_REG_A0 = 11;
|
||||
UC_RISCV_REG_A1 = 12;
|
||||
UC_RISCV_REG_A2 = 13;
|
||||
UC_RISCV_REG_A3 = 14;
|
||||
UC_RISCV_REG_A4 = 15;
|
||||
UC_RISCV_REG_A5 = 16;
|
||||
UC_RISCV_REG_A6 = 17;
|
||||
UC_RISCV_REG_A7 = 18;
|
||||
UC_RISCV_REG_S2 = 19;
|
||||
UC_RISCV_REG_S3 = 20;
|
||||
UC_RISCV_REG_S4 = 21;
|
||||
UC_RISCV_REG_S5 = 22;
|
||||
UC_RISCV_REG_S6 = 23;
|
||||
UC_RISCV_REG_S7 = 24;
|
||||
UC_RISCV_REG_S8 = 25;
|
||||
UC_RISCV_REG_S9 = 26;
|
||||
UC_RISCV_REG_S10 = 27;
|
||||
UC_RISCV_REG_S11 = 28;
|
||||
UC_RISCV_REG_T3 = 29;
|
||||
UC_RISCV_REG_T4 = 30;
|
||||
UC_RISCV_REG_T5 = 31;
|
||||
UC_RISCV_REG_T6 = 32;
|
||||
UC_RISCV_REG_FT0 = 33;
|
||||
UC_RISCV_REG_FT1 = 34;
|
||||
UC_RISCV_REG_FT2 = 35;
|
||||
UC_RISCV_REG_FT3 = 36;
|
||||
UC_RISCV_REG_FT4 = 37;
|
||||
UC_RISCV_REG_FT5 = 38;
|
||||
UC_RISCV_REG_FT6 = 39;
|
||||
UC_RISCV_REG_FT7 = 40;
|
||||
UC_RISCV_REG_FS0 = 41;
|
||||
UC_RISCV_REG_FS1 = 42;
|
||||
UC_RISCV_REG_FA0 = 43;
|
||||
UC_RISCV_REG_FA1 = 44;
|
||||
UC_RISCV_REG_FA2 = 45;
|
||||
UC_RISCV_REG_FA3 = 46;
|
||||
UC_RISCV_REG_FA4 = 47;
|
||||
UC_RISCV_REG_FA5 = 48;
|
||||
UC_RISCV_REG_FA6 = 49;
|
||||
UC_RISCV_REG_FA7 = 50;
|
||||
UC_RISCV_REG_FS2 = 51;
|
||||
UC_RISCV_REG_FS3 = 52;
|
||||
UC_RISCV_REG_FS4 = 53;
|
||||
UC_RISCV_REG_FS5 = 54;
|
||||
UC_RISCV_REG_FS6 = 55;
|
||||
UC_RISCV_REG_FS7 = 56;
|
||||
UC_RISCV_REG_FS8 = 57;
|
||||
UC_RISCV_REG_FS9 = 58;
|
||||
UC_RISCV_REG_FS10 = 59;
|
||||
UC_RISCV_REG_FS11 = 60;
|
||||
UC_RISCV_REG_FT8 = 61;
|
||||
UC_RISCV_REG_FT9 = 62;
|
||||
UC_RISCV_REG_FT10 = 63;
|
||||
UC_RISCV_REG_FT11 = 64;
|
||||
|
||||
implementation
|
||||
end.
|
||||
@@ -4,13 +4,14 @@ unit UnicornConst;
|
||||
|
||||
interface
|
||||
|
||||
const UC_API_MAJOR = 1;
|
||||
const UC_API_MAJOR = 2;
|
||||
|
||||
UC_API_MINOR = 0;
|
||||
UC_VERSION_MAJOR = 1;
|
||||
UC_VERSION_MAJOR = 2;
|
||||
|
||||
UC_VERSION_MINOR = 0;
|
||||
UC_VERSION_EXTRA = 3;
|
||||
|
||||
UC_VERSION_EXTRA = 0;
|
||||
UC_SECOND_SCALE = 1000000;
|
||||
UC_MILISECOND_SCALE = 1000;
|
||||
UC_ARCH_ARM = 1;
|
||||
@@ -20,7 +21,8 @@ const UC_API_MAJOR = 1;
|
||||
UC_ARCH_PPC = 5;
|
||||
UC_ARCH_SPARC = 6;
|
||||
UC_ARCH_M68K = 7;
|
||||
UC_ARCH_MAX = 8;
|
||||
UC_ARCH_RISCV = 8;
|
||||
UC_ARCH_MAX = 9;
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0;
|
||||
UC_MODE_BIG_ENDIAN = 1073741824;
|
||||
@@ -32,7 +34,6 @@ const UC_API_MAJOR = 1;
|
||||
UC_MODE_ARM926 = 128;
|
||||
UC_MODE_ARM946 = 256;
|
||||
UC_MODE_ARM1176 = 512;
|
||||
UC_MODE_ARMBE8 = 1024;
|
||||
UC_MODE_MICRO = 16;
|
||||
UC_MODE_MIPS3 = 32;
|
||||
UC_MODE_MIPS32R6 = 64;
|
||||
@@ -47,6 +48,8 @@ const UC_API_MAJOR = 1;
|
||||
UC_MODE_SPARC32 = 4;
|
||||
UC_MODE_SPARC64 = 8;
|
||||
UC_MODE_V9 = 16;
|
||||
UC_MODE_RISCV32 = 4;
|
||||
UC_MODE_RISCV64 = 8;
|
||||
|
||||
UC_ERR_OK = 0;
|
||||
UC_ERR_NOMEM = 1;
|
||||
|
||||
@@ -108,7 +108,7 @@ type
|
||||
@user_data: user data passed to tracing APIs
|
||||
|
||||
@return: return true to continue, or false to stop program (due to invalid memory).
|
||||
NOTE: returning true to continue execution will only work if the accessed
|
||||
NOTE: returning true to continue execution will only work if if the accessed
|
||||
memory is made accessible with the correct permissions during the hook.
|
||||
|
||||
In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED callback,
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e -x
|
||||
|
||||
cd bindings/python
|
||||
|
||||
# Compile wheels
|
||||
if [ -f /opt/python/cp36-cp36m/bin/python ];then
|
||||
/opt/python/cp36-cp36m/bin/python setup.py bdist_wheel
|
||||
else
|
||||
python3 setup.py bdist_wheel
|
||||
fi
|
||||
cd dist
|
||||
auditwheel repair *.whl
|
||||
mv -f wheelhouse/*.whl .
|
||||
@@ -45,7 +45,7 @@ def test_arm64():
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing one instruction at ADDRESS with customized callback
|
||||
# tracing one instruction with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
|
||||
65
bindings/python/sample_ppc.py
Executable file
65
bindings/python/sample_ppc.py
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for PPC of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.ppc_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
PPC_CODE = b"\x7F\x46\x1A\x14" # add r26, r6, r3
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# Test PPC
|
||||
def test_ppc():
|
||||
print("Emulate PPC code")
|
||||
try:
|
||||
# Initialize emulator in PPC EB mode
|
||||
mu = Uc(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, PPC_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_PPC_REG_3, 0x1234)
|
||||
mu.reg_write(UC_PPC_REG_6, 0x6789)
|
||||
mu.reg_write(UC_PPC_REG_26, 0x5555)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(PPC_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r26 = mu.reg_read(UC_PPC_REG_26)
|
||||
print(">>> r26 = 0x%x" % r26)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_ppc()
|
||||
|
||||
71
bindings/python/sample_riscv.py
Executable file
71
bindings/python/sample_riscv.py
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for RISCV of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.riscv_const import *
|
||||
|
||||
|
||||
'''
|
||||
$ cstool riscv64 1305100093850502
|
||||
0 13 05 10 00 addi a0, zero, 1
|
||||
4 93 85 05 02 addi a1, a1, 0x20
|
||||
'''
|
||||
RISCV_CODE = b"\x13\x05\x10\x00\x93\x85\x05\x02"
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# Test RISCV
|
||||
def test_riscv():
|
||||
print("Emulate RISCV code")
|
||||
try:
|
||||
# Initialize emulator in RISCV32 mode
|
||||
mu = Uc(UC_ARCH_RISCV, UC_MODE_RISCV32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, RISCV_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_RISCV_REG_A0, 0x1234)
|
||||
mu.reg_write(UC_RISCV_REG_A1, 0x7890)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(RISCV_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
a0 = mu.reg_read(UC_RISCV_REG_A0)
|
||||
a1 = mu.reg_read(UC_RISCV_REG_A1)
|
||||
print(">>> A0 = 0x%x" %a0)
|
||||
print(">>> A1 = 0x%x" %a1)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_riscv()
|
||||
|
||||
@@ -16,6 +16,7 @@ X86_CODE64 = b"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\
|
||||
X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
||||
X86_CODE64_SYSCALL = b'\x0f\x05' # SYSCALL
|
||||
X86_CODE16 = b'\x00\x00' # add byte ptr [bx + si], al
|
||||
X86_MMIO_CODE = b"\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" # mov [0x20004], ecx; mov ecx, [0x20004]
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x1000000
|
||||
@@ -386,7 +387,6 @@ def test_i386_loop():
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
# Test X86 32 bit with IN/OUT instruction
|
||||
def test_i386_inout():
|
||||
print("Emulate i386 code with IN/OUT instructions")
|
||||
@@ -464,6 +464,9 @@ def test_i386_context_save():
|
||||
print(">>> Unpickling CPU context")
|
||||
saved_context = pickle.loads(pickled_saved_context)
|
||||
|
||||
print(">>> Modifying some register.")
|
||||
saved_context.reg_write(UC_X86_REG_EAX, 0xc8c8)
|
||||
|
||||
print(">>> CPU context restored. Below is the CPU context")
|
||||
mu.context_restore(saved_context)
|
||||
print(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
|
||||
@@ -628,6 +631,38 @@ def test_x86_16():
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
def mmio_read_cb(uc, offset, size, data):
|
||||
print(f">>> Read IO memory at offset {hex(offset)} with {hex(size)} bytes and return 0x19260817")
|
||||
|
||||
return 0x19260817
|
||||
|
||||
def mmio_write_cb(uc, offset, size, value, data):
|
||||
print(f">>> Write value {hex(value)} to IO memory at offset {hex(offset)} with {hex(size)} bytes")
|
||||
|
||||
def test_i386_mmio():
|
||||
print("Test i386 IO memory")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 8KB memory for this emulation and write the code
|
||||
mu.mem_map(0x10000, 0x8000)
|
||||
mu.mem_write(0x10000, X86_MMIO_CODE)
|
||||
|
||||
# map the IO memory
|
||||
mu.mmio_map(0x20000, 0x4000, mmio_read_cb, None, mmio_write_cb, None)
|
||||
|
||||
# prepare registers.
|
||||
mu.reg_write(UC_X86_REG_ECX, 0xdeadbeef)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(0x10000, 0x10000 + len(X86_MMIO_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(f">>> Emulation done. ECX={hex(mu.reg_read(UC_X86_REG_ECX))}")
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_x86_16()
|
||||
@@ -651,3 +686,5 @@ if __name__ == '__main__':
|
||||
test_x86_64()
|
||||
print("=" * 35)
|
||||
test_x86_64_syscall()
|
||||
print("=" * 35)
|
||||
test_i386_mmio()
|
||||
|
||||
@@ -15,7 +15,6 @@ from distutils.util import get_platform
|
||||
from distutils.command.build import build
|
||||
from distutils.command.sdist import sdist
|
||||
from setuptools.command.bdist_egg import bdist_egg
|
||||
from setuptools.command.develop import develop
|
||||
|
||||
SYSTEM = sys.platform
|
||||
|
||||
@@ -23,36 +22,18 @@ SYSTEM = sys.platform
|
||||
IS_64BITS = platform.architecture()[0] == '64bit'
|
||||
|
||||
# are we building from the repository or from a source distribution?
|
||||
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
LIBS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'lib')
|
||||
HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include')
|
||||
SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
||||
BUILD_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..')
|
||||
UC_DIR = os.path.join(ROOT_DIR, '../..')
|
||||
BUILD_DIR = os.path.join(UC_DIR, 'build')
|
||||
|
||||
# Parse version from pkgconfig.mk
|
||||
VERSION_DATA = {}
|
||||
with open(os.path.join(BUILD_DIR, 'pkgconfig.mk')) as fp:
|
||||
lines = fp.readlines()
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if len(line) == 0:
|
||||
continue
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
if '=' not in line:
|
||||
continue
|
||||
|
||||
k, v = line.split('=', 1)
|
||||
k = k.strip()
|
||||
v = v.strip()
|
||||
if len(k) == 0 or len(v) == 0:
|
||||
continue
|
||||
VERSION_DATA[k] = v
|
||||
|
||||
if 'PKG_MAJOR' not in VERSION_DATA or \
|
||||
'PKG_MINOR' not in VERSION_DATA or \
|
||||
'PKG_EXTRA' not in VERSION_DATA:
|
||||
raise Exception("Malformed pkgconfig.mk")
|
||||
VERSION_DATA['PKG_MAJOR'] = "2"
|
||||
VERSION_DATA['PKG_MINOR'] = "0"
|
||||
VERSION_DATA['PKG_EXTRA'] = "0"
|
||||
# VERSION_DATA['PKG_TAG'] = "0"
|
||||
|
||||
if 'PKG_TAG' in VERSION_DATA:
|
||||
VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}.{PKG_TAG}'.format(**VERSION_DATA)
|
||||
@@ -63,12 +44,9 @@ if SYSTEM == 'darwin':
|
||||
LIBRARY_FILE = "libunicorn.dylib"
|
||||
MAC_LIBRARY_FILE = "libunicorn*.dylib"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
elif SYSTEM == 'win32':
|
||||
elif SYSTEM in ('win32', 'cygwin'):
|
||||
LIBRARY_FILE = "unicorn.dll"
|
||||
STATIC_LIBRARY_FILE = "unicorn.lib"
|
||||
elif SYSTEM == 'cygwin':
|
||||
LIBRARY_FILE = "cygunicorn.dll"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
else:
|
||||
LIBRARY_FILE = "libunicorn.so"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
@@ -84,7 +62,6 @@ def copy_sources():
|
||||
"""
|
||||
src = []
|
||||
|
||||
os.system('make -C %s clean' % os.path.join(ROOT_DIR, '../..'))
|
||||
shutil.rmtree(SRC_DIR, ignore_errors=True)
|
||||
os.mkdir(SRC_DIR)
|
||||
|
||||
@@ -108,9 +85,8 @@ def copy_sources():
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../README.md")))
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.TXT")))
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../RELEASE_NOTES")))
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../make.sh")))
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../cmake.sh")))
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../CMakeLists.txt")))
|
||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../pkgconfig.mk")))
|
||||
|
||||
for filename in src:
|
||||
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
||||
@@ -130,7 +106,7 @@ def build_libraries():
|
||||
os.mkdir(LIBS_DIR)
|
||||
|
||||
# copy public headers
|
||||
shutil.copytree(os.path.join(BUILD_DIR, 'include', 'unicorn'), os.path.join(HEADERS_DIR, 'unicorn'))
|
||||
shutil.copytree(os.path.join(UC_DIR, 'include', 'unicorn'), os.path.join(HEADERS_DIR, 'unicorn'))
|
||||
|
||||
# check if a prebuilt library exists
|
||||
# if so, use it instead of building
|
||||
@@ -141,35 +117,37 @@ def build_libraries():
|
||||
return
|
||||
|
||||
# otherwise, build!!
|
||||
os.chdir(BUILD_DIR)
|
||||
os.chdir(UC_DIR)
|
||||
|
||||
try:
|
||||
subprocess.check_call(['msbuild', '-ver'])
|
||||
subprocess.check_call(['msbuild', '/help'])
|
||||
except:
|
||||
has_msbuild = False
|
||||
else:
|
||||
has_msbuild = True
|
||||
|
||||
if has_msbuild and SYSTEM == 'win32':
|
||||
if platform.architecture()[0] == '32bit':
|
||||
plat = 'Win32'
|
||||
elif 'win32' in sys.argv:
|
||||
plat = 'Win32'
|
||||
else:
|
||||
plat = 'x64'
|
||||
|
||||
plat = 'Win32' if platform.architecture()[0] == '32bit' else 'x64'
|
||||
conf = 'Debug' if os.getenv('DEBUG', '') else 'Release'
|
||||
subprocess.call(['msbuild', 'unicorn.sln', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf], cwd=os.path.join(BUILD_DIR, 'msvc'))
|
||||
subprocess.call(['msbuild', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf], cwd=os.path.join(UC_DIR, 'msvc'))
|
||||
|
||||
obj_dir = os.path.join(BUILD_DIR, 'msvc', plat, conf)
|
||||
obj_dir = os.path.join(UC_DIR, 'msvc', plat, conf)
|
||||
shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR)
|
||||
shutil.copy(os.path.join(obj_dir, STATIC_LIBRARY_FILE), LIBS_DIR)
|
||||
else:
|
||||
# platform description refs at https://docs.python.org/2/library/sys.html#sys.platform
|
||||
new_env = dict(os.environ)
|
||||
new_env['UNICORN_BUILD_CORE_ONLY'] = 'yes'
|
||||
cmd = ['sh', './make.sh']
|
||||
if SYSTEM == "win32":
|
||||
if not os.path.exists(BUILD_DIR):
|
||||
os.mkdir(BUILD_DIR)
|
||||
os.chdir(BUILD_DIR)
|
||||
cmd = ['sh', '../cmake.sh']
|
||||
if SYSTEM == "cygwin":
|
||||
if IS_64BITS:
|
||||
cmd.append('cygwin-mingw64')
|
||||
else:
|
||||
cmd.append('cygwin-mingw32')
|
||||
elif SYSTEM == "win32":
|
||||
if IS_64BITS:
|
||||
cmd.append('cross-win64')
|
||||
else:
|
||||
@@ -196,6 +174,7 @@ def build_libraries():
|
||||
sys.exit(1)
|
||||
os.chdir(cwd)
|
||||
|
||||
|
||||
class custom_sdist(sdist):
|
||||
def run(self):
|
||||
clean_bins()
|
||||
@@ -211,12 +190,6 @@ class custom_build(build):
|
||||
build_libraries()
|
||||
return build.run(self)
|
||||
|
||||
class custom_develop(develop):
|
||||
def run(self):
|
||||
log.info("Building C extensions")
|
||||
build_libraries()
|
||||
return develop.run(self)
|
||||
|
||||
class custom_bdist_egg(bdist_egg):
|
||||
def run(self):
|
||||
self.run_command('build')
|
||||
@@ -225,6 +198,10 @@ class custom_bdist_egg(bdist_egg):
|
||||
def dummy_src():
|
||||
return []
|
||||
|
||||
cmdclass = {}
|
||||
cmdclass['build'] = custom_build
|
||||
cmdclass['sdist'] = custom_sdist
|
||||
cmdclass['bdist_egg'] = custom_bdist_egg
|
||||
|
||||
if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
||||
idx = sys.argv.index('bdist_wheel') + 1
|
||||
@@ -245,14 +222,28 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
||||
# https://www.python.org/dev/peps/pep-0425/
|
||||
sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_'))
|
||||
|
||||
try:
|
||||
from setuptools.command.develop import develop
|
||||
class custom_develop(develop):
|
||||
def run(self):
|
||||
log.info("Building C extensions")
|
||||
build_libraries()
|
||||
return develop.run(self)
|
||||
|
||||
cmdclass['develop'] = custom_develop
|
||||
except ImportError:
|
||||
print("Proper 'develop' support unavailable.")
|
||||
|
||||
def join_all(src, files):
|
||||
return tuple(os.path.join(src, f) for f in files)
|
||||
|
||||
long_desc = '''
|
||||
Unicorn is a lightweight, multi-platform, multi-architecture CPU emulator framework
|
||||
based on [QEMU](https://qemu.org).
|
||||
based on [QEMU](http://qemu.org).
|
||||
|
||||
Unicorn offers some unparalleled features:
|
||||
|
||||
- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, SPARC, and X86 (16, 32, 64-bit)
|
||||
- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, SPARC and X86 (16, 32, 64-bit)
|
||||
- Clean/simple/lightweight/intuitive architecture-neutral API
|
||||
- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua.
|
||||
- Native support for Windows & *nix (with Mac OSX, Linux, *BSD & Solaris confirmed)
|
||||
@@ -261,7 +252,7 @@ Unicorn offers some unparalleled features:
|
||||
- Thread-safety by design
|
||||
- Distributed under free software license GPLv2
|
||||
|
||||
Further information is available at https://www.unicorn-engine.org
|
||||
Further information is available at http://www.unicorn-engine.org
|
||||
'''
|
||||
|
||||
setup(
|
||||
@@ -273,18 +264,18 @@ setup(
|
||||
author_email='aquynh@gmail.com',
|
||||
description='Unicorn CPU emulator engine',
|
||||
long_description=long_desc,
|
||||
long_description_content_type="text/markdown",
|
||||
url='https://www.unicorn-engine.org',
|
||||
#long_description_content_type="text/markdown",
|
||||
url='http://www.unicorn-engine.org',
|
||||
classifiers=[
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 3',
|
||||
],
|
||||
requires=['ctypes'],
|
||||
cmdclass={'build': custom_build, 'develop': custom_develop, 'sdist': custom_sdist, 'bdist_egg': custom_bdist_egg},
|
||||
zip_safe=False,
|
||||
cmdclass=cmdclass,
|
||||
zip_safe=True,
|
||||
include_package_data=True,
|
||||
is_pure=False,
|
||||
is_pure=True,
|
||||
package_data={
|
||||
'unicorn': ['lib/*', 'include/unicorn/*']
|
||||
}
|
||||
|
||||
@@ -120,7 +120,28 @@ UC_ARM_REG_IPSR = 114
|
||||
UC_ARM_REG_MSP = 115
|
||||
UC_ARM_REG_PSP = 116
|
||||
UC_ARM_REG_CONTROL = 117
|
||||
UC_ARM_REG_ENDING = 118
|
||||
UC_ARM_REG_IAPSR = 118
|
||||
UC_ARM_REG_EAPSR = 119
|
||||
UC_ARM_REG_XPSR = 120
|
||||
UC_ARM_REG_EPSR = 121
|
||||
UC_ARM_REG_IEPSR = 122
|
||||
UC_ARM_REG_PRIMASK = 123
|
||||
UC_ARM_REG_BASEPRI = 124
|
||||
UC_ARM_REG_BASEPRI_MAX = 125
|
||||
UC_ARM_REG_FAULTMASK = 126
|
||||
UC_ARM_REG_APSR_NZCVQ = 127
|
||||
UC_ARM_REG_APSR_G = 128
|
||||
UC_ARM_REG_APSR_NZCVQG = 129
|
||||
UC_ARM_REG_IAPSR_NZCVQ = 130
|
||||
UC_ARM_REG_IAPSR_G = 131
|
||||
UC_ARM_REG_IAPSR_NZCVQG = 132
|
||||
UC_ARM_REG_EAPSR_NZCVQ = 133
|
||||
UC_ARM_REG_EAPSR_G = 134
|
||||
UC_ARM_REG_EAPSR_NZCVQG = 135
|
||||
UC_ARM_REG_XPSR_NZCVQ = 136
|
||||
UC_ARM_REG_XPSR_G = 137
|
||||
UC_ARM_REG_XPSR_NZCVQG = 138
|
||||
UC_ARM_REG_ENDING = 139
|
||||
|
||||
# alias registers
|
||||
UC_ARM_REG_R13 = 12
|
||||
|
||||
40
bindings/python/unicorn/ppc_const.py
Normal file
40
bindings/python/unicorn/ppc_const.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.py]
|
||||
|
||||
# PPC registers
|
||||
|
||||
UC_PPC_REG_INVALID = 0
|
||||
|
||||
# General purpose registers
|
||||
UC_PPC_REG_PC = 1
|
||||
UC_PPC_REG_0 = 2
|
||||
UC_PPC_REG_1 = 3
|
||||
UC_PPC_REG_2 = 4
|
||||
UC_PPC_REG_3 = 5
|
||||
UC_PPC_REG_4 = 6
|
||||
UC_PPC_REG_5 = 7
|
||||
UC_PPC_REG_6 = 8
|
||||
UC_PPC_REG_7 = 9
|
||||
UC_PPC_REG_8 = 10
|
||||
UC_PPC_REG_9 = 11
|
||||
UC_PPC_REG_10 = 12
|
||||
UC_PPC_REG_11 = 13
|
||||
UC_PPC_REG_12 = 14
|
||||
UC_PPC_REG_13 = 15
|
||||
UC_PPC_REG_14 = 16
|
||||
UC_PPC_REG_15 = 17
|
||||
UC_PPC_REG_16 = 18
|
||||
UC_PPC_REG_17 = 19
|
||||
UC_PPC_REG_18 = 20
|
||||
UC_PPC_REG_19 = 21
|
||||
UC_PPC_REG_20 = 22
|
||||
UC_PPC_REG_21 = 23
|
||||
UC_PPC_REG_22 = 24
|
||||
UC_PPC_REG_23 = 25
|
||||
UC_PPC_REG_24 = 26
|
||||
UC_PPC_REG_25 = 27
|
||||
UC_PPC_REG_26 = 28
|
||||
UC_PPC_REG_27 = 29
|
||||
UC_PPC_REG_28 = 30
|
||||
UC_PPC_REG_29 = 31
|
||||
UC_PPC_REG_30 = 32
|
||||
UC_PPC_REG_31 = 33
|
||||
142
bindings/python/unicorn/riscv_const.py
Normal file
142
bindings/python/unicorn/riscv_const.py
Normal file
@@ -0,0 +1,142 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.py]
|
||||
|
||||
# RISCV registers
|
||||
|
||||
UC_RISCV_REG_INVALID = 0
|
||||
|
||||
# General purpose registers
|
||||
UC_RISCV_REG_X0 = 1
|
||||
UC_RISCV_REG_X1 = 2
|
||||
UC_RISCV_REG_X2 = 3
|
||||
UC_RISCV_REG_X3 = 4
|
||||
UC_RISCV_REG_X4 = 5
|
||||
UC_RISCV_REG_X5 = 6
|
||||
UC_RISCV_REG_X6 = 7
|
||||
UC_RISCV_REG_X7 = 8
|
||||
UC_RISCV_REG_X8 = 9
|
||||
UC_RISCV_REG_X9 = 10
|
||||
UC_RISCV_REG_X10 = 11
|
||||
UC_RISCV_REG_X11 = 12
|
||||
UC_RISCV_REG_X12 = 13
|
||||
UC_RISCV_REG_X13 = 14
|
||||
UC_RISCV_REG_X14 = 15
|
||||
UC_RISCV_REG_X15 = 16
|
||||
UC_RISCV_REG_X16 = 17
|
||||
UC_RISCV_REG_X17 = 18
|
||||
UC_RISCV_REG_X18 = 19
|
||||
UC_RISCV_REG_X19 = 20
|
||||
UC_RISCV_REG_X20 = 21
|
||||
UC_RISCV_REG_X21 = 22
|
||||
UC_RISCV_REG_X22 = 23
|
||||
UC_RISCV_REG_X23 = 24
|
||||
UC_RISCV_REG_X24 = 25
|
||||
UC_RISCV_REG_X25 = 26
|
||||
UC_RISCV_REG_X26 = 27
|
||||
UC_RISCV_REG_X27 = 28
|
||||
UC_RISCV_REG_X28 = 29
|
||||
UC_RISCV_REG_X29 = 30
|
||||
UC_RISCV_REG_X30 = 31
|
||||
UC_RISCV_REG_X31 = 32
|
||||
|
||||
# Floating-point registers
|
||||
UC_RISCV_REG_F0 = 33
|
||||
UC_RISCV_REG_F1 = 34
|
||||
UC_RISCV_REG_F2 = 35
|
||||
UC_RISCV_REG_F3 = 36
|
||||
UC_RISCV_REG_F4 = 37
|
||||
UC_RISCV_REG_F5 = 38
|
||||
UC_RISCV_REG_F6 = 39
|
||||
UC_RISCV_REG_F7 = 40
|
||||
UC_RISCV_REG_F8 = 41
|
||||
UC_RISCV_REG_F9 = 42
|
||||
UC_RISCV_REG_F10 = 43
|
||||
UC_RISCV_REG_F11 = 44
|
||||
UC_RISCV_REG_F12 = 45
|
||||
UC_RISCV_REG_F13 = 46
|
||||
UC_RISCV_REG_F14 = 47
|
||||
UC_RISCV_REG_F15 = 48
|
||||
UC_RISCV_REG_F16 = 49
|
||||
UC_RISCV_REG_F17 = 50
|
||||
UC_RISCV_REG_F18 = 51
|
||||
UC_RISCV_REG_F19 = 52
|
||||
UC_RISCV_REG_F20 = 53
|
||||
UC_RISCV_REG_F21 = 54
|
||||
UC_RISCV_REG_F22 = 55
|
||||
UC_RISCV_REG_F23 = 56
|
||||
UC_RISCV_REG_F24 = 57
|
||||
UC_RISCV_REG_F25 = 58
|
||||
UC_RISCV_REG_F26 = 59
|
||||
UC_RISCV_REG_F27 = 60
|
||||
UC_RISCV_REG_F28 = 61
|
||||
UC_RISCV_REG_F29 = 62
|
||||
UC_RISCV_REG_F30 = 63
|
||||
UC_RISCV_REG_F31 = 64
|
||||
UC_RISCV_REG_PC = 65
|
||||
UC_RISCV_REG_ENDING = 66
|
||||
|
||||
# Alias registers
|
||||
UC_RISCV_REG_ZERO = 1
|
||||
UC_RISCV_REG_RA = 2
|
||||
UC_RISCV_REG_SP = 3
|
||||
UC_RISCV_REG_GP = 4
|
||||
UC_RISCV_REG_TP = 5
|
||||
UC_RISCV_REG_T0 = 6
|
||||
UC_RISCV_REG_T1 = 7
|
||||
UC_RISCV_REG_T2 = 8
|
||||
UC_RISCV_REG_S0 = 9
|
||||
UC_RISCV_REG_FP = 9
|
||||
UC_RISCV_REG_S1 = 10
|
||||
UC_RISCV_REG_A0 = 11
|
||||
UC_RISCV_REG_A1 = 12
|
||||
UC_RISCV_REG_A2 = 13
|
||||
UC_RISCV_REG_A3 = 14
|
||||
UC_RISCV_REG_A4 = 15
|
||||
UC_RISCV_REG_A5 = 16
|
||||
UC_RISCV_REG_A6 = 17
|
||||
UC_RISCV_REG_A7 = 18
|
||||
UC_RISCV_REG_S2 = 19
|
||||
UC_RISCV_REG_S3 = 20
|
||||
UC_RISCV_REG_S4 = 21
|
||||
UC_RISCV_REG_S5 = 22
|
||||
UC_RISCV_REG_S6 = 23
|
||||
UC_RISCV_REG_S7 = 24
|
||||
UC_RISCV_REG_S8 = 25
|
||||
UC_RISCV_REG_S9 = 26
|
||||
UC_RISCV_REG_S10 = 27
|
||||
UC_RISCV_REG_S11 = 28
|
||||
UC_RISCV_REG_T3 = 29
|
||||
UC_RISCV_REG_T4 = 30
|
||||
UC_RISCV_REG_T5 = 31
|
||||
UC_RISCV_REG_T6 = 32
|
||||
UC_RISCV_REG_FT0 = 33
|
||||
UC_RISCV_REG_FT1 = 34
|
||||
UC_RISCV_REG_FT2 = 35
|
||||
UC_RISCV_REG_FT3 = 36
|
||||
UC_RISCV_REG_FT4 = 37
|
||||
UC_RISCV_REG_FT5 = 38
|
||||
UC_RISCV_REG_FT6 = 39
|
||||
UC_RISCV_REG_FT7 = 40
|
||||
UC_RISCV_REG_FS0 = 41
|
||||
UC_RISCV_REG_FS1 = 42
|
||||
UC_RISCV_REG_FA0 = 43
|
||||
UC_RISCV_REG_FA1 = 44
|
||||
UC_RISCV_REG_FA2 = 45
|
||||
UC_RISCV_REG_FA3 = 46
|
||||
UC_RISCV_REG_FA4 = 47
|
||||
UC_RISCV_REG_FA5 = 48
|
||||
UC_RISCV_REG_FA6 = 49
|
||||
UC_RISCV_REG_FA7 = 50
|
||||
UC_RISCV_REG_FS2 = 51
|
||||
UC_RISCV_REG_FS3 = 52
|
||||
UC_RISCV_REG_FS4 = 53
|
||||
UC_RISCV_REG_FS5 = 54
|
||||
UC_RISCV_REG_FS6 = 55
|
||||
UC_RISCV_REG_FS7 = 56
|
||||
UC_RISCV_REG_FS8 = 57
|
||||
UC_RISCV_REG_FS9 = 58
|
||||
UC_RISCV_REG_FS10 = 59
|
||||
UC_RISCV_REG_FS11 = 60
|
||||
UC_RISCV_REG_FT8 = 61
|
||||
UC_RISCV_REG_FT9 = 62
|
||||
UC_RISCV_REG_FT10 = 63
|
||||
UC_RISCV_REG_FT11 = 64
|
||||
@@ -3,12 +3,12 @@
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import distutils.sysconfig
|
||||
from functools import wraps
|
||||
import pkg_resources
|
||||
import inspect
|
||||
import os.path
|
||||
import sys
|
||||
import weakref
|
||||
import functools
|
||||
|
||||
from . import x86_const, arm64_const, unicorn_const as uc
|
||||
|
||||
@@ -105,6 +105,8 @@ def _setup_prototype(lib, fname, restype, *argtypes):
|
||||
getattr(lib, fname).argtypes = argtypes
|
||||
|
||||
ucerr = ctypes.c_int
|
||||
uc_mode = ctypes.c_int
|
||||
uc_arch = ctypes.c_int
|
||||
uc_engine = ctypes.c_void_p
|
||||
uc_context = ctypes.c_void_p
|
||||
uc_hook_h = ctypes.c_size_t
|
||||
@@ -130,6 +132,7 @@ _setup_prototype(_uc, "uc_mem_write", ucerr, uc_engine, ctypes.c_uint64, ctypes.
|
||||
_setup_prototype(_uc, "uc_emu_start", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
|
||||
_setup_prototype(_uc, "uc_emu_stop", ucerr, uc_engine)
|
||||
_setup_prototype(_uc, "uc_hook_del", ucerr, uc_engine, uc_hook_h)
|
||||
_setup_prototype(_uc, "uc_mmio_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_mem_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
|
||||
_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t)
|
||||
@@ -140,12 +143,12 @@ _setup_prototype(_uc, "uc_free", ucerr, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_context_save", ucerr, uc_engine, uc_context)
|
||||
_setup_prototype(_uc, "uc_context_restore", ucerr, uc_engine, uc_context)
|
||||
_setup_prototype(_uc, "uc_context_size", ctypes.c_size_t, uc_engine)
|
||||
_setup_prototype(_uc, "uc_context_reg_read", ucerr, uc_context, ctypes.c_int, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_context_reg_write", ucerr, uc_context, ctypes.c_int, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_context_free", ucerr, uc_context)
|
||||
_setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32))
|
||||
|
||||
# uc_hook_add is special due to variable number of arguments
|
||||
_uc.uc_hook_add = _uc.uc_hook_add
|
||||
_uc.uc_hook_add.restype = ucerr
|
||||
# https://bugs.python.org/issue42880
|
||||
_setup_prototype(_uc, "uc_hook_add", ucerr, uc_engine, ctypes.POINTER(uc_hook_h), ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64)
|
||||
|
||||
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
|
||||
UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p)
|
||||
@@ -168,7 +171,12 @@ UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p
|
||||
)
|
||||
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
||||
|
||||
UC_MMIO_READ_CB = ctypes.CFUNCTYPE(
|
||||
ctypes.c_uint64, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_void_p
|
||||
)
|
||||
UC_MMIO_WRITE_CB = ctypes.CFUNCTYPE(
|
||||
None, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_uint64, ctypes.c_void_p
|
||||
)
|
||||
|
||||
# access to error code via @errno of UcError
|
||||
class UcError(Exception):
|
||||
@@ -199,27 +207,103 @@ def version_bind():
|
||||
def uc_arch_supported(query):
|
||||
return _uc.uc_arch_supported(query)
|
||||
|
||||
# uc_reg_read/write and uc_context_reg_read/write.
|
||||
def reg_read(reg_read_func, arch, reg_id, opt=None):
|
||||
if arch == uc.UC_ARCH_X86:
|
||||
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||
reg = uc_x86_mmr()
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.selector, reg.base, reg.limit, reg.flags
|
||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||
reg = uc_x86_float80()
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.mantissa, reg.exponent
|
||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||
reg = uc_x86_xmm()
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.low_qword | (reg.high_qword << 64)
|
||||
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
||||
reg = uc_x86_ymm()
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.first_qword | (reg.second_qword << 64) | (reg.third_qword << 128) | (reg.fourth_qword << 192)
|
||||
if reg_id is x86_const.UC_X86_REG_MSR:
|
||||
if opt is None:
|
||||
raise UcError(uc.UC_ERR_ARG)
|
||||
reg = uc_x86_msr()
|
||||
reg.rid = opt
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.value
|
||||
|
||||
def _catch_hook_exception(func):
|
||||
@wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
"""Catches exceptions raised in hook functions.
|
||||
if arch == uc.UC_ARCH_ARM64:
|
||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
reg = uc_arm64_neon128()
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.low_qword | (reg.high_qword << 64)
|
||||
|
||||
If an exception is raised, it is saved to the Uc object and a call to stop
|
||||
emulation is issued.
|
||||
"""
|
||||
try:
|
||||
return func(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
# If multiple hooks raise exceptions, just use the first one
|
||||
if self._hook_exception is None:
|
||||
self._hook_exception = e
|
||||
# read to 64bit number to be safe
|
||||
reg = ctypes.c_uint64(0)
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.value
|
||||
|
||||
self.emu_stop()
|
||||
def reg_write(reg_write_func, arch, reg_id, value):
|
||||
reg = None
|
||||
|
||||
return wrapper
|
||||
if arch == uc.UC_ARCH_X86:
|
||||
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||
assert isinstance(value, tuple) and len(value) == 4
|
||||
reg = uc_x86_mmr()
|
||||
reg.selector = value[0]
|
||||
reg.base = value[1]
|
||||
reg.limit = value[2]
|
||||
reg.flags = value[3]
|
||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||
reg = uc_x86_float80()
|
||||
reg.mantissa = value[0]
|
||||
reg.exponent = value[1]
|
||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||
reg = uc_x86_xmm()
|
||||
reg.low_qword = value & 0xffffffffffffffff
|
||||
reg.high_qword = value >> 64
|
||||
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
||||
reg = uc_x86_ymm()
|
||||
reg.first_qword = value & 0xffffffffffffffff
|
||||
reg.second_qword = (value >> 64) & 0xffffffffffffffff
|
||||
reg.third_qword = (value >> 128) & 0xffffffffffffffff
|
||||
reg.fourth_qword = value >> 192
|
||||
if reg_id is x86_const.UC_X86_REG_MSR:
|
||||
reg = uc_x86_msr()
|
||||
reg.rid = value[0]
|
||||
reg.value = value[1]
|
||||
|
||||
if arch == uc.UC_ARCH_ARM64:
|
||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
reg = uc_arm64_neon128()
|
||||
reg.low_qword = value & 0xffffffffffffffff
|
||||
reg.high_qword = value >> 64
|
||||
|
||||
if reg is None:
|
||||
# convert to 64bit number to be safe
|
||||
reg = ctypes.c_uint64(value)
|
||||
|
||||
status = reg_write_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
return
|
||||
|
||||
class uc_x86_mmr(ctypes.Structure):
|
||||
"""Memory-Management Register for instructions IDTR, GDTR, LDTR, TR."""
|
||||
@@ -306,6 +390,8 @@ class Uc(object):
|
||||
def __init__(self, arch, mode):
|
||||
# verify version compatibility with the core before doing anything
|
||||
(major, minor, _combined) = uc_version()
|
||||
# print("core version =", uc_version())
|
||||
# print("binding version =", uc.UC_API_MAJOR, uc.UC_API_MINOR)
|
||||
if major != uc.UC_API_MAJOR or minor != uc.UC_API_MINOR:
|
||||
self._uch = None
|
||||
# our binding version is different from the core's API version
|
||||
@@ -319,10 +405,9 @@ class Uc(object):
|
||||
raise UcError(status)
|
||||
# internal mapping table to save callback & userdata
|
||||
self._callbacks = {}
|
||||
self._ctype_cbs = {}
|
||||
self._ctype_cbs = []
|
||||
self._callback_count = 0
|
||||
self._cleanup.register(self)
|
||||
self._hook_exception = None # The exception raised in a hook
|
||||
|
||||
@staticmethod
|
||||
def release_handle(uch):
|
||||
@@ -340,9 +425,6 @@ class Uc(object):
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
if self._hook_exception is not None:
|
||||
raise self._hook_exception
|
||||
|
||||
# stop emulation
|
||||
def emu_stop(self):
|
||||
status = _uc.uc_emu_stop(self._uch)
|
||||
@@ -351,100 +433,11 @@ class Uc(object):
|
||||
|
||||
# return the value of a register
|
||||
def reg_read(self, reg_id, opt=None):
|
||||
if self._arch == uc.UC_ARCH_X86:
|
||||
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||
reg = uc_x86_mmr()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.selector, reg.base, reg.limit, reg.flags
|
||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||
reg = uc_x86_float80()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.mantissa, reg.exponent
|
||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||
reg = uc_x86_xmm()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.low_qword | (reg.high_qword << 64)
|
||||
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
||||
reg = uc_x86_ymm()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.first_qword | (reg.second_qword << 64) | (reg.third_qword << 128) | (reg.fourth_qword << 192)
|
||||
if reg_id is x86_const.UC_X86_REG_MSR:
|
||||
if opt is None:
|
||||
raise UcError(uc.UC_ERR_ARG)
|
||||
reg = uc_x86_msr()
|
||||
reg.rid = opt
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.value
|
||||
|
||||
if self._arch == uc.UC_ARCH_ARM64:
|
||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
reg = uc_arm64_neon128()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.low_qword | (reg.high_qword << 64)
|
||||
|
||||
# read to 64bit number to be safe
|
||||
reg = ctypes.c_uint64(0)
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.value
|
||||
return reg_read(functools.partial(_uc.uc_reg_read, self._uch), self._arch, reg_id, opt)
|
||||
|
||||
# write to a register
|
||||
def reg_write(self, reg_id, value):
|
||||
reg = None
|
||||
|
||||
if self._arch == uc.UC_ARCH_X86:
|
||||
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||
assert isinstance(value, tuple) and len(value) == 4
|
||||
reg = uc_x86_mmr()
|
||||
reg.selector = value[0]
|
||||
reg.base = value[1]
|
||||
reg.limit = value[2]
|
||||
reg.flags = value[3]
|
||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||
reg = uc_x86_float80()
|
||||
reg.mantissa = value[0]
|
||||
reg.exponent = value[1]
|
||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||
reg = uc_x86_xmm()
|
||||
reg.low_qword = value & 0xffffffffffffffff
|
||||
reg.high_qword = value >> 64
|
||||
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
||||
reg = uc_x86_ymm()
|
||||
reg.first_qword = value & 0xffffffffffffffff
|
||||
reg.second_qword = (value >> 64) & 0xffffffffffffffff
|
||||
reg.third_qword = (value >> 128) & 0xffffffffffffffff
|
||||
reg.fourth_qword = value >> 192
|
||||
if reg_id is x86_const.UC_X86_REG_MSR:
|
||||
reg = uc_x86_msr()
|
||||
reg.rid = value[0]
|
||||
reg.value = value[1]
|
||||
|
||||
if self._arch == uc.UC_ARCH_ARM64:
|
||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
reg = uc_arm64_neon128()
|
||||
reg.low_qword = value & 0xffffffffffffffff
|
||||
reg.high_qword = value >> 64
|
||||
|
||||
if reg is None:
|
||||
# convert to 64bit number to be safe
|
||||
reg = ctypes.c_uint64(value)
|
||||
|
||||
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg_write(functools.partial(_uc.uc_reg_write, self._uch), self._arch, reg_id, value)
|
||||
|
||||
# read from MSR - X86 only
|
||||
def msr_read(self, msr_id):
|
||||
@@ -468,6 +461,33 @@ class Uc(object):
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
def _mmio_map_read_cb(self, handle, offset, size, user_data):
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, offset, size, data)
|
||||
|
||||
def _mmio_map_write_cb(self, handle, offset, size, value, user_data):
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, offset, size, value, data)
|
||||
|
||||
def mmio_map(self, address, size, read_cb, user_data_read, write_cb, user_data_write):
|
||||
internal_read_cb = ctypes.cast(UC_MMIO_READ_CB(self._mmio_map_read_cb), UC_MMIO_READ_CB)
|
||||
internal_write_cb = ctypes.cast(UC_MMIO_WRITE_CB(self._mmio_map_write_cb), UC_MMIO_WRITE_CB)
|
||||
|
||||
self._callback_count += 1
|
||||
self._callbacks[self._callback_count] = (read_cb, user_data_read)
|
||||
read_count = self._callback_count
|
||||
self._callback_count += 1
|
||||
self._callbacks[self._callback_count] = (write_cb, user_data_write)
|
||||
write_count = self._callback_count
|
||||
|
||||
status = _uc.uc_mmio_map(self._uch, address, size, internal_read_cb, read_count, internal_write_cb, write_count)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
# https://docs.python.org/3/library/ctypes.html#callback-functions
|
||||
self._ctype_cbs.append(internal_read_cb)
|
||||
self._ctype_cbs.append(internal_write_cb)
|
||||
|
||||
# map a range of memory
|
||||
def mem_map(self, address, size, perms=uc.UC_PROT_ALL):
|
||||
status = _uc.uc_mem_map(self._uch, address, size, perms)
|
||||
@@ -500,49 +520,41 @@ class Uc(object):
|
||||
raise UcError(status)
|
||||
return result.value
|
||||
|
||||
@_catch_hook_exception
|
||||
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)
|
||||
|
||||
@_catch_hook_exception
|
||||
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)
|
||||
|
||||
@_catch_hook_exception
|
||||
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)
|
||||
|
||||
@_catch_hook_exception
|
||||
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)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_invalid_cb(self, handle, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
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)
|
||||
|
||||
@_catch_hook_exception
|
||||
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)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_syscall_cb(self, handle, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
@@ -615,7 +627,7 @@ class Uc(object):
|
||||
)
|
||||
|
||||
# save the ctype function so gc will leave it alone.
|
||||
self._ctype_cbs[self._callback_count] = cb
|
||||
self._ctype_cbs.append(cb)
|
||||
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
@@ -631,7 +643,7 @@ class Uc(object):
|
||||
h = 0
|
||||
|
||||
def context_save(self):
|
||||
context = UcContext(self._uch)
|
||||
context = UcContext(self._uch, self._arch, self._mode)
|
||||
status = _uc.uc_context_save(self._uch, context.context)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
@@ -664,14 +676,16 @@ class Uc(object):
|
||||
|
||||
|
||||
class UcContext:
|
||||
def __init__(self, h):
|
||||
def __init__(self, h, arch, mode):
|
||||
self._context = uc_context()
|
||||
self._size = _uc.uc_context_size(h)
|
||||
self._to_free = True
|
||||
status = _uc.uc_context_alloc(h, ctypes.byref(self._context))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
self._arch = arch
|
||||
self._mode = mode
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
return self._context
|
||||
@@ -680,16 +694,34 @@ class UcContext:
|
||||
def size(self):
|
||||
return self._size
|
||||
|
||||
@property
|
||||
def arch(self):
|
||||
return self._arch
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
return self._mode
|
||||
|
||||
# return the value of a register
|
||||
def reg_read(self, reg_id, opt=None):
|
||||
return reg_read(functools.partial(_uc.uc_context_reg_read, self._context), self.arch, reg_id, opt)
|
||||
|
||||
# write to a register
|
||||
def reg_write(self, reg_id, value):
|
||||
return reg_write(functools.partial(_uc.uc_context_reg_write, self._context), self.arch, reg_id, value)
|
||||
|
||||
# Make UcContext picklable
|
||||
def __getstate__(self):
|
||||
return (bytes(self), self.size)
|
||||
|
||||
return (bytes(self), self.size, self.arch, self.mode)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self._size = state[1]
|
||||
self._context = ctypes.cast(ctypes.create_string_buffer(state[0], self._size), uc_context)
|
||||
# __init__ won'e be invoked, so we are safe to set it here.
|
||||
self._to_free = False
|
||||
|
||||
self._arch = state[2]
|
||||
self._mode = state[3]
|
||||
|
||||
def __bytes__(self):
|
||||
return ctypes.string_at(self.context, self.size)
|
||||
|
||||
@@ -708,6 +740,8 @@ def debug():
|
||||
"sparc": uc.UC_ARCH_SPARC,
|
||||
"m68k": uc.UC_ARCH_M68K,
|
||||
"x86": uc.UC_ARCH_X86,
|
||||
"riscv": uc.UC_ARCH_RISCV,
|
||||
"ppc": uc.UC_ARCH_PPC,
|
||||
}
|
||||
|
||||
all_archs = ""
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py]
|
||||
UC_API_MAJOR = 1
|
||||
UC_API_MAJOR = 2
|
||||
|
||||
UC_API_MINOR = 0
|
||||
UC_VERSION_MAJOR = 1
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 3
|
||||
|
||||
UC_VERSION_EXTRA = 0
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
@@ -15,7 +16,8 @@ UC_ARCH_X86 = 4
|
||||
UC_ARCH_PPC = 5
|
||||
UC_ARCH_SPARC = 6
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_RISCV = 8
|
||||
UC_ARCH_MAX = 9
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0
|
||||
UC_MODE_BIG_ENDIAN = 1073741824
|
||||
@@ -27,7 +29,6 @@ UC_MODE_V8 = 64
|
||||
UC_MODE_ARM926 = 128
|
||||
UC_MODE_ARM946 = 256
|
||||
UC_MODE_ARM1176 = 512
|
||||
UC_MODE_ARMBE8 = 1024
|
||||
UC_MODE_MICRO = 16
|
||||
UC_MODE_MIPS3 = 32
|
||||
UC_MODE_MIPS32R6 = 64
|
||||
@@ -42,6 +43,8 @@ UC_MODE_QPX = 16
|
||||
UC_MODE_SPARC32 = 4
|
||||
UC_MODE_SPARC64 = 8
|
||||
UC_MODE_V9 = 16
|
||||
UC_MODE_RISCV32 = 4
|
||||
UC_MODE_RISCV64 = 8
|
||||
|
||||
UC_ERR_OK = 0
|
||||
UC_ERR_NOMEM = 1
|
||||
|
||||
@@ -254,7 +254,9 @@ UC_X86_REG_MSR = 248
|
||||
UC_X86_REG_MXCSR = 249
|
||||
UC_X86_REG_FS_BASE = 250
|
||||
UC_X86_REG_GS_BASE = 251
|
||||
UC_X86_REG_ENDING = 252
|
||||
UC_X86_REG_FLAGS = 252
|
||||
UC_X86_REG_RFLAGS = 253
|
||||
UC_X86_REG_ENDING = 254
|
||||
|
||||
# X86 instructions
|
||||
|
||||
|
||||
43
bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb
Normal file
43
bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.rb]
|
||||
|
||||
module UnicornEngine
|
||||
|
||||
# PPC registers
|
||||
|
||||
UC_PPC_REG_INVALID = 0
|
||||
|
||||
# General purpose registers
|
||||
UC_PPC_REG_PC = 1
|
||||
UC_PPC_REG_0 = 2
|
||||
UC_PPC_REG_1 = 3
|
||||
UC_PPC_REG_2 = 4
|
||||
UC_PPC_REG_3 = 5
|
||||
UC_PPC_REG_4 = 6
|
||||
UC_PPC_REG_5 = 7
|
||||
UC_PPC_REG_6 = 8
|
||||
UC_PPC_REG_7 = 9
|
||||
UC_PPC_REG_8 = 10
|
||||
UC_PPC_REG_9 = 11
|
||||
UC_PPC_REG_10 = 12
|
||||
UC_PPC_REG_11 = 13
|
||||
UC_PPC_REG_12 = 14
|
||||
UC_PPC_REG_13 = 15
|
||||
UC_PPC_REG_14 = 16
|
||||
UC_PPC_REG_15 = 17
|
||||
UC_PPC_REG_16 = 18
|
||||
UC_PPC_REG_17 = 19
|
||||
UC_PPC_REG_18 = 20
|
||||
UC_PPC_REG_19 = 21
|
||||
UC_PPC_REG_20 = 22
|
||||
UC_PPC_REG_21 = 23
|
||||
UC_PPC_REG_22 = 24
|
||||
UC_PPC_REG_23 = 25
|
||||
UC_PPC_REG_24 = 26
|
||||
UC_PPC_REG_25 = 27
|
||||
UC_PPC_REG_26 = 28
|
||||
UC_PPC_REG_27 = 29
|
||||
UC_PPC_REG_28 = 30
|
||||
UC_PPC_REG_29 = 31
|
||||
UC_PPC_REG_30 = 32
|
||||
UC_PPC_REG_31 = 33
|
||||
end
|
||||
145
bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb
Normal file
145
bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb
Normal file
@@ -0,0 +1,145 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.rb]
|
||||
|
||||
module UnicornEngine
|
||||
|
||||
# RISCV registers
|
||||
|
||||
UC_RISCV_REG_INVALID = 0
|
||||
|
||||
# General purpose registers
|
||||
UC_RISCV_REG_X0 = 1
|
||||
UC_RISCV_REG_X1 = 2
|
||||
UC_RISCV_REG_X2 = 3
|
||||
UC_RISCV_REG_X3 = 4
|
||||
UC_RISCV_REG_X4 = 5
|
||||
UC_RISCV_REG_X5 = 6
|
||||
UC_RISCV_REG_X6 = 7
|
||||
UC_RISCV_REG_X7 = 8
|
||||
UC_RISCV_REG_X8 = 9
|
||||
UC_RISCV_REG_X9 = 10
|
||||
UC_RISCV_REG_X10 = 11
|
||||
UC_RISCV_REG_X11 = 12
|
||||
UC_RISCV_REG_X12 = 13
|
||||
UC_RISCV_REG_X13 = 14
|
||||
UC_RISCV_REG_X14 = 15
|
||||
UC_RISCV_REG_X15 = 16
|
||||
UC_RISCV_REG_X16 = 17
|
||||
UC_RISCV_REG_X17 = 18
|
||||
UC_RISCV_REG_X18 = 19
|
||||
UC_RISCV_REG_X19 = 20
|
||||
UC_RISCV_REG_X20 = 21
|
||||
UC_RISCV_REG_X21 = 22
|
||||
UC_RISCV_REG_X22 = 23
|
||||
UC_RISCV_REG_X23 = 24
|
||||
UC_RISCV_REG_X24 = 25
|
||||
UC_RISCV_REG_X25 = 26
|
||||
UC_RISCV_REG_X26 = 27
|
||||
UC_RISCV_REG_X27 = 28
|
||||
UC_RISCV_REG_X28 = 29
|
||||
UC_RISCV_REG_X29 = 30
|
||||
UC_RISCV_REG_X30 = 31
|
||||
UC_RISCV_REG_X31 = 32
|
||||
|
||||
# Floating-point registers
|
||||
UC_RISCV_REG_F0 = 33
|
||||
UC_RISCV_REG_F1 = 34
|
||||
UC_RISCV_REG_F2 = 35
|
||||
UC_RISCV_REG_F3 = 36
|
||||
UC_RISCV_REG_F4 = 37
|
||||
UC_RISCV_REG_F5 = 38
|
||||
UC_RISCV_REG_F6 = 39
|
||||
UC_RISCV_REG_F7 = 40
|
||||
UC_RISCV_REG_F8 = 41
|
||||
UC_RISCV_REG_F9 = 42
|
||||
UC_RISCV_REG_F10 = 43
|
||||
UC_RISCV_REG_F11 = 44
|
||||
UC_RISCV_REG_F12 = 45
|
||||
UC_RISCV_REG_F13 = 46
|
||||
UC_RISCV_REG_F14 = 47
|
||||
UC_RISCV_REG_F15 = 48
|
||||
UC_RISCV_REG_F16 = 49
|
||||
UC_RISCV_REG_F17 = 50
|
||||
UC_RISCV_REG_F18 = 51
|
||||
UC_RISCV_REG_F19 = 52
|
||||
UC_RISCV_REG_F20 = 53
|
||||
UC_RISCV_REG_F21 = 54
|
||||
UC_RISCV_REG_F22 = 55
|
||||
UC_RISCV_REG_F23 = 56
|
||||
UC_RISCV_REG_F24 = 57
|
||||
UC_RISCV_REG_F25 = 58
|
||||
UC_RISCV_REG_F26 = 59
|
||||
UC_RISCV_REG_F27 = 60
|
||||
UC_RISCV_REG_F28 = 61
|
||||
UC_RISCV_REG_F29 = 62
|
||||
UC_RISCV_REG_F30 = 63
|
||||
UC_RISCV_REG_F31 = 64
|
||||
UC_RISCV_REG_PC = 65
|
||||
UC_RISCV_REG_ENDING = 66
|
||||
|
||||
# Alias registers
|
||||
UC_RISCV_REG_ZERO = 1
|
||||
UC_RISCV_REG_RA = 2
|
||||
UC_RISCV_REG_SP = 3
|
||||
UC_RISCV_REG_GP = 4
|
||||
UC_RISCV_REG_TP = 5
|
||||
UC_RISCV_REG_T0 = 6
|
||||
UC_RISCV_REG_T1 = 7
|
||||
UC_RISCV_REG_T2 = 8
|
||||
UC_RISCV_REG_S0 = 9
|
||||
UC_RISCV_REG_FP = 9
|
||||
UC_RISCV_REG_S1 = 10
|
||||
UC_RISCV_REG_A0 = 11
|
||||
UC_RISCV_REG_A1 = 12
|
||||
UC_RISCV_REG_A2 = 13
|
||||
UC_RISCV_REG_A3 = 14
|
||||
UC_RISCV_REG_A4 = 15
|
||||
UC_RISCV_REG_A5 = 16
|
||||
UC_RISCV_REG_A6 = 17
|
||||
UC_RISCV_REG_A7 = 18
|
||||
UC_RISCV_REG_S2 = 19
|
||||
UC_RISCV_REG_S3 = 20
|
||||
UC_RISCV_REG_S4 = 21
|
||||
UC_RISCV_REG_S5 = 22
|
||||
UC_RISCV_REG_S6 = 23
|
||||
UC_RISCV_REG_S7 = 24
|
||||
UC_RISCV_REG_S8 = 25
|
||||
UC_RISCV_REG_S9 = 26
|
||||
UC_RISCV_REG_S10 = 27
|
||||
UC_RISCV_REG_S11 = 28
|
||||
UC_RISCV_REG_T3 = 29
|
||||
UC_RISCV_REG_T4 = 30
|
||||
UC_RISCV_REG_T5 = 31
|
||||
UC_RISCV_REG_T6 = 32
|
||||
UC_RISCV_REG_FT0 = 33
|
||||
UC_RISCV_REG_FT1 = 34
|
||||
UC_RISCV_REG_FT2 = 35
|
||||
UC_RISCV_REG_FT3 = 36
|
||||
UC_RISCV_REG_FT4 = 37
|
||||
UC_RISCV_REG_FT5 = 38
|
||||
UC_RISCV_REG_FT6 = 39
|
||||
UC_RISCV_REG_FT7 = 40
|
||||
UC_RISCV_REG_FS0 = 41
|
||||
UC_RISCV_REG_FS1 = 42
|
||||
UC_RISCV_REG_FA0 = 43
|
||||
UC_RISCV_REG_FA1 = 44
|
||||
UC_RISCV_REG_FA2 = 45
|
||||
UC_RISCV_REG_FA3 = 46
|
||||
UC_RISCV_REG_FA4 = 47
|
||||
UC_RISCV_REG_FA5 = 48
|
||||
UC_RISCV_REG_FA6 = 49
|
||||
UC_RISCV_REG_FA7 = 50
|
||||
UC_RISCV_REG_FS2 = 51
|
||||
UC_RISCV_REG_FS3 = 52
|
||||
UC_RISCV_REG_FS4 = 53
|
||||
UC_RISCV_REG_FS5 = 54
|
||||
UC_RISCV_REG_FS6 = 55
|
||||
UC_RISCV_REG_FS7 = 56
|
||||
UC_RISCV_REG_FS8 = 57
|
||||
UC_RISCV_REG_FS9 = 58
|
||||
UC_RISCV_REG_FS10 = 59
|
||||
UC_RISCV_REG_FS11 = 60
|
||||
UC_RISCV_REG_FT8 = 61
|
||||
UC_RISCV_REG_FT9 = 62
|
||||
UC_RISCV_REG_FT10 = 63
|
||||
UC_RISCV_REG_FT11 = 64
|
||||
end
|
||||
@@ -1,13 +1,14 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.rb]
|
||||
|
||||
module UnicornEngine
|
||||
UC_API_MAJOR = 1
|
||||
UC_API_MAJOR = 2
|
||||
|
||||
UC_API_MINOR = 0
|
||||
UC_VERSION_MAJOR = 1
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 3
|
||||
|
||||
UC_VERSION_EXTRA = 0
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
@@ -17,7 +18,8 @@ module UnicornEngine
|
||||
UC_ARCH_PPC = 5
|
||||
UC_ARCH_SPARC = 6
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_RISCV = 8
|
||||
UC_ARCH_MAX = 9
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0
|
||||
UC_MODE_BIG_ENDIAN = 1073741824
|
||||
@@ -29,7 +31,6 @@ module UnicornEngine
|
||||
UC_MODE_ARM926 = 128
|
||||
UC_MODE_ARM946 = 256
|
||||
UC_MODE_ARM1176 = 512
|
||||
UC_MODE_ARMBE8 = 1024
|
||||
UC_MODE_MICRO = 16
|
||||
UC_MODE_MIPS3 = 32
|
||||
UC_MODE_MIPS32R6 = 64
|
||||
@@ -44,6 +45,8 @@ module UnicornEngine
|
||||
UC_MODE_SPARC32 = 4
|
||||
UC_MODE_SPARC64 = 8
|
||||
UC_MODE_V9 = 16
|
||||
UC_MODE_RISCV32 = 4
|
||||
UC_MODE_RISCV64 = 8
|
||||
|
||||
UC_ERR_OK = 0
|
||||
UC_ERR_NOMEM = 1
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -1,27 +0,0 @@
|
||||
[package]
|
||||
name = "unicorn"
|
||||
version = "1.0.0"
|
||||
authors = ["Lukas Seidel"]
|
||||
documentation = ""
|
||||
edition = "2018"
|
||||
include = [
|
||||
"/.gitmodules",
|
||||
"/COPYING",
|
||||
"/Cargo.toml",
|
||||
"/README.md",
|
||||
"/src/*",
|
||||
]
|
||||
license = "GPL-2.0"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/unicorn-engine/unicorn/"
|
||||
description = "Rust bindings for the Unicorn emulator with utility functions"
|
||||
build = "build.rs"
|
||||
links = "unicorn"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
libc = "0.2"
|
||||
capstone="0.6.0"
|
||||
|
||||
[build-dependencies]
|
||||
build-helper = "0.1"
|
||||
@@ -1,45 +0,0 @@
|
||||
# unicorn-rs
|
||||
|
||||
Rust bindings for the [Unicorn](http://www.unicorn-engine.org/) emulator with utility functions.
|
||||
|
||||
An extended version for fuzzing with AFL++ support can be found in https://github.com/aflplusplus/unicornafl.
|
||||
|
||||
```rust
|
||||
use unicorn::RegisterARM;
|
||||
use unicorn::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
|
||||
|
||||
fn main() {
|
||||
let arm_code32: Vec<u8> = vec![0x17, 0x00, 0x40, 0xe2]; // sub r0, #23
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
emu.mem_map(0x1000, 0x4000, Permission::ALL).expect("failed to map code page");
|
||||
emu.mem_write(0x1000, &arm_code32).expect("failed to write instructions");
|
||||
|
||||
emu.reg_write(RegisterARM::R0 as i32, 123).expect("failed write R0");
|
||||
emu.reg_write(RegisterARM::R5 as i32, 1337).expect("failed write R5");
|
||||
|
||||
let _ = emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
|
||||
assert_eq!(emu.reg_read(RegisterARM::R0 as i32), Ok(100));
|
||||
assert_eq!(emu.reg_read(RegisterARM::R5 as i32), Ok(1337));
|
||||
}
|
||||
```
|
||||
Further sample code can be found in ```tests/unicorn.rs```.
|
||||
|
||||
## Installation
|
||||
|
||||
This project has been tested on Linux, OS X and Windows.
|
||||
|
||||
To use unicorn-rs, simply add it as a dependency to the Cargo.toml of your program.
|
||||
|
||||
```
|
||||
[dependencies]
|
||||
unicorn = { path = "/path/to/bindings/rust", version="1.0.0" }
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
These bindings are based on Sébastien Duquette's (@ekse) [unicorn-rs](https://github.com/unicorn-rs/unicorn-rs).
|
||||
We picked up the project, as it is no longer maintained.
|
||||
Thanks to all contributers.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
use std::{env, process::Command};
|
||||
|
||||
use build_helper::rustc::{link_lib, link_search};
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=unicorn");
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let unicorn = "libunicorn.a";
|
||||
let _ = Command::new("cp")
|
||||
.current_dir("../..")
|
||||
.arg(&unicorn)
|
||||
.arg(&out_dir)
|
||||
.status()
|
||||
.unwrap();
|
||||
link_search(
|
||||
Some(build_helper::SearchKind::Native),
|
||||
build_helper::out_dir(),
|
||||
);
|
||||
link_lib(Some(build_helper::LibKind::Static), "unicorn");
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterARM {
|
||||
// ARM registers
|
||||
INVALID = 0,
|
||||
APSR = 1,
|
||||
APSR_NZCV = 2,
|
||||
CPSR = 3,
|
||||
FPEXC = 4,
|
||||
FPINST = 5,
|
||||
FPSCR = 6,
|
||||
FPSCR_NZCV = 7,
|
||||
FPSID = 8,
|
||||
ITSTATE = 9,
|
||||
LR = 10,
|
||||
PC = 11,
|
||||
SP = 12,
|
||||
SPSR = 13,
|
||||
D0 = 14,
|
||||
D1 = 15,
|
||||
D2 = 16,
|
||||
D3 = 17,
|
||||
D4 = 18,
|
||||
D5 = 19,
|
||||
D6 = 20,
|
||||
D7 = 21,
|
||||
D8 = 22,
|
||||
D9 = 23,
|
||||
D10 = 24,
|
||||
D11 = 25,
|
||||
D12 = 26,
|
||||
D13 = 27,
|
||||
D14 = 28,
|
||||
D15 = 29,
|
||||
D16 = 30,
|
||||
D17 = 31,
|
||||
D18 = 32,
|
||||
D19 = 33,
|
||||
D20 = 34,
|
||||
D21 = 35,
|
||||
D22 = 36,
|
||||
D23 = 37,
|
||||
D24 = 38,
|
||||
D25 = 39,
|
||||
D26 = 40,
|
||||
D27 = 41,
|
||||
D28 = 42,
|
||||
D29 = 43,
|
||||
D30 = 44,
|
||||
D31 = 45,
|
||||
FPINST2 = 46,
|
||||
MVFR0 = 47,
|
||||
MVFR1 = 48,
|
||||
MVFR2 = 49,
|
||||
Q0 = 50,
|
||||
Q1 = 51,
|
||||
Q2 = 52,
|
||||
Q3 = 53,
|
||||
Q4 = 54,
|
||||
Q5 = 55,
|
||||
Q6 = 56,
|
||||
Q7 = 57,
|
||||
Q8 = 58,
|
||||
Q9 = 59,
|
||||
Q10 = 60,
|
||||
Q11 = 61,
|
||||
Q12 = 62,
|
||||
Q13 = 63,
|
||||
Q14 = 64,
|
||||
Q15 = 65,
|
||||
R0 = 66,
|
||||
R1 = 67,
|
||||
R2 = 68,
|
||||
R3 = 69,
|
||||
R4 = 70,
|
||||
R5 = 71,
|
||||
R6 = 72,
|
||||
R7 = 73,
|
||||
R8 = 74,
|
||||
R9 = 75,
|
||||
R10 = 76,
|
||||
R11 = 77,
|
||||
R12 = 78,
|
||||
S0 = 79,
|
||||
S1 = 80,
|
||||
S2 = 81,
|
||||
S3 = 82,
|
||||
S4 = 83,
|
||||
S5 = 84,
|
||||
S6 = 85,
|
||||
S7 = 86,
|
||||
S8 = 87,
|
||||
S9 = 88,
|
||||
S10 = 89,
|
||||
S11 = 90,
|
||||
S12 = 91,
|
||||
S13 = 92,
|
||||
S14 = 93,
|
||||
S15 = 94,
|
||||
S16 = 95,
|
||||
S17 = 96,
|
||||
S18 = 97,
|
||||
S19 = 98,
|
||||
S20 = 99,
|
||||
S21 = 100,
|
||||
S22 = 101,
|
||||
S23 = 102,
|
||||
S24 = 103,
|
||||
S25 = 104,
|
||||
S26 = 105,
|
||||
S27 = 106,
|
||||
S28 = 107,
|
||||
S29 = 108,
|
||||
S30 = 109,
|
||||
S31 = 110,
|
||||
C1_C0_2 = 111,
|
||||
C13_C0_2 = 112,
|
||||
C13_C0_3 = 113,
|
||||
IPSR = 114,
|
||||
MSP = 115,
|
||||
PSP = 116,
|
||||
CONTROL = 117,
|
||||
XPSR = 118,
|
||||
ENDING = 119,
|
||||
// alias registers
|
||||
// (assoc) R13 = 12,
|
||||
// (assoc) R14 = 10,
|
||||
// (assoc) R15 = 11,
|
||||
// (assoc) SB = 75,
|
||||
// (assoc) SL = 76,
|
||||
// (assoc) FP = 77,
|
||||
// (assoc) IP = 78,
|
||||
}
|
||||
|
||||
impl RegisterARM {
|
||||
pub const R13: RegisterARM = RegisterARM::SP;
|
||||
pub const R14: RegisterARM = RegisterARM::LR;
|
||||
pub const R15: RegisterARM = RegisterARM::PC;
|
||||
pub const SB: RegisterARM = RegisterARM::R9;
|
||||
pub const SL: RegisterARM = RegisterARM::R10;
|
||||
pub const FP: RegisterARM = RegisterARM::R11;
|
||||
pub const IP: RegisterARM = RegisterARM::R12;
|
||||
}
|
||||
@@ -1,321 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// ARM64 registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterARM64 {
|
||||
INVALID = 0,
|
||||
X29 = 1,
|
||||
X30 = 2,
|
||||
NZCV = 3,
|
||||
SP = 4,
|
||||
WSP = 5,
|
||||
WZR = 6,
|
||||
XZR = 7,
|
||||
B0 = 8,
|
||||
B1 = 9,
|
||||
B2 = 10,
|
||||
B3 = 11,
|
||||
B4 = 12,
|
||||
B5 = 13,
|
||||
B6 = 14,
|
||||
B7 = 15,
|
||||
B8 = 16,
|
||||
B9 = 17,
|
||||
B10 = 18,
|
||||
B11 = 19,
|
||||
B12 = 20,
|
||||
B13 = 21,
|
||||
B14 = 22,
|
||||
B15 = 23,
|
||||
B16 = 24,
|
||||
B17 = 25,
|
||||
B18 = 26,
|
||||
B19 = 27,
|
||||
B20 = 28,
|
||||
B21 = 29,
|
||||
B22 = 30,
|
||||
B23 = 31,
|
||||
B24 = 32,
|
||||
B25 = 33,
|
||||
B26 = 34,
|
||||
B27 = 35,
|
||||
B28 = 36,
|
||||
B29 = 37,
|
||||
B30 = 38,
|
||||
B31 = 39,
|
||||
D0 = 40,
|
||||
D1 = 41,
|
||||
D2 = 42,
|
||||
D3 = 43,
|
||||
D4 = 44,
|
||||
D5 = 45,
|
||||
D6 = 46,
|
||||
D7 = 47,
|
||||
D8 = 48,
|
||||
D9 = 49,
|
||||
D10 = 50,
|
||||
D11 = 51,
|
||||
D12 = 52,
|
||||
D13 = 53,
|
||||
D14 = 54,
|
||||
D15 = 55,
|
||||
D16 = 56,
|
||||
D17 = 57,
|
||||
D18 = 58,
|
||||
D19 = 59,
|
||||
D20 = 60,
|
||||
D21 = 61,
|
||||
D22 = 62,
|
||||
D23 = 63,
|
||||
D24 = 64,
|
||||
D25 = 65,
|
||||
D26 = 66,
|
||||
D27 = 67,
|
||||
D28 = 68,
|
||||
D29 = 69,
|
||||
D30 = 70,
|
||||
D31 = 71,
|
||||
H0 = 72,
|
||||
H1 = 73,
|
||||
H2 = 74,
|
||||
H3 = 75,
|
||||
H4 = 76,
|
||||
H5 = 77,
|
||||
H6 = 78,
|
||||
H7 = 79,
|
||||
H8 = 80,
|
||||
H9 = 81,
|
||||
H10 = 82,
|
||||
H11 = 83,
|
||||
H12 = 84,
|
||||
H13 = 85,
|
||||
H14 = 86,
|
||||
H15 = 87,
|
||||
H16 = 88,
|
||||
H17 = 89,
|
||||
H18 = 90,
|
||||
H19 = 91,
|
||||
H20 = 92,
|
||||
H21 = 93,
|
||||
H22 = 94,
|
||||
H23 = 95,
|
||||
H24 = 96,
|
||||
H25 = 97,
|
||||
H26 = 98,
|
||||
H27 = 99,
|
||||
H28 = 100,
|
||||
H29 = 101,
|
||||
H30 = 102,
|
||||
H31 = 103,
|
||||
Q0 = 104,
|
||||
Q1 = 105,
|
||||
Q2 = 106,
|
||||
Q3 = 107,
|
||||
Q4 = 108,
|
||||
Q5 = 109,
|
||||
Q6 = 110,
|
||||
Q7 = 111,
|
||||
Q8 = 112,
|
||||
Q9 = 113,
|
||||
Q10 = 114,
|
||||
Q11 = 115,
|
||||
Q12 = 116,
|
||||
Q13 = 117,
|
||||
Q14 = 118,
|
||||
Q15 = 119,
|
||||
Q16 = 120,
|
||||
Q17 = 121,
|
||||
Q18 = 122,
|
||||
Q19 = 123,
|
||||
Q20 = 124,
|
||||
Q21 = 125,
|
||||
Q22 = 126,
|
||||
Q23 = 127,
|
||||
Q24 = 128,
|
||||
Q25 = 129,
|
||||
Q26 = 130,
|
||||
Q27 = 131,
|
||||
Q28 = 132,
|
||||
Q29 = 133,
|
||||
Q30 = 134,
|
||||
Q31 = 135,
|
||||
S0 = 136,
|
||||
S1 = 137,
|
||||
S2 = 138,
|
||||
S3 = 139,
|
||||
S4 = 140,
|
||||
S5 = 141,
|
||||
S6 = 142,
|
||||
S7 = 143,
|
||||
S8 = 144,
|
||||
S9 = 145,
|
||||
S10 = 146,
|
||||
S11 = 147,
|
||||
S12 = 148,
|
||||
S13 = 149,
|
||||
S14 = 150,
|
||||
S15 = 151,
|
||||
S16 = 152,
|
||||
S17 = 153,
|
||||
S18 = 154,
|
||||
S19 = 155,
|
||||
S20 = 156,
|
||||
S21 = 157,
|
||||
S22 = 158,
|
||||
S23 = 159,
|
||||
S24 = 160,
|
||||
S25 = 161,
|
||||
S26 = 162,
|
||||
S27 = 163,
|
||||
S28 = 164,
|
||||
S29 = 165,
|
||||
S30 = 166,
|
||||
S31 = 167,
|
||||
W0 = 168,
|
||||
W1 = 169,
|
||||
W2 = 170,
|
||||
W3 = 171,
|
||||
W4 = 172,
|
||||
W5 = 173,
|
||||
W6 = 174,
|
||||
W7 = 175,
|
||||
W8 = 176,
|
||||
W9 = 177,
|
||||
W10 = 178,
|
||||
W11 = 179,
|
||||
W12 = 180,
|
||||
W13 = 181,
|
||||
W14 = 182,
|
||||
W15 = 183,
|
||||
W16 = 184,
|
||||
W17 = 185,
|
||||
W18 = 186,
|
||||
W19 = 187,
|
||||
W20 = 188,
|
||||
W21 = 189,
|
||||
W22 = 190,
|
||||
W23 = 191,
|
||||
W24 = 192,
|
||||
W25 = 193,
|
||||
W26 = 194,
|
||||
W27 = 195,
|
||||
W28 = 196,
|
||||
W29 = 197,
|
||||
W30 = 198,
|
||||
X0 = 199,
|
||||
X1 = 200,
|
||||
X2 = 201,
|
||||
X3 = 202,
|
||||
X4 = 203,
|
||||
X5 = 204,
|
||||
X6 = 205,
|
||||
X7 = 206,
|
||||
X8 = 207,
|
||||
X9 = 208,
|
||||
X10 = 209,
|
||||
X11 = 210,
|
||||
X12 = 211,
|
||||
X13 = 212,
|
||||
X14 = 213,
|
||||
X15 = 214,
|
||||
X16 = 215,
|
||||
X17 = 216,
|
||||
X18 = 217,
|
||||
X19 = 218,
|
||||
X20 = 219,
|
||||
X21 = 220,
|
||||
X22 = 221,
|
||||
X23 = 222,
|
||||
X24 = 223,
|
||||
X25 = 224,
|
||||
X26 = 225,
|
||||
X27 = 226,
|
||||
X28 = 227,
|
||||
V0 = 228,
|
||||
V1 = 229,
|
||||
V2 = 230,
|
||||
V3 = 231,
|
||||
V4 = 232,
|
||||
V5 = 233,
|
||||
V6 = 234,
|
||||
V7 = 235,
|
||||
V8 = 236,
|
||||
V9 = 237,
|
||||
V10 = 238,
|
||||
V11 = 239,
|
||||
V12 = 240,
|
||||
V13 = 241,
|
||||
V14 = 242,
|
||||
V15 = 243,
|
||||
V16 = 244,
|
||||
V17 = 245,
|
||||
V18 = 246,
|
||||
V19 = 247,
|
||||
V20 = 248,
|
||||
V21 = 249,
|
||||
V22 = 250,
|
||||
V23 = 251,
|
||||
V24 = 252,
|
||||
V25 = 253,
|
||||
V26 = 254,
|
||||
V27 = 255,
|
||||
V28 = 256,
|
||||
V29 = 257,
|
||||
V30 = 258,
|
||||
V31 = 259,
|
||||
|
||||
// pseudo registers
|
||||
PC = 260,
|
||||
CPACR_EL1 = 261,
|
||||
|
||||
// thread registers
|
||||
TPIDR_EL0 = 262,
|
||||
TPIDRRO_EL0 = 263,
|
||||
TPIDR_EL1 = 264,
|
||||
PSTATE = 265,
|
||||
|
||||
// exception link registers
|
||||
ELR_EL0 = 266,
|
||||
ELR_EL1 = 267,
|
||||
ELR_EL2 = 268,
|
||||
ELR_EL3 = 269,
|
||||
|
||||
// stack pointers registers
|
||||
SP_EL0 = 270,
|
||||
SP_EL1 = 271,
|
||||
SP_EL2 = 272,
|
||||
SP_EL3 = 273,
|
||||
|
||||
// other CP15 registers
|
||||
TTBR0_EL1 = 274,
|
||||
TTBR1_EL1 = 275,
|
||||
ESR_EL0 = 276,
|
||||
ESR_EL1 = 277,
|
||||
ESR_EL2 = 278,
|
||||
ESR_EL3 = 279,
|
||||
FAR_EL0 = 280,
|
||||
FAR_EL1 = 281,
|
||||
FAR_EL2 = 282,
|
||||
FAR_EL3 = 283,
|
||||
PAR_EL1 = 284,
|
||||
MAIR_EL1 = 285,
|
||||
VBAR_EL0 = 286,
|
||||
VBAR_EL1 = 287,
|
||||
VBAR_EL2 = 288,
|
||||
VBAR_EL3 = 289,
|
||||
ENDING = 290,
|
||||
|
||||
// alias registers
|
||||
// (assoc) IP0 = 215,
|
||||
// (assoc) IP1 = 216,
|
||||
// (assoc) FP = 1,
|
||||
// (assoc) LR = 2,
|
||||
}
|
||||
|
||||
impl RegisterARM64 {
|
||||
pub const IP0: RegisterARM64 = RegisterARM64::X16;
|
||||
pub const IP1: RegisterARM64 = RegisterARM64::X17;
|
||||
pub const FP: RegisterARM64 = RegisterARM64::X29;
|
||||
pub const LR: RegisterARM64 = RegisterARM64::X30;
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::unicorn_const::*;
|
||||
use libc::{c_char, c_int};
|
||||
use std::ffi::c_void;
|
||||
use std::pin::Pin;
|
||||
|
||||
pub type uc_handle = *mut c_void;
|
||||
pub type uc_hook = *mut c_void;
|
||||
pub type uc_context = libc::size_t;
|
||||
|
||||
extern "C" {
|
||||
pub fn uc_version(major: *mut u32, minor: *mut u32) -> u32;
|
||||
pub fn uc_arch_supported(arch: Arch) -> bool;
|
||||
pub fn uc_open(arch: Arch, mode: Mode, engine: *mut uc_handle) -> uc_error;
|
||||
pub fn uc_close(engine: uc_handle) -> uc_error;
|
||||
pub fn uc_context_free(mem: uc_context) -> uc_error;
|
||||
pub fn uc_errno(engine: uc_handle) -> uc_error;
|
||||
pub fn uc_strerror(error_code: uc_error) -> *const c_char;
|
||||
pub fn uc_reg_write(engine: uc_handle, regid: c_int, value: *const c_void) -> uc_error;
|
||||
pub fn uc_reg_read(engine: uc_handle, regid: c_int, value: *mut c_void) -> uc_error;
|
||||
pub fn uc_mem_write(
|
||||
engine: uc_handle,
|
||||
address: u64,
|
||||
bytes: *const u8,
|
||||
size: libc::size_t,
|
||||
) -> uc_error;
|
||||
pub fn uc_mem_read(
|
||||
engine: uc_handle,
|
||||
address: u64,
|
||||
bytes: *mut u8,
|
||||
size: libc::size_t,
|
||||
) -> uc_error;
|
||||
pub fn uc_mem_map(engine: uc_handle, address: u64, size: libc::size_t, perms: u32) -> uc_error;
|
||||
pub fn uc_mem_map_ptr(
|
||||
engine: uc_handle,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
perms: u32,
|
||||
ptr: *mut c_void,
|
||||
) -> uc_error;
|
||||
pub fn uc_mem_unmap(engine: uc_handle, address: u64, size: libc::size_t) -> uc_error;
|
||||
pub fn uc_mem_protect(
|
||||
engine: uc_handle,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
perms: u32,
|
||||
) -> uc_error;
|
||||
pub fn uc_mem_regions(
|
||||
engine: uc_handle,
|
||||
regions: *const *const MemRegion,
|
||||
count: *mut u32,
|
||||
) -> uc_error;
|
||||
pub fn uc_emu_start(
|
||||
engine: uc_handle,
|
||||
begin: u64,
|
||||
until: u64,
|
||||
timeout: u64,
|
||||
count: libc::size_t,
|
||||
) -> uc_error;
|
||||
pub fn uc_emu_stop(engine: uc_handle) -> uc_error;
|
||||
pub fn uc_hook_add(
|
||||
engine: uc_handle,
|
||||
hook: *mut uc_hook,
|
||||
hook_type: HookType,
|
||||
callback: *mut c_void,
|
||||
user_data: *mut c_void,
|
||||
begin: u64,
|
||||
end: u64,
|
||||
...
|
||||
) -> uc_error;
|
||||
pub fn uc_hook_del(engine: uc_handle, hook: uc_hook) -> uc_error;
|
||||
pub fn uc_query(engine: uc_handle, query_type: Query, result: *mut libc::size_t) -> uc_error;
|
||||
pub fn uc_context_alloc(engine: uc_handle, context: *mut uc_context) -> uc_error;
|
||||
pub fn uc_context_save(engine: uc_handle, context: uc_context) -> uc_error;
|
||||
pub fn uc_context_restore(engine: uc_handle, context: uc_context) -> uc_error;
|
||||
}
|
||||
|
||||
pub struct CodeHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u64, u32)>,
|
||||
}
|
||||
|
||||
pub struct BlockHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u64, u32)>,
|
||||
}
|
||||
|
||||
pub struct MemHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, MemType, u64, usize, i64)>,
|
||||
}
|
||||
|
||||
pub struct InterruptHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u32)>,
|
||||
}
|
||||
|
||||
pub struct InstructionInHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u32, usize)>,
|
||||
}
|
||||
|
||||
pub struct InstructionOutHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u32, usize, u32)>,
|
||||
}
|
||||
|
||||
pub struct InstructionSysHook {
|
||||
pub unicorn: *mut crate::UnicornInner,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle)>,
|
||||
}
|
||||
|
||||
pub extern "C" fn code_hook_proxy(
|
||||
uc: uc_handle,
|
||||
address: u64,
|
||||
size: u32,
|
||||
user_data: *mut CodeHook,
|
||||
) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(
|
||||
crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
},
|
||||
address,
|
||||
size,
|
||||
);
|
||||
}
|
||||
|
||||
pub extern "C" fn block_hook_proxy(
|
||||
uc: uc_handle,
|
||||
address: u64,
|
||||
size: u32,
|
||||
user_data: *mut BlockHook,
|
||||
) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(
|
||||
crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
},
|
||||
address,
|
||||
size,
|
||||
);
|
||||
}
|
||||
|
||||
pub extern "C" fn mem_hook_proxy(
|
||||
uc: uc_handle,
|
||||
mem_type: MemType,
|
||||
address: u64,
|
||||
size: u32,
|
||||
value: i64,
|
||||
user_data: *mut MemHook,
|
||||
) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(
|
||||
crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
},
|
||||
mem_type,
|
||||
address,
|
||||
size as usize,
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
pub extern "C" fn intr_hook_proxy(uc: uc_handle, value: u32, user_data: *mut InterruptHook) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(
|
||||
crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
},
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_in_hook_proxy(
|
||||
uc: uc_handle,
|
||||
port: u32,
|
||||
size: usize,
|
||||
user_data: *mut InstructionInHook,
|
||||
) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(
|
||||
crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
},
|
||||
port,
|
||||
size,
|
||||
);
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_out_hook_proxy(
|
||||
uc: uc_handle,
|
||||
port: u32,
|
||||
size: usize,
|
||||
value: u32,
|
||||
user_data: *mut InstructionOutHook,
|
||||
) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(
|
||||
crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
},
|
||||
port,
|
||||
size,
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_sys_hook_proxy(uc: uc_handle, user_data: *mut InstructionSysHook) {
|
||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
||||
assert_eq!(uc, unicorn.uc);
|
||||
callback(crate::UnicornHandle {
|
||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
||||
});
|
||||
}
|
||||
@@ -1,784 +0,0 @@
|
||||
//! Bindings for the Unicorn emulator.
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//! # Example use
|
||||
//!
|
||||
//! ```rust
|
||||
//!
|
||||
//! use unicorn::RegisterARM;
|
||||
//! use unicorn::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let arm_code32: Vec<u8> = vec![0x17, 0x00, 0x40, 0xe2]; // sub r0, #23
|
||||
//!
|
||||
//! let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
|
||||
//! let mut emu = unicorn.borrow();
|
||||
//! emu.mem_map(0x1000, 0x4000, Permission::ALL).expect("failed to map code page");
|
||||
//! emu.mem_write(0x1000, &arm_code32).expect("failed to write instructions");
|
||||
//!
|
||||
//! emu.reg_write(RegisterARM::R0 as i32, 123).expect("failed write R0");
|
||||
//! emu.reg_write(RegisterARM::R5 as i32, 1337).expect("failed write R5");
|
||||
//!
|
||||
//! let _ = emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
|
||||
//! assert_eq!(emu.reg_read(RegisterARM::R0 as i32), Ok(100));
|
||||
//! assert_eq!(emu.reg_read(RegisterARM::R5 as i32), Ok(1337));
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
||||
mod ffi;
|
||||
pub mod unicorn_const;
|
||||
|
||||
mod arm;
|
||||
mod arm64;
|
||||
mod m68k;
|
||||
mod mips;
|
||||
mod ppc;
|
||||
mod sparc;
|
||||
mod x86;
|
||||
pub use crate::{arm::*, arm64::*, m68k::*, mips::*, ppc::*, sparc::*, x86::*};
|
||||
|
||||
use ffi::uc_handle;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::marker::PhantomPinned;
|
||||
use std::pin::Pin;
|
||||
use unicorn_const::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Context {
|
||||
context: ffi::uc_context,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new() -> Self {
|
||||
Context { context: 0 }
|
||||
}
|
||||
pub fn is_initialized(&self) -> bool {
|
||||
self.context != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Context {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::uc_context_free(self.context) };
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A Unicorn emulator instance.
|
||||
pub struct Unicorn {
|
||||
inner: Pin<Box<UnicornInner>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Handle used to safely access exposed functions and data of a Unicorn instance.
|
||||
pub struct UnicornHandle<'a> {
|
||||
inner: Pin<&'a mut UnicornInner>,
|
||||
}
|
||||
|
||||
/// Internal Management struct
|
||||
pub struct UnicornInner {
|
||||
pub uc: uc_handle,
|
||||
pub arch: Arch,
|
||||
pub code_hooks: HashMap<*mut libc::c_void, Box<ffi::CodeHook>>,
|
||||
pub block_hooks: HashMap<*mut libc::c_void, Box<ffi::BlockHook>>,
|
||||
pub mem_hooks: HashMap<*mut libc::c_void, Box<ffi::MemHook>>,
|
||||
pub intr_hooks: HashMap<*mut libc::c_void, Box<ffi::InterruptHook>>,
|
||||
pub insn_in_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionInHook>>,
|
||||
pub insn_out_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionOutHook>>,
|
||||
pub insn_sys_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionSysHook>>,
|
||||
_pin: PhantomPinned,
|
||||
}
|
||||
|
||||
impl Unicorn {
|
||||
/// Create a new instance of the unicorn engine for the specified architecture
|
||||
/// and hardware mode.
|
||||
pub fn new(arch: Arch, mode: Mode) -> Result<Unicorn, uc_error> {
|
||||
let mut handle = std::ptr::null_mut();
|
||||
let err = unsafe { ffi::uc_open(arch, mode, &mut handle) };
|
||||
if err == uc_error::OK {
|
||||
Ok(Unicorn {
|
||||
inner: Box::pin(UnicornInner {
|
||||
uc: handle,
|
||||
arch: arch,
|
||||
code_hooks: HashMap::new(),
|
||||
block_hooks: HashMap::new(),
|
||||
mem_hooks: HashMap::new(),
|
||||
intr_hooks: HashMap::new(),
|
||||
insn_in_hooks: HashMap::new(),
|
||||
insn_out_hooks: HashMap::new(),
|
||||
insn_sys_hooks: HashMap::new(),
|
||||
_pin: std::marker::PhantomPinned,
|
||||
}),
|
||||
})
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow<'a>(&'a mut self) -> UnicornHandle<'a> {
|
||||
UnicornHandle {
|
||||
inner: self.inner.as_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Unicorn {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::uc_close(self.inner.uc) };
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for UnicornInner {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(formatter, "Unicorn {{ uc: {:p} }}", self.uc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UnicornHandle<'a> {
|
||||
|
||||
/// Return the architecture of the current emulator.
|
||||
pub fn get_arch(&self) -> Arch {
|
||||
self.inner.arch
|
||||
}
|
||||
|
||||
/// Returns a vector with the memory regions that are mapped in the emulator.
|
||||
pub fn mem_regions(&self) -> Result<Vec<MemRegion>, uc_error> {
|
||||
let mut nb_regions: u32 = 0;
|
||||
let mut p_regions: *const MemRegion = std::ptr::null_mut();
|
||||
let err = unsafe { ffi::uc_mem_regions(self.inner.uc, &mut p_regions, &mut nb_regions) };
|
||||
if err == uc_error::OK {
|
||||
let mut regions = Vec::new();
|
||||
for i in 0..nb_regions {
|
||||
regions.push(unsafe { std::mem::transmute_copy(&*p_regions.offset(i as isize)) });
|
||||
}
|
||||
unsafe { libc::free(p_regions as _) };
|
||||
Ok(regions)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a range of bytes from memory at the specified address.
|
||||
pub fn mem_read(&self, address: u64, buf: &mut [u8]) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_mem_read(self.inner.uc, address, buf.as_mut_ptr(), buf.len()) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a range of bytes from memory at the specified address as vector.
|
||||
pub fn mem_read_as_vec(&self, address: u64, size: usize) -> Result<Vec<u8>, uc_error> {
|
||||
let mut buf = vec![0; size];
|
||||
let err = unsafe { ffi::uc_mem_read(self.inner.uc, address, buf.as_mut_ptr(), size) };
|
||||
if err == uc_error::OK {
|
||||
Ok(buf)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mem_write(&mut self, address: u64, bytes: &[u8]) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_mem_write(self.inner.uc, address, bytes.as_ptr(), bytes.len()) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Map an existing memory region in the emulator at the specified address.
|
||||
///
|
||||
/// This function is marked unsafe because it is the responsibility of the caller to
|
||||
/// ensure that `size` matches the size of the passed buffer, an invalid `size` value will
|
||||
/// likely cause a crash in unicorn.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
///
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
///
|
||||
/// `ptr` is a pointer to the provided memory region that will be used by the emulator.
|
||||
pub fn mem_map_ptr(
|
||||
&mut self,
|
||||
address: u64,
|
||||
size: usize,
|
||||
perms: Permission,
|
||||
ptr: *mut c_void,
|
||||
) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_mem_map_ptr(self.inner.uc, address, size, perms.bits(), ptr) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Map a memory region in the emulator at the specified address.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mem_map(
|
||||
&mut self,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
perms: Permission,
|
||||
) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_mem_map(self.inner.uc, address, size, perms.bits()) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unmap a memory region.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mem_unmap(&mut self, address: u64, size: libc::size_t) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_mem_unmap(self.inner.uc, address, size) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the memory permissions for an existing memory region.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mem_protect(
|
||||
&mut self,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
perms: Permission,
|
||||
) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_mem_protect(self.inner.uc, address, size, perms.bits()) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write an unsigned value from a register.
|
||||
pub fn reg_write<T: Into<i32>>(&mut self, regid: T, value: u64) -> Result<(), uc_error> {
|
||||
let err =
|
||||
unsafe { ffi::uc_reg_write(self.inner.uc, regid.into(), &value as *const _ as _) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write variable sized values into registers.
|
||||
///
|
||||
/// The user has to make sure that the buffer length matches the register size.
|
||||
/// This adds support for registers >64 bit (GDTR/IDTR, XMM, YMM, ZMM (x86); Q, V (arm64)).
|
||||
pub fn reg_write_long<T: Into<i32>>(&self, regid: T, value: Box<[u8]>) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_reg_write(self.inner.uc, regid.into(), value.as_ptr() as _) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read an unsigned value from a register.
|
||||
///
|
||||
/// Not to be used with registers larger than 64 bit.
|
||||
pub fn reg_read<T: Into<i32>>(&self, regid: T) -> Result<u64, uc_error> {
|
||||
let mut value: u64 = 0;
|
||||
let err =
|
||||
unsafe { ffi::uc_reg_read(self.inner.uc, regid.into(), &mut value as *mut u64 as _) };
|
||||
if err == uc_error::OK {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read 128, 256 or 512 bit register value into heap allocated byte array.
|
||||
///
|
||||
/// This adds safe support for registers >64 bit (GDTR/IDTR, XMM, YMM, ZMM (x86); Q, V (arm64)).
|
||||
pub fn reg_read_long<T: Into<i32>>(&self, regid: T) -> Result<Box<[u8]>, uc_error> {
|
||||
let err: uc_error;
|
||||
let boxed: Box<[u8]>;
|
||||
let mut value: Vec<u8>;
|
||||
let curr_reg_id = regid.into();
|
||||
let curr_arch = self.get_arch();
|
||||
|
||||
if curr_arch == Arch::X86 {
|
||||
if curr_reg_id >= x86::RegisterX86::XMM0 as i32
|
||||
&& curr_reg_id <= x86::RegisterX86::XMM31 as i32
|
||||
{
|
||||
value = vec![0; 16];
|
||||
} else if curr_reg_id >= x86::RegisterX86::YMM0 as i32
|
||||
&& curr_reg_id <= x86::RegisterX86::YMM31 as i32
|
||||
{
|
||||
value = vec![0; 32];
|
||||
} else if curr_reg_id >= x86::RegisterX86::ZMM0 as i32
|
||||
&& curr_reg_id <= x86::RegisterX86::ZMM31 as i32
|
||||
{
|
||||
value = vec![0; 64];
|
||||
} else if curr_reg_id == x86::RegisterX86::GDTR as i32
|
||||
|| curr_reg_id == x86::RegisterX86::IDTR as i32
|
||||
{
|
||||
value = vec![0; 10]; // 64 bit base address in IA-32e mode
|
||||
} else {
|
||||
return Err(uc_error::ARG);
|
||||
}
|
||||
} else if curr_arch == Arch::ARM64 {
|
||||
if (curr_reg_id >= arm64::RegisterARM64::Q0 as i32
|
||||
&& curr_reg_id <= arm64::RegisterARM64::Q31 as i32)
|
||||
|| (curr_reg_id >= arm64::RegisterARM64::V0 as i32
|
||||
&& curr_reg_id <= arm64::RegisterARM64::V31 as i32)
|
||||
{
|
||||
value = vec![0; 16];
|
||||
} else {
|
||||
return Err(uc_error::ARG);
|
||||
}
|
||||
} else {
|
||||
return Err(uc_error::ARCH);
|
||||
}
|
||||
|
||||
err = unsafe { ffi::uc_reg_read(self.inner.uc, curr_reg_id, value.as_mut_ptr() as _) };
|
||||
|
||||
if err == uc_error::OK {
|
||||
boxed = value.into_boxed_slice();
|
||||
Ok(boxed)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a signed 32-bit value from a register.
|
||||
pub fn reg_read_i32<T: Into<i32>>(&self, regid: T) -> Result<i32, uc_error> {
|
||||
let mut value: i32 = 0;
|
||||
let err =
|
||||
unsafe { ffi::uc_reg_read(self.inner.uc, regid.into(), &mut value as *mut i32 as _) };
|
||||
if err == uc_error::OK {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a code hook.
|
||||
pub fn add_code_hook<F: 'static>(
|
||||
&mut self,
|
||||
begin: u64,
|
||||
end: u64,
|
||||
callback: F,
|
||||
) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle, u64, u32),
|
||||
{
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::CodeHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
HookType::CODE,
|
||||
ffi::code_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
begin,
|
||||
end,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.code_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a block hook.
|
||||
pub fn add_block_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle, u64, u32),
|
||||
{
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::BlockHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
HookType::BLOCK,
|
||||
ffi::block_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
1,
|
||||
0,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.block_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a memory hook.
|
||||
pub fn add_mem_hook<F: 'static>(
|
||||
&mut self,
|
||||
hook_type: HookType,
|
||||
begin: u64,
|
||||
end: u64,
|
||||
callback: F,
|
||||
) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle, MemType, u64, usize, i64),
|
||||
{
|
||||
if !(HookType::MEM_ALL | HookType::MEM_READ_AFTER).contains(hook_type) {
|
||||
return Err(uc_error::ARG);
|
||||
}
|
||||
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::MemHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
hook_type,
|
||||
ffi::mem_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
begin,
|
||||
end,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.mem_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add an interrupt hook.
|
||||
pub fn add_intr_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle, u32),
|
||||
{
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::InterruptHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
HookType::INTR,
|
||||
ffi::intr_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.intr_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add hook for x86 IN instruction.
|
||||
pub fn add_insn_in_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle, u32, usize),
|
||||
{
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::InstructionInHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
HookType::INSN,
|
||||
ffi::insn_in_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
0,
|
||||
0,
|
||||
x86::InsnX86::IN,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.insn_in_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add hook for x86 OUT instruction.
|
||||
pub fn add_insn_out_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle, u32, usize, u32),
|
||||
{
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::InstructionOutHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
HookType::INSN,
|
||||
ffi::insn_out_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
0,
|
||||
0,
|
||||
x86::InsnX86::OUT,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.insn_out_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add hook for x86 SYSCALL or SYSENTER.
|
||||
pub fn add_insn_sys_hook<F: 'static>(
|
||||
&mut self,
|
||||
insn_type: x86::InsnSysX86,
|
||||
begin: u64,
|
||||
end: u64,
|
||||
callback: F,
|
||||
) -> Result<ffi::uc_hook, uc_error>
|
||||
where
|
||||
F: FnMut(UnicornHandle),
|
||||
{
|
||||
let mut hook_ptr = std::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::InstructionSysHook {
|
||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_hook_add(
|
||||
self.inner.uc,
|
||||
&mut hook_ptr,
|
||||
HookType::INSN,
|
||||
ffi::insn_sys_hook_proxy as _,
|
||||
user_data.as_mut() as *mut _ as _,
|
||||
begin,
|
||||
end,
|
||||
insn_type,
|
||||
)
|
||||
};
|
||||
if err == uc_error::OK {
|
||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
||||
.insn_sys_hooks
|
||||
.insert(hook_ptr, user_data);
|
||||
Ok(hook_ptr)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a hook.
|
||||
///
|
||||
/// `hook` is the value returned by `add_*_hook` functions.
|
||||
pub fn remove_hook(&mut self, hook: ffi::uc_hook) -> Result<(), uc_error> {
|
||||
let handle = unsafe { self.inner.as_mut().get_unchecked_mut() };
|
||||
let err: uc_error;
|
||||
let mut in_one_hashmap = false;
|
||||
|
||||
if handle.code_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.code_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if handle.mem_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.mem_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if handle.block_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.block_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if handle.intr_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.intr_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if handle.insn_in_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.insn_in_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if handle.insn_out_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.insn_out_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if handle.insn_sys_hooks.contains_key(&hook) {
|
||||
in_one_hashmap = true;
|
||||
handle.insn_sys_hooks.remove(&hook);
|
||||
}
|
||||
|
||||
if in_one_hashmap {
|
||||
err = unsafe { ffi::uc_hook_del(handle.uc, hook) };
|
||||
} else {
|
||||
err = uc_error::HOOK;
|
||||
}
|
||||
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocate and return an empty Unicorn context.
|
||||
///
|
||||
/// To be populated via context_save.
|
||||
pub fn context_alloc(&self) -> Result<Context, uc_error> {
|
||||
let mut empty_context: ffi::uc_context = Default::default();
|
||||
let err = unsafe { ffi::uc_context_alloc(self.inner.uc, &mut empty_context) };
|
||||
if err == uc_error::OK {
|
||||
Ok(Context {
|
||||
context: empty_context,
|
||||
})
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Save current Unicorn context to previously allocated Context struct.
|
||||
pub fn context_save(&self, context: &mut Context) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_context_save(self.inner.uc, context.context) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocate and return a Context struct initialized with the current CPU context.
|
||||
///
|
||||
/// This can be used for fast rollbacks with context_restore.
|
||||
/// In case of many non-concurrent context saves, use context_alloc and *_save
|
||||
/// individually to avoid unnecessary allocations.
|
||||
pub fn context_init(&self) -> Result<Context, uc_error> {
|
||||
let mut new_context: ffi::uc_context = Default::default();
|
||||
let err = unsafe { ffi::uc_context_alloc(self.inner.uc, &mut new_context) };
|
||||
if err != uc_error::OK {
|
||||
return Err(err);
|
||||
}
|
||||
let err = unsafe { ffi::uc_context_save(self.inner.uc, new_context) };
|
||||
if err == uc_error::OK {
|
||||
Ok(Context {
|
||||
context: new_context,
|
||||
})
|
||||
} else {
|
||||
unsafe { ffi::uc_context_free(new_context) };
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Restore a previously saved Unicorn context.
|
||||
///
|
||||
/// Perform a quick rollback of the CPU context, including registers and some
|
||||
/// internal metadata. Contexts may not be shared across engine instances with
|
||||
/// differing arches or modes. Memory has to be restored manually, if needed.
|
||||
pub fn context_restore(&self, context: &Context) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_context_restore(self.inner.uc, context.context) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Emulate machine code for a specified duration.
|
||||
///
|
||||
/// `begin` is the address where to start the emulation. The emulation stops if `until`
|
||||
/// is hit. `timeout` specifies a duration in microseconds after which the emulation is
|
||||
/// stopped (infinite execution if set to 0). `count` is the maximum number of instructions
|
||||
/// to emulate (emulate all the available instructions if set to 0).
|
||||
pub fn emu_start(
|
||||
&mut self,
|
||||
begin: u64,
|
||||
until: u64,
|
||||
timeout: u64,
|
||||
count: usize,
|
||||
) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_emu_start(self.inner.uc, begin, until, timeout, count as _) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Stop the emulation.
|
||||
///
|
||||
/// This is usually called from callback function in hooks.
|
||||
/// NOTE: For now, this will stop the execution only after the current block.
|
||||
pub fn emu_stop(&mut self) -> Result<(), uc_error> {
|
||||
let err = unsafe { ffi::uc_emu_stop(self.inner.uc) };
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Query the internal status of the engine.
|
||||
///
|
||||
/// supported: MODE, PAGE_SIZE, ARCH
|
||||
pub fn query(&self, query: Query) -> Result<usize, uc_error> {
|
||||
let mut result: libc::size_t = Default::default();
|
||||
let err = unsafe { ffi::uc_query(self.inner.uc, query, &mut result) };
|
||||
if err == uc_error::OK {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// M68K registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterM68K {
|
||||
INVALID = 0,
|
||||
A0,
|
||||
A1,
|
||||
A2,
|
||||
A3,
|
||||
A4,
|
||||
A5,
|
||||
A6,
|
||||
A7,
|
||||
D0,
|
||||
D1,
|
||||
D2,
|
||||
D3,
|
||||
D4,
|
||||
D5,
|
||||
D6,
|
||||
D7,
|
||||
SR,
|
||||
PC,
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// MIPS registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterMIPS {
|
||||
INVALID = 0,
|
||||
|
||||
// General purpose registers
|
||||
PC = 1,
|
||||
GPR0 = 2,
|
||||
GPR1 = 3,
|
||||
GPR2 = 4,
|
||||
GPR3 = 5,
|
||||
GPR4 = 6,
|
||||
GPR5 = 7,
|
||||
GPR6 = 8,
|
||||
GPR7 = 9,
|
||||
GPR8 = 10,
|
||||
GPR9 = 11,
|
||||
GPR10 = 12,
|
||||
GPR11 = 13,
|
||||
GPR12 = 14,
|
||||
GPR13 = 15,
|
||||
GPR14 = 16,
|
||||
GPR15 = 17,
|
||||
GPR16 = 18,
|
||||
GPR17 = 19,
|
||||
GPR18 = 20,
|
||||
GPR19 = 21,
|
||||
GPR20 = 22,
|
||||
GPR21 = 23,
|
||||
GPR22 = 24,
|
||||
GPR23 = 25,
|
||||
GPR24 = 26,
|
||||
GPR25 = 27,
|
||||
GPR26 = 28,
|
||||
GPR27 = 29,
|
||||
GPR28 = 30,
|
||||
GPR29 = 31,
|
||||
GPR30 = 32,
|
||||
GPR31 = 33,
|
||||
|
||||
// DSP registers
|
||||
DSPCCOND = 34,
|
||||
DSPCARRY = 35,
|
||||
DSPEFI = 36,
|
||||
DSPOUTFLAG = 37,
|
||||
DSPOUTFLAG16_19 = 38,
|
||||
DSPOUTFLAG20 = 39,
|
||||
DSPOUTFLAG21 = 40,
|
||||
DSPOUTFLAG22 = 41,
|
||||
DSPOUTFLAG23 = 42,
|
||||
DSPPOS = 43,
|
||||
DSPSCOUNT = 44,
|
||||
|
||||
// ACC registers
|
||||
AC0 = 45,
|
||||
AC1 = 46,
|
||||
AC2 = 47,
|
||||
AC3 = 48,
|
||||
|
||||
// COP registers
|
||||
CC0 = 49,
|
||||
CC1 = 50,
|
||||
CC2 = 51,
|
||||
CC3 = 52,
|
||||
CC4 = 53,
|
||||
CC5 = 54,
|
||||
CC6 = 55,
|
||||
CC7 = 56,
|
||||
|
||||
// FPU registers
|
||||
F0 = 57,
|
||||
F1 = 58,
|
||||
F2 = 59,
|
||||
F3 = 60,
|
||||
F4 = 61,
|
||||
F5 = 62,
|
||||
F6 = 63,
|
||||
F7 = 64,
|
||||
F8 = 65,
|
||||
F9 = 66,
|
||||
F10 = 67,
|
||||
F11 = 68,
|
||||
F12 = 69,
|
||||
F13 = 70,
|
||||
F14 = 71,
|
||||
F15 = 72,
|
||||
F16 = 73,
|
||||
F17 = 74,
|
||||
F18 = 75,
|
||||
F19 = 76,
|
||||
F20 = 77,
|
||||
F21 = 78,
|
||||
F22 = 79,
|
||||
F23 = 80,
|
||||
F24 = 81,
|
||||
F25 = 82,
|
||||
F26 = 83,
|
||||
F27 = 84,
|
||||
F28 = 85,
|
||||
F29 = 86,
|
||||
F30 = 87,
|
||||
F31 = 88,
|
||||
FCC0 = 89,
|
||||
FCC1 = 90,
|
||||
FCC2 = 91,
|
||||
FCC3 = 92,
|
||||
FCC4 = 93,
|
||||
FCC5 = 94,
|
||||
FCC6 = 95,
|
||||
FCC7 = 96,
|
||||
|
||||
// AFPR128
|
||||
W0 = 97,
|
||||
W1 = 98,
|
||||
W2 = 99,
|
||||
W3 = 100,
|
||||
W4 = 101,
|
||||
W5 = 102,
|
||||
W6 = 103,
|
||||
W7 = 104,
|
||||
W8 = 105,
|
||||
W9 = 106,
|
||||
W10 = 107,
|
||||
W11 = 108,
|
||||
W12 = 109,
|
||||
W13 = 110,
|
||||
W14 = 111,
|
||||
W15 = 112,
|
||||
W16 = 113,
|
||||
W17 = 114,
|
||||
W18 = 115,
|
||||
W19 = 116,
|
||||
W20 = 117,
|
||||
W21 = 118,
|
||||
W22 = 119,
|
||||
W23 = 120,
|
||||
W24 = 121,
|
||||
W25 = 122,
|
||||
W26 = 123,
|
||||
W27 = 124,
|
||||
W28 = 125,
|
||||
W29 = 126,
|
||||
W30 = 127,
|
||||
W31 = 128,
|
||||
HI = 129,
|
||||
LO = 130,
|
||||
P0 = 131,
|
||||
P1 = 132,
|
||||
P2 = 133,
|
||||
MPL0 = 134,
|
||||
MPL1 = 135,
|
||||
MPL2 = 136,
|
||||
CP0_CONFIG3 = 137,
|
||||
CP0_USERLOCAL = 138,
|
||||
ENDING = 139,
|
||||
|
||||
// alias registers
|
||||
// (assoc) ZERO = 2,
|
||||
// (assoc) AT = 3,
|
||||
// (assoc) V0 = 4,
|
||||
// (assoc) V1 = 5,
|
||||
// (assoc) A0 = 6,
|
||||
// (assoc) A1 = 7,
|
||||
// (assoc) A2 = 8,
|
||||
// (assoc) A3 = 9,
|
||||
// (assoc) T0 = 10,
|
||||
// (assoc) T1 = 11,
|
||||
// (assoc) T2 = 12,
|
||||
// (assoc) T3 = 13,
|
||||
// (assoc) T4 = 14,
|
||||
// (assoc) T5 = 15,
|
||||
// (assoc) T6 = 16,
|
||||
// (assoc) T7 = 17,
|
||||
// (assoc) S0 = 18,
|
||||
// (assoc) S1 = 19,
|
||||
// (assoc) S2 = 20,
|
||||
// (assoc) S3 = 21,
|
||||
// (assoc) S4 = 22,
|
||||
// (assoc) S5 = 23,
|
||||
// (assoc) S6 = 24,
|
||||
// (assoc) S7 = 25,
|
||||
// (assoc) T8 = 26,
|
||||
// (assoc) T9 = 27,
|
||||
// (assoc) K0 = 28,
|
||||
// (assoc) K1 = 29,
|
||||
// (assoc) GP = 30,
|
||||
// (assoc) SP = 31,
|
||||
// (assoc) FP = 32,
|
||||
// (assoc) S8 = 32,
|
||||
// (assoc) RA = 33,
|
||||
// (assoc) HI0 = 45,
|
||||
// (assoc) HI1 = 46,
|
||||
// (assoc) HI2 = 47,
|
||||
// (assoc) HI3 = 48,
|
||||
// (assoc) LO0 = 45,
|
||||
// (assoc) LO1 = 46,
|
||||
// (assoc) LO2 = 47,
|
||||
// (assoc) LO3 = 48,
|
||||
}
|
||||
|
||||
impl RegisterMIPS {
|
||||
pub const ZERO: RegisterMIPS = RegisterMIPS::GPR0;
|
||||
pub const AT: RegisterMIPS = RegisterMIPS::GPR1;
|
||||
pub const V0: RegisterMIPS = RegisterMIPS::GPR2;
|
||||
pub const V1: RegisterMIPS = RegisterMIPS::GPR3;
|
||||
pub const A0: RegisterMIPS = RegisterMIPS::GPR4;
|
||||
pub const A1: RegisterMIPS = RegisterMIPS::GPR5;
|
||||
pub const A2: RegisterMIPS = RegisterMIPS::GPR6;
|
||||
pub const A3: RegisterMIPS = RegisterMIPS::GPR7;
|
||||
pub const T0: RegisterMIPS = RegisterMIPS::GPR8;
|
||||
pub const T1: RegisterMIPS = RegisterMIPS::GPR9;
|
||||
pub const T2: RegisterMIPS = RegisterMIPS::GPR10;
|
||||
pub const T3: RegisterMIPS = RegisterMIPS::GPR11;
|
||||
pub const T4: RegisterMIPS = RegisterMIPS::GPR12;
|
||||
pub const T5: RegisterMIPS = RegisterMIPS::GPR13;
|
||||
pub const T6: RegisterMIPS = RegisterMIPS::GPR14;
|
||||
pub const T7: RegisterMIPS = RegisterMIPS::GPR15;
|
||||
pub const S0: RegisterMIPS = RegisterMIPS::GPR16;
|
||||
pub const S1: RegisterMIPS = RegisterMIPS::GPR17;
|
||||
pub const S2: RegisterMIPS = RegisterMIPS::GPR18;
|
||||
pub const S3: RegisterMIPS = RegisterMIPS::GPR19;
|
||||
pub const S4: RegisterMIPS = RegisterMIPS::GPR20;
|
||||
pub const S5: RegisterMIPS = RegisterMIPS::GPR21;
|
||||
pub const S6: RegisterMIPS = RegisterMIPS::GPR22;
|
||||
pub const S7: RegisterMIPS = RegisterMIPS::GPR23;
|
||||
pub const T8: RegisterMIPS = RegisterMIPS::GPR24;
|
||||
pub const T9: RegisterMIPS = RegisterMIPS::GPR25;
|
||||
pub const K0: RegisterMIPS = RegisterMIPS::GPR26;
|
||||
pub const K1: RegisterMIPS = RegisterMIPS::GPR27;
|
||||
pub const GP: RegisterMIPS = RegisterMIPS::GPR28;
|
||||
pub const SP: RegisterMIPS = RegisterMIPS::GPR29;
|
||||
pub const FP: RegisterMIPS = RegisterMIPS::GPR30;
|
||||
pub const S8: RegisterMIPS = RegisterMIPS::GPR30;
|
||||
pub const RA: RegisterMIPS = RegisterMIPS::GPR31;
|
||||
pub const HI0: RegisterMIPS = RegisterMIPS::AC0;
|
||||
pub const HI1: RegisterMIPS = RegisterMIPS::AC1;
|
||||
pub const HI2: RegisterMIPS = RegisterMIPS::AC2;
|
||||
pub const HI3: RegisterMIPS = RegisterMIPS::AC3;
|
||||
pub const LO0: RegisterMIPS = RegisterMIPS::AC0;
|
||||
pub const LO1: RegisterMIPS = RegisterMIPS::AC1;
|
||||
pub const LO2: RegisterMIPS = RegisterMIPS::AC2;
|
||||
pub const LO3: RegisterMIPS = RegisterMIPS::AC3;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
// PowerPC registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterPPC {
|
||||
INVALID = 0,
|
||||
PC = 1,
|
||||
GPR0 = 2,
|
||||
GPR1 = 3,
|
||||
GPR2 = 4,
|
||||
GPR3 = 5,
|
||||
GPR4 = 6,
|
||||
GPR5 = 7,
|
||||
GPR6 = 8,
|
||||
GPR7 = 9,
|
||||
GPR8 = 10,
|
||||
GPR9 = 11,
|
||||
GPR10 = 12,
|
||||
GPR11 = 13,
|
||||
GPR12 = 14,
|
||||
GPR13 = 15,
|
||||
GPR14 = 16,
|
||||
GPR15 = 17,
|
||||
GPR16 = 18,
|
||||
GPR17 = 19,
|
||||
GPR18 = 20,
|
||||
GPR19 = 21,
|
||||
GPR20 = 22,
|
||||
GPR21 = 23,
|
||||
GPR22 = 24,
|
||||
GPR23 = 25,
|
||||
GPR24 = 26,
|
||||
GPR25 = 27,
|
||||
GPR26 = 28,
|
||||
GPR27 = 29,
|
||||
GPR28 = 30,
|
||||
GPR29 = 31,
|
||||
GPR30 = 32,
|
||||
GPR31 = 33,
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
// SPARC registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterSPARC {
|
||||
INVALID = 0,
|
||||
F0 = 1,
|
||||
F1 = 2,
|
||||
F2 = 3,
|
||||
F3 = 4,
|
||||
F4 = 5,
|
||||
F5 = 6,
|
||||
F6 = 7,
|
||||
F7 = 8,
|
||||
F8 = 9,
|
||||
F9 = 10,
|
||||
F10 = 11,
|
||||
F11 = 12,
|
||||
F12 = 13,
|
||||
F13 = 14,
|
||||
F14 = 15,
|
||||
F15 = 16,
|
||||
F16 = 17,
|
||||
F17 = 18,
|
||||
F18 = 19,
|
||||
F19 = 20,
|
||||
F20 = 21,
|
||||
F21 = 22,
|
||||
F22 = 23,
|
||||
F23 = 24,
|
||||
F24 = 25,
|
||||
F25 = 26,
|
||||
F26 = 27,
|
||||
F27 = 28,
|
||||
F28 = 29,
|
||||
F29 = 30,
|
||||
F30 = 31,
|
||||
F31 = 32,
|
||||
F32 = 33,
|
||||
F34 = 34,
|
||||
F36 = 35,
|
||||
F38 = 36,
|
||||
F40 = 37,
|
||||
F42 = 38,
|
||||
F44 = 39,
|
||||
F46 = 40,
|
||||
F48 = 41,
|
||||
F50 = 42,
|
||||
F52 = 43,
|
||||
F54 = 44,
|
||||
F56 = 45,
|
||||
F58 = 46,
|
||||
F60 = 47,
|
||||
F62 = 48,
|
||||
FCC0 = 49,
|
||||
FCC1 = 50,
|
||||
FCC2 = 51,
|
||||
FCC3 = 52,
|
||||
G0 = 53,
|
||||
G1 = 54,
|
||||
G2 = 55,
|
||||
G3 = 56,
|
||||
G4 = 57,
|
||||
G5 = 58,
|
||||
G6 = 59,
|
||||
G7 = 60,
|
||||
I0 = 61,
|
||||
I1 = 62,
|
||||
I2 = 63,
|
||||
I3 = 64,
|
||||
I4 = 65,
|
||||
I5 = 66,
|
||||
FP = 67,
|
||||
I7 = 68,
|
||||
ICC = 69,
|
||||
L0 = 70,
|
||||
L1 = 71,
|
||||
L2 = 72,
|
||||
L3 = 73,
|
||||
L4 = 74,
|
||||
L5 = 75,
|
||||
L6 = 76,
|
||||
L7 = 77,
|
||||
O0 = 78,
|
||||
O1 = 79,
|
||||
O2 = 80,
|
||||
O3 = 81,
|
||||
O4 = 82,
|
||||
O5 = 83,
|
||||
SP = 84,
|
||||
O7 = 85,
|
||||
Y = 86,
|
||||
XCC = 87,
|
||||
PC = 88,
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
use bitflags::bitflags;
|
||||
|
||||
pub const API_MAJOR: u64 = 1;
|
||||
pub const API_MINOR: u64 = 0;
|
||||
pub const VERSION_MAJOR: u64 = 1;
|
||||
pub const VERSION_MINOR: u64 = 0;
|
||||
pub const VERSION_EXTRA: u64 = 2;
|
||||
pub const SECOND_SCALE: u64 = 1_000_000;
|
||||
pub const MILISECOND_SCALE: u64 = 1_000;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum uc_error {
|
||||
OK = 0,
|
||||
NOMEM = 1,
|
||||
ARCH = 2,
|
||||
HANDLE = 3,
|
||||
MODE = 4,
|
||||
VERSION = 5,
|
||||
READ_UNMAPPED = 6,
|
||||
WRITE_UNMAPPED = 7,
|
||||
FETCH_UNMAPPED = 8,
|
||||
HOOK = 9,
|
||||
INSN_INVALID = 10,
|
||||
MAP = 11,
|
||||
WRITE_PROT = 12,
|
||||
READ_PROT = 13,
|
||||
FETCH_PROT = 14,
|
||||
ARG = 15,
|
||||
READ_UNALIGNED = 16,
|
||||
WRITE_UNALIGNED = 17,
|
||||
FETCH_UNALIGNED = 18,
|
||||
HOOK_EXIST = 19,
|
||||
RESOURCE = 20,
|
||||
EXCEPTION = 21,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum MemType {
|
||||
READ = 16,
|
||||
WRITE = 17,
|
||||
FETCH = 18,
|
||||
READ_UNMAPPED = 19,
|
||||
WRITE_UNMAPPED = 20,
|
||||
FETCH_UNMAPPED = 21,
|
||||
WRITE_PROT = 22,
|
||||
READ_PROT = 23,
|
||||
FETCH_PROT = 24,
|
||||
READ_AFTER = 25,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[repr(C)]
|
||||
pub struct HookType: i32 {
|
||||
const INTR = 1;
|
||||
const INSN = 2;
|
||||
const CODE = 4;
|
||||
const BLOCK = 8;
|
||||
|
||||
const MEM_READ_UNMAPPED = 0x10;
|
||||
const MEM_WRITE_UNMAPPED = 0x20;
|
||||
const MEM_FETCH_UNMAPPED = 0x40;
|
||||
const MEM_UNMAPPED = Self::MEM_READ_UNMAPPED.bits | Self::MEM_WRITE_UNMAPPED.bits | Self::MEM_FETCH_UNMAPPED.bits;
|
||||
|
||||
const MEM_READ_PROT = 0x80;
|
||||
const MEM_WRITE_PROT = 0x100;
|
||||
const MEM_FETCH_PROT = 0x200;
|
||||
const MEM_PROT = Self::MEM_READ_PROT.bits | Self::MEM_WRITE_PROT.bits | Self::MEM_FETCH_PROT.bits;
|
||||
|
||||
const MEM_READ = 0x400;
|
||||
const MEM_WRITE = 0x800;
|
||||
const MEM_FETCH = 0x1000;
|
||||
const MEM_VALID = Self::MEM_READ.bits | Self::MEM_WRITE.bits | Self::MEM_FETCH.bits;
|
||||
|
||||
const MEM_READ_AFTER = 0x2000;
|
||||
|
||||
const INSN_INVALID = 0x4000;
|
||||
|
||||
const MEM_READ_INVALID = Self::MEM_READ_UNMAPPED.bits | Self::MEM_READ_PROT.bits;
|
||||
const MEM_WRITE_INVALID = Self::MEM_WRITE_UNMAPPED.bits | Self::MEM_WRITE_PROT.bits;
|
||||
const MEM_FETCH_INVALID = Self::MEM_FETCH_UNMAPPED.bits | Self::MEM_FETCH_PROT.bits;
|
||||
const MEM_INVALID = Self::MEM_READ_INVALID.bits | Self::MEM_WRITE_INVALID.bits | Self::MEM_FETCH_INVALID.bits;
|
||||
|
||||
const MEM_ALL = Self::MEM_VALID.bits | Self::MEM_INVALID.bits;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum Query {
|
||||
MODE = 1,
|
||||
PAGE_SIZE = 2,
|
||||
ARCH = 3,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[repr(C)]
|
||||
pub struct Permission : u32 {
|
||||
const NONE = 0;
|
||||
const READ = 1;
|
||||
const WRITE = 2;
|
||||
const EXEC = 4;
|
||||
const ALL = Self::READ.bits | Self::WRITE.bits | Self::EXEC.bits;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MemRegion {
|
||||
pub begin: u64,
|
||||
pub end: u64,
|
||||
pub perms: Permission,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum Arch {
|
||||
ARM = 1,
|
||||
ARM64 = 2,
|
||||
MIPS = 3,
|
||||
X86 = 4,
|
||||
PPC = 5,
|
||||
SPARC = 6,
|
||||
M68K = 7,
|
||||
MAX = 8,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[repr(C)]
|
||||
pub struct Mode: i32 {
|
||||
const LITTLE_ENDIAN = 0;
|
||||
const BIG_ENDIAN = 0x4000_0000;
|
||||
|
||||
const ARM = 0;
|
||||
const THUMB = 0x10;
|
||||
const MCLASS = 0x20;
|
||||
const V8 = 0x40;
|
||||
const ARM926 = 0x80;
|
||||
const ARM946 = 0x100;
|
||||
const ARM1176 = 0x200;
|
||||
const MICRO = Self::THUMB.bits;
|
||||
const MIPS3 = Self::MCLASS.bits;
|
||||
const MIPS32R6 = Self::V8.bits;
|
||||
const MIPS32 = 4;
|
||||
const MIPS64 = 8;
|
||||
const MODE_16 = 2;
|
||||
const MODE_32 = Self::MIPS32.bits;
|
||||
const MODE_64 = Self::MIPS64.bits;
|
||||
const PPC32 = Self::MIPS32.bits;
|
||||
const PPC64 = Self::MIPS64.bits;
|
||||
const QPX = Self::THUMB.bits;
|
||||
const SPARC32 = Self::MIPS32.bits;
|
||||
const SPARC64 = Self::MIPS64.bits;
|
||||
const V9 = Self::THUMB.bits;
|
||||
}
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
// X86 registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterX86 {
|
||||
INVALID = 0,
|
||||
AH,
|
||||
AL,
|
||||
AX,
|
||||
BH,
|
||||
BL,
|
||||
BP,
|
||||
BPL,
|
||||
BX,
|
||||
CH,
|
||||
CL,
|
||||
CS,
|
||||
CX,
|
||||
DH,
|
||||
DI,
|
||||
DIL,
|
||||
DL,
|
||||
DS,
|
||||
DX,
|
||||
EAX,
|
||||
EBP,
|
||||
EBX,
|
||||
ECX,
|
||||
EDI,
|
||||
EDX,
|
||||
EFLAGS,
|
||||
EIP,
|
||||
EIZ,
|
||||
ES,
|
||||
ESI,
|
||||
ESP,
|
||||
FPSW,
|
||||
FS,
|
||||
GS,
|
||||
IP,
|
||||
RAX,
|
||||
RBP,
|
||||
RBX,
|
||||
RCX,
|
||||
RDI,
|
||||
RDX,
|
||||
RIP,
|
||||
RIZ,
|
||||
RSI,
|
||||
RSP,
|
||||
SI,
|
||||
SIL,
|
||||
SP,
|
||||
SPL,
|
||||
SS,
|
||||
CR0,
|
||||
CR1,
|
||||
CR2,
|
||||
CR3,
|
||||
CR4,
|
||||
CR5,
|
||||
CR6,
|
||||
CR7,
|
||||
CR8,
|
||||
CR9,
|
||||
CR10,
|
||||
CR11,
|
||||
CR12,
|
||||
CR13,
|
||||
CR14,
|
||||
CR15,
|
||||
DR0,
|
||||
DR1,
|
||||
DR2,
|
||||
DR3,
|
||||
DR4,
|
||||
DR5,
|
||||
DR6,
|
||||
DR7,
|
||||
DR8,
|
||||
DR9,
|
||||
DR10,
|
||||
DR11,
|
||||
DR12,
|
||||
DR13,
|
||||
DR14,
|
||||
DR15,
|
||||
FP0,
|
||||
FP1,
|
||||
FP2,
|
||||
FP3,
|
||||
FP4,
|
||||
FP5,
|
||||
FP6,
|
||||
FP7,
|
||||
K0,
|
||||
K1,
|
||||
K2,
|
||||
K3,
|
||||
K4,
|
||||
K5,
|
||||
K6,
|
||||
K7,
|
||||
MM0,
|
||||
MM1,
|
||||
MM2,
|
||||
MM3,
|
||||
MM4,
|
||||
MM5,
|
||||
MM6,
|
||||
MM7,
|
||||
R8,
|
||||
R9,
|
||||
R10,
|
||||
R11,
|
||||
R12,
|
||||
R13,
|
||||
R14,
|
||||
R15,
|
||||
ST0,
|
||||
ST1,
|
||||
ST2,
|
||||
ST3,
|
||||
ST4,
|
||||
ST5,
|
||||
ST6,
|
||||
ST7,
|
||||
XMM0,
|
||||
XMM1,
|
||||
XMM2,
|
||||
XMM3,
|
||||
XMM4,
|
||||
XMM5,
|
||||
XMM6,
|
||||
XMM7,
|
||||
XMM8,
|
||||
XMM9,
|
||||
XMM10,
|
||||
XMM11,
|
||||
XMM12,
|
||||
XMM13,
|
||||
XMM14,
|
||||
XMM15,
|
||||
XMM16,
|
||||
XMM17,
|
||||
XMM18,
|
||||
XMM19,
|
||||
XMM20,
|
||||
XMM21,
|
||||
XMM22,
|
||||
XMM23,
|
||||
XMM24,
|
||||
XMM25,
|
||||
XMM26,
|
||||
XMM27,
|
||||
XMM28,
|
||||
XMM29,
|
||||
XMM30,
|
||||
XMM31,
|
||||
YMM0,
|
||||
YMM1,
|
||||
YMM2,
|
||||
YMM3,
|
||||
YMM4,
|
||||
YMM5,
|
||||
YMM6,
|
||||
YMM7,
|
||||
YMM8,
|
||||
YMM9,
|
||||
YMM10,
|
||||
YMM11,
|
||||
YMM12,
|
||||
YMM13,
|
||||
YMM14,
|
||||
YMM15,
|
||||
YMM16,
|
||||
YMM17,
|
||||
YMM18,
|
||||
YMM19,
|
||||
YMM20,
|
||||
YMM21,
|
||||
YMM22,
|
||||
YMM23,
|
||||
YMM24,
|
||||
YMM25,
|
||||
YMM26,
|
||||
YMM27,
|
||||
YMM28,
|
||||
YMM29,
|
||||
YMM30,
|
||||
YMM31,
|
||||
ZMM0,
|
||||
ZMM1,
|
||||
ZMM2,
|
||||
ZMM3,
|
||||
ZMM4,
|
||||
ZMM5,
|
||||
ZMM6,
|
||||
ZMM7,
|
||||
ZMM8,
|
||||
ZMM9,
|
||||
ZMM10,
|
||||
ZMM11,
|
||||
ZMM12,
|
||||
ZMM13,
|
||||
ZMM14,
|
||||
ZMM15,
|
||||
ZMM16,
|
||||
ZMM17,
|
||||
ZMM18,
|
||||
ZMM19,
|
||||
ZMM20,
|
||||
ZMM21,
|
||||
ZMM22,
|
||||
ZMM23,
|
||||
ZMM24,
|
||||
ZMM25,
|
||||
ZMM26,
|
||||
ZMM27,
|
||||
ZMM28,
|
||||
ZMM29,
|
||||
ZMM30,
|
||||
ZMM31,
|
||||
R8B,
|
||||
R9B,
|
||||
R10B,
|
||||
R11B,
|
||||
R12B,
|
||||
R13B,
|
||||
R14B,
|
||||
R15B,
|
||||
R8D,
|
||||
R9D,
|
||||
R10D,
|
||||
R11D,
|
||||
R12D,
|
||||
R13D,
|
||||
R14D,
|
||||
R15D,
|
||||
R8W,
|
||||
R9W,
|
||||
R10W,
|
||||
R11W,
|
||||
R12W,
|
||||
R13W,
|
||||
R14W,
|
||||
R15W,
|
||||
IDTR,
|
||||
GDTR,
|
||||
LDTR,
|
||||
TR,
|
||||
FPCW,
|
||||
FPTAG,
|
||||
MSR,
|
||||
MXCSR,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum InsnX86 {
|
||||
IN = 218,
|
||||
OUT = 500,
|
||||
SYSCALL = 699,
|
||||
SYSENTER = 700,
|
||||
RET = 151,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum InsnSysX86 {
|
||||
SYSCALL = InsnX86::SYSCALL as isize,
|
||||
SYSENTER = InsnX86::SYSENTER as isize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub struct X86Mmr {
|
||||
pub selector: u64,
|
||||
pub base: u64,
|
||||
pub limit: u32,
|
||||
pub flags: u32,
|
||||
}
|
||||
@@ -1,683 +0,0 @@
|
||||
#![deny(rust_2018_idioms)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use unicorn::unicorn_const::{uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE};
|
||||
use unicorn::{InsnSysX86, RegisterARM, RegisterMIPS, RegisterPPC, RegisterX86};
|
||||
|
||||
pub static X86_REGISTERS: [RegisterX86; 145] = [
|
||||
RegisterX86::AH,
|
||||
RegisterX86::AL,
|
||||
RegisterX86::AX,
|
||||
RegisterX86::BH,
|
||||
RegisterX86::BL,
|
||||
RegisterX86::BP,
|
||||
RegisterX86::BPL,
|
||||
RegisterX86::BX,
|
||||
RegisterX86::CH,
|
||||
RegisterX86::CL,
|
||||
RegisterX86::CS,
|
||||
RegisterX86::CX,
|
||||
RegisterX86::DH,
|
||||
RegisterX86::DI,
|
||||
RegisterX86::DIL,
|
||||
RegisterX86::DL,
|
||||
RegisterX86::DS,
|
||||
RegisterX86::DX,
|
||||
RegisterX86::EAX,
|
||||
RegisterX86::EBP,
|
||||
RegisterX86::EBX,
|
||||
RegisterX86::ECX,
|
||||
RegisterX86::EDI,
|
||||
RegisterX86::EDX,
|
||||
RegisterX86::EFLAGS,
|
||||
RegisterX86::EIP,
|
||||
RegisterX86::EIZ,
|
||||
RegisterX86::ES,
|
||||
RegisterX86::ESI,
|
||||
RegisterX86::ESP,
|
||||
RegisterX86::FPSW,
|
||||
RegisterX86::FS,
|
||||
RegisterX86::GS,
|
||||
RegisterX86::IP,
|
||||
RegisterX86::RAX,
|
||||
RegisterX86::RBP,
|
||||
RegisterX86::RBX,
|
||||
RegisterX86::RCX,
|
||||
RegisterX86::RDI,
|
||||
RegisterX86::RDX,
|
||||
RegisterX86::RIP,
|
||||
RegisterX86::RIZ,
|
||||
RegisterX86::RSI,
|
||||
RegisterX86::RSP,
|
||||
RegisterX86::SI,
|
||||
RegisterX86::SIL,
|
||||
RegisterX86::SP,
|
||||
RegisterX86::SPL,
|
||||
RegisterX86::SS,
|
||||
RegisterX86::CR0,
|
||||
RegisterX86::CR1,
|
||||
RegisterX86::CR2,
|
||||
RegisterX86::CR3,
|
||||
RegisterX86::CR4,
|
||||
RegisterX86::CR5,
|
||||
RegisterX86::CR6,
|
||||
RegisterX86::CR7,
|
||||
RegisterX86::CR8,
|
||||
RegisterX86::CR9,
|
||||
RegisterX86::CR10,
|
||||
RegisterX86::CR11,
|
||||
RegisterX86::CR12,
|
||||
RegisterX86::CR13,
|
||||
RegisterX86::CR14,
|
||||
RegisterX86::CR15,
|
||||
RegisterX86::DR0,
|
||||
RegisterX86::DR1,
|
||||
RegisterX86::DR2,
|
||||
RegisterX86::DR3,
|
||||
RegisterX86::DR4,
|
||||
RegisterX86::DR5,
|
||||
RegisterX86::DR6,
|
||||
RegisterX86::DR7,
|
||||
RegisterX86::DR8,
|
||||
RegisterX86::DR9,
|
||||
RegisterX86::DR10,
|
||||
RegisterX86::DR11,
|
||||
RegisterX86::DR12,
|
||||
RegisterX86::DR13,
|
||||
RegisterX86::DR14,
|
||||
RegisterX86::DR15,
|
||||
RegisterX86::FP0,
|
||||
RegisterX86::FP1,
|
||||
RegisterX86::FP2,
|
||||
RegisterX86::FP3,
|
||||
RegisterX86::FP4,
|
||||
RegisterX86::FP5,
|
||||
RegisterX86::FP6,
|
||||
RegisterX86::FP7,
|
||||
RegisterX86::K0,
|
||||
RegisterX86::K1,
|
||||
RegisterX86::K2,
|
||||
RegisterX86::K3,
|
||||
RegisterX86::K4,
|
||||
RegisterX86::K5,
|
||||
RegisterX86::K6,
|
||||
RegisterX86::K7,
|
||||
RegisterX86::MM0,
|
||||
RegisterX86::MM1,
|
||||
RegisterX86::MM2,
|
||||
RegisterX86::MM3,
|
||||
RegisterX86::MM4,
|
||||
RegisterX86::MM5,
|
||||
RegisterX86::MM6,
|
||||
RegisterX86::MM7,
|
||||
RegisterX86::R8,
|
||||
RegisterX86::R9,
|
||||
RegisterX86::R10,
|
||||
RegisterX86::R11,
|
||||
RegisterX86::R12,
|
||||
RegisterX86::R13,
|
||||
RegisterX86::R14,
|
||||
RegisterX86::R15,
|
||||
RegisterX86::ST0,
|
||||
RegisterX86::ST1,
|
||||
RegisterX86::ST2,
|
||||
RegisterX86::ST3,
|
||||
RegisterX86::ST4,
|
||||
RegisterX86::ST5,
|
||||
RegisterX86::ST6,
|
||||
RegisterX86::ST7,
|
||||
RegisterX86::R8B,
|
||||
RegisterX86::R9B,
|
||||
RegisterX86::R10B,
|
||||
RegisterX86::R11B,
|
||||
RegisterX86::R12B,
|
||||
RegisterX86::R13B,
|
||||
RegisterX86::R14B,
|
||||
RegisterX86::R15B,
|
||||
RegisterX86::R8D,
|
||||
RegisterX86::R9D,
|
||||
RegisterX86::R10D,
|
||||
RegisterX86::R11D,
|
||||
RegisterX86::R12D,
|
||||
RegisterX86::R13D,
|
||||
RegisterX86::R14D,
|
||||
RegisterX86::R15D,
|
||||
RegisterX86::R8W,
|
||||
RegisterX86::R9W,
|
||||
RegisterX86::R10W,
|
||||
RegisterX86::R11W,
|
||||
RegisterX86::R12W,
|
||||
RegisterX86::R13W,
|
||||
RegisterX86::R14W,
|
||||
RegisterX86::R15W,
|
||||
];
|
||||
|
||||
type Unicorn<'a> = unicorn::UnicornHandle<'a>;
|
||||
|
||||
#[test]
|
||||
fn emulate_x86() {
|
||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.reg_write(RegisterX86::EAX as i32, 123), Ok(()));
|
||||
assert_eq!(emu.reg_read(RegisterX86::EAX as i32), Ok(123));
|
||||
|
||||
// Attempt to write to memory before mapping it.
|
||||
assert_eq!(
|
||||
emu.mem_write(0x1000, &x86_code32),
|
||||
(Err(uc_error::WRITE_UNMAPPED))
|
||||
);
|
||||
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mem_read_as_vec(0x1000, x86_code32.len()),
|
||||
Ok(x86_code32.clone())
|
||||
);
|
||||
|
||||
assert_eq!(emu.reg_write(RegisterX86::ECX as i32, 10), Ok(()));
|
||||
assert_eq!(emu.reg_write(RegisterX86::EDX as i32, 50), Ok(()));
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
(0x1000 + x86_code32.len()) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.reg_read(RegisterX86::ECX as i32), Ok(11));
|
||||
assert_eq!(emu.reg_read(RegisterX86::EDX as i32), Ok(49));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_code_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct CodeExpectation(u64, u32);
|
||||
let expects = vec![CodeExpectation(0x1000, 1), CodeExpectation(0x1001, 1)];
|
||||
let codes: Vec<CodeExpectation> = Vec::new();
|
||||
let codes_cell = Rc::new(RefCell::new(codes));
|
||||
|
||||
let callback_codes = codes_cell.clone();
|
||||
let callback = move |_: Unicorn<'_>, address: u64, size: u32| {
|
||||
let mut codes = callback_codes.borrow_mut();
|
||||
codes.push(CodeExpectation(address, size));
|
||||
};
|
||||
|
||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_code_hook(0x1000, 0x2000, callback)
|
||||
.expect("failed to add code hook");
|
||||
assert_eq!(
|
||||
emu.emu_start(0x1000, 0x1002, 10 * SECOND_SCALE, 1000),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(expects, *codes_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_intr_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct IntrExpectation(u32);
|
||||
let expect = IntrExpectation(0x80);
|
||||
let intr_cell = Rc::new(RefCell::new(IntrExpectation(0)));
|
||||
|
||||
let callback_intr = intr_cell.clone();
|
||||
let callback = move |_: Unicorn<'_>, intno: u32| {
|
||||
*callback_intr.borrow_mut() = IntrExpectation(intno);
|
||||
};
|
||||
|
||||
let x86_code32: Vec<u8> = vec![0xcd, 0x80]; // INT 0x80;
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_intr_hook(callback)
|
||||
.expect("failed to add intr hook");
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
0x1000 + x86_code32.len() as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(expect, *intr_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_mem_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct MemExpectation(MemType, u64, usize, i64);
|
||||
let expects = vec![
|
||||
MemExpectation(MemType::WRITE, 0x2000, 4, 0xdeadbeef),
|
||||
MemExpectation(MemType::READ_UNMAPPED, 0x10000, 4, 0),
|
||||
MemExpectation(MemType::READ, 0x10000, 4, 0),
|
||||
];
|
||||
let mems: Vec<MemExpectation> = Vec::new();
|
||||
let mems_cell = Rc::new(RefCell::new(mems));
|
||||
|
||||
let callback_mems = mems_cell.clone();
|
||||
let callback =
|
||||
move |_: Unicorn<'_>, mem_type: MemType, address: u64, size: usize, value: i64| {
|
||||
let mut mems = callback_mems.borrow_mut();
|
||||
mems.push(MemExpectation(mem_type, address, size, value));
|
||||
};
|
||||
|
||||
// mov eax, 0xdeadbeef;
|
||||
// mov [0x2000], eax;
|
||||
// mov eax, [0x10000];
|
||||
let x86_code32: Vec<u8> = vec![
|
||||
0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xA3, 0x00, 0x20, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x01, 0x00,
|
||||
];
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_mem_hook(HookType::MEM_ALL, 0, std::u64::MAX, callback)
|
||||
.expect("failed to add memory hook");
|
||||
assert_eq!(emu.reg_write(RegisterX86::EAX as i32, 0x123), Ok(()));
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
0x1000 + x86_code32.len() as u64,
|
||||
10 * SECOND_SCALE,
|
||||
0x1000
|
||||
),
|
||||
Err(uc_error::READ_UNMAPPED)
|
||||
);
|
||||
|
||||
assert_eq!(expects, *mems_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_insn_in_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct InsnInExpectation(u32, usize);
|
||||
let expect = InsnInExpectation(0x10, 4);
|
||||
let insn_cell = Rc::new(RefCell::new(InsnInExpectation(0, 0)));
|
||||
|
||||
let callback_insn = insn_cell.clone();
|
||||
let callback = move |_: Unicorn<'_>, port: u32, size: usize| {
|
||||
*callback_insn.borrow_mut() = InsnInExpectation(port, size);
|
||||
};
|
||||
|
||||
let x86_code32: Vec<u8> = vec![0xe5, 0x10]; // IN eax, 0x10;
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_insn_in_hook(callback)
|
||||
.expect("failed to add in hook");
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
0x1000 + x86_code32.len() as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(expect, *insn_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_insn_out_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct InsnOutExpectation(u32, usize, u32);
|
||||
let expect = InsnOutExpectation(0x46, 1, 0x32);
|
||||
let insn_cell = Rc::new(RefCell::new(InsnOutExpectation(0, 0, 0)));
|
||||
|
||||
let callback_insn = insn_cell.clone();
|
||||
let callback = move |_: Unicorn<'_>, port: u32, size: usize, value: u32| {
|
||||
*callback_insn.borrow_mut() = InsnOutExpectation(port, size, value);
|
||||
};
|
||||
|
||||
let x86_code32: Vec<u8> = vec![0xb0, 0x32, 0xe6, 0x46]; // MOV al, 0x32; OUT 0x46, al;
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_insn_out_hook(callback)
|
||||
.expect("failed to add out hook");
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
0x1000 + x86_code32.len() as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(expect, *insn_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_insn_sys_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct InsnSysExpectation(u64);
|
||||
let expect = InsnSysExpectation(0xdeadbeef);
|
||||
let insn_cell = Rc::new(RefCell::new(InsnSysExpectation(0)));
|
||||
|
||||
let callback_insn = insn_cell.clone();
|
||||
let callback = move |uc: Unicorn<'_>| {
|
||||
println!("!!!!");
|
||||
let rax = uc.reg_read(RegisterX86::RAX as i32).unwrap();
|
||||
*callback_insn.borrow_mut() = InsnSysExpectation(rax);
|
||||
};
|
||||
|
||||
// MOV rax, 0xdeadbeef; SYSCALL;
|
||||
let x86_code: Vec<u8> = vec![
|
||||
0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05,
|
||||
];
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_64)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_insn_sys_hook(InsnSysX86::SYSCALL, 1, 0, callback)
|
||||
.expect("failed to add syscall hook");
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
0x1000 + x86_code.len() as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(expect, *insn_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emulate_arm() {
|
||||
let arm_code32: Vec<u8> = vec![0x83, 0xb0]; // sub sp, #0xc
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::THUMB)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.reg_write(RegisterARM::R1 as i32, 123), Ok(()));
|
||||
assert_eq!(emu.reg_read(RegisterARM::R1 as i32), Ok(123));
|
||||
|
||||
// Attempt to write to memory before mapping it.
|
||||
assert_eq!(
|
||||
emu.mem_write(0x1000, &arm_code32),
|
||||
(Err(uc_error::WRITE_UNMAPPED))
|
||||
);
|
||||
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &arm_code32), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mem_read_as_vec(0x1000, arm_code32.len()),
|
||||
Ok(arm_code32.clone())
|
||||
);
|
||||
|
||||
assert_eq!(emu.reg_write(RegisterARM::SP as i32, 12), Ok(()));
|
||||
assert_eq!(emu.reg_write(RegisterARM::R0 as i32, 10), Ok(()));
|
||||
|
||||
// ARM checks the least significant bit of the address to know
|
||||
// if the code is in Thumb mode.
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000 | 0x01,
|
||||
(0x1000 | (0x01 + arm_code32.len())) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.reg_read(RegisterARM::SP as i32), Ok(0));
|
||||
assert_eq!(emu.reg_read(RegisterARM::R0 as i32), Ok(10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emulate_mips() {
|
||||
let mips_code32 = vec![0x56, 0x34, 0x21, 0x34]; // ori $at, $at, 0x3456;
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::MIPS, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &mips_code32), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mem_read_as_vec(0x1000, mips_code32.len()),
|
||||
Ok(mips_code32.clone())
|
||||
);
|
||||
assert_eq!(emu.reg_write(RegisterMIPS::AT as i32, 0), Ok(()));
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
(0x1000 + mips_code32.len()) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.reg_read(RegisterMIPS::AT as i32), Ok(0x3456));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emulate_ppc() {
|
||||
let ppc_code32 = vec![0x7F, 0x46, 0x1A, 0x14]; // add 26, 6, 3
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::PPC, Mode::PPC32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &ppc_code32), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mem_read_as_vec(0x1000, ppc_code32.len()),
|
||||
Ok(ppc_code32.clone())
|
||||
);
|
||||
assert_eq!(emu.reg_write(RegisterPPC::GPR3 as i32, 42), Ok(()));
|
||||
assert_eq!(emu.reg_write(RegisterPPC::GPR6 as i32, 1337), Ok(()));
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
(0x1000 + ppc_code32.len()) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.reg_read(RegisterPPC::GPR26 as i32), Ok(1379));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mem_unmapping() {
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_unmap(0x1000, 0x4000), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mem_map_ptr() {
|
||||
// Use an array for the emulator memory.
|
||||
let mut mem: [u8; 4000] = [0; 4000];
|
||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
|
||||
// Attempt to write to memory before mapping it.
|
||||
assert_eq!(
|
||||
emu.mem_write(0x1000, &x86_code32),
|
||||
(Err(uc_error::WRITE_UNMAPPED))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
emu.mem_map_ptr(0x1000, 0x4000, Permission::ALL, mem.as_mut_ptr() as _),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mem_read_as_vec(0x1000, x86_code32.len()),
|
||||
Ok(x86_code32.clone())
|
||||
);
|
||||
|
||||
assert_eq!(emu.reg_write(RegisterX86::ECX as i32, 10), Ok(()));
|
||||
assert_eq!(emu.reg_write(RegisterX86::EDX as i32, 50), Ok(()));
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
(0x1000 + x86_code32.len()) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.reg_read(RegisterX86::ECX as i32), Ok(11));
|
||||
assert_eq!(emu.reg_read(RegisterX86::EDX as i32), Ok(49));
|
||||
assert_eq!(emu.mem_unmap(0x1000, 0x4000), Ok(()));
|
||||
|
||||
// Use a Vec for the emulator memory.
|
||||
let mut mem: Vec<u8> = Vec::new();
|
||||
mem.reserve(4000);
|
||||
|
||||
// Attempt to write to memory before mapping it.
|
||||
assert_eq!(
|
||||
emu.mem_write(0x1000, &x86_code32),
|
||||
(Err(uc_error::WRITE_UNMAPPED))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
emu.mem_map_ptr(0x1000, 0x4000, Permission::ALL, mem.as_mut_ptr() as _),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mem_read_as_vec(0x1000, x86_code32.len()),
|
||||
Ok(x86_code32.clone())
|
||||
);
|
||||
|
||||
assert_eq!(emu.reg_write(RegisterX86::ECX as i32, 10), Ok(()));
|
||||
assert_eq!(emu.reg_write(RegisterX86::EDX as i32, 50), Ok(()));
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
0x1000,
|
||||
(0x1000 + x86_code32.len()) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000
|
||||
),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(emu.reg_read(RegisterX86::ECX as i32), Ok(11));
|
||||
assert_eq!(emu.reg_read(RegisterX86::EDX as i32), Ok(49));
|
||||
assert_eq!(emu.mem_unmap(0x1000, 0x4000), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_context_save_and_restore() {
|
||||
for mode in vec![Mode::MODE_32, Mode::MODE_64] {
|
||||
let x86_code: Vec<u8> = vec![
|
||||
0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05,
|
||||
];
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, mode)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code), Ok(()));
|
||||
let _ = emu.emu_start(
|
||||
0x1000,
|
||||
(0x1000 + x86_code.len()) as u64,
|
||||
10 * SECOND_SCALE,
|
||||
1000,
|
||||
);
|
||||
|
||||
/* now, save the context... */
|
||||
let context = emu.context_init();
|
||||
let context = context.unwrap();
|
||||
|
||||
/* and create a new emulator, into which we will "restore" that context */
|
||||
let mut unicorn2 = unicorn::Unicorn::new(Arch::X86, mode)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let emu2 = unicorn2.borrow();
|
||||
assert_eq!(emu2.context_restore(&context), Ok(()));
|
||||
for register in X86_REGISTERS.iter() {
|
||||
println!("Testing register {:?}", register);
|
||||
assert_eq!(
|
||||
emu2.reg_read(*register as i32),
|
||||
emu.reg_read(*register as i32)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x86_block_callback() {
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct BlockExpectation(u64, u32);
|
||||
let expects = vec![BlockExpectation(0x1000, 2), BlockExpectation(0x1000, 2)];
|
||||
let blocks: Vec<BlockExpectation> = Vec::new();
|
||||
let blocks_cell = Rc::new(RefCell::new(blocks));
|
||||
|
||||
let callback_blocks = blocks_cell.clone();
|
||||
let callback = move |_: Unicorn<'_>, address: u64, size: u32| {
|
||||
let mut blocks = callback_blocks.borrow_mut();
|
||||
blocks.push(BlockExpectation(address, size));
|
||||
};
|
||||
|
||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
||||
|
||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
||||
.expect("failed to initialize unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
||||
|
||||
let hook = emu
|
||||
.add_block_hook(callback)
|
||||
.expect("failed to add block hook");
|
||||
assert_eq!(
|
||||
emu.emu_start(0x1000, 0x1002, 10 * SECOND_SCALE, 1000),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(expects, *blocks_cell.borrow());
|
||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
||||
}
|
||||
@@ -59,7 +59,8 @@ Public Enum uc_arch
|
||||
UC_ARCH_PPC = 5 ' PowerPC architecture (currently unsupported)
|
||||
UC_ARCH_SPARC = 6 ' Sparc architecture
|
||||
UC_ARCH_M68K = 7 ' M68K architecture
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_RISCV = 8 ' RISCV architecture
|
||||
UC_ARCH_MAX = 9
|
||||
End Enum
|
||||
|
||||
Public Enum uc_prot
|
||||
@@ -130,6 +131,8 @@ Public Enum uc_mode 'from /bindings/dotnet/common.fs
|
||||
' UC_MODE_SPARC32 = 4 '32-bit mode
|
||||
' UC_MODE_SPARC64 = 8 '64-bit mode
|
||||
' UC_MODE_V9 = 16 'SparcV9 mode (currently unsupported)
|
||||
' UC_MODE_RISCV32 = 4 '32-bit mode
|
||||
' UC_MODE_RISCV64 = 8 '64-bit mode
|
||||
End Enum
|
||||
|
||||
Public Enum uc_hook_type 'from /bindings/dotnet/common.fs
|
||||
|
||||
Reference in New Issue
Block a user