diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..04e13156 --- /dev/null +++ b/.clang-format @@ -0,0 +1,16 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +UseTab: Never +BreakBeforeBraces: Linux +AllowShortIfStatementsOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortFunctionsOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +IndentCaseLabels: false +ColumnLimit: 80 +SortIncludes: false +AllowShortLambdasOnASingleLine: Inline +AlwaysBreakBeforeMultilineStrings: false +BreakStringLiterals: true +PointerAlignment: Right diff --git a/.github/workflows/Crate-publishing.yml b/.github/workflows/Crate-publishing.yml index fcd5552b..bcbd2cb1 100644 --- a/.github/workflows/Crate-publishing.yml +++ b/.github/workflows/Crate-publishing.yml @@ -15,7 +15,7 @@ on: pull_request: env: - CI: true + UNICORN_VERSION: dev jobs: build: diff --git a/CMakeLists.txt b/CMakeLists.txt index d6fb9bf2..88e428d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1108,6 +1108,11 @@ if (UNICORN_HAS_RISCV) set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_riscv) endif() +# Extra tests +set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_mem) +set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_ctl) +set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_ctl) + target_compile_options(unicorn PRIVATE ${UNICORN_COMPILE_OPTIONS} ) diff --git a/bindings/Makefile b/bindings/Makefile index 296b44f3..bc5fb243 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -24,8 +24,8 @@ build: $(MAKE) -C go gen_const $(MAKE) -C java gen_const $(MAKE) -C ruby gen_const - python const_generator.py dotnet - python const_generator.py pascal + python3 const_generator.py dotnet + python3 const_generator.py pascal install: build $(MAKE) -C python install @@ -40,7 +40,7 @@ python: %.c.txt: c $(ENV_VARS) ../samples/$(@:%.c.txt=%) > $@ %.py.txt: python - $(ENV_VARS) python python/$(@:%.txt=%) > $@ + $(ENV_VARS) python3 python/$(@:%.txt=%) > $@ %.py.test: %.c.txt %.py.txt $(DIFF) -u $(@:%.py.test=%.c.txt) $(@:%.py.test=%.py.txt) diff --git a/bindings/const_generator.py b/bindings/const_generator.py index 30b870d8..64c518a8 100644 --- a/bindings/const_generator.py +++ b/bindings/const_generator.py @@ -136,7 +136,20 @@ def gen(lang): previous = {} count = 0 - for line in lines: + skip = 0 + in_comment = False + + for lno, line in enumerate(lines): + if "/*" in line: + in_comment = True + if "*/" in line: + in_comment = False + if in_comment: + continue + if skip > 0: + # Due to clang-format, values may come up in the next line + skip -= 1 + continue line = line.strip() if line.startswith(MARKUP): # markup for comments @@ -148,6 +161,8 @@ def gen(lang): continue tmp = line.strip().split(',') + if len(tmp) >= 2 and tmp[0] != "#define" and not tmp[0].startswith("UC_"): + continue for t in tmp: t = t.strip() if not t or t.startswith('//'): continue @@ -159,18 +174,52 @@ def gen(lang): define = True f.pop(0) f.insert(1, '=') - - if f[0].startswith("UC_" + prefix.upper()): + if f[0].startswith("UC_" + prefix.upper()) or f[0].startswith("UC_CPU"): if len(f) > 1 and f[1] not in ('//', '='): print("WARNING: Unable to convert %s" % f) print(" Line =", line) continue elif len(f) > 1 and f[1] == '=': - rhs = ''.join(f[2:]) + # Like: + # UC_A = + # (1 << 2) + # #define UC_B \ + # (UC_A | UC_C) + # Let's search the next line + if len(f) == 2: + if lno == len(lines) - 1: + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + skip += 1 + next_line = lines[lno + 1] + next_line_tmp = next_line.strip().split(",") + rhs = next_line_tmp[0] + elif f[-1] == "\\": + idx = 0 + rhs = "" + while True: + idx += 1 + if lno + idx == len(lines): + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + skip += 1 + next_line = lines[lno + idx] + next_line_f = re.split('\s+', next_line.strip()) + if next_line_f[-1] == "\\": + rhs += "".join(next_line_f[:-1]) + else: + rhs += next_line.strip() + break + else: + rhs = ''.join(f[2:]) else: rhs = str(count) + lhs = f[0].strip() + #print(f'lhs: {lhs} rhs: {rhs} f:{f}') # evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1" match = re.match(r'(?P\s*\d+\s*<<\s*\d+\s*)', rhs) if match: diff --git a/bindings/dotnet/UnicornManaged/Const/Arm.fs b/bindings/dotnet/UnicornManaged/Const/Arm.fs index 76deda67..d0e039fe 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm.fs @@ -7,6 +7,40 @@ open System [] module Arm = + let UC_CPU_ARM_926 = 0 + let UC_CPU_ARM_946 = 1 + let UC_CPU_ARM_1026 = 2 + let UC_CPU_ARM_1136_R2 = 3 + let UC_CPU_ARM_1136 = 4 + let UC_CPU_ARM_1176 = 5 + let UC_CPU_ARM_11MPCORE = 6 + let UC_CPU_ARM_CORTEX_M0 = 7 + let UC_CPU_ARM_CORTEX_M3 = 8 + let UC_CPU_ARM_CORTEX_M4 = 9 + let UC_CPU_ARM_CORTEX_M7 = 10 + let UC_CPU_ARM_CORTEX_M33 = 11 + let UC_CPU_ARM_CORTEX_R5 = 12 + let UC_CPU_ARM_CORTEX_R5F = 13 + let UC_CPU_ARM_CORTEX_A8 = 14 + let UC_CPU_ARM_CORTEX_A9 = 15 + let UC_CPU_ARM_CORTEX_A7 = 16 + let UC_CPU_ARM_CORTEX_A15 = 17 + let UC_CPU_ARM_TI925T = 18 + let UC_CPU_ARM_SA1100 = 19 + let UC_CPU_ARM_SA1110 = 20 + let UC_CPU_ARM_PXA250 = 21 + let UC_CPU_ARM_PXA255 = 22 + let UC_CPU_ARM_PXA260 = 23 + let UC_CPU_ARM_PXA261 = 24 + let UC_CPU_ARM_PXA262 = 25 + let UC_CPU_ARM_PXA270A0 = 26 + let UC_CPU_ARM_PXA270A1 = 27 + let UC_CPU_ARM_PXA270B0 = 28 + let UC_CPU_ARM_PXA270B1 = 29 + let UC_CPU_ARM_PXA270C0 = 30 + let UC_CPU_ARM_PXA270C5 = 31 + let UC_CPU_ARM_MAX = 32 + // ARM registers let UC_ARM_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Arm64.fs b/bindings/dotnet/UnicornManaged/Const/Arm64.fs index a2ec894e..56d0de58 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm64.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm64.fs @@ -7,6 +7,11 @@ open System [] module Arm64 = + let UC_CPU_AARCH64_A57 = 0 + let UC_CPU_AARCH64_A53 = 1 + let UC_CPU_AARCH64_A72 = 2 + let UC_CPU_AARCH64_MAX = 3 + // ARM64 registers let UC_ARM64_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 0b91cac1..9ec83525 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -112,6 +112,22 @@ module Common = let UC_QUERY_ARCH = 3 let UC_QUERY_TIMEOUT = 4 + let UC_CTL_IO_NONE = 0 + let UC_CTL_IO_WRITE = 1 + let UC_CTL_IO_READ = 2 + let UC_CTL_IO_READ_WRITE = 3 + + let UC_CTL_UC_MODE = 0 + let UC_CTL_UC_PAGE_SIZE = 1 + let UC_CTL_UC_ARCH = 2 + let UC_CTL_UC_TIMEOUT = 3 + let UC_CTL_UC_EXITS_CNT = 4 + let UC_CTL_UC_EXITS = 5 + let UC_CTL_CPU_MODEL = 6 + let UC_CTL_TB_EDGE = 7 + let UC_CTL_TB_REQUEST_CACHE = 8 + let UC_CTL_TB_REMOVE_CACHE = 9 + let UC_PROT_NONE = 0 let UC_PROT_READ = 1 let UC_PROT_WRITE = 2 diff --git a/bindings/dotnet/UnicornManaged/Const/M68k.fs b/bindings/dotnet/UnicornManaged/Const/M68k.fs index 8fc5157e..36808a79 100644 --- a/bindings/dotnet/UnicornManaged/Const/M68k.fs +++ b/bindings/dotnet/UnicornManaged/Const/M68k.fs @@ -7,6 +7,16 @@ open System [] module M68k = + let UC_CPU_M5206_CPU = 0 + let UC_CPU_M68000_CPU = 1 + let UC_CPU_M68020_CPU = 2 + let UC_CPU_M68030_CPU = 3 + let UC_CPU_M68040_CPU = 4 + let UC_CPU_M68060_CPU = 5 + let UC_CPU_M5208_CPU = 6 + let UC_CPU_CFV4E_CPU = 7 + let UC_CPU_ANY_CPU = 8 + // M68K registers let UC_M68K_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Mips.fs b/bindings/dotnet/UnicornManaged/Const/Mips.fs index a8ac5925..48a65287 100644 --- a/bindings/dotnet/UnicornManaged/Const/Mips.fs +++ b/bindings/dotnet/UnicornManaged/Const/Mips.fs @@ -7,6 +7,36 @@ open System [] module Mips = + let UC_CPU_MIPS_4KC = 0 + let UC_CPU_MIPS_4KM = 1 + let UC_CPU_MIPS_4KECR1 = 2 + let UC_CPU_MIPS_4KEMR1 = 3 + let UC_CPU_MIPS_4KEC = 4 + let UC_CPU_MIPS_4KEM = 5 + let UC_CPU_MIPS_24KC = 6 + let UC_CPU_MIPS_24KEC = 7 + let UC_CPU_MIPS_24KF = 8 + let UC_CPU_MIPS_34KF = 9 + let UC_CPU_MIPS_74KF = 10 + let UC_CPU_MIPS_M14K = 11 + let UC_CPU_MIPS_M14KC = 12 + let UC_CPU_MIPS_P5600 = 13 + let UC_CPU_MIPS_MIPS32R6_GENERIC = 14 + let UC_CPU_MIPS_I7200 = 15 + let UC_CPU_MIPS_R4000 = 16 + let UC_CPU_MIPS_VR5432 = 17 + let UC_CPU_MIPS_5KC = 18 + let UC_CPU_MIPS_5KF = 19 + let UC_CPU_MIPS_20KC = 20 + let UC_CPU_MIPS_MIPS64R2_GENERIC = 21 + let UC_CPU_MIPS_5KEC = 22 + let UC_CPU_MIPS_5KEF = 23 + let UC_CPU_MIPS_I6400 = 24 + let UC_CPU_MIPS_I6500 = 25 + let UC_CPU_MIPS_LOONGSON_2E = 26 + let UC_CPU_MIPS_LOONGSON_2F = 27 + let UC_CPU_MIPS_MIPS64DSPR2 = 28 + // MIPS registers let UC_MIPS_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Ppc.fs b/bindings/dotnet/UnicornManaged/Const/Ppc.fs index 2e6c91aa..cfa5be62 100644 --- a/bindings/dotnet/UnicornManaged/Const/Ppc.fs +++ b/bindings/dotnet/UnicornManaged/Const/Ppc.fs @@ -7,6 +7,307 @@ open System [] module Ppc = + let UC_CPU_PPC_401A1 = 0 + let UC_CPU_PPC_401B2 = 1 + let UC_CPU_PPC_401C2 = 2 + let UC_CPU_PPC_401D2 = 3 + let UC_CPU_PPC_401E2 = 4 + let UC_CPU_PPC_401F2 = 5 + let UC_CPU_PPC_401G2 = 6 + let UC_CPU_PPC_COBRA = 7 + let UC_CPU_PPC_403GA = 8 + let UC_CPU_PPC_403GB = 9 + let UC_CPU_PPC_403GC = 10 + let UC_CPU_PPC_403GCX = 11 + let UC_CPU_PPC_405D2 = 12 + let UC_CPU_PPC_405D4 = 13 + let UC_CPU_PPC_405CRA = 14 + let UC_CPU_PPC_405CRB = 15 + let UC_CPU_PPC_405CRC = 16 + let UC_CPU_PPC_405EP = 17 + let UC_CPU_PPC_405EZ = 18 + let UC_CPU_PPC_405GPA = 19 + let UC_CPU_PPC_405GPB = 20 + let UC_CPU_PPC_405GPC = 21 + let UC_CPU_PPC_405GPD = 22 + let UC_CPU_PPC_405GPR = 23 + let UC_CPU_PPC_405LP = 24 + let UC_CPU_PPC_NPE405H = 25 + let UC_CPU_PPC_NPE405H2 = 26 + let UC_CPU_PPC_NPE405L = 27 + let UC_CPU_PPC_NPE4GS3 = 28 + let UC_CPU_PPC_STB03 = 29 + let UC_CPU_PPC_STB04 = 30 + let UC_CPU_PPC_STB25 = 31 + let UC_CPU_PPC_X2VP4 = 32 + let UC_CPU_PPC_440_XILINX = 33 + let UC_CPU_PPC_440EPA = 34 + let UC_CPU_PPC_440EPB = 35 + let UC_CPU_PPC_440GPB = 36 + let UC_CPU_PPC_440GPC = 37 + let UC_CPU_PPC_440GRX = 38 + let UC_CPU_PPC_440GXA = 39 + let UC_CPU_PPC_440GXB = 40 + let UC_CPU_PPC_440GXC = 41 + let UC_CPU_PPC_440GXF = 42 + let UC_CPU_PPC_440SP = 43 + let UC_CPU_PPC_440SP2 = 44 + let UC_CPU_PPC_440SPE = 45 + let UC_CPU_PPC_460EXB = 46 + let UC_CPU_PPC_MPC5XX = 47 + let UC_CPU_PPC_MPC8XX = 48 + let UC_CPU_PPC_G2 = 49 + let UC_CPU_PPC_G2H4 = 50 + let UC_CPU_PPC_G2GP = 51 + let UC_CPU_PPC_G2LS = 52 + let UC_CPU_PPC_MPC603 = 53 + let UC_CPU_PPC_G2_HIP3 = 54 + let UC_CPU_PPC_G2_HIP4 = 55 + let UC_CPU_PPC_G2LE = 56 + let UC_CPU_PPC_G2LEGP = 57 + let UC_CPU_PPC_G2LELS = 58 + let UC_CPU_PPC_G2LEGP1 = 59 + let UC_CPU_PPC_G2LEGP3 = 60 + let UC_CPU_PPC_E200Z5 = 61 + let UC_CPU_PPC_E200Z6 = 62 + let UC_CPU_PPC_E300C1 = 63 + let UC_CPU_PPC_E300C2 = 64 + let UC_CPU_PPC_E300C3 = 65 + let UC_CPU_PPC_E300C4 = 66 + let UC_CPU_PPC_E500V1_V10 = 67 + let UC_CPU_PPC_E500V1_V20 = 68 + let UC_CPU_PPC_E500V2_V10 = 69 + let UC_CPU_PPC_E500V2_V11 = 70 + let UC_CPU_PPC_E500V2_V20 = 71 + let UC_CPU_PPC_E500V2_V21 = 72 + let UC_CPU_PPC_E500V2_V22 = 73 + let UC_CPU_PPC_E500V2_V30 = 74 + let UC_CPU_PPC_E500MC = 75 + let UC_CPU_PPC_E5500 = 76 + let UC_CPU_PPC_E6500 = 77 + let UC_CPU_PPC_E600 = 78 + let UC_CPU_PPC_601_V0 = 79 + let UC_CPU_PPC_601_V1 = 80 + let UC_CPU_PPC_601_V2 = 81 + let UC_CPU_PPC_602 = 82 + let UC_CPU_PPC_603 = 83 + let UC_CPU_PPC_603E_V11 = 84 + let UC_CPU_PPC_603E_V12 = 85 + let UC_CPU_PPC_603E_V13 = 86 + let UC_CPU_PPC_603E_V14 = 87 + let UC_CPU_PPC_603E_V22 = 88 + let UC_CPU_PPC_603E_V3 = 89 + let UC_CPU_PPC_603E_V4 = 90 + let UC_CPU_PPC_603E_V41 = 91 + let UC_CPU_PPC_603E7T = 92 + let UC_CPU_PPC_603E7V = 93 + let UC_CPU_PPC_603E7V1 = 94 + let UC_CPU_PPC_603E7V2 = 95 + let UC_CPU_PPC_603E7 = 96 + let UC_CPU_PPC_603P = 97 + let UC_CPU_PPC_604 = 98 + let UC_CPU_PPC_604E_V10 = 99 + let UC_CPU_PPC_604E_V22 = 100 + let UC_CPU_PPC_604E_V24 = 101 + let UC_CPU_PPC_604R = 102 + let UC_CPU_PPC_7X0_V10 = 103 + let UC_CPU_PPC_7X0_V20 = 104 + let UC_CPU_PPC_7X0_V21 = 105 + let UC_CPU_PPC_7X0_V22 = 106 + let UC_CPU_PPC_7X0_V30 = 107 + let UC_CPU_PPC_7X0_V31 = 108 + let UC_CPU_PPC_740E = 109 + let UC_CPU_PPC_750E = 110 + let UC_CPU_PPC_7X0P = 111 + let UC_CPU_PPC_750CL_V10 = 112 + let UC_CPU_PPC_750CL_V20 = 113 + let UC_CPU_PPC_750CX_V10 = 114 + let UC_CPU_PPC_750CX_V20 = 115 + let UC_CPU_PPC_750CX_V21 = 116 + let UC_CPU_PPC_750CX_V22 = 117 + let UC_CPU_PPC_750CXE_V21 = 118 + let UC_CPU_PPC_750CXE_V22 = 119 + let UC_CPU_PPC_750CXE_V23 = 120 + let UC_CPU_PPC_750CXE_V24 = 121 + let UC_CPU_PPC_750CXE_V24B = 122 + let UC_CPU_PPC_750CXE_V30 = 123 + let UC_CPU_PPC_750CXE_V31 = 124 + let UC_CPU_PPC_750CXE_V31B = 125 + let UC_CPU_PPC_750CXR = 126 + let UC_CPU_PPC_750FL = 127 + let UC_CPU_PPC_750FX_V10 = 128 + let UC_CPU_PPC_750FX_V20 = 129 + let UC_CPU_PPC_750FX_V21 = 130 + let UC_CPU_PPC_750FX_V22 = 131 + let UC_CPU_PPC_750FX_V23 = 132 + let UC_CPU_PPC_750GL = 133 + let UC_CPU_PPC_750GX_V10 = 134 + let UC_CPU_PPC_750GX_V11 = 135 + let UC_CPU_PPC_750GX_V12 = 136 + let UC_CPU_PPC_750L_V20 = 137 + let UC_CPU_PPC_750L_V21 = 138 + let UC_CPU_PPC_750L_V22 = 139 + let UC_CPU_PPC_750L_V30 = 140 + let UC_CPU_PPC_750L_V32 = 141 + let UC_CPU_PPC_7X5_V10 = 142 + let UC_CPU_PPC_7X5_V11 = 143 + let UC_CPU_PPC_7X5_V20 = 144 + let UC_CPU_PPC_7X5_V21 = 145 + let UC_CPU_PPC_7X5_V22 = 146 + let UC_CPU_PPC_7X5_V23 = 147 + let UC_CPU_PPC_7X5_V24 = 148 + let UC_CPU_PPC_7X5_V25 = 149 + let UC_CPU_PPC_7X5_V26 = 150 + let UC_CPU_PPC_7X5_V27 = 151 + let UC_CPU_PPC_7X5_V28 = 152 + let UC_CPU_PPC_7400_V10 = 153 + let UC_CPU_PPC_7400_V11 = 154 + let UC_CPU_PPC_7400_V20 = 155 + let UC_CPU_PPC_7400_V21 = 156 + let UC_CPU_PPC_7400_V22 = 157 + let UC_CPU_PPC_7400_V26 = 158 + let UC_CPU_PPC_7400_V27 = 159 + let UC_CPU_PPC_7400_V28 = 160 + let UC_CPU_PPC_7400_V29 = 161 + let UC_CPU_PPC_7410_V10 = 162 + let UC_CPU_PPC_7410_V11 = 163 + let UC_CPU_PPC_7410_V12 = 164 + let UC_CPU_PPC_7410_V13 = 165 + let UC_CPU_PPC_7410_V14 = 166 + let UC_CPU_PPC_7448_V10 = 167 + let UC_CPU_PPC_7448_V11 = 168 + let UC_CPU_PPC_7448_V20 = 169 + let UC_CPU_PPC_7448_V21 = 170 + let UC_CPU_PPC_7450_V10 = 171 + let UC_CPU_PPC_7450_V11 = 172 + let UC_CPU_PPC_7450_V12 = 173 + let UC_CPU_PPC_7450_V20 = 174 + let UC_CPU_PPC_7450_V21 = 175 + let UC_CPU_PPC_74X1_V23 = 176 + let UC_CPU_PPC_74X1_V210 = 177 + let UC_CPU_PPC_74X5_V10 = 178 + let UC_CPU_PPC_74X5_V21 = 179 + let UC_CPU_PPC_74X5_V32 = 180 + let UC_CPU_PPC_74X5_V33 = 181 + let UC_CPU_PPC_74X5_V34 = 182 + let UC_CPU_PPC_74X7_V10 = 183 + let UC_CPU_PPC_74X7_V11 = 184 + let UC_CPU_PPC_74X7_V12 = 185 + let UC_CPU_PPC_74X7A_V10 = 186 + let UC_CPU_PPC_74X7A_V11 = 187 + let UC_CPU_PPC_74X7A_V12 = 188 + let UC_CPU_PPC_IOP480 = 1 + let UC_CPU_PPC_X2VP20 = 42 + let UC_CPU_PPC_440GRA = 35 + let UC_CPU_PPC_440EPX = 38 + let UC_CPU_PPC_MPC5200_V10 = 59 + let UC_CPU_PPC_MPC5200_V11 = 59 + let UC_CPU_PPC_MPC5200_V12 = 59 + let UC_CPU_PPC_MPC5200B_V20 = 59 + let UC_CPU_PPC_MPC5200B_V21 = 59 + let UC_CPU_PPC_MPC834X = 63 + let UC_CPU_PPC_MPC837X = 66 + let UC_CPU_PPC_E500 = 73 + let UC_CPU_PPC_MPC8533_V10 = 72 + let UC_CPU_PPC_MPC8533_V11 = 73 + let UC_CPU_PPC_MPC8533E_V10 = 72 + let UC_CPU_PPC_MPC8533E_V11 = 73 + let UC_CPU_PPC_MPC8540_V10 = 67 + let UC_CPU_PPC_MPC8540_V20 = 68 + let UC_CPU_PPC_MPC8540_V21 = 68 + let UC_CPU_PPC_MPC8541_V10 = 68 + let UC_CPU_PPC_MPC8541_V11 = 68 + let UC_CPU_PPC_MPC8541E_V10 = 68 + let UC_CPU_PPC_MPC8541E_V11 = 68 + let UC_CPU_PPC_MPC8543_V10 = 69 + let UC_CPU_PPC_MPC8543_V11 = 70 + let UC_CPU_PPC_MPC8543_V20 = 71 + let UC_CPU_PPC_MPC8543_V21 = 72 + let UC_CPU_PPC_MPC8543E_V10 = 69 + let UC_CPU_PPC_MPC8543E_V11 = 70 + let UC_CPU_PPC_MPC8543E_V20 = 71 + let UC_CPU_PPC_MPC8543E_V21 = 72 + let UC_CPU_PPC_MPC8544_V10 = 72 + let UC_CPU_PPC_MPC8544_V11 = 73 + let UC_CPU_PPC_MPC8544E_V11 = 73 + let UC_CPU_PPC_MPC8544E_V10 = 72 + let UC_CPU_PPC_MPC8545_V10 = 69 + let UC_CPU_PPC_MPC8545_V20 = 71 + let UC_CPU_PPC_MPC8545_V21 = 72 + let UC_CPU_PPC_MPC8545E_V10 = 69 + let UC_CPU_PPC_MPC8545E_V20 = 71 + let UC_CPU_PPC_MPC8545E_V21 = 72 + let UC_CPU_PPC_MPC8547E_V10 = 69 + let UC_CPU_PPC_MPC8547E_V20 = 71 + let UC_CPU_PPC_MPC8547E_V21 = 72 + let UC_CPU_PPC_MPC8548_V10 = 69 + let UC_CPU_PPC_MPC8548_V11 = 70 + let UC_CPU_PPC_MPC8548_V20 = 71 + let UC_CPU_PPC_MPC8548_V21 = 72 + let UC_CPU_PPC_MPC8548E_V10 = 69 + let UC_CPU_PPC_MPC8548E_V11 = 70 + let UC_CPU_PPC_MPC8548E_V20 = 71 + let UC_CPU_PPC_MPC8548E_V21 = 72 + let UC_CPU_PPC_MPC8555_V10 = 69 + let UC_CPU_PPC_MPC8555_V11 = 70 + let UC_CPU_PPC_MPC8555E_V10 = 69 + let UC_CPU_PPC_MPC8555E_V11 = 70 + let UC_CPU_PPC_MPC8560_V10 = 69 + let UC_CPU_PPC_MPC8560_V20 = 71 + let UC_CPU_PPC_MPC8560_V21 = 72 + let UC_CPU_PPC_MPC8567 = 73 + let UC_CPU_PPC_MPC8567E = 73 + let UC_CPU_PPC_MPC8568 = 73 + let UC_CPU_PPC_MPC8568E = 73 + let UC_CPU_PPC_MPC8572 = 74 + let UC_CPU_PPC_MPC8572E = 74 + let UC_CPU_PPC_MPC8610 = 78 + let UC_CPU_PPC_MPC8641 = 78 + let UC_CPU_PPC_MPC8641D = 78 + + let UC_CPU_PPC64_620 = 0 + let UC_CPU_PPC64_630 = 1 + let UC_CPU_PPC64_631 = 2 + let UC_CPU_PPC64_POWER4 = 3 + let UC_CPU_PPC64_POWER4P = 4 + let UC_CPU_PPC64_POWER5 = 5 + let UC_CPU_PPC64_POWER5P_V21 = 6 + let UC_CPU_PPC64_POWER6 = 7 + let UC_CPU_PPC64_POWER_SERVER_MASK = 8 + let UC_CPU_PPC64_POWER7_BASE = 9 + let UC_CPU_PPC64_POWER7_V23 = 10 + let UC_CPU_PPC64_POWER7P_BASE = 11 + let UC_CPU_PPC64_POWER7P_V21 = 12 + let UC_CPU_PPC64_POWER8E_BASE = 13 + let UC_CPU_PPC64_POWER8E_V21 = 14 + let UC_CPU_PPC64_POWER8_BASE = 15 + let UC_CPU_PPC64_POWER8_V20 = 16 + let UC_CPU_PPC64_POWER8NVL_BASE = 17 + let UC_CPU_PPC64_POWER8NVL_V10 = 18 + let UC_CPU_PPC64_POWER9_BASE = 19 + let UC_CPU_PPC64_POWER9_DD1 = 20 + let UC_CPU_PPC64_POWER9_DD20 = 21 + let UC_CPU_PPC64_POWER10_BASE = 22 + let UC_CPU_PPC64_POWER10_DD1 = 23 + let UC_CPU_PPC64_970_V22 = 24 + let UC_CPU_PPC64_970FX_V10 = 25 + let UC_CPU_PPC64_970FX_V20 = 26 + let UC_CPU_PPC64_970FX_V21 = 27 + let UC_CPU_PPC64_970FX_V30 = 28 + let UC_CPU_PPC64_970FX_V31 = 29 + let UC_CPU_PPC64_970MP_V10 = 30 + let UC_CPU_PPC64_970MP_V11 = 31 + let UC_CPU_PPC64_CELL_V10 = 32 + let UC_CPU_PPC64_CELL_V20 = 33 + let UC_CPU_PPC64_CELL_V30 = 34 + let UC_CPU_PPC64_CELL_V31 = 35 + let UC_CPU_PPC64_RS64 = 36 + let UC_CPU_PPC64_RS64II = 37 + let UC_CPU_PPC64_RS64III = 38 + let UC_CPU_PPC64_RS64IV = 39 + let UC_CPU_PPC64_CELL_V32 = 35 + let UC_CPU_PPC64_CELL = 35 + // PPC registers let UC_PPC_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Riscv.fs b/bindings/dotnet/UnicornManaged/Const/Riscv.fs index 5fd11e95..ca5881f1 100644 --- a/bindings/dotnet/UnicornManaged/Const/Riscv.fs +++ b/bindings/dotnet/UnicornManaged/Const/Riscv.fs @@ -7,6 +7,16 @@ open System [] module Riscv = + let UC_CPU_RISCV32_ANY = 0 + let UC_CPU_RISCV32_BASE32 = 1 + let UC_CPU_RISCV32_SIFIVE_E31 = 2 + let UC_CPU_RISCV32_SIFIVE_U34 = 3 + + let UC_CPU_RISCV64_ANY = 0 + let UC_CPU_RISCV64_BASE64 = 1 + let UC_CPU_RISCV64_SIFIVE_E51 = 2 + let UC_CPU_RISCV64_SIFIVE_U54 = 3 + // RISCV registers let UC_RISCV_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Sparc.fs b/bindings/dotnet/UnicornManaged/Const/Sparc.fs index 9a91e1a7..c6c15dd6 100644 --- a/bindings/dotnet/UnicornManaged/Const/Sparc.fs +++ b/bindings/dotnet/UnicornManaged/Const/Sparc.fs @@ -7,6 +7,38 @@ open System [] module Sparc = + let UC_CPU_SPARC_FUJITSU_MB86904 = 0 + let UC_CPU_SPARC_FUJITSU_MB86907 = 1 + let UC_CPU_SPARC_TI_MICROSPARC_I = 2 + let UC_CPU_SPARC_TI_MICROSPARC_II = 3 + let UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4 + let UC_CPU_SPARC_TI_SUPERSPARC_40 = 5 + let UC_CPU_SPARC_TI_SUPERSPARC_50 = 6 + let UC_CPU_SPARC_TI_SUPERSPARC_51 = 7 + let UC_CPU_SPARC_TI_SUPERSPARC_60 = 8 + let UC_CPU_SPARC_TI_SUPERSPARC_61 = 9 + let UC_CPU_SPARC_TI_SUPERSPARC_II = 10 + let UC_CPU_SPARC_LEON2 = 11 + let UC_CPU_SPARC_LEON3 = 12 + + let UC_CPU_SPARC64_FUJITSU = 0 + let UC_CPU_SPARC64_FUJITSU_III = 1 + let UC_CPU_SPARC64_FUJITSU_IV = 2 + let UC_CPU_SPARC64_FUJITSU_V = 3 + let UC_CPU_SPARC64_TI_ULTRASPARC_I = 4 + let UC_CPU_SPARC64_TI_ULTRASPARC_II = 5 + let UC_CPU_SPARC64_TI_ULTRASPARC_III = 6 + let UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7 + let UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8 + let UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 + let UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 + let UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 + let UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16 + // SPARC registers let UC_SPARC_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/X86.fs b/bindings/dotnet/UnicornManaged/Const/X86.fs index fd5ddba6..11c7217b 100644 --- a/bindings/dotnet/UnicornManaged/Const/X86.fs +++ b/bindings/dotnet/UnicornManaged/Const/X86.fs @@ -7,6 +7,45 @@ open System [] module X86 = + let UC_CPU_X86_QEMU64 = 0 + let UC_CPU_X86_PHENOM = 1 + let UC_CPU_X86_CORE2DUO = 2 + let UC_CPU_X86_KVM64 = 3 + let UC_CPU_X86_QEMU32 = 4 + let UC_CPU_X86_KVM32 = 5 + let UC_CPU_X86_COREDUO = 6 + let UC_CPU_X86_486 = 7 + let UC_CPU_X86_PENTIUM = 8 + let UC_CPU_X86_PENTIUM2 = 9 + let UC_CPU_X86_PENTIUM3 = 10 + let UC_CPU_X86_ATHLON = 11 + let UC_CPU_X86_N270 = 12 + let UC_CPU_X86_CONROE = 13 + let UC_CPU_X86_PENRYN = 14 + let UC_CPU_X86_NEHALEM = 15 + let UC_CPU_X86_WESTMERE = 16 + let UC_CPU_X86_SANDYBRIDGE = 17 + let UC_CPU_X86_IVYBRIDGE = 18 + let UC_CPU_X86_HASWELL = 19 + let UC_CPU_X86_BROADWELL = 20 + let UC_CPU_X86_SKYLAKE_CLIENT = 21 + let UC_CPU_X86_SKYLAKE_SERVER = 22 + let UC_CPU_X86_CASCADELAKE_SERVER = 23 + let UC_CPU_X86_COOPERLAKE = 24 + let UC_CPU_X86_ICELAKE_CLIENT = 25 + let UC_CPU_X86_ICELAKE_SERVER = 26 + let UC_CPU_X86_DENVERTON = 27 + let UC_CPU_X86_SNOWRIDGE = 28 + let UC_CPU_X86_KNIGHTSMILL = 29 + let UC_CPU_X86_OPTERON_G1 = 30 + let UC_CPU_X86_OPTERON_G2 = 31 + let UC_CPU_X86_OPTERON_G3 = 32 + let UC_CPU_X86_OPTERON_G4 = 33 + let UC_CPU_X86_OPTERON_G5 = 34 + let UC_CPU_X86_EPYC = 35 + let UC_CPU_X86_DHYANA = 36 + let UC_CPU_X86_EPYC_ROME = 37 + // X86 registers let UC_X86_REG_INVALID = 0 diff --git a/bindings/go/Makefile b/bindings/go/Makefile index fe898ae1..f8b0d5f1 100644 --- a/bindings/go/Makefile +++ b/bindings/go/Makefile @@ -6,7 +6,7 @@ all: gen_const cd unicorn && go build gen_const: - cd .. && python const_generator.py go + cd .. && python3 const_generator.py go test: all cd unicorn && LD_LIBRARY_PATH=../../../ DYLD_LIBRARY_PATH=../../../ go test diff --git a/bindings/go/unicorn/arm64_const.go b/bindings/go/unicorn/arm64_const.go index fb8dc906..d2bfd18a 100644 --- a/bindings/go/unicorn/arm64_const.go +++ b/bindings/go/unicorn/arm64_const.go @@ -2,6 +2,11 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.go] const ( + CPU_AARCH64_A57 = 0 + CPU_AARCH64_A53 = 1 + CPU_AARCH64_A72 = 2 + CPU_AARCH64_MAX = 3 + // ARM64 registers ARM64_REG_INVALID = 0 diff --git a/bindings/go/unicorn/arm_const.go b/bindings/go/unicorn/arm_const.go index eab0e336..007c9cad 100644 --- a/bindings/go/unicorn/arm_const.go +++ b/bindings/go/unicorn/arm_const.go @@ -2,6 +2,40 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.go] const ( + CPU_ARM_926 = 0 + CPU_ARM_946 = 1 + CPU_ARM_1026 = 2 + CPU_ARM_1136_R2 = 3 + CPU_ARM_1136 = 4 + CPU_ARM_1176 = 5 + CPU_ARM_11MPCORE = 6 + CPU_ARM_CORTEX_M0 = 7 + CPU_ARM_CORTEX_M3 = 8 + CPU_ARM_CORTEX_M4 = 9 + CPU_ARM_CORTEX_M7 = 10 + CPU_ARM_CORTEX_M33 = 11 + CPU_ARM_CORTEX_R5 = 12 + CPU_ARM_CORTEX_R5F = 13 + CPU_ARM_CORTEX_A8 = 14 + CPU_ARM_CORTEX_A9 = 15 + CPU_ARM_CORTEX_A7 = 16 + CPU_ARM_CORTEX_A15 = 17 + CPU_ARM_TI925T = 18 + CPU_ARM_SA1100 = 19 + CPU_ARM_SA1110 = 20 + CPU_ARM_PXA250 = 21 + CPU_ARM_PXA255 = 22 + CPU_ARM_PXA260 = 23 + CPU_ARM_PXA261 = 24 + CPU_ARM_PXA262 = 25 + CPU_ARM_PXA270A0 = 26 + CPU_ARM_PXA270A1 = 27 + CPU_ARM_PXA270B0 = 28 + CPU_ARM_PXA270B1 = 29 + CPU_ARM_PXA270C0 = 30 + CPU_ARM_PXA270C5 = 31 + CPU_ARM_MAX = 32 + // ARM registers ARM_REG_INVALID = 0 diff --git a/bindings/go/unicorn/m68k_const.go b/bindings/go/unicorn/m68k_const.go index 36ba914a..efa02e03 100644 --- a/bindings/go/unicorn/m68k_const.go +++ b/bindings/go/unicorn/m68k_const.go @@ -2,6 +2,16 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.go] const ( + CPU_M5206_CPU = 0 + CPU_M68000_CPU = 1 + CPU_M68020_CPU = 2 + CPU_M68030_CPU = 3 + CPU_M68040_CPU = 4 + CPU_M68060_CPU = 5 + CPU_M5208_CPU = 6 + CPU_CFV4E_CPU = 7 + CPU_ANY_CPU = 8 + // M68K registers M68K_REG_INVALID = 0 diff --git a/bindings/go/unicorn/mips_const.go b/bindings/go/unicorn/mips_const.go index 20a33756..e45291b5 100644 --- a/bindings/go/unicorn/mips_const.go +++ b/bindings/go/unicorn/mips_const.go @@ -2,6 +2,36 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.go] const ( + CPU_MIPS_4KC = 0 + CPU_MIPS_4KM = 1 + CPU_MIPS_4KECR1 = 2 + CPU_MIPS_4KEMR1 = 3 + CPU_MIPS_4KEC = 4 + CPU_MIPS_4KEM = 5 + CPU_MIPS_24KC = 6 + CPU_MIPS_24KEC = 7 + CPU_MIPS_24KF = 8 + CPU_MIPS_34KF = 9 + CPU_MIPS_74KF = 10 + CPU_MIPS_M14K = 11 + CPU_MIPS_M14KC = 12 + CPU_MIPS_P5600 = 13 + CPU_MIPS_MIPS32R6_GENERIC = 14 + CPU_MIPS_I7200 = 15 + CPU_MIPS_R4000 = 16 + CPU_MIPS_VR5432 = 17 + CPU_MIPS_5KC = 18 + CPU_MIPS_5KF = 19 + CPU_MIPS_20KC = 20 + CPU_MIPS_MIPS64R2_GENERIC = 21 + CPU_MIPS_5KEC = 22 + CPU_MIPS_5KEF = 23 + CPU_MIPS_I6400 = 24 + CPU_MIPS_I6500 = 25 + CPU_MIPS_LOONGSON_2E = 26 + CPU_MIPS_LOONGSON_2F = 27 + CPU_MIPS_MIPS64DSPR2 = 28 + // MIPS registers MIPS_REG_INVALID = 0 diff --git a/bindings/go/unicorn/ppc_const.go b/bindings/go/unicorn/ppc_const.go index f0180eeb..03eba18e 100644 --- a/bindings/go/unicorn/ppc_const.go +++ b/bindings/go/unicorn/ppc_const.go @@ -2,6 +2,307 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.go] const ( + CPU_PPC_401A1 = 0 + CPU_PPC_401B2 = 1 + CPU_PPC_401C2 = 2 + CPU_PPC_401D2 = 3 + CPU_PPC_401E2 = 4 + CPU_PPC_401F2 = 5 + CPU_PPC_401G2 = 6 + CPU_PPC_COBRA = 7 + CPU_PPC_403GA = 8 + CPU_PPC_403GB = 9 + CPU_PPC_403GC = 10 + CPU_PPC_403GCX = 11 + CPU_PPC_405D2 = 12 + CPU_PPC_405D4 = 13 + CPU_PPC_405CRA = 14 + CPU_PPC_405CRB = 15 + CPU_PPC_405CRC = 16 + CPU_PPC_405EP = 17 + CPU_PPC_405EZ = 18 + CPU_PPC_405GPA = 19 + CPU_PPC_405GPB = 20 + CPU_PPC_405GPC = 21 + CPU_PPC_405GPD = 22 + CPU_PPC_405GPR = 23 + CPU_PPC_405LP = 24 + CPU_PPC_NPE405H = 25 + CPU_PPC_NPE405H2 = 26 + CPU_PPC_NPE405L = 27 + CPU_PPC_NPE4GS3 = 28 + CPU_PPC_STB03 = 29 + CPU_PPC_STB04 = 30 + CPU_PPC_STB25 = 31 + CPU_PPC_X2VP4 = 32 + CPU_PPC_440_XILINX = 33 + CPU_PPC_440EPA = 34 + CPU_PPC_440EPB = 35 + CPU_PPC_440GPB = 36 + CPU_PPC_440GPC = 37 + CPU_PPC_440GRX = 38 + CPU_PPC_440GXA = 39 + CPU_PPC_440GXB = 40 + CPU_PPC_440GXC = 41 + CPU_PPC_440GXF = 42 + CPU_PPC_440SP = 43 + CPU_PPC_440SP2 = 44 + CPU_PPC_440SPE = 45 + CPU_PPC_460EXB = 46 + CPU_PPC_MPC5XX = 47 + CPU_PPC_MPC8XX = 48 + CPU_PPC_G2 = 49 + CPU_PPC_G2H4 = 50 + CPU_PPC_G2GP = 51 + CPU_PPC_G2LS = 52 + CPU_PPC_MPC603 = 53 + CPU_PPC_G2_HIP3 = 54 + CPU_PPC_G2_HIP4 = 55 + CPU_PPC_G2LE = 56 + CPU_PPC_G2LEGP = 57 + CPU_PPC_G2LELS = 58 + CPU_PPC_G2LEGP1 = 59 + CPU_PPC_G2LEGP3 = 60 + CPU_PPC_E200Z5 = 61 + CPU_PPC_E200Z6 = 62 + CPU_PPC_E300C1 = 63 + CPU_PPC_E300C2 = 64 + CPU_PPC_E300C3 = 65 + CPU_PPC_E300C4 = 66 + CPU_PPC_E500V1_V10 = 67 + CPU_PPC_E500V1_V20 = 68 + CPU_PPC_E500V2_V10 = 69 + CPU_PPC_E500V2_V11 = 70 + CPU_PPC_E500V2_V20 = 71 + CPU_PPC_E500V2_V21 = 72 + CPU_PPC_E500V2_V22 = 73 + CPU_PPC_E500V2_V30 = 74 + CPU_PPC_E500MC = 75 + CPU_PPC_E5500 = 76 + CPU_PPC_E6500 = 77 + CPU_PPC_E600 = 78 + CPU_PPC_601_V0 = 79 + CPU_PPC_601_V1 = 80 + CPU_PPC_601_V2 = 81 + CPU_PPC_602 = 82 + CPU_PPC_603 = 83 + CPU_PPC_603E_V11 = 84 + CPU_PPC_603E_V12 = 85 + CPU_PPC_603E_V13 = 86 + CPU_PPC_603E_V14 = 87 + CPU_PPC_603E_V22 = 88 + CPU_PPC_603E_V3 = 89 + CPU_PPC_603E_V4 = 90 + CPU_PPC_603E_V41 = 91 + CPU_PPC_603E7T = 92 + CPU_PPC_603E7V = 93 + CPU_PPC_603E7V1 = 94 + CPU_PPC_603E7V2 = 95 + CPU_PPC_603E7 = 96 + CPU_PPC_603P = 97 + CPU_PPC_604 = 98 + CPU_PPC_604E_V10 = 99 + CPU_PPC_604E_V22 = 100 + CPU_PPC_604E_V24 = 101 + CPU_PPC_604R = 102 + CPU_PPC_7X0_V10 = 103 + CPU_PPC_7X0_V20 = 104 + CPU_PPC_7X0_V21 = 105 + CPU_PPC_7X0_V22 = 106 + CPU_PPC_7X0_V30 = 107 + CPU_PPC_7X0_V31 = 108 + CPU_PPC_740E = 109 + CPU_PPC_750E = 110 + CPU_PPC_7X0P = 111 + CPU_PPC_750CL_V10 = 112 + CPU_PPC_750CL_V20 = 113 + CPU_PPC_750CX_V10 = 114 + CPU_PPC_750CX_V20 = 115 + CPU_PPC_750CX_V21 = 116 + CPU_PPC_750CX_V22 = 117 + CPU_PPC_750CXE_V21 = 118 + CPU_PPC_750CXE_V22 = 119 + CPU_PPC_750CXE_V23 = 120 + CPU_PPC_750CXE_V24 = 121 + CPU_PPC_750CXE_V24B = 122 + CPU_PPC_750CXE_V30 = 123 + CPU_PPC_750CXE_V31 = 124 + CPU_PPC_750CXE_V31B = 125 + CPU_PPC_750CXR = 126 + CPU_PPC_750FL = 127 + CPU_PPC_750FX_V10 = 128 + CPU_PPC_750FX_V20 = 129 + CPU_PPC_750FX_V21 = 130 + CPU_PPC_750FX_V22 = 131 + CPU_PPC_750FX_V23 = 132 + CPU_PPC_750GL = 133 + CPU_PPC_750GX_V10 = 134 + CPU_PPC_750GX_V11 = 135 + CPU_PPC_750GX_V12 = 136 + CPU_PPC_750L_V20 = 137 + CPU_PPC_750L_V21 = 138 + CPU_PPC_750L_V22 = 139 + CPU_PPC_750L_V30 = 140 + CPU_PPC_750L_V32 = 141 + CPU_PPC_7X5_V10 = 142 + CPU_PPC_7X5_V11 = 143 + CPU_PPC_7X5_V20 = 144 + CPU_PPC_7X5_V21 = 145 + CPU_PPC_7X5_V22 = 146 + CPU_PPC_7X5_V23 = 147 + CPU_PPC_7X5_V24 = 148 + CPU_PPC_7X5_V25 = 149 + CPU_PPC_7X5_V26 = 150 + CPU_PPC_7X5_V27 = 151 + CPU_PPC_7X5_V28 = 152 + CPU_PPC_7400_V10 = 153 + CPU_PPC_7400_V11 = 154 + CPU_PPC_7400_V20 = 155 + CPU_PPC_7400_V21 = 156 + CPU_PPC_7400_V22 = 157 + CPU_PPC_7400_V26 = 158 + CPU_PPC_7400_V27 = 159 + CPU_PPC_7400_V28 = 160 + CPU_PPC_7400_V29 = 161 + CPU_PPC_7410_V10 = 162 + CPU_PPC_7410_V11 = 163 + CPU_PPC_7410_V12 = 164 + CPU_PPC_7410_V13 = 165 + CPU_PPC_7410_V14 = 166 + CPU_PPC_7448_V10 = 167 + CPU_PPC_7448_V11 = 168 + CPU_PPC_7448_V20 = 169 + CPU_PPC_7448_V21 = 170 + CPU_PPC_7450_V10 = 171 + CPU_PPC_7450_V11 = 172 + CPU_PPC_7450_V12 = 173 + CPU_PPC_7450_V20 = 174 + CPU_PPC_7450_V21 = 175 + CPU_PPC_74X1_V23 = 176 + CPU_PPC_74X1_V210 = 177 + CPU_PPC_74X5_V10 = 178 + CPU_PPC_74X5_V21 = 179 + CPU_PPC_74X5_V32 = 180 + CPU_PPC_74X5_V33 = 181 + CPU_PPC_74X5_V34 = 182 + CPU_PPC_74X7_V10 = 183 + CPU_PPC_74X7_V11 = 184 + CPU_PPC_74X7_V12 = 185 + CPU_PPC_74X7A_V10 = 186 + CPU_PPC_74X7A_V11 = 187 + CPU_PPC_74X7A_V12 = 188 + CPU_PPC_IOP480 = 1 + CPU_PPC_X2VP20 = 42 + CPU_PPC_440GRA = 35 + CPU_PPC_440EPX = 38 + CPU_PPC_MPC5200_V10 = 59 + CPU_PPC_MPC5200_V11 = 59 + CPU_PPC_MPC5200_V12 = 59 + CPU_PPC_MPC5200B_V20 = 59 + CPU_PPC_MPC5200B_V21 = 59 + CPU_PPC_MPC834X = 63 + CPU_PPC_MPC837X = 66 + CPU_PPC_E500 = 73 + CPU_PPC_MPC8533_V10 = 72 + CPU_PPC_MPC8533_V11 = 73 + CPU_PPC_MPC8533E_V10 = 72 + CPU_PPC_MPC8533E_V11 = 73 + CPU_PPC_MPC8540_V10 = 67 + CPU_PPC_MPC8540_V20 = 68 + CPU_PPC_MPC8540_V21 = 68 + CPU_PPC_MPC8541_V10 = 68 + CPU_PPC_MPC8541_V11 = 68 + CPU_PPC_MPC8541E_V10 = 68 + CPU_PPC_MPC8541E_V11 = 68 + CPU_PPC_MPC8543_V10 = 69 + CPU_PPC_MPC8543_V11 = 70 + CPU_PPC_MPC8543_V20 = 71 + CPU_PPC_MPC8543_V21 = 72 + CPU_PPC_MPC8543E_V10 = 69 + CPU_PPC_MPC8543E_V11 = 70 + CPU_PPC_MPC8543E_V20 = 71 + CPU_PPC_MPC8543E_V21 = 72 + CPU_PPC_MPC8544_V10 = 72 + CPU_PPC_MPC8544_V11 = 73 + CPU_PPC_MPC8544E_V11 = 73 + CPU_PPC_MPC8544E_V10 = 72 + CPU_PPC_MPC8545_V10 = 69 + CPU_PPC_MPC8545_V20 = 71 + CPU_PPC_MPC8545_V21 = 72 + CPU_PPC_MPC8545E_V10 = 69 + CPU_PPC_MPC8545E_V20 = 71 + CPU_PPC_MPC8545E_V21 = 72 + CPU_PPC_MPC8547E_V10 = 69 + CPU_PPC_MPC8547E_V20 = 71 + CPU_PPC_MPC8547E_V21 = 72 + CPU_PPC_MPC8548_V10 = 69 + CPU_PPC_MPC8548_V11 = 70 + CPU_PPC_MPC8548_V20 = 71 + CPU_PPC_MPC8548_V21 = 72 + CPU_PPC_MPC8548E_V10 = 69 + CPU_PPC_MPC8548E_V11 = 70 + CPU_PPC_MPC8548E_V20 = 71 + CPU_PPC_MPC8548E_V21 = 72 + CPU_PPC_MPC8555_V10 = 69 + CPU_PPC_MPC8555_V11 = 70 + CPU_PPC_MPC8555E_V10 = 69 + CPU_PPC_MPC8555E_V11 = 70 + CPU_PPC_MPC8560_V10 = 69 + CPU_PPC_MPC8560_V20 = 71 + CPU_PPC_MPC8560_V21 = 72 + CPU_PPC_MPC8567 = 73 + CPU_PPC_MPC8567E = 73 + CPU_PPC_MPC8568 = 73 + CPU_PPC_MPC8568E = 73 + CPU_PPC_MPC8572 = 74 + CPU_PPC_MPC8572E = 74 + CPU_PPC_MPC8610 = 78 + CPU_PPC_MPC8641 = 78 + CPU_PPC_MPC8641D = 78 + + CPU_PPC64_620 = 0 + CPU_PPC64_630 = 1 + CPU_PPC64_631 = 2 + CPU_PPC64_POWER4 = 3 + CPU_PPC64_POWER4P = 4 + CPU_PPC64_POWER5 = 5 + CPU_PPC64_POWER5P_V21 = 6 + CPU_PPC64_POWER6 = 7 + CPU_PPC64_POWER_SERVER_MASK = 8 + CPU_PPC64_POWER7_BASE = 9 + CPU_PPC64_POWER7_V23 = 10 + CPU_PPC64_POWER7P_BASE = 11 + CPU_PPC64_POWER7P_V21 = 12 + CPU_PPC64_POWER8E_BASE = 13 + CPU_PPC64_POWER8E_V21 = 14 + CPU_PPC64_POWER8_BASE = 15 + CPU_PPC64_POWER8_V20 = 16 + CPU_PPC64_POWER8NVL_BASE = 17 + CPU_PPC64_POWER8NVL_V10 = 18 + CPU_PPC64_POWER9_BASE = 19 + CPU_PPC64_POWER9_DD1 = 20 + CPU_PPC64_POWER9_DD20 = 21 + CPU_PPC64_POWER10_BASE = 22 + CPU_PPC64_POWER10_DD1 = 23 + CPU_PPC64_970_V22 = 24 + CPU_PPC64_970FX_V10 = 25 + CPU_PPC64_970FX_V20 = 26 + CPU_PPC64_970FX_V21 = 27 + CPU_PPC64_970FX_V30 = 28 + CPU_PPC64_970FX_V31 = 29 + CPU_PPC64_970MP_V10 = 30 + CPU_PPC64_970MP_V11 = 31 + CPU_PPC64_CELL_V10 = 32 + CPU_PPC64_CELL_V20 = 33 + CPU_PPC64_CELL_V30 = 34 + CPU_PPC64_CELL_V31 = 35 + CPU_PPC64_RS64 = 36 + CPU_PPC64_RS64II = 37 + CPU_PPC64_RS64III = 38 + CPU_PPC64_RS64IV = 39 + CPU_PPC64_CELL_V32 = 35 + CPU_PPC64_CELL = 35 + // PPC registers PPC_REG_INVALID = 0 diff --git a/bindings/go/unicorn/riscv_const.go b/bindings/go/unicorn/riscv_const.go index 506a9f90..4295dcc6 100644 --- a/bindings/go/unicorn/riscv_const.go +++ b/bindings/go/unicorn/riscv_const.go @@ -2,6 +2,16 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.go] const ( + CPU_RISCV32_ANY = 0 + CPU_RISCV32_BASE32 = 1 + CPU_RISCV32_SIFIVE_E31 = 2 + CPU_RISCV32_SIFIVE_U34 = 3 + + CPU_RISCV64_ANY = 0 + CPU_RISCV64_BASE64 = 1 + CPU_RISCV64_SIFIVE_E51 = 2 + CPU_RISCV64_SIFIVE_U54 = 3 + // RISCV registers RISCV_REG_INVALID = 0 diff --git a/bindings/go/unicorn/sparc_const.go b/bindings/go/unicorn/sparc_const.go index afd94f45..02bea244 100644 --- a/bindings/go/unicorn/sparc_const.go +++ b/bindings/go/unicorn/sparc_const.go @@ -2,6 +2,38 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.go] const ( + CPU_SPARC_FUJITSU_MB86904 = 0 + CPU_SPARC_FUJITSU_MB86907 = 1 + CPU_SPARC_TI_MICROSPARC_I = 2 + CPU_SPARC_TI_MICROSPARC_II = 3 + CPU_SPARC_TI_MICROSPARC_IIEP = 4 + CPU_SPARC_TI_SUPERSPARC_40 = 5 + CPU_SPARC_TI_SUPERSPARC_50 = 6 + CPU_SPARC_TI_SUPERSPARC_51 = 7 + CPU_SPARC_TI_SUPERSPARC_60 = 8 + CPU_SPARC_TI_SUPERSPARC_61 = 9 + CPU_SPARC_TI_SUPERSPARC_II = 10 + CPU_SPARC_LEON2 = 11 + CPU_SPARC_LEON3 = 12 + + CPU_SPARC64_FUJITSU = 0 + CPU_SPARC64_FUJITSU_III = 1 + CPU_SPARC64_FUJITSU_IV = 2 + CPU_SPARC64_FUJITSU_V = 3 + CPU_SPARC64_TI_ULTRASPARC_I = 4 + CPU_SPARC64_TI_ULTRASPARC_II = 5 + CPU_SPARC64_TI_ULTRASPARC_III = 6 + CPU_SPARC64_TI_ULTRASPARC_IIE = 7 + CPU_SPARC64_SUN_ULTRASPARC_III = 8 + CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 + CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 + CPU_SPARC64_SUN_ULTRASPARC_IV = 11 + CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 + CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 + CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 + CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 + CPU_SPARC64_NEC_ULTRASPARC_I = 16 + // SPARC registers SPARC_REG_INVALID = 0 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 6196fde5..883453da 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -107,6 +107,22 @@ const ( QUERY_ARCH = 3 QUERY_TIMEOUT = 4 + CTL_IO_NONE = 0 + CTL_IO_WRITE = 1 + CTL_IO_READ = 2 + CTL_IO_READ_WRITE = 3 + + CTL_UC_MODE = 0 + CTL_UC_PAGE_SIZE = 1 + CTL_UC_ARCH = 2 + CTL_UC_TIMEOUT = 3 + CTL_UC_EXITS_CNT = 4 + CTL_UC_EXITS = 5 + CTL_CPU_MODEL = 6 + CTL_TB_EDGE = 7 + CTL_TB_REQUEST_CACHE = 8 + CTL_TB_REMOVE_CACHE = 9 + PROT_NONE = 0 PROT_READ = 1 PROT_WRITE = 2 diff --git a/bindings/go/unicorn/x86_const.go b/bindings/go/unicorn/x86_const.go index 2a5015bf..c8c45848 100644 --- a/bindings/go/unicorn/x86_const.go +++ b/bindings/go/unicorn/x86_const.go @@ -2,6 +2,45 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.go] const ( + CPU_X86_QEMU64 = 0 + CPU_X86_PHENOM = 1 + CPU_X86_CORE2DUO = 2 + CPU_X86_KVM64 = 3 + CPU_X86_QEMU32 = 4 + CPU_X86_KVM32 = 5 + CPU_X86_COREDUO = 6 + CPU_X86_486 = 7 + CPU_X86_PENTIUM = 8 + CPU_X86_PENTIUM2 = 9 + CPU_X86_PENTIUM3 = 10 + CPU_X86_ATHLON = 11 + CPU_X86_N270 = 12 + CPU_X86_CONROE = 13 + CPU_X86_PENRYN = 14 + CPU_X86_NEHALEM = 15 + CPU_X86_WESTMERE = 16 + CPU_X86_SANDYBRIDGE = 17 + CPU_X86_IVYBRIDGE = 18 + CPU_X86_HASWELL = 19 + CPU_X86_BROADWELL = 20 + CPU_X86_SKYLAKE_CLIENT = 21 + CPU_X86_SKYLAKE_SERVER = 22 + CPU_X86_CASCADELAKE_SERVER = 23 + CPU_X86_COOPERLAKE = 24 + CPU_X86_ICELAKE_CLIENT = 25 + CPU_X86_ICELAKE_SERVER = 26 + CPU_X86_DENVERTON = 27 + CPU_X86_SNOWRIDGE = 28 + CPU_X86_KNIGHTSMILL = 29 + CPU_X86_OPTERON_G1 = 30 + CPU_X86_OPTERON_G2 = 31 + CPU_X86_OPTERON_G3 = 32 + CPU_X86_OPTERON_G4 = 33 + CPU_X86_OPTERON_G5 = 34 + CPU_X86_EPYC = 35 + CPU_X86_DHYANA = 36 + CPU_X86_EPYC_ROME = 37 + // X86 registers X86_REG_INVALID = 0 diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 73d20725..313db888 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -19,7 +19,7 @@ uninstall: $(MAKE) -f Makefile.build uninstall gen_const: - cd .. && python const_generator.py java + cd .. && python3 const_generator.py java clean: rm -f unicorn/*.class diff --git a/bindings/java/unicorn/Arm64Const.java b/bindings/java/unicorn/Arm64Const.java index dc70de85..93cb6975 100644 --- a/bindings/java/unicorn/Arm64Const.java +++ b/bindings/java/unicorn/Arm64Const.java @@ -4,6 +4,11 @@ package unicorn; public interface Arm64Const { + public static final int UC_CPU_AARCH64_A57 = 0; + public static final int UC_CPU_AARCH64_A53 = 1; + public static final int UC_CPU_AARCH64_A72 = 2; + public static final int UC_CPU_AARCH64_MAX = 3; + // ARM64 registers public static final int UC_ARM64_REG_INVALID = 0; diff --git a/bindings/java/unicorn/ArmConst.java b/bindings/java/unicorn/ArmConst.java index 4508430a..4f68cf51 100644 --- a/bindings/java/unicorn/ArmConst.java +++ b/bindings/java/unicorn/ArmConst.java @@ -4,6 +4,40 @@ package unicorn; public interface ArmConst { + public static final int UC_CPU_ARM_926 = 0; + public static final int UC_CPU_ARM_946 = 1; + public static final int UC_CPU_ARM_1026 = 2; + public static final int UC_CPU_ARM_1136_R2 = 3; + public static final int UC_CPU_ARM_1136 = 4; + public static final int UC_CPU_ARM_1176 = 5; + public static final int UC_CPU_ARM_11MPCORE = 6; + public static final int UC_CPU_ARM_CORTEX_M0 = 7; + public static final int UC_CPU_ARM_CORTEX_M3 = 8; + public static final int UC_CPU_ARM_CORTEX_M4 = 9; + public static final int UC_CPU_ARM_CORTEX_M7 = 10; + public static final int UC_CPU_ARM_CORTEX_M33 = 11; + public static final int UC_CPU_ARM_CORTEX_R5 = 12; + public static final int UC_CPU_ARM_CORTEX_R5F = 13; + public static final int UC_CPU_ARM_CORTEX_A8 = 14; + public static final int UC_CPU_ARM_CORTEX_A9 = 15; + public static final int UC_CPU_ARM_CORTEX_A7 = 16; + public static final int UC_CPU_ARM_CORTEX_A15 = 17; + public static final int UC_CPU_ARM_TI925T = 18; + public static final int UC_CPU_ARM_SA1100 = 19; + public static final int UC_CPU_ARM_SA1110 = 20; + public static final int UC_CPU_ARM_PXA250 = 21; + public static final int UC_CPU_ARM_PXA255 = 22; + public static final int UC_CPU_ARM_PXA260 = 23; + public static final int UC_CPU_ARM_PXA261 = 24; + public static final int UC_CPU_ARM_PXA262 = 25; + public static final int UC_CPU_ARM_PXA270A0 = 26; + public static final int UC_CPU_ARM_PXA270A1 = 27; + public static final int UC_CPU_ARM_PXA270B0 = 28; + public static final int UC_CPU_ARM_PXA270B1 = 29; + public static final int UC_CPU_ARM_PXA270C0 = 30; + public static final int UC_CPU_ARM_PXA270C5 = 31; + public static final int UC_CPU_ARM_MAX = 32; + // ARM registers public static final int UC_ARM_REG_INVALID = 0; diff --git a/bindings/java/unicorn/M68kConst.java b/bindings/java/unicorn/M68kConst.java index 4f0574d8..fa7d2d66 100644 --- a/bindings/java/unicorn/M68kConst.java +++ b/bindings/java/unicorn/M68kConst.java @@ -4,6 +4,16 @@ package unicorn; public interface M68kConst { + public static final int UC_CPU_M5206_CPU = 0; + public static final int UC_CPU_M68000_CPU = 1; + public static final int UC_CPU_M68020_CPU = 2; + public static final int UC_CPU_M68030_CPU = 3; + public static final int UC_CPU_M68040_CPU = 4; + public static final int UC_CPU_M68060_CPU = 5; + public static final int UC_CPU_M5208_CPU = 6; + public static final int UC_CPU_CFV4E_CPU = 7; + public static final int UC_CPU_ANY_CPU = 8; + // M68K registers public static final int UC_M68K_REG_INVALID = 0; diff --git a/bindings/java/unicorn/MipsConst.java b/bindings/java/unicorn/MipsConst.java index bace395c..43c53ac0 100644 --- a/bindings/java/unicorn/MipsConst.java +++ b/bindings/java/unicorn/MipsConst.java @@ -4,6 +4,36 @@ package unicorn; public interface MipsConst { + public static final int UC_CPU_MIPS_4KC = 0; + public static final int UC_CPU_MIPS_4KM = 1; + public static final int UC_CPU_MIPS_4KECR1 = 2; + public static final int UC_CPU_MIPS_4KEMR1 = 3; + public static final int UC_CPU_MIPS_4KEC = 4; + public static final int UC_CPU_MIPS_4KEM = 5; + public static final int UC_CPU_MIPS_24KC = 6; + public static final int UC_CPU_MIPS_24KEC = 7; + public static final int UC_CPU_MIPS_24KF = 8; + public static final int UC_CPU_MIPS_34KF = 9; + public static final int UC_CPU_MIPS_74KF = 10; + public static final int UC_CPU_MIPS_M14K = 11; + public static final int UC_CPU_MIPS_M14KC = 12; + public static final int UC_CPU_MIPS_P5600 = 13; + public static final int UC_CPU_MIPS_MIPS32R6_GENERIC = 14; + public static final int UC_CPU_MIPS_I7200 = 15; + public static final int UC_CPU_MIPS_R4000 = 16; + public static final int UC_CPU_MIPS_VR5432 = 17; + public static final int UC_CPU_MIPS_5KC = 18; + public static final int UC_CPU_MIPS_5KF = 19; + public static final int UC_CPU_MIPS_20KC = 20; + public static final int UC_CPU_MIPS_MIPS64R2_GENERIC = 21; + public static final int UC_CPU_MIPS_5KEC = 22; + public static final int UC_CPU_MIPS_5KEF = 23; + public static final int UC_CPU_MIPS_I6400 = 24; + public static final int UC_CPU_MIPS_I6500 = 25; + public static final int UC_CPU_MIPS_LOONGSON_2E = 26; + public static final int UC_CPU_MIPS_LOONGSON_2F = 27; + public static final int UC_CPU_MIPS_MIPS64DSPR2 = 28; + // MIPS registers public static final int UC_MIPS_REG_INVALID = 0; diff --git a/bindings/java/unicorn/PpcConst.java b/bindings/java/unicorn/PpcConst.java index 86597be6..09cada99 100644 --- a/bindings/java/unicorn/PpcConst.java +++ b/bindings/java/unicorn/PpcConst.java @@ -4,6 +4,307 @@ package unicorn; public interface PpcConst { + public static final int UC_CPU_PPC_401A1 = 0; + public static final int UC_CPU_PPC_401B2 = 1; + public static final int UC_CPU_PPC_401C2 = 2; + public static final int UC_CPU_PPC_401D2 = 3; + public static final int UC_CPU_PPC_401E2 = 4; + public static final int UC_CPU_PPC_401F2 = 5; + public static final int UC_CPU_PPC_401G2 = 6; + public static final int UC_CPU_PPC_COBRA = 7; + public static final int UC_CPU_PPC_403GA = 8; + public static final int UC_CPU_PPC_403GB = 9; + public static final int UC_CPU_PPC_403GC = 10; + public static final int UC_CPU_PPC_403GCX = 11; + public static final int UC_CPU_PPC_405D2 = 12; + public static final int UC_CPU_PPC_405D4 = 13; + public static final int UC_CPU_PPC_405CRA = 14; + public static final int UC_CPU_PPC_405CRB = 15; + public static final int UC_CPU_PPC_405CRC = 16; + public static final int UC_CPU_PPC_405EP = 17; + public static final int UC_CPU_PPC_405EZ = 18; + public static final int UC_CPU_PPC_405GPA = 19; + public static final int UC_CPU_PPC_405GPB = 20; + public static final int UC_CPU_PPC_405GPC = 21; + public static final int UC_CPU_PPC_405GPD = 22; + public static final int UC_CPU_PPC_405GPR = 23; + public static final int UC_CPU_PPC_405LP = 24; + public static final int UC_CPU_PPC_NPE405H = 25; + public static final int UC_CPU_PPC_NPE405H2 = 26; + public static final int UC_CPU_PPC_NPE405L = 27; + public static final int UC_CPU_PPC_NPE4GS3 = 28; + public static final int UC_CPU_PPC_STB03 = 29; + public static final int UC_CPU_PPC_STB04 = 30; + public static final int UC_CPU_PPC_STB25 = 31; + public static final int UC_CPU_PPC_X2VP4 = 32; + public static final int UC_CPU_PPC_440_XILINX = 33; + public static final int UC_CPU_PPC_440EPA = 34; + public static final int UC_CPU_PPC_440EPB = 35; + public static final int UC_CPU_PPC_440GPB = 36; + public static final int UC_CPU_PPC_440GPC = 37; + public static final int UC_CPU_PPC_440GRX = 38; + public static final int UC_CPU_PPC_440GXA = 39; + public static final int UC_CPU_PPC_440GXB = 40; + public static final int UC_CPU_PPC_440GXC = 41; + public static final int UC_CPU_PPC_440GXF = 42; + public static final int UC_CPU_PPC_440SP = 43; + public static final int UC_CPU_PPC_440SP2 = 44; + public static final int UC_CPU_PPC_440SPE = 45; + public static final int UC_CPU_PPC_460EXB = 46; + public static final int UC_CPU_PPC_MPC5XX = 47; + public static final int UC_CPU_PPC_MPC8XX = 48; + public static final int UC_CPU_PPC_G2 = 49; + public static final int UC_CPU_PPC_G2H4 = 50; + public static final int UC_CPU_PPC_G2GP = 51; + public static final int UC_CPU_PPC_G2LS = 52; + public static final int UC_CPU_PPC_MPC603 = 53; + public static final int UC_CPU_PPC_G2_HIP3 = 54; + public static final int UC_CPU_PPC_G2_HIP4 = 55; + public static final int UC_CPU_PPC_G2LE = 56; + public static final int UC_CPU_PPC_G2LEGP = 57; + public static final int UC_CPU_PPC_G2LELS = 58; + public static final int UC_CPU_PPC_G2LEGP1 = 59; + public static final int UC_CPU_PPC_G2LEGP3 = 60; + public static final int UC_CPU_PPC_E200Z5 = 61; + public static final int UC_CPU_PPC_E200Z6 = 62; + public static final int UC_CPU_PPC_E300C1 = 63; + public static final int UC_CPU_PPC_E300C2 = 64; + public static final int UC_CPU_PPC_E300C3 = 65; + public static final int UC_CPU_PPC_E300C4 = 66; + public static final int UC_CPU_PPC_E500V1_V10 = 67; + public static final int UC_CPU_PPC_E500V1_V20 = 68; + public static final int UC_CPU_PPC_E500V2_V10 = 69; + public static final int UC_CPU_PPC_E500V2_V11 = 70; + public static final int UC_CPU_PPC_E500V2_V20 = 71; + public static final int UC_CPU_PPC_E500V2_V21 = 72; + public static final int UC_CPU_PPC_E500V2_V22 = 73; + public static final int UC_CPU_PPC_E500V2_V30 = 74; + public static final int UC_CPU_PPC_E500MC = 75; + public static final int UC_CPU_PPC_E5500 = 76; + public static final int UC_CPU_PPC_E6500 = 77; + public static final int UC_CPU_PPC_E600 = 78; + public static final int UC_CPU_PPC_601_V0 = 79; + public static final int UC_CPU_PPC_601_V1 = 80; + public static final int UC_CPU_PPC_601_V2 = 81; + public static final int UC_CPU_PPC_602 = 82; + public static final int UC_CPU_PPC_603 = 83; + public static final int UC_CPU_PPC_603E_V11 = 84; + public static final int UC_CPU_PPC_603E_V12 = 85; + public static final int UC_CPU_PPC_603E_V13 = 86; + public static final int UC_CPU_PPC_603E_V14 = 87; + public static final int UC_CPU_PPC_603E_V22 = 88; + public static final int UC_CPU_PPC_603E_V3 = 89; + public static final int UC_CPU_PPC_603E_V4 = 90; + public static final int UC_CPU_PPC_603E_V41 = 91; + public static final int UC_CPU_PPC_603E7T = 92; + public static final int UC_CPU_PPC_603E7V = 93; + public static final int UC_CPU_PPC_603E7V1 = 94; + public static final int UC_CPU_PPC_603E7V2 = 95; + public static final int UC_CPU_PPC_603E7 = 96; + public static final int UC_CPU_PPC_603P = 97; + public static final int UC_CPU_PPC_604 = 98; + public static final int UC_CPU_PPC_604E_V10 = 99; + public static final int UC_CPU_PPC_604E_V22 = 100; + public static final int UC_CPU_PPC_604E_V24 = 101; + public static final int UC_CPU_PPC_604R = 102; + public static final int UC_CPU_PPC_7X0_V10 = 103; + public static final int UC_CPU_PPC_7X0_V20 = 104; + public static final int UC_CPU_PPC_7X0_V21 = 105; + public static final int UC_CPU_PPC_7X0_V22 = 106; + public static final int UC_CPU_PPC_7X0_V30 = 107; + public static final int UC_CPU_PPC_7X0_V31 = 108; + public static final int UC_CPU_PPC_740E = 109; + public static final int UC_CPU_PPC_750E = 110; + public static final int UC_CPU_PPC_7X0P = 111; + public static final int UC_CPU_PPC_750CL_V10 = 112; + public static final int UC_CPU_PPC_750CL_V20 = 113; + public static final int UC_CPU_PPC_750CX_V10 = 114; + public static final int UC_CPU_PPC_750CX_V20 = 115; + public static final int UC_CPU_PPC_750CX_V21 = 116; + public static final int UC_CPU_PPC_750CX_V22 = 117; + public static final int UC_CPU_PPC_750CXE_V21 = 118; + public static final int UC_CPU_PPC_750CXE_V22 = 119; + public static final int UC_CPU_PPC_750CXE_V23 = 120; + public static final int UC_CPU_PPC_750CXE_V24 = 121; + public static final int UC_CPU_PPC_750CXE_V24B = 122; + public static final int UC_CPU_PPC_750CXE_V30 = 123; + public static final int UC_CPU_PPC_750CXE_V31 = 124; + public static final int UC_CPU_PPC_750CXE_V31B = 125; + public static final int UC_CPU_PPC_750CXR = 126; + public static final int UC_CPU_PPC_750FL = 127; + public static final int UC_CPU_PPC_750FX_V10 = 128; + public static final int UC_CPU_PPC_750FX_V20 = 129; + public static final int UC_CPU_PPC_750FX_V21 = 130; + public static final int UC_CPU_PPC_750FX_V22 = 131; + public static final int UC_CPU_PPC_750FX_V23 = 132; + public static final int UC_CPU_PPC_750GL = 133; + public static final int UC_CPU_PPC_750GX_V10 = 134; + public static final int UC_CPU_PPC_750GX_V11 = 135; + public static final int UC_CPU_PPC_750GX_V12 = 136; + public static final int UC_CPU_PPC_750L_V20 = 137; + public static final int UC_CPU_PPC_750L_V21 = 138; + public static final int UC_CPU_PPC_750L_V22 = 139; + public static final int UC_CPU_PPC_750L_V30 = 140; + public static final int UC_CPU_PPC_750L_V32 = 141; + public static final int UC_CPU_PPC_7X5_V10 = 142; + public static final int UC_CPU_PPC_7X5_V11 = 143; + public static final int UC_CPU_PPC_7X5_V20 = 144; + public static final int UC_CPU_PPC_7X5_V21 = 145; + public static final int UC_CPU_PPC_7X5_V22 = 146; + public static final int UC_CPU_PPC_7X5_V23 = 147; + public static final int UC_CPU_PPC_7X5_V24 = 148; + public static final int UC_CPU_PPC_7X5_V25 = 149; + public static final int UC_CPU_PPC_7X5_V26 = 150; + public static final int UC_CPU_PPC_7X5_V27 = 151; + public static final int UC_CPU_PPC_7X5_V28 = 152; + public static final int UC_CPU_PPC_7400_V10 = 153; + public static final int UC_CPU_PPC_7400_V11 = 154; + public static final int UC_CPU_PPC_7400_V20 = 155; + public static final int UC_CPU_PPC_7400_V21 = 156; + public static final int UC_CPU_PPC_7400_V22 = 157; + public static final int UC_CPU_PPC_7400_V26 = 158; + public static final int UC_CPU_PPC_7400_V27 = 159; + public static final int UC_CPU_PPC_7400_V28 = 160; + public static final int UC_CPU_PPC_7400_V29 = 161; + public static final int UC_CPU_PPC_7410_V10 = 162; + public static final int UC_CPU_PPC_7410_V11 = 163; + public static final int UC_CPU_PPC_7410_V12 = 164; + public static final int UC_CPU_PPC_7410_V13 = 165; + public static final int UC_CPU_PPC_7410_V14 = 166; + public static final int UC_CPU_PPC_7448_V10 = 167; + public static final int UC_CPU_PPC_7448_V11 = 168; + public static final int UC_CPU_PPC_7448_V20 = 169; + public static final int UC_CPU_PPC_7448_V21 = 170; + public static final int UC_CPU_PPC_7450_V10 = 171; + public static final int UC_CPU_PPC_7450_V11 = 172; + public static final int UC_CPU_PPC_7450_V12 = 173; + public static final int UC_CPU_PPC_7450_V20 = 174; + public static final int UC_CPU_PPC_7450_V21 = 175; + public static final int UC_CPU_PPC_74X1_V23 = 176; + public static final int UC_CPU_PPC_74X1_V210 = 177; + public static final int UC_CPU_PPC_74X5_V10 = 178; + public static final int UC_CPU_PPC_74X5_V21 = 179; + public static final int UC_CPU_PPC_74X5_V32 = 180; + public static final int UC_CPU_PPC_74X5_V33 = 181; + public static final int UC_CPU_PPC_74X5_V34 = 182; + public static final int UC_CPU_PPC_74X7_V10 = 183; + public static final int UC_CPU_PPC_74X7_V11 = 184; + public static final int UC_CPU_PPC_74X7_V12 = 185; + public static final int UC_CPU_PPC_74X7A_V10 = 186; + public static final int UC_CPU_PPC_74X7A_V11 = 187; + public static final int UC_CPU_PPC_74X7A_V12 = 188; + public static final int UC_CPU_PPC_IOP480 = 1; + public static final int UC_CPU_PPC_X2VP20 = 42; + public static final int UC_CPU_PPC_440GRA = 35; + public static final int UC_CPU_PPC_440EPX = 38; + public static final int UC_CPU_PPC_MPC5200_V10 = 59; + public static final int UC_CPU_PPC_MPC5200_V11 = 59; + public static final int UC_CPU_PPC_MPC5200_V12 = 59; + public static final int UC_CPU_PPC_MPC5200B_V20 = 59; + public static final int UC_CPU_PPC_MPC5200B_V21 = 59; + public static final int UC_CPU_PPC_MPC834X = 63; + public static final int UC_CPU_PPC_MPC837X = 66; + public static final int UC_CPU_PPC_E500 = 73; + public static final int UC_CPU_PPC_MPC8533_V10 = 72; + public static final int UC_CPU_PPC_MPC8533_V11 = 73; + public static final int UC_CPU_PPC_MPC8533E_V10 = 72; + public static final int UC_CPU_PPC_MPC8533E_V11 = 73; + public static final int UC_CPU_PPC_MPC8540_V10 = 67; + public static final int UC_CPU_PPC_MPC8540_V20 = 68; + public static final int UC_CPU_PPC_MPC8540_V21 = 68; + public static final int UC_CPU_PPC_MPC8541_V10 = 68; + public static final int UC_CPU_PPC_MPC8541_V11 = 68; + public static final int UC_CPU_PPC_MPC8541E_V10 = 68; + public static final int UC_CPU_PPC_MPC8541E_V11 = 68; + public static final int UC_CPU_PPC_MPC8543_V10 = 69; + public static final int UC_CPU_PPC_MPC8543_V11 = 70; + public static final int UC_CPU_PPC_MPC8543_V20 = 71; + public static final int UC_CPU_PPC_MPC8543_V21 = 72; + public static final int UC_CPU_PPC_MPC8543E_V10 = 69; + public static final int UC_CPU_PPC_MPC8543E_V11 = 70; + public static final int UC_CPU_PPC_MPC8543E_V20 = 71; + public static final int UC_CPU_PPC_MPC8543E_V21 = 72; + public static final int UC_CPU_PPC_MPC8544_V10 = 72; + public static final int UC_CPU_PPC_MPC8544_V11 = 73; + public static final int UC_CPU_PPC_MPC8544E_V11 = 73; + public static final int UC_CPU_PPC_MPC8544E_V10 = 72; + public static final int UC_CPU_PPC_MPC8545_V10 = 69; + public static final int UC_CPU_PPC_MPC8545_V20 = 71; + public static final int UC_CPU_PPC_MPC8545_V21 = 72; + public static final int UC_CPU_PPC_MPC8545E_V10 = 69; + public static final int UC_CPU_PPC_MPC8545E_V20 = 71; + public static final int UC_CPU_PPC_MPC8545E_V21 = 72; + public static final int UC_CPU_PPC_MPC8547E_V10 = 69; + public static final int UC_CPU_PPC_MPC8547E_V20 = 71; + public static final int UC_CPU_PPC_MPC8547E_V21 = 72; + public static final int UC_CPU_PPC_MPC8548_V10 = 69; + public static final int UC_CPU_PPC_MPC8548_V11 = 70; + public static final int UC_CPU_PPC_MPC8548_V20 = 71; + public static final int UC_CPU_PPC_MPC8548_V21 = 72; + public static final int UC_CPU_PPC_MPC8548E_V10 = 69; + public static final int UC_CPU_PPC_MPC8548E_V11 = 70; + public static final int UC_CPU_PPC_MPC8548E_V20 = 71; + public static final int UC_CPU_PPC_MPC8548E_V21 = 72; + public static final int UC_CPU_PPC_MPC8555_V10 = 69; + public static final int UC_CPU_PPC_MPC8555_V11 = 70; + public static final int UC_CPU_PPC_MPC8555E_V10 = 69; + public static final int UC_CPU_PPC_MPC8555E_V11 = 70; + public static final int UC_CPU_PPC_MPC8560_V10 = 69; + public static final int UC_CPU_PPC_MPC8560_V20 = 71; + public static final int UC_CPU_PPC_MPC8560_V21 = 72; + public static final int UC_CPU_PPC_MPC8567 = 73; + public static final int UC_CPU_PPC_MPC8567E = 73; + public static final int UC_CPU_PPC_MPC8568 = 73; + public static final int UC_CPU_PPC_MPC8568E = 73; + public static final int UC_CPU_PPC_MPC8572 = 74; + public static final int UC_CPU_PPC_MPC8572E = 74; + public static final int UC_CPU_PPC_MPC8610 = 78; + public static final int UC_CPU_PPC_MPC8641 = 78; + public static final int UC_CPU_PPC_MPC8641D = 78; + + public static final int UC_CPU_PPC64_620 = 0; + public static final int UC_CPU_PPC64_630 = 1; + public static final int UC_CPU_PPC64_631 = 2; + public static final int UC_CPU_PPC64_POWER4 = 3; + public static final int UC_CPU_PPC64_POWER4P = 4; + public static final int UC_CPU_PPC64_POWER5 = 5; + public static final int UC_CPU_PPC64_POWER5P_V21 = 6; + public static final int UC_CPU_PPC64_POWER6 = 7; + public static final int UC_CPU_PPC64_POWER_SERVER_MASK = 8; + public static final int UC_CPU_PPC64_POWER7_BASE = 9; + public static final int UC_CPU_PPC64_POWER7_V23 = 10; + public static final int UC_CPU_PPC64_POWER7P_BASE = 11; + public static final int UC_CPU_PPC64_POWER7P_V21 = 12; + public static final int UC_CPU_PPC64_POWER8E_BASE = 13; + public static final int UC_CPU_PPC64_POWER8E_V21 = 14; + public static final int UC_CPU_PPC64_POWER8_BASE = 15; + public static final int UC_CPU_PPC64_POWER8_V20 = 16; + public static final int UC_CPU_PPC64_POWER8NVL_BASE = 17; + public static final int UC_CPU_PPC64_POWER8NVL_V10 = 18; + public static final int UC_CPU_PPC64_POWER9_BASE = 19; + public static final int UC_CPU_PPC64_POWER9_DD1 = 20; + public static final int UC_CPU_PPC64_POWER9_DD20 = 21; + public static final int UC_CPU_PPC64_POWER10_BASE = 22; + public static final int UC_CPU_PPC64_POWER10_DD1 = 23; + public static final int UC_CPU_PPC64_970_V22 = 24; + public static final int UC_CPU_PPC64_970FX_V10 = 25; + public static final int UC_CPU_PPC64_970FX_V20 = 26; + public static final int UC_CPU_PPC64_970FX_V21 = 27; + public static final int UC_CPU_PPC64_970FX_V30 = 28; + public static final int UC_CPU_PPC64_970FX_V31 = 29; + public static final int UC_CPU_PPC64_970MP_V10 = 30; + public static final int UC_CPU_PPC64_970MP_V11 = 31; + public static final int UC_CPU_PPC64_CELL_V10 = 32; + public static final int UC_CPU_PPC64_CELL_V20 = 33; + public static final int UC_CPU_PPC64_CELL_V30 = 34; + public static final int UC_CPU_PPC64_CELL_V31 = 35; + public static final int UC_CPU_PPC64_RS64 = 36; + public static final int UC_CPU_PPC64_RS64II = 37; + public static final int UC_CPU_PPC64_RS64III = 38; + public static final int UC_CPU_PPC64_RS64IV = 39; + public static final int UC_CPU_PPC64_CELL_V32 = 35; + public static final int UC_CPU_PPC64_CELL = 35; + // PPC registers public static final int UC_PPC_REG_INVALID = 0; diff --git a/bindings/java/unicorn/RiscvConst.java b/bindings/java/unicorn/RiscvConst.java index ca375f1a..d835296c 100644 --- a/bindings/java/unicorn/RiscvConst.java +++ b/bindings/java/unicorn/RiscvConst.java @@ -4,6 +4,16 @@ package unicorn; public interface RiscvConst { + public static final int UC_CPU_RISCV32_ANY = 0; + public static final int UC_CPU_RISCV32_BASE32 = 1; + public static final int UC_CPU_RISCV32_SIFIVE_E31 = 2; + public static final int UC_CPU_RISCV32_SIFIVE_U34 = 3; + + public static final int UC_CPU_RISCV64_ANY = 0; + public static final int UC_CPU_RISCV64_BASE64 = 1; + public static final int UC_CPU_RISCV64_SIFIVE_E51 = 2; + public static final int UC_CPU_RISCV64_SIFIVE_U54 = 3; + // RISCV registers public static final int UC_RISCV_REG_INVALID = 0; diff --git a/bindings/java/unicorn/SparcConst.java b/bindings/java/unicorn/SparcConst.java index de0dc184..27b3b618 100644 --- a/bindings/java/unicorn/SparcConst.java +++ b/bindings/java/unicorn/SparcConst.java @@ -4,6 +4,38 @@ package unicorn; public interface SparcConst { + public static final int UC_CPU_SPARC_FUJITSU_MB86904 = 0; + public static final int UC_CPU_SPARC_FUJITSU_MB86907 = 1; + public static final int UC_CPU_SPARC_TI_MICROSPARC_I = 2; + public static final int UC_CPU_SPARC_TI_MICROSPARC_II = 3; + public static final int UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_40 = 5; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_50 = 6; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_51 = 7; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_60 = 8; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_61 = 9; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_II = 10; + public static final int UC_CPU_SPARC_LEON2 = 11; + public static final int UC_CPU_SPARC_LEON3 = 12; + + public static final int UC_CPU_SPARC64_FUJITSU = 0; + public static final int UC_CPU_SPARC64_FUJITSU_III = 1; + public static final int UC_CPU_SPARC64_FUJITSU_IV = 2; + public static final int UC_CPU_SPARC64_FUJITSU_V = 3; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_I = 4; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_II = 5; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_III = 6; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15; + public static final int UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16; + // SPARC registers public static final int UC_SPARC_REG_INVALID = 0; diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index f4396003..0c519d65 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -109,6 +109,22 @@ public interface UnicornConst { public static final int UC_QUERY_ARCH = 3; public static final int UC_QUERY_TIMEOUT = 4; + public static final int UC_CTL_IO_NONE = 0; + public static final int UC_CTL_IO_WRITE = 1; + public static final int UC_CTL_IO_READ = 2; + public static final int UC_CTL_IO_READ_WRITE = 3; + + public static final int UC_CTL_UC_MODE = 0; + public static final int UC_CTL_UC_PAGE_SIZE = 1; + public static final int UC_CTL_UC_ARCH = 2; + public static final int UC_CTL_UC_TIMEOUT = 3; + public static final int UC_CTL_UC_EXITS_CNT = 4; + public static final int UC_CTL_UC_EXITS = 5; + public static final int UC_CTL_CPU_MODEL = 6; + public static final int UC_CTL_TB_EDGE = 7; + public static final int UC_CTL_TB_REQUEST_CACHE = 8; + public static final int UC_CTL_TB_REMOVE_CACHE = 9; + public static final int UC_PROT_NONE = 0; public static final int UC_PROT_READ = 1; public static final int UC_PROT_WRITE = 2; diff --git a/bindings/java/unicorn/X86Const.java b/bindings/java/unicorn/X86Const.java index a097b525..a12e55bc 100644 --- a/bindings/java/unicorn/X86Const.java +++ b/bindings/java/unicorn/X86Const.java @@ -4,6 +4,45 @@ package unicorn; public interface X86Const { + public static final int UC_CPU_X86_QEMU64 = 0; + public static final int UC_CPU_X86_PHENOM = 1; + public static final int UC_CPU_X86_CORE2DUO = 2; + public static final int UC_CPU_X86_KVM64 = 3; + public static final int UC_CPU_X86_QEMU32 = 4; + public static final int UC_CPU_X86_KVM32 = 5; + public static final int UC_CPU_X86_COREDUO = 6; + public static final int UC_CPU_X86_486 = 7; + public static final int UC_CPU_X86_PENTIUM = 8; + public static final int UC_CPU_X86_PENTIUM2 = 9; + public static final int UC_CPU_X86_PENTIUM3 = 10; + public static final int UC_CPU_X86_ATHLON = 11; + public static final int UC_CPU_X86_N270 = 12; + public static final int UC_CPU_X86_CONROE = 13; + public static final int UC_CPU_X86_PENRYN = 14; + public static final int UC_CPU_X86_NEHALEM = 15; + public static final int UC_CPU_X86_WESTMERE = 16; + public static final int UC_CPU_X86_SANDYBRIDGE = 17; + public static final int UC_CPU_X86_IVYBRIDGE = 18; + public static final int UC_CPU_X86_HASWELL = 19; + public static final int UC_CPU_X86_BROADWELL = 20; + public static final int UC_CPU_X86_SKYLAKE_CLIENT = 21; + public static final int UC_CPU_X86_SKYLAKE_SERVER = 22; + public static final int UC_CPU_X86_CASCADELAKE_SERVER = 23; + public static final int UC_CPU_X86_COOPERLAKE = 24; + public static final int UC_CPU_X86_ICELAKE_CLIENT = 25; + public static final int UC_CPU_X86_ICELAKE_SERVER = 26; + public static final int UC_CPU_X86_DENVERTON = 27; + public static final int UC_CPU_X86_SNOWRIDGE = 28; + public static final int UC_CPU_X86_KNIGHTSMILL = 29; + public static final int UC_CPU_X86_OPTERON_G1 = 30; + public static final int UC_CPU_X86_OPTERON_G2 = 31; + public static final int UC_CPU_X86_OPTERON_G3 = 32; + public static final int UC_CPU_X86_OPTERON_G4 = 33; + public static final int UC_CPU_X86_OPTERON_G5 = 34; + public static final int UC_CPU_X86_EPYC = 35; + public static final int UC_CPU_X86_DHYANA = 36; + public static final int UC_CPU_X86_EPYC_ROME = 37; + // X86 registers public static final int UC_X86_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/Arm64Const.pas b/bindings/pascal/unicorn/Arm64Const.pas index d348039a..416ec2f7 100644 --- a/bindings/pascal/unicorn/Arm64Const.pas +++ b/bindings/pascal/unicorn/Arm64Const.pas @@ -5,6 +5,11 @@ unit Arm64Const; interface const + UC_CPU_AARCH64_A57 = 0; + UC_CPU_AARCH64_A53 = 1; + UC_CPU_AARCH64_A72 = 2; + UC_CPU_AARCH64_MAX = 3; + // ARM64 registers UC_ARM64_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/ArmConst.pas b/bindings/pascal/unicorn/ArmConst.pas index b70b8326..1a85d9f3 100644 --- a/bindings/pascal/unicorn/ArmConst.pas +++ b/bindings/pascal/unicorn/ArmConst.pas @@ -5,6 +5,40 @@ unit ArmConst; interface const + UC_CPU_ARM_926 = 0; + UC_CPU_ARM_946 = 1; + UC_CPU_ARM_1026 = 2; + UC_CPU_ARM_1136_R2 = 3; + UC_CPU_ARM_1136 = 4; + UC_CPU_ARM_1176 = 5; + UC_CPU_ARM_11MPCORE = 6; + UC_CPU_ARM_CORTEX_M0 = 7; + UC_CPU_ARM_CORTEX_M3 = 8; + UC_CPU_ARM_CORTEX_M4 = 9; + UC_CPU_ARM_CORTEX_M7 = 10; + UC_CPU_ARM_CORTEX_M33 = 11; + UC_CPU_ARM_CORTEX_R5 = 12; + UC_CPU_ARM_CORTEX_R5F = 13; + UC_CPU_ARM_CORTEX_A8 = 14; + UC_CPU_ARM_CORTEX_A9 = 15; + UC_CPU_ARM_CORTEX_A7 = 16; + UC_CPU_ARM_CORTEX_A15 = 17; + UC_CPU_ARM_TI925T = 18; + UC_CPU_ARM_SA1100 = 19; + UC_CPU_ARM_SA1110 = 20; + UC_CPU_ARM_PXA250 = 21; + UC_CPU_ARM_PXA255 = 22; + UC_CPU_ARM_PXA260 = 23; + UC_CPU_ARM_PXA261 = 24; + UC_CPU_ARM_PXA262 = 25; + UC_CPU_ARM_PXA270A0 = 26; + UC_CPU_ARM_PXA270A1 = 27; + UC_CPU_ARM_PXA270B0 = 28; + UC_CPU_ARM_PXA270B1 = 29; + UC_CPU_ARM_PXA270C0 = 30; + UC_CPU_ARM_PXA270C5 = 31; + UC_CPU_ARM_MAX = 32; + // ARM registers UC_ARM_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/M68kConst.pas b/bindings/pascal/unicorn/M68kConst.pas index be78f78a..0db7ee82 100644 --- a/bindings/pascal/unicorn/M68kConst.pas +++ b/bindings/pascal/unicorn/M68kConst.pas @@ -5,6 +5,16 @@ unit M68kConst; interface const + UC_CPU_M5206_CPU = 0; + UC_CPU_M68000_CPU = 1; + UC_CPU_M68020_CPU = 2; + UC_CPU_M68030_CPU = 3; + UC_CPU_M68040_CPU = 4; + UC_CPU_M68060_CPU = 5; + UC_CPU_M5208_CPU = 6; + UC_CPU_CFV4E_CPU = 7; + UC_CPU_ANY_CPU = 8; + // M68K registers UC_M68K_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/MipsConst.pas b/bindings/pascal/unicorn/MipsConst.pas index 90f22248..3b1df5f0 100644 --- a/bindings/pascal/unicorn/MipsConst.pas +++ b/bindings/pascal/unicorn/MipsConst.pas @@ -5,6 +5,36 @@ unit MipsConst; interface const + UC_CPU_MIPS_4KC = 0; + UC_CPU_MIPS_4KM = 1; + UC_CPU_MIPS_4KECR1 = 2; + UC_CPU_MIPS_4KEMR1 = 3; + UC_CPU_MIPS_4KEC = 4; + UC_CPU_MIPS_4KEM = 5; + UC_CPU_MIPS_24KC = 6; + UC_CPU_MIPS_24KEC = 7; + UC_CPU_MIPS_24KF = 8; + UC_CPU_MIPS_34KF = 9; + UC_CPU_MIPS_74KF = 10; + UC_CPU_MIPS_M14K = 11; + UC_CPU_MIPS_M14KC = 12; + UC_CPU_MIPS_P5600 = 13; + UC_CPU_MIPS_MIPS32R6_GENERIC = 14; + UC_CPU_MIPS_I7200 = 15; + UC_CPU_MIPS_R4000 = 16; + UC_CPU_MIPS_VR5432 = 17; + UC_CPU_MIPS_5KC = 18; + UC_CPU_MIPS_5KF = 19; + UC_CPU_MIPS_20KC = 20; + UC_CPU_MIPS_MIPS64R2_GENERIC = 21; + UC_CPU_MIPS_5KEC = 22; + UC_CPU_MIPS_5KEF = 23; + UC_CPU_MIPS_I6400 = 24; + UC_CPU_MIPS_I6500 = 25; + UC_CPU_MIPS_LOONGSON_2E = 26; + UC_CPU_MIPS_LOONGSON_2F = 27; + UC_CPU_MIPS_MIPS64DSPR2 = 28; + // MIPS registers UC_MIPS_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/PpcConst.pas b/bindings/pascal/unicorn/PpcConst.pas index 2c6633db..9158c4e3 100644 --- a/bindings/pascal/unicorn/PpcConst.pas +++ b/bindings/pascal/unicorn/PpcConst.pas @@ -5,6 +5,307 @@ unit PpcConst; interface const + UC_CPU_PPC_401A1 = 0; + UC_CPU_PPC_401B2 = 1; + UC_CPU_PPC_401C2 = 2; + UC_CPU_PPC_401D2 = 3; + UC_CPU_PPC_401E2 = 4; + UC_CPU_PPC_401F2 = 5; + UC_CPU_PPC_401G2 = 6; + UC_CPU_PPC_COBRA = 7; + UC_CPU_PPC_403GA = 8; + UC_CPU_PPC_403GB = 9; + UC_CPU_PPC_403GC = 10; + UC_CPU_PPC_403GCX = 11; + UC_CPU_PPC_405D2 = 12; + UC_CPU_PPC_405D4 = 13; + UC_CPU_PPC_405CRA = 14; + UC_CPU_PPC_405CRB = 15; + UC_CPU_PPC_405CRC = 16; + UC_CPU_PPC_405EP = 17; + UC_CPU_PPC_405EZ = 18; + UC_CPU_PPC_405GPA = 19; + UC_CPU_PPC_405GPB = 20; + UC_CPU_PPC_405GPC = 21; + UC_CPU_PPC_405GPD = 22; + UC_CPU_PPC_405GPR = 23; + UC_CPU_PPC_405LP = 24; + UC_CPU_PPC_NPE405H = 25; + UC_CPU_PPC_NPE405H2 = 26; + UC_CPU_PPC_NPE405L = 27; + UC_CPU_PPC_NPE4GS3 = 28; + UC_CPU_PPC_STB03 = 29; + UC_CPU_PPC_STB04 = 30; + UC_CPU_PPC_STB25 = 31; + UC_CPU_PPC_X2VP4 = 32; + UC_CPU_PPC_440_XILINX = 33; + UC_CPU_PPC_440EPA = 34; + UC_CPU_PPC_440EPB = 35; + UC_CPU_PPC_440GPB = 36; + UC_CPU_PPC_440GPC = 37; + UC_CPU_PPC_440GRX = 38; + UC_CPU_PPC_440GXA = 39; + UC_CPU_PPC_440GXB = 40; + UC_CPU_PPC_440GXC = 41; + UC_CPU_PPC_440GXF = 42; + UC_CPU_PPC_440SP = 43; + UC_CPU_PPC_440SP2 = 44; + UC_CPU_PPC_440SPE = 45; + UC_CPU_PPC_460EXB = 46; + UC_CPU_PPC_MPC5XX = 47; + UC_CPU_PPC_MPC8XX = 48; + UC_CPU_PPC_G2 = 49; + UC_CPU_PPC_G2H4 = 50; + UC_CPU_PPC_G2GP = 51; + UC_CPU_PPC_G2LS = 52; + UC_CPU_PPC_MPC603 = 53; + UC_CPU_PPC_G2_HIP3 = 54; + UC_CPU_PPC_G2_HIP4 = 55; + UC_CPU_PPC_G2LE = 56; + UC_CPU_PPC_G2LEGP = 57; + UC_CPU_PPC_G2LELS = 58; + UC_CPU_PPC_G2LEGP1 = 59; + UC_CPU_PPC_G2LEGP3 = 60; + UC_CPU_PPC_E200Z5 = 61; + UC_CPU_PPC_E200Z6 = 62; + UC_CPU_PPC_E300C1 = 63; + UC_CPU_PPC_E300C2 = 64; + UC_CPU_PPC_E300C3 = 65; + UC_CPU_PPC_E300C4 = 66; + UC_CPU_PPC_E500V1_V10 = 67; + UC_CPU_PPC_E500V1_V20 = 68; + UC_CPU_PPC_E500V2_V10 = 69; + UC_CPU_PPC_E500V2_V11 = 70; + UC_CPU_PPC_E500V2_V20 = 71; + UC_CPU_PPC_E500V2_V21 = 72; + UC_CPU_PPC_E500V2_V22 = 73; + UC_CPU_PPC_E500V2_V30 = 74; + UC_CPU_PPC_E500MC = 75; + UC_CPU_PPC_E5500 = 76; + UC_CPU_PPC_E6500 = 77; + UC_CPU_PPC_E600 = 78; + UC_CPU_PPC_601_V0 = 79; + UC_CPU_PPC_601_V1 = 80; + UC_CPU_PPC_601_V2 = 81; + UC_CPU_PPC_602 = 82; + UC_CPU_PPC_603 = 83; + UC_CPU_PPC_603E_V11 = 84; + UC_CPU_PPC_603E_V12 = 85; + UC_CPU_PPC_603E_V13 = 86; + UC_CPU_PPC_603E_V14 = 87; + UC_CPU_PPC_603E_V22 = 88; + UC_CPU_PPC_603E_V3 = 89; + UC_CPU_PPC_603E_V4 = 90; + UC_CPU_PPC_603E_V41 = 91; + UC_CPU_PPC_603E7T = 92; + UC_CPU_PPC_603E7V = 93; + UC_CPU_PPC_603E7V1 = 94; + UC_CPU_PPC_603E7V2 = 95; + UC_CPU_PPC_603E7 = 96; + UC_CPU_PPC_603P = 97; + UC_CPU_PPC_604 = 98; + UC_CPU_PPC_604E_V10 = 99; + UC_CPU_PPC_604E_V22 = 100; + UC_CPU_PPC_604E_V24 = 101; + UC_CPU_PPC_604R = 102; + UC_CPU_PPC_7X0_V10 = 103; + UC_CPU_PPC_7X0_V20 = 104; + UC_CPU_PPC_7X0_V21 = 105; + UC_CPU_PPC_7X0_V22 = 106; + UC_CPU_PPC_7X0_V30 = 107; + UC_CPU_PPC_7X0_V31 = 108; + UC_CPU_PPC_740E = 109; + UC_CPU_PPC_750E = 110; + UC_CPU_PPC_7X0P = 111; + UC_CPU_PPC_750CL_V10 = 112; + UC_CPU_PPC_750CL_V20 = 113; + UC_CPU_PPC_750CX_V10 = 114; + UC_CPU_PPC_750CX_V20 = 115; + UC_CPU_PPC_750CX_V21 = 116; + UC_CPU_PPC_750CX_V22 = 117; + UC_CPU_PPC_750CXE_V21 = 118; + UC_CPU_PPC_750CXE_V22 = 119; + UC_CPU_PPC_750CXE_V23 = 120; + UC_CPU_PPC_750CXE_V24 = 121; + UC_CPU_PPC_750CXE_V24B = 122; + UC_CPU_PPC_750CXE_V30 = 123; + UC_CPU_PPC_750CXE_V31 = 124; + UC_CPU_PPC_750CXE_V31B = 125; + UC_CPU_PPC_750CXR = 126; + UC_CPU_PPC_750FL = 127; + UC_CPU_PPC_750FX_V10 = 128; + UC_CPU_PPC_750FX_V20 = 129; + UC_CPU_PPC_750FX_V21 = 130; + UC_CPU_PPC_750FX_V22 = 131; + UC_CPU_PPC_750FX_V23 = 132; + UC_CPU_PPC_750GL = 133; + UC_CPU_PPC_750GX_V10 = 134; + UC_CPU_PPC_750GX_V11 = 135; + UC_CPU_PPC_750GX_V12 = 136; + UC_CPU_PPC_750L_V20 = 137; + UC_CPU_PPC_750L_V21 = 138; + UC_CPU_PPC_750L_V22 = 139; + UC_CPU_PPC_750L_V30 = 140; + UC_CPU_PPC_750L_V32 = 141; + UC_CPU_PPC_7X5_V10 = 142; + UC_CPU_PPC_7X5_V11 = 143; + UC_CPU_PPC_7X5_V20 = 144; + UC_CPU_PPC_7X5_V21 = 145; + UC_CPU_PPC_7X5_V22 = 146; + UC_CPU_PPC_7X5_V23 = 147; + UC_CPU_PPC_7X5_V24 = 148; + UC_CPU_PPC_7X5_V25 = 149; + UC_CPU_PPC_7X5_V26 = 150; + UC_CPU_PPC_7X5_V27 = 151; + UC_CPU_PPC_7X5_V28 = 152; + UC_CPU_PPC_7400_V10 = 153; + UC_CPU_PPC_7400_V11 = 154; + UC_CPU_PPC_7400_V20 = 155; + UC_CPU_PPC_7400_V21 = 156; + UC_CPU_PPC_7400_V22 = 157; + UC_CPU_PPC_7400_V26 = 158; + UC_CPU_PPC_7400_V27 = 159; + UC_CPU_PPC_7400_V28 = 160; + UC_CPU_PPC_7400_V29 = 161; + UC_CPU_PPC_7410_V10 = 162; + UC_CPU_PPC_7410_V11 = 163; + UC_CPU_PPC_7410_V12 = 164; + UC_CPU_PPC_7410_V13 = 165; + UC_CPU_PPC_7410_V14 = 166; + UC_CPU_PPC_7448_V10 = 167; + UC_CPU_PPC_7448_V11 = 168; + UC_CPU_PPC_7448_V20 = 169; + UC_CPU_PPC_7448_V21 = 170; + UC_CPU_PPC_7450_V10 = 171; + UC_CPU_PPC_7450_V11 = 172; + UC_CPU_PPC_7450_V12 = 173; + UC_CPU_PPC_7450_V20 = 174; + UC_CPU_PPC_7450_V21 = 175; + UC_CPU_PPC_74X1_V23 = 176; + UC_CPU_PPC_74X1_V210 = 177; + UC_CPU_PPC_74X5_V10 = 178; + UC_CPU_PPC_74X5_V21 = 179; + UC_CPU_PPC_74X5_V32 = 180; + UC_CPU_PPC_74X5_V33 = 181; + UC_CPU_PPC_74X5_V34 = 182; + UC_CPU_PPC_74X7_V10 = 183; + UC_CPU_PPC_74X7_V11 = 184; + UC_CPU_PPC_74X7_V12 = 185; + UC_CPU_PPC_74X7A_V10 = 186; + UC_CPU_PPC_74X7A_V11 = 187; + UC_CPU_PPC_74X7A_V12 = 188; + UC_CPU_PPC_IOP480 = 1; + UC_CPU_PPC_X2VP20 = 42; + UC_CPU_PPC_440GRA = 35; + UC_CPU_PPC_440EPX = 38; + UC_CPU_PPC_MPC5200_V10 = 59; + UC_CPU_PPC_MPC5200_V11 = 59; + UC_CPU_PPC_MPC5200_V12 = 59; + UC_CPU_PPC_MPC5200B_V20 = 59; + UC_CPU_PPC_MPC5200B_V21 = 59; + UC_CPU_PPC_MPC834X = 63; + UC_CPU_PPC_MPC837X = 66; + UC_CPU_PPC_E500 = 73; + UC_CPU_PPC_MPC8533_V10 = 72; + UC_CPU_PPC_MPC8533_V11 = 73; + UC_CPU_PPC_MPC8533E_V10 = 72; + UC_CPU_PPC_MPC8533E_V11 = 73; + UC_CPU_PPC_MPC8540_V10 = 67; + UC_CPU_PPC_MPC8540_V20 = 68; + UC_CPU_PPC_MPC8540_V21 = 68; + UC_CPU_PPC_MPC8541_V10 = 68; + UC_CPU_PPC_MPC8541_V11 = 68; + UC_CPU_PPC_MPC8541E_V10 = 68; + UC_CPU_PPC_MPC8541E_V11 = 68; + UC_CPU_PPC_MPC8543_V10 = 69; + UC_CPU_PPC_MPC8543_V11 = 70; + UC_CPU_PPC_MPC8543_V20 = 71; + UC_CPU_PPC_MPC8543_V21 = 72; + UC_CPU_PPC_MPC8543E_V10 = 69; + UC_CPU_PPC_MPC8543E_V11 = 70; + UC_CPU_PPC_MPC8543E_V20 = 71; + UC_CPU_PPC_MPC8543E_V21 = 72; + UC_CPU_PPC_MPC8544_V10 = 72; + UC_CPU_PPC_MPC8544_V11 = 73; + UC_CPU_PPC_MPC8544E_V11 = 73; + UC_CPU_PPC_MPC8544E_V10 = 72; + UC_CPU_PPC_MPC8545_V10 = 69; + UC_CPU_PPC_MPC8545_V20 = 71; + UC_CPU_PPC_MPC8545_V21 = 72; + UC_CPU_PPC_MPC8545E_V10 = 69; + UC_CPU_PPC_MPC8545E_V20 = 71; + UC_CPU_PPC_MPC8545E_V21 = 72; + UC_CPU_PPC_MPC8547E_V10 = 69; + UC_CPU_PPC_MPC8547E_V20 = 71; + UC_CPU_PPC_MPC8547E_V21 = 72; + UC_CPU_PPC_MPC8548_V10 = 69; + UC_CPU_PPC_MPC8548_V11 = 70; + UC_CPU_PPC_MPC8548_V20 = 71; + UC_CPU_PPC_MPC8548_V21 = 72; + UC_CPU_PPC_MPC8548E_V10 = 69; + UC_CPU_PPC_MPC8548E_V11 = 70; + UC_CPU_PPC_MPC8548E_V20 = 71; + UC_CPU_PPC_MPC8548E_V21 = 72; + UC_CPU_PPC_MPC8555_V10 = 69; + UC_CPU_PPC_MPC8555_V11 = 70; + UC_CPU_PPC_MPC8555E_V10 = 69; + UC_CPU_PPC_MPC8555E_V11 = 70; + UC_CPU_PPC_MPC8560_V10 = 69; + UC_CPU_PPC_MPC8560_V20 = 71; + UC_CPU_PPC_MPC8560_V21 = 72; + UC_CPU_PPC_MPC8567 = 73; + UC_CPU_PPC_MPC8567E = 73; + UC_CPU_PPC_MPC8568 = 73; + UC_CPU_PPC_MPC8568E = 73; + UC_CPU_PPC_MPC8572 = 74; + UC_CPU_PPC_MPC8572E = 74; + UC_CPU_PPC_MPC8610 = 78; + UC_CPU_PPC_MPC8641 = 78; + UC_CPU_PPC_MPC8641D = 78; + + UC_CPU_PPC64_620 = 0; + UC_CPU_PPC64_630 = 1; + UC_CPU_PPC64_631 = 2; + UC_CPU_PPC64_POWER4 = 3; + UC_CPU_PPC64_POWER4P = 4; + UC_CPU_PPC64_POWER5 = 5; + UC_CPU_PPC64_POWER5P_V21 = 6; + UC_CPU_PPC64_POWER6 = 7; + UC_CPU_PPC64_POWER_SERVER_MASK = 8; + UC_CPU_PPC64_POWER7_BASE = 9; + UC_CPU_PPC64_POWER7_V23 = 10; + UC_CPU_PPC64_POWER7P_BASE = 11; + UC_CPU_PPC64_POWER7P_V21 = 12; + UC_CPU_PPC64_POWER8E_BASE = 13; + UC_CPU_PPC64_POWER8E_V21 = 14; + UC_CPU_PPC64_POWER8_BASE = 15; + UC_CPU_PPC64_POWER8_V20 = 16; + UC_CPU_PPC64_POWER8NVL_BASE = 17; + UC_CPU_PPC64_POWER8NVL_V10 = 18; + UC_CPU_PPC64_POWER9_BASE = 19; + UC_CPU_PPC64_POWER9_DD1 = 20; + UC_CPU_PPC64_POWER9_DD20 = 21; + UC_CPU_PPC64_POWER10_BASE = 22; + UC_CPU_PPC64_POWER10_DD1 = 23; + UC_CPU_PPC64_970_V22 = 24; + UC_CPU_PPC64_970FX_V10 = 25; + UC_CPU_PPC64_970FX_V20 = 26; + UC_CPU_PPC64_970FX_V21 = 27; + UC_CPU_PPC64_970FX_V30 = 28; + UC_CPU_PPC64_970FX_V31 = 29; + UC_CPU_PPC64_970MP_V10 = 30; + UC_CPU_PPC64_970MP_V11 = 31; + UC_CPU_PPC64_CELL_V10 = 32; + UC_CPU_PPC64_CELL_V20 = 33; + UC_CPU_PPC64_CELL_V30 = 34; + UC_CPU_PPC64_CELL_V31 = 35; + UC_CPU_PPC64_RS64 = 36; + UC_CPU_PPC64_RS64II = 37; + UC_CPU_PPC64_RS64III = 38; + UC_CPU_PPC64_RS64IV = 39; + UC_CPU_PPC64_CELL_V32 = 35; + UC_CPU_PPC64_CELL = 35; + // PPC registers UC_PPC_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/RiscvConst.pas b/bindings/pascal/unicorn/RiscvConst.pas index 7aaa9b74..98a30ce5 100644 --- a/bindings/pascal/unicorn/RiscvConst.pas +++ b/bindings/pascal/unicorn/RiscvConst.pas @@ -5,6 +5,16 @@ unit RiscvConst; interface const + UC_CPU_RISCV32_ANY = 0; + UC_CPU_RISCV32_BASE32 = 1; + UC_CPU_RISCV32_SIFIVE_E31 = 2; + UC_CPU_RISCV32_SIFIVE_U34 = 3; + + UC_CPU_RISCV64_ANY = 0; + UC_CPU_RISCV64_BASE64 = 1; + UC_CPU_RISCV64_SIFIVE_E51 = 2; + UC_CPU_RISCV64_SIFIVE_U54 = 3; + // RISCV registers UC_RISCV_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/SparcConst.pas b/bindings/pascal/unicorn/SparcConst.pas index 32ed3013..9e77d3bb 100644 --- a/bindings/pascal/unicorn/SparcConst.pas +++ b/bindings/pascal/unicorn/SparcConst.pas @@ -5,6 +5,38 @@ unit SparcConst; interface const + UC_CPU_SPARC_FUJITSU_MB86904 = 0; + UC_CPU_SPARC_FUJITSU_MB86907 = 1; + UC_CPU_SPARC_TI_MICROSPARC_I = 2; + UC_CPU_SPARC_TI_MICROSPARC_II = 3; + UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4; + UC_CPU_SPARC_TI_SUPERSPARC_40 = 5; + UC_CPU_SPARC_TI_SUPERSPARC_50 = 6; + UC_CPU_SPARC_TI_SUPERSPARC_51 = 7; + UC_CPU_SPARC_TI_SUPERSPARC_60 = 8; + UC_CPU_SPARC_TI_SUPERSPARC_61 = 9; + UC_CPU_SPARC_TI_SUPERSPARC_II = 10; + UC_CPU_SPARC_LEON2 = 11; + UC_CPU_SPARC_LEON3 = 12; + + UC_CPU_SPARC64_FUJITSU = 0; + UC_CPU_SPARC64_FUJITSU_III = 1; + UC_CPU_SPARC64_FUJITSU_IV = 2; + UC_CPU_SPARC64_FUJITSU_V = 3; + UC_CPU_SPARC64_TI_ULTRASPARC_I = 4; + UC_CPU_SPARC64_TI_ULTRASPARC_II = 5; + UC_CPU_SPARC64_TI_ULTRASPARC_III = 6; + UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7; + UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8; + UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9; + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10; + UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11; + UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12; + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13; + UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14; + UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15; + UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16; + // SPARC registers UC_SPARC_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 29303b89..6884687b 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -110,6 +110,22 @@ const UC_API_MAJOR = 2; UC_QUERY_ARCH = 3; UC_QUERY_TIMEOUT = 4; + UC_CTL_IO_NONE = 0; + UC_CTL_IO_WRITE = 1; + UC_CTL_IO_READ = 2; + UC_CTL_IO_READ_WRITE = 3; + + UC_CTL_UC_MODE = 0; + UC_CTL_UC_PAGE_SIZE = 1; + UC_CTL_UC_ARCH = 2; + UC_CTL_UC_TIMEOUT = 3; + UC_CTL_UC_EXITS_CNT = 4; + UC_CTL_UC_EXITS = 5; + UC_CTL_CPU_MODEL = 6; + UC_CTL_TB_EDGE = 7; + UC_CTL_TB_REQUEST_CACHE = 8; + UC_CTL_TB_REMOVE_CACHE = 9; + UC_PROT_NONE = 0; UC_PROT_READ = 1; UC_PROT_WRITE = 2; diff --git a/bindings/pascal/unicorn/X86Const.pas b/bindings/pascal/unicorn/X86Const.pas index 9f05a6f6..446f7602 100644 --- a/bindings/pascal/unicorn/X86Const.pas +++ b/bindings/pascal/unicorn/X86Const.pas @@ -5,6 +5,45 @@ unit X86Const; interface const + UC_CPU_X86_QEMU64 = 0; + UC_CPU_X86_PHENOM = 1; + UC_CPU_X86_CORE2DUO = 2; + UC_CPU_X86_KVM64 = 3; + UC_CPU_X86_QEMU32 = 4; + UC_CPU_X86_KVM32 = 5; + UC_CPU_X86_COREDUO = 6; + UC_CPU_X86_486 = 7; + UC_CPU_X86_PENTIUM = 8; + UC_CPU_X86_PENTIUM2 = 9; + UC_CPU_X86_PENTIUM3 = 10; + UC_CPU_X86_ATHLON = 11; + UC_CPU_X86_N270 = 12; + UC_CPU_X86_CONROE = 13; + UC_CPU_X86_PENRYN = 14; + UC_CPU_X86_NEHALEM = 15; + UC_CPU_X86_WESTMERE = 16; + UC_CPU_X86_SANDYBRIDGE = 17; + UC_CPU_X86_IVYBRIDGE = 18; + UC_CPU_X86_HASWELL = 19; + UC_CPU_X86_BROADWELL = 20; + UC_CPU_X86_SKYLAKE_CLIENT = 21; + UC_CPU_X86_SKYLAKE_SERVER = 22; + UC_CPU_X86_CASCADELAKE_SERVER = 23; + UC_CPU_X86_COOPERLAKE = 24; + UC_CPU_X86_ICELAKE_CLIENT = 25; + UC_CPU_X86_ICELAKE_SERVER = 26; + UC_CPU_X86_DENVERTON = 27; + UC_CPU_X86_SNOWRIDGE = 28; + UC_CPU_X86_KNIGHTSMILL = 29; + UC_CPU_X86_OPTERON_G1 = 30; + UC_CPU_X86_OPTERON_G2 = 31; + UC_CPU_X86_OPTERON_G3 = 32; + UC_CPU_X86_OPTERON_G4 = 33; + UC_CPU_X86_OPTERON_G5 = 34; + UC_CPU_X86_EPYC = 35; + UC_CPU_X86_DHYANA = 36; + UC_CPU_X86_EPYC_ROME = 37; + // X86 registers UC_X86_REG_INVALID = 0; diff --git a/bindings/python/Makefile b/bindings/python/Makefile index ea831fd9..363d646f 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -3,16 +3,16 @@ .PHONY: gen_const install install3 clean sdist sdist3 bdist bdist3 sdist_win bdist_win gen_const: - cd .. && python const_generator.py python + cd .. && python3 const_generator.py python install: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll if test -n "${DESTDIR}"; then \ - python setup.py install --root="${DESTDIR}"; \ + python3 setup.py install --root="${DESTDIR}"; \ else \ - python setup.py install; \ + python3 setup.py install; \ fi install3: @@ -30,7 +30,7 @@ sdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python setup.py sdist register upload + python3 setup.py sdist register upload # build & upload PyPi package with source code of the core sdist3: @@ -44,7 +44,7 @@ bdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python setup.py bdist_wheel register upload + python3 setup.py bdist_wheel register upload # build & upload PyPi package with precompiled core bdist3: @@ -57,7 +57,7 @@ bdist3: # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand sdist_win: rm -rf src/ dist/ - python setup.py sdist register upload + python3 setup.py sdist register upload # build & upload PyPi package with prebuilt core # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand diff --git a/bindings/python/unicorn/arm64_const.py b/bindings/python/unicorn/arm64_const.py index ae8e77eb..867aba49 100644 --- a/bindings/python/unicorn/arm64_const.py +++ b/bindings/python/unicorn/arm64_const.py @@ -1,5 +1,10 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.py] +UC_CPU_AARCH64_A57 = 0 +UC_CPU_AARCH64_A53 = 1 +UC_CPU_AARCH64_A72 = 2 +UC_CPU_AARCH64_MAX = 3 + # ARM64 registers UC_ARM64_REG_INVALID = 0 diff --git a/bindings/python/unicorn/arm_const.py b/bindings/python/unicorn/arm_const.py index 8526f2b9..af8fb5ab 100644 --- a/bindings/python/unicorn/arm_const.py +++ b/bindings/python/unicorn/arm_const.py @@ -1,5 +1,39 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.py] +UC_CPU_ARM_926 = 0 +UC_CPU_ARM_946 = 1 +UC_CPU_ARM_1026 = 2 +UC_CPU_ARM_1136_R2 = 3 +UC_CPU_ARM_1136 = 4 +UC_CPU_ARM_1176 = 5 +UC_CPU_ARM_11MPCORE = 6 +UC_CPU_ARM_CORTEX_M0 = 7 +UC_CPU_ARM_CORTEX_M3 = 8 +UC_CPU_ARM_CORTEX_M4 = 9 +UC_CPU_ARM_CORTEX_M7 = 10 +UC_CPU_ARM_CORTEX_M33 = 11 +UC_CPU_ARM_CORTEX_R5 = 12 +UC_CPU_ARM_CORTEX_R5F = 13 +UC_CPU_ARM_CORTEX_A8 = 14 +UC_CPU_ARM_CORTEX_A9 = 15 +UC_CPU_ARM_CORTEX_A7 = 16 +UC_CPU_ARM_CORTEX_A15 = 17 +UC_CPU_ARM_TI925T = 18 +UC_CPU_ARM_SA1100 = 19 +UC_CPU_ARM_SA1110 = 20 +UC_CPU_ARM_PXA250 = 21 +UC_CPU_ARM_PXA255 = 22 +UC_CPU_ARM_PXA260 = 23 +UC_CPU_ARM_PXA261 = 24 +UC_CPU_ARM_PXA262 = 25 +UC_CPU_ARM_PXA270A0 = 26 +UC_CPU_ARM_PXA270A1 = 27 +UC_CPU_ARM_PXA270B0 = 28 +UC_CPU_ARM_PXA270B1 = 29 +UC_CPU_ARM_PXA270C0 = 30 +UC_CPU_ARM_PXA270C5 = 31 +UC_CPU_ARM_MAX = 32 + # ARM registers UC_ARM_REG_INVALID = 0 diff --git a/bindings/python/unicorn/m68k_const.py b/bindings/python/unicorn/m68k_const.py index 37b00b99..f585b225 100644 --- a/bindings/python/unicorn/m68k_const.py +++ b/bindings/python/unicorn/m68k_const.py @@ -1,5 +1,15 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.py] +UC_CPU_M5206_CPU = 0 +UC_CPU_M68000_CPU = 1 +UC_CPU_M68020_CPU = 2 +UC_CPU_M68030_CPU = 3 +UC_CPU_M68040_CPU = 4 +UC_CPU_M68060_CPU = 5 +UC_CPU_M5208_CPU = 6 +UC_CPU_CFV4E_CPU = 7 +UC_CPU_ANY_CPU = 8 + # M68K registers UC_M68K_REG_INVALID = 0 diff --git a/bindings/python/unicorn/mips_const.py b/bindings/python/unicorn/mips_const.py index a8370ae4..43b0e49f 100644 --- a/bindings/python/unicorn/mips_const.py +++ b/bindings/python/unicorn/mips_const.py @@ -1,5 +1,35 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.py] +UC_CPU_MIPS_4KC = 0 +UC_CPU_MIPS_4KM = 1 +UC_CPU_MIPS_4KECR1 = 2 +UC_CPU_MIPS_4KEMR1 = 3 +UC_CPU_MIPS_4KEC = 4 +UC_CPU_MIPS_4KEM = 5 +UC_CPU_MIPS_24KC = 6 +UC_CPU_MIPS_24KEC = 7 +UC_CPU_MIPS_24KF = 8 +UC_CPU_MIPS_34KF = 9 +UC_CPU_MIPS_74KF = 10 +UC_CPU_MIPS_M14K = 11 +UC_CPU_MIPS_M14KC = 12 +UC_CPU_MIPS_P5600 = 13 +UC_CPU_MIPS_MIPS32R6_GENERIC = 14 +UC_CPU_MIPS_I7200 = 15 +UC_CPU_MIPS_R4000 = 16 +UC_CPU_MIPS_VR5432 = 17 +UC_CPU_MIPS_5KC = 18 +UC_CPU_MIPS_5KF = 19 +UC_CPU_MIPS_20KC = 20 +UC_CPU_MIPS_MIPS64R2_GENERIC = 21 +UC_CPU_MIPS_5KEC = 22 +UC_CPU_MIPS_5KEF = 23 +UC_CPU_MIPS_I6400 = 24 +UC_CPU_MIPS_I6500 = 25 +UC_CPU_MIPS_LOONGSON_2E = 26 +UC_CPU_MIPS_LOONGSON_2F = 27 +UC_CPU_MIPS_MIPS64DSPR2 = 28 + # MIPS registers UC_MIPS_REG_INVALID = 0 diff --git a/bindings/python/unicorn/ppc_const.py b/bindings/python/unicorn/ppc_const.py index 18162dac..1d4813cb 100644 --- a/bindings/python/unicorn/ppc_const.py +++ b/bindings/python/unicorn/ppc_const.py @@ -1,5 +1,306 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.py] +UC_CPU_PPC_401A1 = 0 +UC_CPU_PPC_401B2 = 1 +UC_CPU_PPC_401C2 = 2 +UC_CPU_PPC_401D2 = 3 +UC_CPU_PPC_401E2 = 4 +UC_CPU_PPC_401F2 = 5 +UC_CPU_PPC_401G2 = 6 +UC_CPU_PPC_COBRA = 7 +UC_CPU_PPC_403GA = 8 +UC_CPU_PPC_403GB = 9 +UC_CPU_PPC_403GC = 10 +UC_CPU_PPC_403GCX = 11 +UC_CPU_PPC_405D2 = 12 +UC_CPU_PPC_405D4 = 13 +UC_CPU_PPC_405CRA = 14 +UC_CPU_PPC_405CRB = 15 +UC_CPU_PPC_405CRC = 16 +UC_CPU_PPC_405EP = 17 +UC_CPU_PPC_405EZ = 18 +UC_CPU_PPC_405GPA = 19 +UC_CPU_PPC_405GPB = 20 +UC_CPU_PPC_405GPC = 21 +UC_CPU_PPC_405GPD = 22 +UC_CPU_PPC_405GPR = 23 +UC_CPU_PPC_405LP = 24 +UC_CPU_PPC_NPE405H = 25 +UC_CPU_PPC_NPE405H2 = 26 +UC_CPU_PPC_NPE405L = 27 +UC_CPU_PPC_NPE4GS3 = 28 +UC_CPU_PPC_STB03 = 29 +UC_CPU_PPC_STB04 = 30 +UC_CPU_PPC_STB25 = 31 +UC_CPU_PPC_X2VP4 = 32 +UC_CPU_PPC_440_XILINX = 33 +UC_CPU_PPC_440EPA = 34 +UC_CPU_PPC_440EPB = 35 +UC_CPU_PPC_440GPB = 36 +UC_CPU_PPC_440GPC = 37 +UC_CPU_PPC_440GRX = 38 +UC_CPU_PPC_440GXA = 39 +UC_CPU_PPC_440GXB = 40 +UC_CPU_PPC_440GXC = 41 +UC_CPU_PPC_440GXF = 42 +UC_CPU_PPC_440SP = 43 +UC_CPU_PPC_440SP2 = 44 +UC_CPU_PPC_440SPE = 45 +UC_CPU_PPC_460EXB = 46 +UC_CPU_PPC_MPC5XX = 47 +UC_CPU_PPC_MPC8XX = 48 +UC_CPU_PPC_G2 = 49 +UC_CPU_PPC_G2H4 = 50 +UC_CPU_PPC_G2GP = 51 +UC_CPU_PPC_G2LS = 52 +UC_CPU_PPC_MPC603 = 53 +UC_CPU_PPC_G2_HIP3 = 54 +UC_CPU_PPC_G2_HIP4 = 55 +UC_CPU_PPC_G2LE = 56 +UC_CPU_PPC_G2LEGP = 57 +UC_CPU_PPC_G2LELS = 58 +UC_CPU_PPC_G2LEGP1 = 59 +UC_CPU_PPC_G2LEGP3 = 60 +UC_CPU_PPC_E200Z5 = 61 +UC_CPU_PPC_E200Z6 = 62 +UC_CPU_PPC_E300C1 = 63 +UC_CPU_PPC_E300C2 = 64 +UC_CPU_PPC_E300C3 = 65 +UC_CPU_PPC_E300C4 = 66 +UC_CPU_PPC_E500V1_V10 = 67 +UC_CPU_PPC_E500V1_V20 = 68 +UC_CPU_PPC_E500V2_V10 = 69 +UC_CPU_PPC_E500V2_V11 = 70 +UC_CPU_PPC_E500V2_V20 = 71 +UC_CPU_PPC_E500V2_V21 = 72 +UC_CPU_PPC_E500V2_V22 = 73 +UC_CPU_PPC_E500V2_V30 = 74 +UC_CPU_PPC_E500MC = 75 +UC_CPU_PPC_E5500 = 76 +UC_CPU_PPC_E6500 = 77 +UC_CPU_PPC_E600 = 78 +UC_CPU_PPC_601_V0 = 79 +UC_CPU_PPC_601_V1 = 80 +UC_CPU_PPC_601_V2 = 81 +UC_CPU_PPC_602 = 82 +UC_CPU_PPC_603 = 83 +UC_CPU_PPC_603E_V11 = 84 +UC_CPU_PPC_603E_V12 = 85 +UC_CPU_PPC_603E_V13 = 86 +UC_CPU_PPC_603E_V14 = 87 +UC_CPU_PPC_603E_V22 = 88 +UC_CPU_PPC_603E_V3 = 89 +UC_CPU_PPC_603E_V4 = 90 +UC_CPU_PPC_603E_V41 = 91 +UC_CPU_PPC_603E7T = 92 +UC_CPU_PPC_603E7V = 93 +UC_CPU_PPC_603E7V1 = 94 +UC_CPU_PPC_603E7V2 = 95 +UC_CPU_PPC_603E7 = 96 +UC_CPU_PPC_603P = 97 +UC_CPU_PPC_604 = 98 +UC_CPU_PPC_604E_V10 = 99 +UC_CPU_PPC_604E_V22 = 100 +UC_CPU_PPC_604E_V24 = 101 +UC_CPU_PPC_604R = 102 +UC_CPU_PPC_7X0_V10 = 103 +UC_CPU_PPC_7X0_V20 = 104 +UC_CPU_PPC_7X0_V21 = 105 +UC_CPU_PPC_7X0_V22 = 106 +UC_CPU_PPC_7X0_V30 = 107 +UC_CPU_PPC_7X0_V31 = 108 +UC_CPU_PPC_740E = 109 +UC_CPU_PPC_750E = 110 +UC_CPU_PPC_7X0P = 111 +UC_CPU_PPC_750CL_V10 = 112 +UC_CPU_PPC_750CL_V20 = 113 +UC_CPU_PPC_750CX_V10 = 114 +UC_CPU_PPC_750CX_V20 = 115 +UC_CPU_PPC_750CX_V21 = 116 +UC_CPU_PPC_750CX_V22 = 117 +UC_CPU_PPC_750CXE_V21 = 118 +UC_CPU_PPC_750CXE_V22 = 119 +UC_CPU_PPC_750CXE_V23 = 120 +UC_CPU_PPC_750CXE_V24 = 121 +UC_CPU_PPC_750CXE_V24B = 122 +UC_CPU_PPC_750CXE_V30 = 123 +UC_CPU_PPC_750CXE_V31 = 124 +UC_CPU_PPC_750CXE_V31B = 125 +UC_CPU_PPC_750CXR = 126 +UC_CPU_PPC_750FL = 127 +UC_CPU_PPC_750FX_V10 = 128 +UC_CPU_PPC_750FX_V20 = 129 +UC_CPU_PPC_750FX_V21 = 130 +UC_CPU_PPC_750FX_V22 = 131 +UC_CPU_PPC_750FX_V23 = 132 +UC_CPU_PPC_750GL = 133 +UC_CPU_PPC_750GX_V10 = 134 +UC_CPU_PPC_750GX_V11 = 135 +UC_CPU_PPC_750GX_V12 = 136 +UC_CPU_PPC_750L_V20 = 137 +UC_CPU_PPC_750L_V21 = 138 +UC_CPU_PPC_750L_V22 = 139 +UC_CPU_PPC_750L_V30 = 140 +UC_CPU_PPC_750L_V32 = 141 +UC_CPU_PPC_7X5_V10 = 142 +UC_CPU_PPC_7X5_V11 = 143 +UC_CPU_PPC_7X5_V20 = 144 +UC_CPU_PPC_7X5_V21 = 145 +UC_CPU_PPC_7X5_V22 = 146 +UC_CPU_PPC_7X5_V23 = 147 +UC_CPU_PPC_7X5_V24 = 148 +UC_CPU_PPC_7X5_V25 = 149 +UC_CPU_PPC_7X5_V26 = 150 +UC_CPU_PPC_7X5_V27 = 151 +UC_CPU_PPC_7X5_V28 = 152 +UC_CPU_PPC_7400_V10 = 153 +UC_CPU_PPC_7400_V11 = 154 +UC_CPU_PPC_7400_V20 = 155 +UC_CPU_PPC_7400_V21 = 156 +UC_CPU_PPC_7400_V22 = 157 +UC_CPU_PPC_7400_V26 = 158 +UC_CPU_PPC_7400_V27 = 159 +UC_CPU_PPC_7400_V28 = 160 +UC_CPU_PPC_7400_V29 = 161 +UC_CPU_PPC_7410_V10 = 162 +UC_CPU_PPC_7410_V11 = 163 +UC_CPU_PPC_7410_V12 = 164 +UC_CPU_PPC_7410_V13 = 165 +UC_CPU_PPC_7410_V14 = 166 +UC_CPU_PPC_7448_V10 = 167 +UC_CPU_PPC_7448_V11 = 168 +UC_CPU_PPC_7448_V20 = 169 +UC_CPU_PPC_7448_V21 = 170 +UC_CPU_PPC_7450_V10 = 171 +UC_CPU_PPC_7450_V11 = 172 +UC_CPU_PPC_7450_V12 = 173 +UC_CPU_PPC_7450_V20 = 174 +UC_CPU_PPC_7450_V21 = 175 +UC_CPU_PPC_74X1_V23 = 176 +UC_CPU_PPC_74X1_V210 = 177 +UC_CPU_PPC_74X5_V10 = 178 +UC_CPU_PPC_74X5_V21 = 179 +UC_CPU_PPC_74X5_V32 = 180 +UC_CPU_PPC_74X5_V33 = 181 +UC_CPU_PPC_74X5_V34 = 182 +UC_CPU_PPC_74X7_V10 = 183 +UC_CPU_PPC_74X7_V11 = 184 +UC_CPU_PPC_74X7_V12 = 185 +UC_CPU_PPC_74X7A_V10 = 186 +UC_CPU_PPC_74X7A_V11 = 187 +UC_CPU_PPC_74X7A_V12 = 188 +UC_CPU_PPC_IOP480 = 1 +UC_CPU_PPC_X2VP20 = 42 +UC_CPU_PPC_440GRA = 35 +UC_CPU_PPC_440EPX = 38 +UC_CPU_PPC_MPC5200_V10 = 59 +UC_CPU_PPC_MPC5200_V11 = 59 +UC_CPU_PPC_MPC5200_V12 = 59 +UC_CPU_PPC_MPC5200B_V20 = 59 +UC_CPU_PPC_MPC5200B_V21 = 59 +UC_CPU_PPC_MPC834X = 63 +UC_CPU_PPC_MPC837X = 66 +UC_CPU_PPC_E500 = 73 +UC_CPU_PPC_MPC8533_V10 = 72 +UC_CPU_PPC_MPC8533_V11 = 73 +UC_CPU_PPC_MPC8533E_V10 = 72 +UC_CPU_PPC_MPC8533E_V11 = 73 +UC_CPU_PPC_MPC8540_V10 = 67 +UC_CPU_PPC_MPC8540_V20 = 68 +UC_CPU_PPC_MPC8540_V21 = 68 +UC_CPU_PPC_MPC8541_V10 = 68 +UC_CPU_PPC_MPC8541_V11 = 68 +UC_CPU_PPC_MPC8541E_V10 = 68 +UC_CPU_PPC_MPC8541E_V11 = 68 +UC_CPU_PPC_MPC8543_V10 = 69 +UC_CPU_PPC_MPC8543_V11 = 70 +UC_CPU_PPC_MPC8543_V20 = 71 +UC_CPU_PPC_MPC8543_V21 = 72 +UC_CPU_PPC_MPC8543E_V10 = 69 +UC_CPU_PPC_MPC8543E_V11 = 70 +UC_CPU_PPC_MPC8543E_V20 = 71 +UC_CPU_PPC_MPC8543E_V21 = 72 +UC_CPU_PPC_MPC8544_V10 = 72 +UC_CPU_PPC_MPC8544_V11 = 73 +UC_CPU_PPC_MPC8544E_V11 = 73 +UC_CPU_PPC_MPC8544E_V10 = 72 +UC_CPU_PPC_MPC8545_V10 = 69 +UC_CPU_PPC_MPC8545_V20 = 71 +UC_CPU_PPC_MPC8545_V21 = 72 +UC_CPU_PPC_MPC8545E_V10 = 69 +UC_CPU_PPC_MPC8545E_V20 = 71 +UC_CPU_PPC_MPC8545E_V21 = 72 +UC_CPU_PPC_MPC8547E_V10 = 69 +UC_CPU_PPC_MPC8547E_V20 = 71 +UC_CPU_PPC_MPC8547E_V21 = 72 +UC_CPU_PPC_MPC8548_V10 = 69 +UC_CPU_PPC_MPC8548_V11 = 70 +UC_CPU_PPC_MPC8548_V20 = 71 +UC_CPU_PPC_MPC8548_V21 = 72 +UC_CPU_PPC_MPC8548E_V10 = 69 +UC_CPU_PPC_MPC8548E_V11 = 70 +UC_CPU_PPC_MPC8548E_V20 = 71 +UC_CPU_PPC_MPC8548E_V21 = 72 +UC_CPU_PPC_MPC8555_V10 = 69 +UC_CPU_PPC_MPC8555_V11 = 70 +UC_CPU_PPC_MPC8555E_V10 = 69 +UC_CPU_PPC_MPC8555E_V11 = 70 +UC_CPU_PPC_MPC8560_V10 = 69 +UC_CPU_PPC_MPC8560_V20 = 71 +UC_CPU_PPC_MPC8560_V21 = 72 +UC_CPU_PPC_MPC8567 = 73 +UC_CPU_PPC_MPC8567E = 73 +UC_CPU_PPC_MPC8568 = 73 +UC_CPU_PPC_MPC8568E = 73 +UC_CPU_PPC_MPC8572 = 74 +UC_CPU_PPC_MPC8572E = 74 +UC_CPU_PPC_MPC8610 = 78 +UC_CPU_PPC_MPC8641 = 78 +UC_CPU_PPC_MPC8641D = 78 + +UC_CPU_PPC64_620 = 0 +UC_CPU_PPC64_630 = 1 +UC_CPU_PPC64_631 = 2 +UC_CPU_PPC64_POWER4 = 3 +UC_CPU_PPC64_POWER4P = 4 +UC_CPU_PPC64_POWER5 = 5 +UC_CPU_PPC64_POWER5P_V21 = 6 +UC_CPU_PPC64_POWER6 = 7 +UC_CPU_PPC64_POWER_SERVER_MASK = 8 +UC_CPU_PPC64_POWER7_BASE = 9 +UC_CPU_PPC64_POWER7_V23 = 10 +UC_CPU_PPC64_POWER7P_BASE = 11 +UC_CPU_PPC64_POWER7P_V21 = 12 +UC_CPU_PPC64_POWER8E_BASE = 13 +UC_CPU_PPC64_POWER8E_V21 = 14 +UC_CPU_PPC64_POWER8_BASE = 15 +UC_CPU_PPC64_POWER8_V20 = 16 +UC_CPU_PPC64_POWER8NVL_BASE = 17 +UC_CPU_PPC64_POWER8NVL_V10 = 18 +UC_CPU_PPC64_POWER9_BASE = 19 +UC_CPU_PPC64_POWER9_DD1 = 20 +UC_CPU_PPC64_POWER9_DD20 = 21 +UC_CPU_PPC64_POWER10_BASE = 22 +UC_CPU_PPC64_POWER10_DD1 = 23 +UC_CPU_PPC64_970_V22 = 24 +UC_CPU_PPC64_970FX_V10 = 25 +UC_CPU_PPC64_970FX_V20 = 26 +UC_CPU_PPC64_970FX_V21 = 27 +UC_CPU_PPC64_970FX_V30 = 28 +UC_CPU_PPC64_970FX_V31 = 29 +UC_CPU_PPC64_970MP_V10 = 30 +UC_CPU_PPC64_970MP_V11 = 31 +UC_CPU_PPC64_CELL_V10 = 32 +UC_CPU_PPC64_CELL_V20 = 33 +UC_CPU_PPC64_CELL_V30 = 34 +UC_CPU_PPC64_CELL_V31 = 35 +UC_CPU_PPC64_RS64 = 36 +UC_CPU_PPC64_RS64II = 37 +UC_CPU_PPC64_RS64III = 38 +UC_CPU_PPC64_RS64IV = 39 +UC_CPU_PPC64_CELL_V32 = 35 +UC_CPU_PPC64_CELL = 35 + # PPC registers UC_PPC_REG_INVALID = 0 diff --git a/bindings/python/unicorn/riscv_const.py b/bindings/python/unicorn/riscv_const.py index e4adbcd7..91463afb 100644 --- a/bindings/python/unicorn/riscv_const.py +++ b/bindings/python/unicorn/riscv_const.py @@ -1,5 +1,15 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.py] +UC_CPU_RISCV32_ANY = 0 +UC_CPU_RISCV32_BASE32 = 1 +UC_CPU_RISCV32_SIFIVE_E31 = 2 +UC_CPU_RISCV32_SIFIVE_U34 = 3 + +UC_CPU_RISCV64_ANY = 0 +UC_CPU_RISCV64_BASE64 = 1 +UC_CPU_RISCV64_SIFIVE_E51 = 2 +UC_CPU_RISCV64_SIFIVE_U54 = 3 + # RISCV registers UC_RISCV_REG_INVALID = 0 diff --git a/bindings/python/unicorn/sparc_const.py b/bindings/python/unicorn/sparc_const.py index 7bd326d0..a15599f0 100644 --- a/bindings/python/unicorn/sparc_const.py +++ b/bindings/python/unicorn/sparc_const.py @@ -1,5 +1,37 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.py] +UC_CPU_SPARC_FUJITSU_MB86904 = 0 +UC_CPU_SPARC_FUJITSU_MB86907 = 1 +UC_CPU_SPARC_TI_MICROSPARC_I = 2 +UC_CPU_SPARC_TI_MICROSPARC_II = 3 +UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4 +UC_CPU_SPARC_TI_SUPERSPARC_40 = 5 +UC_CPU_SPARC_TI_SUPERSPARC_50 = 6 +UC_CPU_SPARC_TI_SUPERSPARC_51 = 7 +UC_CPU_SPARC_TI_SUPERSPARC_60 = 8 +UC_CPU_SPARC_TI_SUPERSPARC_61 = 9 +UC_CPU_SPARC_TI_SUPERSPARC_II = 10 +UC_CPU_SPARC_LEON2 = 11 +UC_CPU_SPARC_LEON3 = 12 + +UC_CPU_SPARC64_FUJITSU = 0 +UC_CPU_SPARC64_FUJITSU_III = 1 +UC_CPU_SPARC64_FUJITSU_IV = 2 +UC_CPU_SPARC64_FUJITSU_V = 3 +UC_CPU_SPARC64_TI_ULTRASPARC_I = 4 +UC_CPU_SPARC64_TI_ULTRASPARC_II = 5 +UC_CPU_SPARC64_TI_ULTRASPARC_III = 6 +UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7 +UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8 +UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 +UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 +UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11 +UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 +UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 +UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 +UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 +UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16 + # SPARC registers UC_SPARC_REG_INVALID = 0 diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index a517572a..10a7ae51 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -105,6 +105,22 @@ UC_QUERY_PAGE_SIZE = 2 UC_QUERY_ARCH = 3 UC_QUERY_TIMEOUT = 4 +UC_CTL_IO_NONE = 0 +UC_CTL_IO_WRITE = 1 +UC_CTL_IO_READ = 2 +UC_CTL_IO_READ_WRITE = 3 + +UC_CTL_UC_MODE = 0 +UC_CTL_UC_PAGE_SIZE = 1 +UC_CTL_UC_ARCH = 2 +UC_CTL_UC_TIMEOUT = 3 +UC_CTL_UC_EXITS_CNT = 4 +UC_CTL_UC_EXITS = 5 +UC_CTL_CPU_MODEL = 6 +UC_CTL_TB_EDGE = 7 +UC_CTL_TB_REQUEST_CACHE = 8 +UC_CTL_TB_REMOVE_CACHE = 9 + UC_PROT_NONE = 0 UC_PROT_READ = 1 UC_PROT_WRITE = 2 diff --git a/bindings/python/unicorn/x86_const.py b/bindings/python/unicorn/x86_const.py index 35803fe7..46454371 100644 --- a/bindings/python/unicorn/x86_const.py +++ b/bindings/python/unicorn/x86_const.py @@ -1,5 +1,44 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.py] +UC_CPU_X86_QEMU64 = 0 +UC_CPU_X86_PHENOM = 1 +UC_CPU_X86_CORE2DUO = 2 +UC_CPU_X86_KVM64 = 3 +UC_CPU_X86_QEMU32 = 4 +UC_CPU_X86_KVM32 = 5 +UC_CPU_X86_COREDUO = 6 +UC_CPU_X86_486 = 7 +UC_CPU_X86_PENTIUM = 8 +UC_CPU_X86_PENTIUM2 = 9 +UC_CPU_X86_PENTIUM3 = 10 +UC_CPU_X86_ATHLON = 11 +UC_CPU_X86_N270 = 12 +UC_CPU_X86_CONROE = 13 +UC_CPU_X86_PENRYN = 14 +UC_CPU_X86_NEHALEM = 15 +UC_CPU_X86_WESTMERE = 16 +UC_CPU_X86_SANDYBRIDGE = 17 +UC_CPU_X86_IVYBRIDGE = 18 +UC_CPU_X86_HASWELL = 19 +UC_CPU_X86_BROADWELL = 20 +UC_CPU_X86_SKYLAKE_CLIENT = 21 +UC_CPU_X86_SKYLAKE_SERVER = 22 +UC_CPU_X86_CASCADELAKE_SERVER = 23 +UC_CPU_X86_COOPERLAKE = 24 +UC_CPU_X86_ICELAKE_CLIENT = 25 +UC_CPU_X86_ICELAKE_SERVER = 26 +UC_CPU_X86_DENVERTON = 27 +UC_CPU_X86_SNOWRIDGE = 28 +UC_CPU_X86_KNIGHTSMILL = 29 +UC_CPU_X86_OPTERON_G1 = 30 +UC_CPU_X86_OPTERON_G2 = 31 +UC_CPU_X86_OPTERON_G3 = 32 +UC_CPU_X86_OPTERON_G4 = 33 +UC_CPU_X86_OPTERON_G5 = 34 +UC_CPU_X86_EPYC = 35 +UC_CPU_X86_DHYANA = 36 +UC_CPU_X86_EPYC_ROME = 37 + # X86 registers UC_X86_REG_INVALID = 0 diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile index 9d52de94..aa92fa53 100644 --- a/bindings/ruby/Makefile +++ b/bindings/ruby/Makefile @@ -8,4 +8,4 @@ install: gen_const cd unicorn_gem && gem install --local pkg/unicorn-engine-1.0.1.gem gen_const: - cd .. && python const_generator.py ruby + cd .. && python3 const_generator.py ruby diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb index 4c98dd0f..ce051599 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb @@ -2,6 +2,11 @@ module UnicornEngine + UC_CPU_AARCH64_A57 = 0 + UC_CPU_AARCH64_A53 = 1 + UC_CPU_AARCH64_A72 = 2 + UC_CPU_AARCH64_MAX = 3 + # ARM64 registers UC_ARM64_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb index 1d908787..66ad11bf 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb @@ -2,6 +2,40 @@ module UnicornEngine + UC_CPU_ARM_926 = 0 + UC_CPU_ARM_946 = 1 + UC_CPU_ARM_1026 = 2 + UC_CPU_ARM_1136_R2 = 3 + UC_CPU_ARM_1136 = 4 + UC_CPU_ARM_1176 = 5 + UC_CPU_ARM_11MPCORE = 6 + UC_CPU_ARM_CORTEX_M0 = 7 + UC_CPU_ARM_CORTEX_M3 = 8 + UC_CPU_ARM_CORTEX_M4 = 9 + UC_CPU_ARM_CORTEX_M7 = 10 + UC_CPU_ARM_CORTEX_M33 = 11 + UC_CPU_ARM_CORTEX_R5 = 12 + UC_CPU_ARM_CORTEX_R5F = 13 + UC_CPU_ARM_CORTEX_A8 = 14 + UC_CPU_ARM_CORTEX_A9 = 15 + UC_CPU_ARM_CORTEX_A7 = 16 + UC_CPU_ARM_CORTEX_A15 = 17 + UC_CPU_ARM_TI925T = 18 + UC_CPU_ARM_SA1100 = 19 + UC_CPU_ARM_SA1110 = 20 + UC_CPU_ARM_PXA250 = 21 + UC_CPU_ARM_PXA255 = 22 + UC_CPU_ARM_PXA260 = 23 + UC_CPU_ARM_PXA261 = 24 + UC_CPU_ARM_PXA262 = 25 + UC_CPU_ARM_PXA270A0 = 26 + UC_CPU_ARM_PXA270A1 = 27 + UC_CPU_ARM_PXA270B0 = 28 + UC_CPU_ARM_PXA270B1 = 29 + UC_CPU_ARM_PXA270C0 = 30 + UC_CPU_ARM_PXA270C5 = 31 + UC_CPU_ARM_MAX = 32 + # ARM registers UC_ARM_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb index dc641535..4a473674 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb @@ -2,6 +2,16 @@ module UnicornEngine + UC_CPU_M5206_CPU = 0 + UC_CPU_M68000_CPU = 1 + UC_CPU_M68020_CPU = 2 + UC_CPU_M68030_CPU = 3 + UC_CPU_M68040_CPU = 4 + UC_CPU_M68060_CPU = 5 + UC_CPU_M5208_CPU = 6 + UC_CPU_CFV4E_CPU = 7 + UC_CPU_ANY_CPU = 8 + # M68K registers UC_M68K_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb index f9fe86bd..13920c06 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb @@ -2,6 +2,36 @@ module UnicornEngine + UC_CPU_MIPS_4KC = 0 + UC_CPU_MIPS_4KM = 1 + UC_CPU_MIPS_4KECR1 = 2 + UC_CPU_MIPS_4KEMR1 = 3 + UC_CPU_MIPS_4KEC = 4 + UC_CPU_MIPS_4KEM = 5 + UC_CPU_MIPS_24KC = 6 + UC_CPU_MIPS_24KEC = 7 + UC_CPU_MIPS_24KF = 8 + UC_CPU_MIPS_34KF = 9 + UC_CPU_MIPS_74KF = 10 + UC_CPU_MIPS_M14K = 11 + UC_CPU_MIPS_M14KC = 12 + UC_CPU_MIPS_P5600 = 13 + UC_CPU_MIPS_MIPS32R6_GENERIC = 14 + UC_CPU_MIPS_I7200 = 15 + UC_CPU_MIPS_R4000 = 16 + UC_CPU_MIPS_VR5432 = 17 + UC_CPU_MIPS_5KC = 18 + UC_CPU_MIPS_5KF = 19 + UC_CPU_MIPS_20KC = 20 + UC_CPU_MIPS_MIPS64R2_GENERIC = 21 + UC_CPU_MIPS_5KEC = 22 + UC_CPU_MIPS_5KEF = 23 + UC_CPU_MIPS_I6400 = 24 + UC_CPU_MIPS_I6500 = 25 + UC_CPU_MIPS_LOONGSON_2E = 26 + UC_CPU_MIPS_LOONGSON_2F = 27 + UC_CPU_MIPS_MIPS64DSPR2 = 28 + # MIPS registers UC_MIPS_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb index e8f33330..94748d5c 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb @@ -2,6 +2,307 @@ module UnicornEngine + UC_CPU_PPC_401A1 = 0 + UC_CPU_PPC_401B2 = 1 + UC_CPU_PPC_401C2 = 2 + UC_CPU_PPC_401D2 = 3 + UC_CPU_PPC_401E2 = 4 + UC_CPU_PPC_401F2 = 5 + UC_CPU_PPC_401G2 = 6 + UC_CPU_PPC_COBRA = 7 + UC_CPU_PPC_403GA = 8 + UC_CPU_PPC_403GB = 9 + UC_CPU_PPC_403GC = 10 + UC_CPU_PPC_403GCX = 11 + UC_CPU_PPC_405D2 = 12 + UC_CPU_PPC_405D4 = 13 + UC_CPU_PPC_405CRA = 14 + UC_CPU_PPC_405CRB = 15 + UC_CPU_PPC_405CRC = 16 + UC_CPU_PPC_405EP = 17 + UC_CPU_PPC_405EZ = 18 + UC_CPU_PPC_405GPA = 19 + UC_CPU_PPC_405GPB = 20 + UC_CPU_PPC_405GPC = 21 + UC_CPU_PPC_405GPD = 22 + UC_CPU_PPC_405GPR = 23 + UC_CPU_PPC_405LP = 24 + UC_CPU_PPC_NPE405H = 25 + UC_CPU_PPC_NPE405H2 = 26 + UC_CPU_PPC_NPE405L = 27 + UC_CPU_PPC_NPE4GS3 = 28 + UC_CPU_PPC_STB03 = 29 + UC_CPU_PPC_STB04 = 30 + UC_CPU_PPC_STB25 = 31 + UC_CPU_PPC_X2VP4 = 32 + UC_CPU_PPC_440_XILINX = 33 + UC_CPU_PPC_440EPA = 34 + UC_CPU_PPC_440EPB = 35 + UC_CPU_PPC_440GPB = 36 + UC_CPU_PPC_440GPC = 37 + UC_CPU_PPC_440GRX = 38 + UC_CPU_PPC_440GXA = 39 + UC_CPU_PPC_440GXB = 40 + UC_CPU_PPC_440GXC = 41 + UC_CPU_PPC_440GXF = 42 + UC_CPU_PPC_440SP = 43 + UC_CPU_PPC_440SP2 = 44 + UC_CPU_PPC_440SPE = 45 + UC_CPU_PPC_460EXB = 46 + UC_CPU_PPC_MPC5XX = 47 + UC_CPU_PPC_MPC8XX = 48 + UC_CPU_PPC_G2 = 49 + UC_CPU_PPC_G2H4 = 50 + UC_CPU_PPC_G2GP = 51 + UC_CPU_PPC_G2LS = 52 + UC_CPU_PPC_MPC603 = 53 + UC_CPU_PPC_G2_HIP3 = 54 + UC_CPU_PPC_G2_HIP4 = 55 + UC_CPU_PPC_G2LE = 56 + UC_CPU_PPC_G2LEGP = 57 + UC_CPU_PPC_G2LELS = 58 + UC_CPU_PPC_G2LEGP1 = 59 + UC_CPU_PPC_G2LEGP3 = 60 + UC_CPU_PPC_E200Z5 = 61 + UC_CPU_PPC_E200Z6 = 62 + UC_CPU_PPC_E300C1 = 63 + UC_CPU_PPC_E300C2 = 64 + UC_CPU_PPC_E300C3 = 65 + UC_CPU_PPC_E300C4 = 66 + UC_CPU_PPC_E500V1_V10 = 67 + UC_CPU_PPC_E500V1_V20 = 68 + UC_CPU_PPC_E500V2_V10 = 69 + UC_CPU_PPC_E500V2_V11 = 70 + UC_CPU_PPC_E500V2_V20 = 71 + UC_CPU_PPC_E500V2_V21 = 72 + UC_CPU_PPC_E500V2_V22 = 73 + UC_CPU_PPC_E500V2_V30 = 74 + UC_CPU_PPC_E500MC = 75 + UC_CPU_PPC_E5500 = 76 + UC_CPU_PPC_E6500 = 77 + UC_CPU_PPC_E600 = 78 + UC_CPU_PPC_601_V0 = 79 + UC_CPU_PPC_601_V1 = 80 + UC_CPU_PPC_601_V2 = 81 + UC_CPU_PPC_602 = 82 + UC_CPU_PPC_603 = 83 + UC_CPU_PPC_603E_V11 = 84 + UC_CPU_PPC_603E_V12 = 85 + UC_CPU_PPC_603E_V13 = 86 + UC_CPU_PPC_603E_V14 = 87 + UC_CPU_PPC_603E_V22 = 88 + UC_CPU_PPC_603E_V3 = 89 + UC_CPU_PPC_603E_V4 = 90 + UC_CPU_PPC_603E_V41 = 91 + UC_CPU_PPC_603E7T = 92 + UC_CPU_PPC_603E7V = 93 + UC_CPU_PPC_603E7V1 = 94 + UC_CPU_PPC_603E7V2 = 95 + UC_CPU_PPC_603E7 = 96 + UC_CPU_PPC_603P = 97 + UC_CPU_PPC_604 = 98 + UC_CPU_PPC_604E_V10 = 99 + UC_CPU_PPC_604E_V22 = 100 + UC_CPU_PPC_604E_V24 = 101 + UC_CPU_PPC_604R = 102 + UC_CPU_PPC_7X0_V10 = 103 + UC_CPU_PPC_7X0_V20 = 104 + UC_CPU_PPC_7X0_V21 = 105 + UC_CPU_PPC_7X0_V22 = 106 + UC_CPU_PPC_7X0_V30 = 107 + UC_CPU_PPC_7X0_V31 = 108 + UC_CPU_PPC_740E = 109 + UC_CPU_PPC_750E = 110 + UC_CPU_PPC_7X0P = 111 + UC_CPU_PPC_750CL_V10 = 112 + UC_CPU_PPC_750CL_V20 = 113 + UC_CPU_PPC_750CX_V10 = 114 + UC_CPU_PPC_750CX_V20 = 115 + UC_CPU_PPC_750CX_V21 = 116 + UC_CPU_PPC_750CX_V22 = 117 + UC_CPU_PPC_750CXE_V21 = 118 + UC_CPU_PPC_750CXE_V22 = 119 + UC_CPU_PPC_750CXE_V23 = 120 + UC_CPU_PPC_750CXE_V24 = 121 + UC_CPU_PPC_750CXE_V24B = 122 + UC_CPU_PPC_750CXE_V30 = 123 + UC_CPU_PPC_750CXE_V31 = 124 + UC_CPU_PPC_750CXE_V31B = 125 + UC_CPU_PPC_750CXR = 126 + UC_CPU_PPC_750FL = 127 + UC_CPU_PPC_750FX_V10 = 128 + UC_CPU_PPC_750FX_V20 = 129 + UC_CPU_PPC_750FX_V21 = 130 + UC_CPU_PPC_750FX_V22 = 131 + UC_CPU_PPC_750FX_V23 = 132 + UC_CPU_PPC_750GL = 133 + UC_CPU_PPC_750GX_V10 = 134 + UC_CPU_PPC_750GX_V11 = 135 + UC_CPU_PPC_750GX_V12 = 136 + UC_CPU_PPC_750L_V20 = 137 + UC_CPU_PPC_750L_V21 = 138 + UC_CPU_PPC_750L_V22 = 139 + UC_CPU_PPC_750L_V30 = 140 + UC_CPU_PPC_750L_V32 = 141 + UC_CPU_PPC_7X5_V10 = 142 + UC_CPU_PPC_7X5_V11 = 143 + UC_CPU_PPC_7X5_V20 = 144 + UC_CPU_PPC_7X5_V21 = 145 + UC_CPU_PPC_7X5_V22 = 146 + UC_CPU_PPC_7X5_V23 = 147 + UC_CPU_PPC_7X5_V24 = 148 + UC_CPU_PPC_7X5_V25 = 149 + UC_CPU_PPC_7X5_V26 = 150 + UC_CPU_PPC_7X5_V27 = 151 + UC_CPU_PPC_7X5_V28 = 152 + UC_CPU_PPC_7400_V10 = 153 + UC_CPU_PPC_7400_V11 = 154 + UC_CPU_PPC_7400_V20 = 155 + UC_CPU_PPC_7400_V21 = 156 + UC_CPU_PPC_7400_V22 = 157 + UC_CPU_PPC_7400_V26 = 158 + UC_CPU_PPC_7400_V27 = 159 + UC_CPU_PPC_7400_V28 = 160 + UC_CPU_PPC_7400_V29 = 161 + UC_CPU_PPC_7410_V10 = 162 + UC_CPU_PPC_7410_V11 = 163 + UC_CPU_PPC_7410_V12 = 164 + UC_CPU_PPC_7410_V13 = 165 + UC_CPU_PPC_7410_V14 = 166 + UC_CPU_PPC_7448_V10 = 167 + UC_CPU_PPC_7448_V11 = 168 + UC_CPU_PPC_7448_V20 = 169 + UC_CPU_PPC_7448_V21 = 170 + UC_CPU_PPC_7450_V10 = 171 + UC_CPU_PPC_7450_V11 = 172 + UC_CPU_PPC_7450_V12 = 173 + UC_CPU_PPC_7450_V20 = 174 + UC_CPU_PPC_7450_V21 = 175 + UC_CPU_PPC_74X1_V23 = 176 + UC_CPU_PPC_74X1_V210 = 177 + UC_CPU_PPC_74X5_V10 = 178 + UC_CPU_PPC_74X5_V21 = 179 + UC_CPU_PPC_74X5_V32 = 180 + UC_CPU_PPC_74X5_V33 = 181 + UC_CPU_PPC_74X5_V34 = 182 + UC_CPU_PPC_74X7_V10 = 183 + UC_CPU_PPC_74X7_V11 = 184 + UC_CPU_PPC_74X7_V12 = 185 + UC_CPU_PPC_74X7A_V10 = 186 + UC_CPU_PPC_74X7A_V11 = 187 + UC_CPU_PPC_74X7A_V12 = 188 + UC_CPU_PPC_IOP480 = 1 + UC_CPU_PPC_X2VP20 = 42 + UC_CPU_PPC_440GRA = 35 + UC_CPU_PPC_440EPX = 38 + UC_CPU_PPC_MPC5200_V10 = 59 + UC_CPU_PPC_MPC5200_V11 = 59 + UC_CPU_PPC_MPC5200_V12 = 59 + UC_CPU_PPC_MPC5200B_V20 = 59 + UC_CPU_PPC_MPC5200B_V21 = 59 + UC_CPU_PPC_MPC834X = 63 + UC_CPU_PPC_MPC837X = 66 + UC_CPU_PPC_E500 = 73 + UC_CPU_PPC_MPC8533_V10 = 72 + UC_CPU_PPC_MPC8533_V11 = 73 + UC_CPU_PPC_MPC8533E_V10 = 72 + UC_CPU_PPC_MPC8533E_V11 = 73 + UC_CPU_PPC_MPC8540_V10 = 67 + UC_CPU_PPC_MPC8540_V20 = 68 + UC_CPU_PPC_MPC8540_V21 = 68 + UC_CPU_PPC_MPC8541_V10 = 68 + UC_CPU_PPC_MPC8541_V11 = 68 + UC_CPU_PPC_MPC8541E_V10 = 68 + UC_CPU_PPC_MPC8541E_V11 = 68 + UC_CPU_PPC_MPC8543_V10 = 69 + UC_CPU_PPC_MPC8543_V11 = 70 + UC_CPU_PPC_MPC8543_V20 = 71 + UC_CPU_PPC_MPC8543_V21 = 72 + UC_CPU_PPC_MPC8543E_V10 = 69 + UC_CPU_PPC_MPC8543E_V11 = 70 + UC_CPU_PPC_MPC8543E_V20 = 71 + UC_CPU_PPC_MPC8543E_V21 = 72 + UC_CPU_PPC_MPC8544_V10 = 72 + UC_CPU_PPC_MPC8544_V11 = 73 + UC_CPU_PPC_MPC8544E_V11 = 73 + UC_CPU_PPC_MPC8544E_V10 = 72 + UC_CPU_PPC_MPC8545_V10 = 69 + UC_CPU_PPC_MPC8545_V20 = 71 + UC_CPU_PPC_MPC8545_V21 = 72 + UC_CPU_PPC_MPC8545E_V10 = 69 + UC_CPU_PPC_MPC8545E_V20 = 71 + UC_CPU_PPC_MPC8545E_V21 = 72 + UC_CPU_PPC_MPC8547E_V10 = 69 + UC_CPU_PPC_MPC8547E_V20 = 71 + UC_CPU_PPC_MPC8547E_V21 = 72 + UC_CPU_PPC_MPC8548_V10 = 69 + UC_CPU_PPC_MPC8548_V11 = 70 + UC_CPU_PPC_MPC8548_V20 = 71 + UC_CPU_PPC_MPC8548_V21 = 72 + UC_CPU_PPC_MPC8548E_V10 = 69 + UC_CPU_PPC_MPC8548E_V11 = 70 + UC_CPU_PPC_MPC8548E_V20 = 71 + UC_CPU_PPC_MPC8548E_V21 = 72 + UC_CPU_PPC_MPC8555_V10 = 69 + UC_CPU_PPC_MPC8555_V11 = 70 + UC_CPU_PPC_MPC8555E_V10 = 69 + UC_CPU_PPC_MPC8555E_V11 = 70 + UC_CPU_PPC_MPC8560_V10 = 69 + UC_CPU_PPC_MPC8560_V20 = 71 + UC_CPU_PPC_MPC8560_V21 = 72 + UC_CPU_PPC_MPC8567 = 73 + UC_CPU_PPC_MPC8567E = 73 + UC_CPU_PPC_MPC8568 = 73 + UC_CPU_PPC_MPC8568E = 73 + UC_CPU_PPC_MPC8572 = 74 + UC_CPU_PPC_MPC8572E = 74 + UC_CPU_PPC_MPC8610 = 78 + UC_CPU_PPC_MPC8641 = 78 + UC_CPU_PPC_MPC8641D = 78 + + UC_CPU_PPC64_620 = 0 + UC_CPU_PPC64_630 = 1 + UC_CPU_PPC64_631 = 2 + UC_CPU_PPC64_POWER4 = 3 + UC_CPU_PPC64_POWER4P = 4 + UC_CPU_PPC64_POWER5 = 5 + UC_CPU_PPC64_POWER5P_V21 = 6 + UC_CPU_PPC64_POWER6 = 7 + UC_CPU_PPC64_POWER_SERVER_MASK = 8 + UC_CPU_PPC64_POWER7_BASE = 9 + UC_CPU_PPC64_POWER7_V23 = 10 + UC_CPU_PPC64_POWER7P_BASE = 11 + UC_CPU_PPC64_POWER7P_V21 = 12 + UC_CPU_PPC64_POWER8E_BASE = 13 + UC_CPU_PPC64_POWER8E_V21 = 14 + UC_CPU_PPC64_POWER8_BASE = 15 + UC_CPU_PPC64_POWER8_V20 = 16 + UC_CPU_PPC64_POWER8NVL_BASE = 17 + UC_CPU_PPC64_POWER8NVL_V10 = 18 + UC_CPU_PPC64_POWER9_BASE = 19 + UC_CPU_PPC64_POWER9_DD1 = 20 + UC_CPU_PPC64_POWER9_DD20 = 21 + UC_CPU_PPC64_POWER10_BASE = 22 + UC_CPU_PPC64_POWER10_DD1 = 23 + UC_CPU_PPC64_970_V22 = 24 + UC_CPU_PPC64_970FX_V10 = 25 + UC_CPU_PPC64_970FX_V20 = 26 + UC_CPU_PPC64_970FX_V21 = 27 + UC_CPU_PPC64_970FX_V30 = 28 + UC_CPU_PPC64_970FX_V31 = 29 + UC_CPU_PPC64_970MP_V10 = 30 + UC_CPU_PPC64_970MP_V11 = 31 + UC_CPU_PPC64_CELL_V10 = 32 + UC_CPU_PPC64_CELL_V20 = 33 + UC_CPU_PPC64_CELL_V30 = 34 + UC_CPU_PPC64_CELL_V31 = 35 + UC_CPU_PPC64_RS64 = 36 + UC_CPU_PPC64_RS64II = 37 + UC_CPU_PPC64_RS64III = 38 + UC_CPU_PPC64_RS64IV = 39 + UC_CPU_PPC64_CELL_V32 = 35 + UC_CPU_PPC64_CELL = 35 + # PPC registers UC_PPC_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb index 2122099d..5eb5cd85 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb @@ -2,6 +2,16 @@ module UnicornEngine + UC_CPU_RISCV32_ANY = 0 + UC_CPU_RISCV32_BASE32 = 1 + UC_CPU_RISCV32_SIFIVE_E31 = 2 + UC_CPU_RISCV32_SIFIVE_U34 = 3 + + UC_CPU_RISCV64_ANY = 0 + UC_CPU_RISCV64_BASE64 = 1 + UC_CPU_RISCV64_SIFIVE_E51 = 2 + UC_CPU_RISCV64_SIFIVE_U54 = 3 + # RISCV registers UC_RISCV_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb index b5c42470..dbf3f938 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb @@ -2,6 +2,38 @@ module UnicornEngine + UC_CPU_SPARC_FUJITSU_MB86904 = 0 + UC_CPU_SPARC_FUJITSU_MB86907 = 1 + UC_CPU_SPARC_TI_MICROSPARC_I = 2 + UC_CPU_SPARC_TI_MICROSPARC_II = 3 + UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4 + UC_CPU_SPARC_TI_SUPERSPARC_40 = 5 + UC_CPU_SPARC_TI_SUPERSPARC_50 = 6 + UC_CPU_SPARC_TI_SUPERSPARC_51 = 7 + UC_CPU_SPARC_TI_SUPERSPARC_60 = 8 + UC_CPU_SPARC_TI_SUPERSPARC_61 = 9 + UC_CPU_SPARC_TI_SUPERSPARC_II = 10 + UC_CPU_SPARC_LEON2 = 11 + UC_CPU_SPARC_LEON3 = 12 + + UC_CPU_SPARC64_FUJITSU = 0 + UC_CPU_SPARC64_FUJITSU_III = 1 + UC_CPU_SPARC64_FUJITSU_IV = 2 + UC_CPU_SPARC64_FUJITSU_V = 3 + UC_CPU_SPARC64_TI_ULTRASPARC_I = 4 + UC_CPU_SPARC64_TI_ULTRASPARC_II = 5 + UC_CPU_SPARC64_TI_ULTRASPARC_III = 6 + UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7 + UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8 + UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 + UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11 + UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 + UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 + UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 + UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16 + # SPARC registers UC_SPARC_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index a09f3e82..b179d3eb 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -107,6 +107,22 @@ module UnicornEngine UC_QUERY_ARCH = 3 UC_QUERY_TIMEOUT = 4 + UC_CTL_IO_NONE = 0 + UC_CTL_IO_WRITE = 1 + UC_CTL_IO_READ = 2 + UC_CTL_IO_READ_WRITE = 3 + + UC_CTL_UC_MODE = 0 + UC_CTL_UC_PAGE_SIZE = 1 + UC_CTL_UC_ARCH = 2 + UC_CTL_UC_TIMEOUT = 3 + UC_CTL_UC_EXITS_CNT = 4 + UC_CTL_UC_EXITS = 5 + UC_CTL_CPU_MODEL = 6 + UC_CTL_TB_EDGE = 7 + UC_CTL_TB_REQUEST_CACHE = 8 + UC_CTL_TB_REMOVE_CACHE = 9 + UC_PROT_NONE = 0 UC_PROT_READ = 1 UC_PROT_WRITE = 2 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb index 49ef2549..6fae393c 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb @@ -2,6 +2,45 @@ module UnicornEngine + UC_CPU_X86_QEMU64 = 0 + UC_CPU_X86_PHENOM = 1 + UC_CPU_X86_CORE2DUO = 2 + UC_CPU_X86_KVM64 = 3 + UC_CPU_X86_QEMU32 = 4 + UC_CPU_X86_KVM32 = 5 + UC_CPU_X86_COREDUO = 6 + UC_CPU_X86_486 = 7 + UC_CPU_X86_PENTIUM = 8 + UC_CPU_X86_PENTIUM2 = 9 + UC_CPU_X86_PENTIUM3 = 10 + UC_CPU_X86_ATHLON = 11 + UC_CPU_X86_N270 = 12 + UC_CPU_X86_CONROE = 13 + UC_CPU_X86_PENRYN = 14 + UC_CPU_X86_NEHALEM = 15 + UC_CPU_X86_WESTMERE = 16 + UC_CPU_X86_SANDYBRIDGE = 17 + UC_CPU_X86_IVYBRIDGE = 18 + UC_CPU_X86_HASWELL = 19 + UC_CPU_X86_BROADWELL = 20 + UC_CPU_X86_SKYLAKE_CLIENT = 21 + UC_CPU_X86_SKYLAKE_SERVER = 22 + UC_CPU_X86_CASCADELAKE_SERVER = 23 + UC_CPU_X86_COOPERLAKE = 24 + UC_CPU_X86_ICELAKE_CLIENT = 25 + UC_CPU_X86_ICELAKE_SERVER = 26 + UC_CPU_X86_DENVERTON = 27 + UC_CPU_X86_SNOWRIDGE = 28 + UC_CPU_X86_KNIGHTSMILL = 29 + UC_CPU_X86_OPTERON_G1 = 30 + UC_CPU_X86_OPTERON_G2 = 31 + UC_CPU_X86_OPTERON_G3 = 32 + UC_CPU_X86_OPTERON_G4 = 33 + UC_CPU_X86_OPTERON_G5 = 34 + UC_CPU_X86_EPYC = 35 + UC_CPU_X86_DHYANA = 36 + UC_CPU_X86_EPYC_ROME = 37 + # X86 registers UC_X86_REG_INVALID = 0 diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index 45d10f16..9c020538 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -25,3 +25,7 @@ libc = "0.2" [build-dependencies] build-helper = "0.1" +reqwest = { version = "0.11", features = ["blocking"] } +flate2 = "1.0.22" +tar = "0.4.37" +bytes = "1.1.0" \ No newline at end of file diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index c128ef14..9900870d 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -1,31 +1,58 @@ -use std::result::Result; +use bytes::Buf; +use flate2::read::GzDecoder; +use reqwest::header::USER_AGENT; +use std::path::PathBuf; use std::{env, process::Command}; +use tar::Archive; + +fn find_unicorn(unicorn_dir: &PathBuf) -> Option { + for entry in std::fs::read_dir(unicorn_dir).ok()? { + let entry = entry.unwrap(); + let path = entry.path(); + + if path.is_dir() && path.file_name()?.to_str()?.contains("unicorn") { + return Some(path); + } + } + + None +} + +fn download_unicorn() -> Option { + // https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-tar + let pkg_version; + if let Ok(unicorn_version) = env::var("UNICORN_VERSION") { + pkg_version = unicorn_version; + } else { + pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); + } + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let client = reqwest::blocking::Client::new(); + let resp = client + .get(format!( + "https://api.github.com/repos/unicorn-engine/unicorn/tarball/{}", + pkg_version + )) + .header(USER_AGENT, "unicorn-engine-rust-bindings") + .send() + .unwrap() + .bytes() + .unwrap(); + let tar = GzDecoder::new(resp.reader()); + + let mut archive = Archive::new(tar); + archive.unpack(&out_dir).unwrap(); + + match find_unicorn(&out_dir) { + Some(dir) => Some(String::from(out_dir.join(dir).to_str()?)), + None => None, + } +} fn main() { - let out_dir = env::var("OUT_DIR").unwrap(); let profile = env::var("PROFILE").unwrap(); - let mut version = String::from("dev"); - if let Result::Ok(version_env) = env::var("UNICORN_BRANCH") { - version = version_env; - } - let unicorn_dir; - if let Result::Ok(_) = env::var("CI") { - unicorn_dir = format!("../.."); - } else { - unicorn_dir = format!("{}/unicorn_git", out_dir); - - Command::new("rm").arg("-rf").arg(&unicorn_dir); - - Command::new("git") - .arg("clone") - .arg("git@github.com:unicorn-engine/unicorn.git") - .arg("-b") - .arg(version) - .arg(&unicorn_dir) - .output() - .expect("Fail to clone Unicorn repository."); - } + let unicorn_dir = download_unicorn().unwrap(); println!("cargo:rerun-if-changed={}", &unicorn_dir); diff --git a/bindings/rust/tests/unicorn.rs b/bindings/rust/tests/unicorn.rs index 6f8f2143..aaf208b3 100644 --- a/bindings/rust/tests/unicorn.rs +++ b/bindings/rust/tests/unicorn.rs @@ -1,6 +1,8 @@ use std::cell::RefCell; use std::rc::Rc; -use unicorn_engine::unicorn_const::{uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE}; +use unicorn_engine::unicorn_const::{ + uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE, +}; use unicorn_engine::{InsnSysX86, RegisterARM, RegisterMIPS, RegisterPPC, RegisterX86}; pub static X86_REGISTERS: [RegisterX86; 125] = [ @@ -602,8 +604,8 @@ fn x86_context_save_and_restore() { let x86_code: Vec = vec![ 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05, ]; - let mut unicorn = - unicorn_engine::Unicorn::new(Arch::X86, mode).expect("failed to initialize unicorn instance"); + let mut unicorn = unicorn_engine::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(())); @@ -619,8 +621,8 @@ fn x86_context_save_and_restore() { let context = context.unwrap(); /* and create a new emulator, into which we will "restore" that context */ - let mut unicorn2 = - unicorn_engine::Unicorn::new(Arch::X86, mode).expect("failed to initialize unicorn instance"); + let mut unicorn2 = unicorn_engine::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() { diff --git a/format.sh b/format.sh new file mode 100644 index 00000000..0bf864e8 --- /dev/null +++ b/format.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +find . -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./msvc -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./include -maxdepth 2 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./tests/unit -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./samples -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./qemu "(" -name "unicorn.c" -or -name "unicorn.h" -or -name "unicorn_arm.c" -or -name "unicorn_aarch64.c" ")" -exec clang-format -i -style=file "{}" ";" diff --git a/glib_compat/gtree.c b/glib_compat/gtree.c index a790d568..b2617a3f 100644 --- a/glib_compat/gtree.c +++ b/glib_compat/gtree.c @@ -260,7 +260,7 @@ static inline GTreeNode *g_tree_node_next (GTreeNode *node) return tmp; } -static void g_tree_remove_all (GTree *tree) +void g_tree_remove_all (GTree *tree) { GTreeNode *node; GTreeNode *next; diff --git a/glib_compat/gtree.h b/glib_compat/gtree.h index f62dbe08..47b6c880 100644 --- a/glib_compat/gtree.h +++ b/glib_compat/gtree.h @@ -44,6 +44,8 @@ void g_tree_destroy (GTree *tree); void g_tree_insert (GTree *tree, gpointer key, gpointer value); +void g_tree_remove_all (GTree *tree); + gboolean g_tree_remove (GTree *tree, gconstpointer key); gpointer g_tree_lookup (GTree *tree, gconstpointer key); diff --git a/include/uc_priv.h b/include/uc_priv.h index 8c564396..17978aaa 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -2,7 +2,6 @@ /* By Nguyen Anh Quynh , 2015 */ /* Modified for Unicorn Engine by Chen Huitao, 2020 */ - #ifndef UC_PRIV_H #define UC_PRIV_H @@ -15,16 +14,22 @@ // These are masks of supported modes for each cpu/arch. // They should be updated when changes are made to the uc_mode enum typedef. -#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ - |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN) -#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) -#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN) -#define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN) -#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) -#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN) -#define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_ARM_MASK \ + (UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_LITTLE_ENDIAN | UC_MODE_MCLASS | \ + UC_MODE_ARM926 | UC_MODE_ARM946 | UC_MODE_ARM1176 | UC_MODE_BIG_ENDIAN) +#define UC_MODE_MIPS_MASK \ + (UC_MODE_MIPS32 | UC_MODE_MIPS64 | UC_MODE_LITTLE_ENDIAN | \ + UC_MODE_BIG_ENDIAN) +#define UC_MODE_X86_MASK \ + (UC_MODE_16 | UC_MODE_32 | UC_MODE_64 | UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_PPC_MASK (UC_MODE_PPC32 | UC_MODE_PPC64 | UC_MODE_BIG_ENDIAN) +#define UC_MODE_SPARC_MASK \ + (UC_MODE_SPARC32 | UC_MODE_SPARC64 | UC_MODE_BIG_ENDIAN) +#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN) +#define UC_MODE_RISCV_MASK \ + (UC_MODE_RISCV32 | UC_MODE_RISCV64 | UC_MODE_LITTLE_ENDIAN) -#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0])) #define READ_QWORD(x) ((uint64_t)x) #define READ_DWORD(x) (x & 0xffffffff) @@ -36,15 +41,21 @@ #define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8)) #define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff)) +struct TranslationBlock; -typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result); +typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, + size_t *result); // return 0 on success, -1 on failure -typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, + void *const *vals, int count); -typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); typedef struct { context_reg_read_t context_reg_read; context_reg_write_t context_reg_write; @@ -52,30 +63,40 @@ typedef struct { typedef void (*reg_reset_t)(struct uc_struct *uc); -typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len); +typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, + const uint8_t *buf, int len); -typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int len); +typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, + int len); -typedef void (*uc_args_void_t)(void*); +typedef void (*uc_args_void_t)(void *); -typedef void (*uc_args_uc_t)(struct uc_struct*); -typedef void (*uc_args_int_uc_t)(struct uc_struct*); +typedef void (*uc_args_uc_t)(struct uc_struct *); +typedef void (*uc_args_int_uc_t)(struct uc_struct *); -typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long); +typedef void (*uc_args_uc_long_t)(struct uc_struct *, unsigned long); typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr); -typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, hwaddr begin, size_t size, uint32_t perms); +typedef MemoryRegion *(*uc_args_uc_ram_size_t)(struct uc_struct *, hwaddr begin, + size_t size, uint32_t perms); -typedef MemoryRegion* (*uc_args_uc_ram_size_ptr_t)(struct uc_struct*, hwaddr begin, size_t size, uint32_t perms, void *ptr); +typedef MemoryRegion *(*uc_args_uc_ram_size_ptr_t)(struct uc_struct *, + hwaddr begin, size_t size, + uint32_t perms, void *ptr); -typedef void (*uc_mem_unmap_t)(struct uc_struct*, MemoryRegion *mr); +typedef void (*uc_mem_unmap_t)(struct uc_struct *, MemoryRegion *mr); typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly); typedef int (*uc_cpus_init)(struct uc_struct *, const char *); -typedef MemoryRegion* (*uc_memory_map_io_t)(struct uc_struct *uc, ram_addr_t begin, size_t size, uc_cb_mmio_read_t read_cb, uc_cb_mmio_write_t write_cb, void *user_data_read, void *user_data_write); +typedef MemoryRegion *(*uc_memory_map_io_t)(struct uc_struct *uc, + ram_addr_t begin, size_t size, + uc_cb_mmio_read_t read_cb, + uc_cb_mmio_write_t write_cb, + void *user_data_read, + void *user_data_write); // which interrupt should make emulation stop? typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno); @@ -84,7 +105,7 @@ typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno); typedef uint64_t (*uc_mem_redirect_t)(uint64_t address); // validate if Unicorn supports hooking a given instruction -typedef bool(*uc_insn_hook_validate)(uint32_t insn_enum); +typedef bool (*uc_insn_hook_validate)(uint32_t insn_enum); // init target page typedef void (*uc_target_page_init)(struct uc_struct *); @@ -95,12 +116,21 @@ typedef void (*uc_softfloat_initialize)(void); // tcg flush softmmu tlb typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc); +// Invalidate the TB at given address +typedef void (*uc_invalidate_tb_t)(struct uc_struct *uc, uint64_t start, + size_t len); + +// Request generating TB at given address +typedef uc_err (*uc_gen_tb_t)(struct uc_struct *uc, uint64_t pc, uc_tb *out_tb); + struct hook { - int type; // UC_HOOK_* - int insn; // instruction for HOOK_INSN - int refs; // reference count to free hook stored in multiple lists - bool to_delete; // set to true when the hook is deleted by the user. The destruction of the hook is delayed. - uint64_t begin, end; // only trigger if PC or memory access is in this address (depends on hook type) + int type; // UC_HOOK_* + int insn; // instruction for HOOK_INSN + int refs; // reference count to free hook stored in multiple lists + bool to_delete; // set to true when the hook is deleted by the user. The + // destruction of the hook is delayed. + uint64_t begin, end; // only trigger if PC or memory access is in this + // address (depends on hook type) void *callback; // a uc_cb_* type void *user_data; }; @@ -127,36 +157,45 @@ typedef enum uc_hook_idx { UC_HOOK_MEM_FETCH_IDX, UC_HOOK_MEM_READ_AFTER_IDX, UC_HOOK_INSN_INVALID_IDX, + UC_HOOK_EDGE_GENERATED_IDX, UC_HOOK_MAX, } uc_hook_idx; +// Copy the essential information from TranslationBlock +#define UC_TB_COPY(uc_tb, tb) \ + do { \ + (uc_tb)->pc = tb->pc; \ + (uc_tb)->icount = tb->icount; \ + (uc_tb)->size = tb->size; \ + } while (0) + // The lowest 6 bits are used for hook type index. -#define UC_HOOK_IDX_MASK ((1<<6)-1) +#define UC_HOOK_IDX_MASK ((1 << 6) - 1) // hook flags -#define UC_HOOK_FLAG_NO_STOP (1 << 6) // Don't stop emulation in this uc_tracecode. +#define UC_HOOK_FLAG_NO_STOP \ + (1 << 6) // Don't stop emulation in this uc_tracecode. // The rest of bits are reserved for hook flags. #define UC_HOOK_FLAG_MASK (~(UC_HOOK_IDX_MASK)) -#define HOOK_FOREACH_VAR_DECLARE \ - struct list_item *cur +#define HOOK_FOREACH_VAR_DECLARE struct list_item *cur // for loop macro to loop over hook lists -#define HOOK_FOREACH(uc, hh, idx) \ - for ( \ - cur = (uc)->hook[idx##_IDX].head; \ - cur != NULL && ((hh) = (struct hook *)cur->data); \ - cur = cur->next) +#define HOOK_FOREACH(uc, hh, idx) \ + for (cur = (uc)->hook[idx##_IDX].head; \ + cur != NULL && ((hh) = (struct hook *)cur->data); cur = cur->next) // if statement to check hook bounds -#define HOOK_BOUND_CHECK(hh, addr) \ - ((((addr) >= (hh)->begin && (addr) <= (hh)->end) \ - || (hh)->begin > (hh)->end) && !((hh)->to_delete)) +#define HOOK_BOUND_CHECK(hh, addr) \ + ((((addr) >= (hh)->begin && (addr) <= (hh)->end) || \ + (hh)->begin > (hh)->end) && \ + !((hh)->to_delete)) #define HOOK_EXISTS(uc, idx) ((uc)->hook[idx##_IDX].head != NULL) -#define HOOK_EXISTS_BOUNDED(uc, idx, addr) _hook_exists_bounded((uc)->hook[idx##_IDX].head, addr) +#define HOOK_EXISTS_BOUNDED(uc, idx, addr) \ + _hook_exists_bounded((uc)->hook[idx##_IDX].head, addr) static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr) { @@ -168,7 +207,7 @@ static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr) return false; } -//relloc increment, KEEP THIS A POWER OF 2! +// relloc increment, KEEP THIS A POWER OF 2! #define MEM_BLOCK_INCR 32 typedef struct TargetPageBits TargetPageBits; @@ -177,7 +216,7 @@ typedef struct TCGContext TCGContext; struct uc_struct { uc_arch arch; uc_mode mode; - uc_err errnum; // qemu/cpu-exec.c + uc_err errnum; // qemu/cpu-exec.c AddressSpace address_space_memory; AddressSpace address_space_io; query_t query; @@ -187,9 +226,10 @@ struct uc_struct { uc_write_mem_t write_mem; uc_read_mem_t read_mem; - uc_args_void_t release; // release resource when uc_close() - uc_args_uc_u64_t set_pc; // set PC for tracecode - uc_args_int_t stop_interrupt; // check if the interrupt should stop emulation + uc_args_void_t release; // release resource when uc_close() + uc_args_uc_u64_t set_pc; // set PC for tracecode + uc_args_int_t + stop_interrupt; // check if the interrupt should stop emulation uc_memory_map_io_t memory_map_io; uc_args_uc_t init_arch, cpu_exec_init_all; @@ -204,6 +244,8 @@ struct uc_struct { uc_target_page_init target_page; uc_softfloat_initialize softfloat_initialize; uc_tcg_flush_tlb tcg_flush_tlb; + uc_invalidate_tb_t uc_invalidate_tb; + uc_gen_tb_t uc_gen_tb; /* only 1 cpu in unicorn, do not need current_cpu to handle current running cpu. */ @@ -212,21 +254,21 @@ struct uc_struct { uc_insn_hook_validate insn_hook_validate; MemoryRegion *system_memory; // qemu/exec.c - MemoryRegion *system_io; // qemu/exec.c + MemoryRegion *system_io; // qemu/exec.c MemoryRegion io_mem_unassigned; // qemu/exec.c - RAMList ram_list; // qemu/exec.c + RAMList ram_list; // qemu/exec.c /* qemu/exec.c */ unsigned int alloc_hint; /* qemu/exec-vary.c */ TargetPageBits *init_target_page; - BounceBuffer bounce; // qemu/cpu-exec.c + BounceBuffer bounce; // qemu/cpu-exec.c volatile sig_atomic_t exit_request; // qemu/cpu-exec.c /* qemu/accel/tcg/cpu-exec-common.c */ /* always be true after call tcg_exec_init(). */ bool tcg_allowed; /* This is a multi-level map on the virtual address space. The bottom level has pointers to PageDesc. */ - void **l1_map; // qemu/accel/tcg/translate-all.c + void **l1_map; // qemu/accel/tcg/translate-all.c size_t l1_map_size; /* qemu/accel/tcg/translate-all.c */ int v_l1_size; @@ -248,28 +290,34 @@ struct uc_struct { uc_hook count_hook; size_t emu_counter; // current counter of uc_emu_start() - size_t emu_count; // save counter of uc_emu_start() + size_t emu_count; // save counter of uc_emu_start() int size_recur_mem; // size for mem access when in a recursive call - bool init_tcg; // already initialized local TCGv variables? - bool stop_request; // request to immediately stop emulation - for uc_emu_stop() - bool quit_request; // request to quit the current TB, but continue to emulate - for uc_mem_protect() - bool emulation_done; // emulation is done by uc_emu_start() - bool timed_out; // emulation timed out, that can retrieve via uc_query(UC_QUERY_TIMEOUT) - QemuThread timer; // timer for emulation timeout - uint64_t timeout; // timeout for uc_emu_start() + bool init_tcg; // already initialized local TCGv variables? + bool stop_request; // request to immediately stop emulation - for + // uc_emu_stop() + bool quit_request; // request to quit the current TB, but continue to + // emulate - for uc_mem_protect() + bool emulation_done; // emulation is done by uc_emu_start() + bool timed_out; // emulation timed out, that can retrieve via + // uc_query(UC_QUERY_TIMEOUT) + QemuThread timer; // timer for emulation timeout + uint64_t timeout; // timeout for uc_emu_start() - uint64_t invalid_addr; // invalid address to be accessed - int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE + uint64_t invalid_addr; // invalid address to be accessed + int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE - uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start()) + int use_exits; + GTree *exits; // addresses where emulation stops (@until param of + // uc_emu_start()) Also see UC_CTL_USE_EXITS for more details. - int thumb; // thumb mode for ARM + int thumb; // thumb mode for ARM MemoryRegion **mapped_blocks; uint32_t mapped_block_count; uint32_t mapped_block_cache_index; - void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c) + void *qemu_thread_data; // to support cross compile to Windows + // (qemu-thread-win32.c) uint32_t target_page_size; uint32_t target_page_align; uint64_t qemu_host_page_size; @@ -277,26 +325,44 @@ struct uc_struct { int qemu_icache_linesize; /* ARCH_REGS_STORAGE_SIZE */ int cpu_context_size; - uint64_t next_pc; // save next PC for some special cases - bool hook_insert; // insert new hook at begin of the hook list (append by default) - bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()? + uint64_t next_pc; // save next PC for some special cases + bool hook_insert; // insert new hook at begin of the hook list (append by + // default) + bool first_tb; // is this the first Translation-Block ever generated since + // uc_emu_start()? struct list saved_contexts; // The contexts saved by this uc_struct. - bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block. + bool no_exit_request; // Disable check_exit_request temporarily. A + // workaround to treat the IT block as a whole block. }; // Metadata stub for the variable-size cpu context used with uc_context_*() // We also save cpu->jmp_env, so emulation can be reentrant struct uc_context { - size_t context_size; // size of the real internal context structure - size_t jmp_env_size; // size of cpu->jmp_env - uc_mode mode; // the mode of this context (uc may be free-ed already) - uc_arch arch; // the arch of this context (uc may be free-ed already) - struct uc_struct *uc; // the uc_struct which creates this context - char data[0]; // context + cpu->jmp_env + size_t context_size; // size of the real internal context structure + size_t jmp_env_size; // size of cpu->jmp_env + uc_mode mode; // the mode of this context (uc may be free-ed already) + uc_arch arch; // the arch of this context (uc may be free-ed already) + struct uc_struct *uc; // the uc_struct which creates this context + char data[0]; // context + cpu->jmp_env }; // check if this address is mapped in (via uc_mem_map()) -MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address); +MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address); + +// We have to support 32bit system so we can't hold uint64_t on void* +static inline void uc_add_exit(uc_engine *uc, uint64_t addr) +{ + uint64_t *new_exit = g_malloc(sizeof(uint64_t)); + *new_exit = addr; + g_tree_insert(uc->exits, (gpointer)new_exit, (gpointer)1); +} + +// This function has to exist since we would like to accept uint32_t or +// it's complex to achieve so. +static inline int uc_addr_is_exit(uc_engine *uc, uint64_t addr) +{ + return g_tree_lookup(uc->exits, (gpointer)(&addr)) == (gpointer)1; +} #endif /* vim: set ts=4 noet: */ diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index 9ce7b0b3..d9cf4949 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -12,9 +12,45 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_arm { + UC_CPU_ARM_926 = 0, + UC_CPU_ARM_946, + UC_CPU_ARM_1026, + UC_CPU_ARM_1136_R2, + UC_CPU_ARM_1136, + UC_CPU_ARM_1176, + UC_CPU_ARM_11MPCORE, + UC_CPU_ARM_CORTEX_M0, + UC_CPU_ARM_CORTEX_M3, + UC_CPU_ARM_CORTEX_M4, + UC_CPU_ARM_CORTEX_M7, + UC_CPU_ARM_CORTEX_M33, + UC_CPU_ARM_CORTEX_R5, + UC_CPU_ARM_CORTEX_R5F, + UC_CPU_ARM_CORTEX_A8, + UC_CPU_ARM_CORTEX_A9, + UC_CPU_ARM_CORTEX_A7, + UC_CPU_ARM_CORTEX_A15, + UC_CPU_ARM_TI925T, + UC_CPU_ARM_SA1100, + UC_CPU_ARM_SA1110, + UC_CPU_ARM_PXA250, + UC_CPU_ARM_PXA255, + UC_CPU_ARM_PXA260, + UC_CPU_ARM_PXA261, + UC_CPU_ARM_PXA262, + UC_CPU_ARM_PXA270A0, + UC_CPU_ARM_PXA270A1, + UC_CPU_ARM_PXA270B0, + UC_CPU_ARM_PXA270B1, + UC_CPU_ARM_PXA270C0, + UC_CPU_ARM_PXA270C5, + UC_CPU_ARM_MAX +} uc_cpu_arm; + //> ARM registers typedef enum uc_arm_reg { UC_ARM_REG_INVALID = 0, @@ -158,7 +194,7 @@ typedef enum uc_arm_reg { UC_ARM_REG_XPSR_NZCVQ, UC_ARM_REG_XPSR_G, UC_ARM_REG_XPSR_NZCVQG, - UC_ARM_REG_ENDING, // <-- mark the end of the list or registers + UC_ARM_REG_ENDING, // <-- mark the end of the list or registers //> alias registers UC_ARM_REG_R13 = UC_ARM_REG_SP, diff --git a/include/unicorn/arm64.h b/include/unicorn/arm64.h index 0f66518d..5cbd6229 100644 --- a/include/unicorn/arm64.h +++ b/include/unicorn/arm64.h @@ -12,9 +12,16 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_aarch64 { + UC_CPU_AARCH64_A57 = 0, + UC_CPU_AARCH64_A53, + UC_CPU_AARCH64_A72, + UC_CPU_AARCH64_MAX +} uc_cpu_aarch64; + //> ARM64 registers typedef enum uc_arm64_reg { UC_ARM64_REG_INVALID = 0, @@ -281,7 +288,7 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_V31, //> pseudo registers - UC_ARM64_REG_PC, // program counter register + UC_ARM64_REG_PC, // program counter register UC_ARM64_REG_CPACR_EL1, @@ -327,7 +334,7 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_VBAR_EL2, UC_ARM64_REG_VBAR_EL3, - UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers + UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers //> alias registers diff --git a/include/unicorn/m68k.h b/include/unicorn/m68k.h index 80e8b920..27ea64df 100644 --- a/include/unicorn/m68k.h +++ b/include/unicorn/m68k.h @@ -12,9 +12,21 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_m68k { + UC_CPU_M5206_CPU = 0, + UC_CPU_M68000_CPU, + UC_CPU_M68020_CPU, + UC_CPU_M68030_CPU, + UC_CPU_M68040_CPU, + UC_CPU_M68060_CPU, + UC_CPU_M5208_CPU, + UC_CPU_CFV4E_CPU, + UC_CPU_ANY_CPU, +} uc_cpu_m68k; + //> M68K registers typedef enum uc_m68k_reg { UC_M68K_REG_INVALID = 0, @@ -40,7 +52,7 @@ typedef enum uc_m68k_reg { UC_M68K_REG_SR, UC_M68K_REG_PC, - UC_M68K_REG_ENDING, // <-- mark the end of the list of registers + UC_M68K_REG_ENDING, // <-- mark the end of the list of registers } uc_m68k_reg; #ifdef __cplusplus diff --git a/include/unicorn/mips.h b/include/unicorn/mips.h index df54893f..977ee534 100644 --- a/include/unicorn/mips.h +++ b/include/unicorn/mips.h @@ -16,9 +16,41 @@ extern "C" { #undef mips #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_mips { + UC_CPU_MIPS_4KC = 0, + UC_CPU_MIPS_4KM, + UC_CPU_MIPS_4KECR1, + UC_CPU_MIPS_4KEMR1, + UC_CPU_MIPS_4KEC, + UC_CPU_MIPS_4KEM, + UC_CPU_MIPS_24KC, + UC_CPU_MIPS_24KEC, + UC_CPU_MIPS_24KF, + UC_CPU_MIPS_34KF, + UC_CPU_MIPS_74KF, + UC_CPU_MIPS_M14K, + UC_CPU_MIPS_M14KC, + UC_CPU_MIPS_P5600, + UC_CPU_MIPS_MIPS32R6_GENERIC, + UC_CPU_MIPS_I7200, + UC_CPU_MIPS_R4000, + UC_CPU_MIPS_VR5432, + UC_CPU_MIPS_5KC, + UC_CPU_MIPS_5KF, + UC_CPU_MIPS_20KC, + UC_CPU_MIPS_MIPS64R2_GENERIC, + UC_CPU_MIPS_5KEC, + UC_CPU_MIPS_5KEF, + UC_CPU_MIPS_I6400, + UC_CPU_MIPS_I6500, + UC_CPU_MIPS_LOONGSON_2E, + UC_CPU_MIPS_LOONGSON_2F, + UC_CPU_MIPS_MIPS64DSPR2 +} uc_cpu_mips; + //> MIPS registers typedef enum UC_MIPS_REG { UC_MIPS_REG_INVALID = 0, @@ -179,7 +211,7 @@ typedef enum UC_MIPS_REG { UC_MIPS_REG_CP0_USERLOCAL, UC_MIPS_REG_CP0_STATUS, - UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers + UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers // alias registers UC_MIPS_REG_ZERO = UC_MIPS_REG_0, @@ -212,7 +244,8 @@ typedef enum UC_MIPS_REG { UC_MIPS_REG_K1 = UC_MIPS_REG_27, UC_MIPS_REG_GP = UC_MIPS_REG_28, UC_MIPS_REG_SP = UC_MIPS_REG_29, - UC_MIPS_REG_FP = UC_MIPS_REG_30, UC_MIPS_REG_S8 = UC_MIPS_REG_30, + UC_MIPS_REG_FP = UC_MIPS_REG_30, + UC_MIPS_REG_S8 = UC_MIPS_REG_30, UC_MIPS_REG_RA = UC_MIPS_REG_31, UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0, diff --git a/include/unicorn/platform.h b/include/unicorn/platform.h index c504924f..25d3562e 100644 --- a/include/unicorn/platform.h +++ b/include/unicorn/platform.h @@ -22,16 +22,17 @@ MSVC++ 7.0 _MSC_VER == 1300 MSVC++ 6.0 _MSC_VER == 1200 MSVC++ 5.0 _MSC_VER == 1100 */ -#define MSC_VER_VS2003 1310 -#define MSC_VER_VS2005 1400 -#define MSC_VER_VS2008 1500 -#define MSC_VER_VS2010 1600 -#define MSC_VER_VS2012 1700 -#define MSC_VER_VS2013 1800 -#define MSC_VER_VS2015 1900 +#define MSC_VER_VS2003 1310 +#define MSC_VER_VS2005 1400 +#define MSC_VER_VS2008 1500 +#define MSC_VER_VS2010 1600 +#define MSC_VER_VS2012 1700 +#define MSC_VER_VS2013 1800 +#define MSC_VER_VS2015 1900 // handle stdbool.h compatibility -#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)) +#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && \ + (defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)) // MSVC // stdbool.h @@ -41,36 +42,38 @@ MSVC++ 5.0 _MSC_VER == 1100 typedef unsigned char bool; #define false 0 #define true 1 -#endif // __cplusplus +#endif // __cplusplus #else // VisualStudio 2013+ -> C99 is supported #include -#endif // (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE) +#endif // (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE) #else // not MSVC -> C99 is supported #include -#endif // !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)) +#endif // !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) + // && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined + // (_WIN64)) #if (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE) // this system does not have stdint.h -typedef signed char int8_t; +typedef signed char int8_t; typedef signed short int16_t; -typedef signed int int32_t; -typedef unsigned char uint8_t; +typedef signed int int32_t; +typedef unsigned char uint8_t; typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef signed long long int64_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; typedef unsigned long long uint64_t; -typedef signed char int_fast8_t; -typedef int int_fast16_t; -typedef int int_fast32_t; -typedef long long int_fast64_t; -typedef unsigned char uint_fast8_t; -typedef unsigned int uint_fast16_t; -typedef unsigned int uint_fast32_t; +typedef signed char int_fast8_t; +typedef int int_fast16_t; +typedef int int_fast32_t; +typedef long long int_fast64_t; +typedef unsigned char uint_fast8_t; +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; typedef unsigned long long uint_fast64_t; #if !defined(_W64) @@ -82,57 +85,57 @@ typedef unsigned long long uint_fast64_t; #endif #ifndef _INTPTR_T_DEFINED - #define _INTPTR_T_DEFINED - #ifdef _WIN64 -typedef long long intptr_t; - #else /* _WIN64 */ -typedef _W64 int intptr_t; - #endif /* _WIN64 */ +#define _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef long long intptr_t; +#else /* _WIN64 */ +typedef _W64 int intptr_t; +#endif /* _WIN64 */ #endif /* _INTPTR_T_DEFINED */ #ifndef _UINTPTR_T_DEFINED - #define _UINTPTR_T_DEFINED - #ifdef _WIN64 +#define _UINTPTR_T_DEFINED +#ifdef _WIN64 typedef unsigned long long uintptr_t; - #else /* _WIN64 */ -typedef _W64 unsigned int uintptr_t; - #endif /* _WIN64 */ +#else /* _WIN64 */ +typedef _W64 unsigned int uintptr_t; +#endif /* _WIN64 */ #endif /* _UINTPTR_T_DEFINED */ -#define INT8_MIN (-127i8 - 1) -#define INT16_MIN (-32767i16 - 1) -#define INT32_MIN (-2147483647i32 - 1) -#define INT64_MIN (-9223372036854775807i64 - 1) -#define INT8_MAX 127i8 -#define INT16_MAX 32767i16 -#define INT32_MAX 2147483647i32 -#define INT64_MAX 9223372036854775807i64 -#define UINT8_MAX 0xffui8 -#define UINT16_MAX 0xffffui16 -#define UINT32_MAX 0xffffffffui32 -#define UINT64_MAX 0xffffffffffffffffui64 +#define INT8_MIN (-127i8 - 1) +#define INT16_MIN (-32767i16 - 1) +#define INT32_MIN (-2147483647i32 - 1) +#define INT64_MIN (-9223372036854775807i64 - 1) +#define INT8_MAX 127i8 +#define INT16_MAX 32767i16 +#define INT32_MAX 2147483647i32 +#define INT64_MAX 9223372036854775807i64 +#define UINT8_MAX 0xffui8 +#define UINT16_MAX 0xffffui16 +#define UINT32_MAX 0xffffffffui32 +#define UINT64_MAX 0xffffffffffffffffui64 -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX #ifdef _WIN64 -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX #else /* _WIN64 */ -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX #endif /* _WIN64 */ #else // this system has stdint.h @@ -142,7 +145,8 @@ typedef _W64 unsigned int uintptr_t; #endif #include -#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE) +#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || + // defined(_KERNEL_MODE) // handle inttypes.h compatibility #if (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013)) || defined(_KERNEL_MODE) @@ -151,52 +155,53 @@ typedef _W64 unsigned int uintptr_t; #define __PRI_8_LENGTH_MODIFIER__ "hh" #define __PRI_64_LENGTH_MODIFIER__ "ll" -#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d" -#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i" -#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o" -#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u" -#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x" -#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X" +#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d" +#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i" +#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o" +#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u" +#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x" +#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X" -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" #if defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) -#define PRId32 "ld" -#define PRIi32 "li" -#define PRIo32 "lo" -#define PRIu32 "lu" -#define PRIx32 "lx" -#define PRIX32 "lX" -#else // OSX -#define PRId32 "d" -#define PRIi32 "i" -#define PRIo32 "o" -#define PRIu32 "u" -#define PRIx32 "x" -#define PRIX32 "X" -#endif // defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) +#define PRId32 "ld" +#define PRIi32 "li" +#define PRIo32 "lo" +#define PRIu32 "lu" +#define PRIx32 "lx" +#define PRIX32 "lX" +#else // OSX +#define PRId32 "d" +#define PRIi32 "i" +#define PRIo32 "o" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#endif // defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) #if defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) // redefine functions from inttypes.h used in cstool #define strtoull _strtoui64 #endif -#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d" -#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i" -#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o" -#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u" -#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x" -#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X" +#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d" +#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i" +#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o" +#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u" +#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x" +#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X" #else // this system has inttypes.h by default #include -#endif // #if defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE) +#endif // #if defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013) || + // defined(_KERNEL_MODE) // sys/time.h compatibility #if defined(_MSC_VER) @@ -220,7 +225,7 @@ static int usleep(uint32_t usec) if (!timer) return -1; - due.QuadPart = (-((int64_t) usec)) * 10LL; + due.QuadPart = (-((int64_t)usec)) * 10LL; if (!SetWaitableTimer(timer, &due, 0, NULL, NULL, 0)) { CloseHandle(timer); return -1; @@ -237,23 +242,22 @@ static int usleep(uint32_t usec) // misc support #if defined(_MSC_VER) -#ifdef _WIN64 -typedef signed __int64 ssize_t; +#ifdef _WIN64 +typedef signed __int64 ssize_t; #else -typedef _W64 signed int ssize_t; +typedef _W64 signed int ssize_t; #endif #ifndef va_copy -#define va_copy(d,s) ((d) = (s)) +#define va_copy(d, s) ((d) = (s)) #endif -#define strcasecmp _stricmp +#define strcasecmp _stricmp #if (_MSC_VER < MSC_VER_VS2015) -#define snprintf _snprintf +#define snprintf _snprintf #endif #if (_MSC_VER <= MSC_VER_VS2013) -#define strtoll _strtoi64 +#define strtoll _strtoi64 #endif #endif - #endif // UNICORN_PLATFORM_H diff --git a/include/unicorn/ppc.h b/include/unicorn/ppc.h index 9fded44c..9d09a990 100644 --- a/include/unicorn/ppc.h +++ b/include/unicorn/ppc.h @@ -12,9 +12,314 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_ppc { + UC_CPU_PPC_401A1 = 0, + UC_CPU_PPC_401B2, + UC_CPU_PPC_401C2, + UC_CPU_PPC_401D2, + UC_CPU_PPC_401E2, + UC_CPU_PPC_401F2, + UC_CPU_PPC_401G2, + UC_CPU_PPC_COBRA, + UC_CPU_PPC_403GA, + UC_CPU_PPC_403GB, + UC_CPU_PPC_403GC, + UC_CPU_PPC_403GCX, + UC_CPU_PPC_405D2, + UC_CPU_PPC_405D4, + UC_CPU_PPC_405CRA, + UC_CPU_PPC_405CRB, + UC_CPU_PPC_405CRC, + UC_CPU_PPC_405EP, + UC_CPU_PPC_405EZ, + UC_CPU_PPC_405GPA, + UC_CPU_PPC_405GPB, + UC_CPU_PPC_405GPC, + UC_CPU_PPC_405GPD, + UC_CPU_PPC_405GPR, + UC_CPU_PPC_405LP, + UC_CPU_PPC_NPE405H, + UC_CPU_PPC_NPE405H2, + UC_CPU_PPC_NPE405L, + UC_CPU_PPC_NPE4GS3, + UC_CPU_PPC_STB03, + UC_CPU_PPC_STB04, + UC_CPU_PPC_STB25, + UC_CPU_PPC_X2VP4, + UC_CPU_PPC_440_XILINX, + UC_CPU_PPC_440EPA, + UC_CPU_PPC_440EPB, + UC_CPU_PPC_440GPB, + UC_CPU_PPC_440GPC, + UC_CPU_PPC_440GRX, + UC_CPU_PPC_440GXA, + UC_CPU_PPC_440GXB, + UC_CPU_PPC_440GXC, + UC_CPU_PPC_440GXF, + UC_CPU_PPC_440SP, + UC_CPU_PPC_440SP2, + UC_CPU_PPC_440SPE, + UC_CPU_PPC_460EXB, + UC_CPU_PPC_MPC5XX, + UC_CPU_PPC_MPC8XX, + UC_CPU_PPC_G2, + UC_CPU_PPC_G2H4, + UC_CPU_PPC_G2GP, + UC_CPU_PPC_G2LS, + UC_CPU_PPC_MPC603, + UC_CPU_PPC_G2_HIP3, + UC_CPU_PPC_G2_HIP4, + UC_CPU_PPC_G2LE, + UC_CPU_PPC_G2LEGP, + UC_CPU_PPC_G2LELS, + UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_G2LEGP3, + UC_CPU_PPC_E200Z5, + UC_CPU_PPC_E200Z6, + UC_CPU_PPC_E300C1, + UC_CPU_PPC_E300C2, + UC_CPU_PPC_E300C3, + UC_CPU_PPC_E300C4, + UC_CPU_PPC_E500V1_V10, + UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_E500V2_V30, + UC_CPU_PPC_E500MC, + UC_CPU_PPC_E5500, + UC_CPU_PPC_E6500, + UC_CPU_PPC_E600, + UC_CPU_PPC_601_V0, + UC_CPU_PPC_601_V1, + UC_CPU_PPC_601_V2, + UC_CPU_PPC_602, + UC_CPU_PPC_603, + UC_CPU_PPC_603E_V11, + UC_CPU_PPC_603E_V12, + UC_CPU_PPC_603E_V13, + UC_CPU_PPC_603E_V14, + UC_CPU_PPC_603E_V22, + UC_CPU_PPC_603E_V3, + UC_CPU_PPC_603E_V4, + UC_CPU_PPC_603E_V41, + UC_CPU_PPC_603E7T, + UC_CPU_PPC_603E7V, + UC_CPU_PPC_603E7V1, + UC_CPU_PPC_603E7V2, + UC_CPU_PPC_603E7, + UC_CPU_PPC_603P, + UC_CPU_PPC_604, + UC_CPU_PPC_604E_V10, + UC_CPU_PPC_604E_V22, + UC_CPU_PPC_604E_V24, + UC_CPU_PPC_604R, + UC_CPU_PPC_7X0_V10, + UC_CPU_PPC_7X0_V20, + UC_CPU_PPC_7X0_V21, + UC_CPU_PPC_7X0_V22, + UC_CPU_PPC_7X0_V30, + UC_CPU_PPC_7X0_V31, + UC_CPU_PPC_740E, + UC_CPU_PPC_750E, + UC_CPU_PPC_7X0P, + UC_CPU_PPC_750CL_V10, + UC_CPU_PPC_750CL_V20, + UC_CPU_PPC_750CX_V10, + UC_CPU_PPC_750CX_V20, + UC_CPU_PPC_750CX_V21, + UC_CPU_PPC_750CX_V22, + UC_CPU_PPC_750CXE_V21, + UC_CPU_PPC_750CXE_V22, + UC_CPU_PPC_750CXE_V23, + UC_CPU_PPC_750CXE_V24, + UC_CPU_PPC_750CXE_V24B, + UC_CPU_PPC_750CXE_V30, + UC_CPU_PPC_750CXE_V31, + UC_CPU_PPC_750CXE_V31B, + UC_CPU_PPC_750CXR, + UC_CPU_PPC_750FL, + UC_CPU_PPC_750FX_V10, + UC_CPU_PPC_750FX_V20, + UC_CPU_PPC_750FX_V21, + UC_CPU_PPC_750FX_V22, + UC_CPU_PPC_750FX_V23, + UC_CPU_PPC_750GL, + UC_CPU_PPC_750GX_V10, + UC_CPU_PPC_750GX_V11, + UC_CPU_PPC_750GX_V12, + UC_CPU_PPC_750L_V20, + UC_CPU_PPC_750L_V21, + UC_CPU_PPC_750L_V22, + UC_CPU_PPC_750L_V30, + UC_CPU_PPC_750L_V32, + UC_CPU_PPC_7X5_V10, + UC_CPU_PPC_7X5_V11, + UC_CPU_PPC_7X5_V20, + UC_CPU_PPC_7X5_V21, + UC_CPU_PPC_7X5_V22, + UC_CPU_PPC_7X5_V23, + UC_CPU_PPC_7X5_V24, + UC_CPU_PPC_7X5_V25, + UC_CPU_PPC_7X5_V26, + UC_CPU_PPC_7X5_V27, + UC_CPU_PPC_7X5_V28, + UC_CPU_PPC_7400_V10, + UC_CPU_PPC_7400_V11, + UC_CPU_PPC_7400_V20, + UC_CPU_PPC_7400_V21, + UC_CPU_PPC_7400_V22, + UC_CPU_PPC_7400_V26, + UC_CPU_PPC_7400_V27, + UC_CPU_PPC_7400_V28, + UC_CPU_PPC_7400_V29, + UC_CPU_PPC_7410_V10, + UC_CPU_PPC_7410_V11, + UC_CPU_PPC_7410_V12, + UC_CPU_PPC_7410_V13, + UC_CPU_PPC_7410_V14, + UC_CPU_PPC_7448_V10, + UC_CPU_PPC_7448_V11, + UC_CPU_PPC_7448_V20, + UC_CPU_PPC_7448_V21, + UC_CPU_PPC_7450_V10, + UC_CPU_PPC_7450_V11, + UC_CPU_PPC_7450_V12, + UC_CPU_PPC_7450_V20, + UC_CPU_PPC_7450_V21, + UC_CPU_PPC_74X1_V23, + UC_CPU_PPC_74X1_V210, + UC_CPU_PPC_74X5_V10, + UC_CPU_PPC_74X5_V21, + UC_CPU_PPC_74X5_V32, + UC_CPU_PPC_74X5_V33, + UC_CPU_PPC_74X5_V34, + UC_CPU_PPC_74X7_V10, + UC_CPU_PPC_74X7_V11, + UC_CPU_PPC_74X7_V12, + UC_CPU_PPC_74X7A_V10, + UC_CPU_PPC_74X7A_V11, + UC_CPU_PPC_74X7A_V12, + UC_CPU_PPC_IOP480 = UC_CPU_PPC_401B2, + UC_CPU_PPC_X2VP20 = UC_CPU_PPC_440GXF, + UC_CPU_PPC_440GRA = UC_CPU_PPC_440EPB, + UC_CPU_PPC_440EPX = UC_CPU_PPC_440GRX, + UC_CPU_PPC_MPC5200_V10 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200_V11 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200_V12 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200B_V20 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200B_V21 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC834X = UC_CPU_PPC_E300C1, + UC_CPU_PPC_MPC837X = UC_CPU_PPC_E300C4, + UC_CPU_PPC_E500 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8533_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8533_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8533E_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8533E_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8540_V10 = UC_CPU_PPC_E500V1_V10, + UC_CPU_PPC_MPC8540_V20 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8540_V21 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541_V10 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541_V11 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541E_V10 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541E_V11 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8543_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8543_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8543_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8543_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8543E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8543E_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8543E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8543E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8544_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8544_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8544E_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8544E_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8545_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8545_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8545_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8545E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8545E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8545E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8547E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8547E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8547E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8548_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8548_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8548_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8548_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8548E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8548E_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8548E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8548E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8555_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8555_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8555E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8555E_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8560_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8560_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8560_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8567 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8567E = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8568 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8568E = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8572 = UC_CPU_PPC_E500V2_V30, + UC_CPU_PPC_MPC8572E = UC_CPU_PPC_E500V2_V30, + UC_CPU_PPC_MPC8610 = UC_CPU_PPC_E600, + UC_CPU_PPC_MPC8641 = UC_CPU_PPC_E600, + UC_CPU_PPC_MPC8641D = UC_CPU_PPC_E600, +} uc_cpu_ppc; + +typedef enum uc_cpu_ppc64 { + UC_CPU_PPC64_620 = 0, + UC_CPU_PPC64_630, + UC_CPU_PPC64_631, + UC_CPU_PPC64_POWER4, + UC_CPU_PPC64_POWER4P, + UC_CPU_PPC64_POWER5, + UC_CPU_PPC64_POWER5P_V21, + UC_CPU_PPC64_POWER6, + UC_CPU_PPC64_POWER_SERVER_MASK, + UC_CPU_PPC64_POWER7_BASE, + UC_CPU_PPC64_POWER7_V23, + UC_CPU_PPC64_POWER7P_BASE, + UC_CPU_PPC64_POWER7P_V21, + UC_CPU_PPC64_POWER8E_BASE, + UC_CPU_PPC64_POWER8E_V21, + UC_CPU_PPC64_POWER8_BASE, + UC_CPU_PPC64_POWER8_V20, + UC_CPU_PPC64_POWER8NVL_BASE, + UC_CPU_PPC64_POWER8NVL_V10, + UC_CPU_PPC64_POWER9_BASE, + UC_CPU_PPC64_POWER9_DD1, + UC_CPU_PPC64_POWER9_DD20, + UC_CPU_PPC64_POWER10_BASE, + UC_CPU_PPC64_POWER10_DD1, + UC_CPU_PPC64_970_V22, + UC_CPU_PPC64_970FX_V10, + UC_CPU_PPC64_970FX_V20, + UC_CPU_PPC64_970FX_V21, + UC_CPU_PPC64_970FX_V30, + UC_CPU_PPC64_970FX_V31, + UC_CPU_PPC64_970MP_V10, + UC_CPU_PPC64_970MP_V11, + UC_CPU_PPC64_CELL_V10, + UC_CPU_PPC64_CELL_V20, + UC_CPU_PPC64_CELL_V30, + UC_CPU_PPC64_CELL_V31, + UC_CPU_PPC64_RS64, + UC_CPU_PPC64_RS64II, + UC_CPU_PPC64_RS64III, + UC_CPU_PPC64_RS64IV, + UC_CPU_PPC64_CELL_V32 = UC_CPU_PPC64_CELL_V31, + UC_CPU_PPC64_CELL = UC_CPU_PPC64_CELL_V32, +} uc_cpu_ppc64; + //> PPC registers typedef enum uc_ppc_reg { UC_PPC_REG_INVALID = 0, diff --git a/include/unicorn/riscv.h b/include/unicorn/riscv.h index 42a26627..be821d77 100644 --- a/include/unicorn/riscv.h +++ b/include/unicorn/riscv.h @@ -12,9 +12,23 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_riscv32 { + UC_CPU_RISCV32_ANY = 0, + UC_CPU_RISCV32_BASE32, + UC_CPU_RISCV32_SIFIVE_E31, + UC_CPU_RISCV32_SIFIVE_U34, +} uc_cpu_riscv32; + +typedef enum uc_cpu_riscv64 { + UC_CPU_RISCV64_ANY = 0, + UC_CPU_RISCV64_BASE64, + UC_CPU_RISCV64_SIFIVE_E51, + UC_CPU_RISCV64_SIFIVE_U54, +} uc_cpu_riscv64; + //> RISCV registers typedef enum uc_riscv_reg { UC_RISCV_REG_INVALID = 0, @@ -53,111 +67,111 @@ typedef enum uc_riscv_reg { UC_RISCV_REG_X31, //> Floating-point registers - UC_RISCV_REG_F0, // "ft0" - UC_RISCV_REG_F1, // "ft1" - UC_RISCV_REG_F2, // "ft2" - UC_RISCV_REG_F3, // "ft3" - UC_RISCV_REG_F4, // "ft4" - UC_RISCV_REG_F5, // "ft5" - UC_RISCV_REG_F6, // "ft6" - UC_RISCV_REG_F7, // "ft7" - UC_RISCV_REG_F8, // "fs0" - UC_RISCV_REG_F9, // "fs1" - UC_RISCV_REG_F10, // "fa0" - UC_RISCV_REG_F11, // "fa1" - UC_RISCV_REG_F12, // "fa2" - UC_RISCV_REG_F13, // "fa3" - UC_RISCV_REG_F14, // "fa4" - UC_RISCV_REG_F15, // "fa5" - UC_RISCV_REG_F16, // "fa6" - UC_RISCV_REG_F17, // "fa7" - UC_RISCV_REG_F18, // "fs2" - UC_RISCV_REG_F19, // "fs3" - UC_RISCV_REG_F20, // "fs4" - UC_RISCV_REG_F21, // "fs5" - UC_RISCV_REG_F22, // "fs6" - UC_RISCV_REG_F23, // "fs7" - UC_RISCV_REG_F24, // "fs8" - UC_RISCV_REG_F25, // "fs9" - UC_RISCV_REG_F26, // "fs10" - UC_RISCV_REG_F27, // "fs11" - UC_RISCV_REG_F28, // "ft8" - UC_RISCV_REG_F29, // "ft9" - UC_RISCV_REG_F30, // "ft10" - UC_RISCV_REG_F31, // "ft11" + UC_RISCV_REG_F0, // "ft0" + UC_RISCV_REG_F1, // "ft1" + UC_RISCV_REG_F2, // "ft2" + UC_RISCV_REG_F3, // "ft3" + UC_RISCV_REG_F4, // "ft4" + UC_RISCV_REG_F5, // "ft5" + UC_RISCV_REG_F6, // "ft6" + UC_RISCV_REG_F7, // "ft7" + UC_RISCV_REG_F8, // "fs0" + UC_RISCV_REG_F9, // "fs1" + UC_RISCV_REG_F10, // "fa0" + UC_RISCV_REG_F11, // "fa1" + UC_RISCV_REG_F12, // "fa2" + UC_RISCV_REG_F13, // "fa3" + UC_RISCV_REG_F14, // "fa4" + UC_RISCV_REG_F15, // "fa5" + UC_RISCV_REG_F16, // "fa6" + UC_RISCV_REG_F17, // "fa7" + UC_RISCV_REG_F18, // "fs2" + UC_RISCV_REG_F19, // "fs3" + UC_RISCV_REG_F20, // "fs4" + UC_RISCV_REG_F21, // "fs5" + UC_RISCV_REG_F22, // "fs6" + UC_RISCV_REG_F23, // "fs7" + UC_RISCV_REG_F24, // "fs8" + UC_RISCV_REG_F25, // "fs9" + UC_RISCV_REG_F26, // "fs10" + UC_RISCV_REG_F27, // "fs11" + UC_RISCV_REG_F28, // "ft8" + UC_RISCV_REG_F29, // "ft9" + UC_RISCV_REG_F30, // "ft10" + UC_RISCV_REG_F31, // "ft11" - UC_RISCV_REG_PC, // PC register + UC_RISCV_REG_PC, // PC register - UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers + UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers //> Alias registers - UC_RISCV_REG_ZERO = UC_RISCV_REG_X0, // "zero" - UC_RISCV_REG_RA = UC_RISCV_REG_X1, // "ra" - UC_RISCV_REG_SP = UC_RISCV_REG_X2, // "sp" - UC_RISCV_REG_GP = UC_RISCV_REG_X3, // "gp" - UC_RISCV_REG_TP = UC_RISCV_REG_X4, // "tp" - UC_RISCV_REG_T0 = UC_RISCV_REG_X5, // "t0" - UC_RISCV_REG_T1 = UC_RISCV_REG_X6, // "t1" - UC_RISCV_REG_T2 = UC_RISCV_REG_X7, // "t2" - UC_RISCV_REG_S0 = UC_RISCV_REG_X8, // "s0" - UC_RISCV_REG_FP = UC_RISCV_REG_X8, // "fp" - UC_RISCV_REG_S1 = UC_RISCV_REG_X9, // "s1" - UC_RISCV_REG_A0 = UC_RISCV_REG_X10, // "a0" - UC_RISCV_REG_A1 = UC_RISCV_REG_X11, // "a1" - UC_RISCV_REG_A2 = UC_RISCV_REG_X12, // "a2" - UC_RISCV_REG_A3 = UC_RISCV_REG_X13, // "a3" - UC_RISCV_REG_A4 = UC_RISCV_REG_X14, // "a4" - UC_RISCV_REG_A5 = UC_RISCV_REG_X15, // "a5" - UC_RISCV_REG_A6 = UC_RISCV_REG_X16, // "a6" - UC_RISCV_REG_A7 = UC_RISCV_REG_X17, // "a7" - UC_RISCV_REG_S2 = UC_RISCV_REG_X18, // "s2" - UC_RISCV_REG_S3 = UC_RISCV_REG_X19, // "s3" - UC_RISCV_REG_S4 = UC_RISCV_REG_X20, // "s4" - UC_RISCV_REG_S5 = UC_RISCV_REG_X21, // "s5" - UC_RISCV_REG_S6 = UC_RISCV_REG_X22, // "s6" - UC_RISCV_REG_S7 = UC_RISCV_REG_X23, // "s7" - UC_RISCV_REG_S8 = UC_RISCV_REG_X24, // "s8" - UC_RISCV_REG_S9 = UC_RISCV_REG_X25, // "s9" - UC_RISCV_REG_S10 = UC_RISCV_REG_X26, // "s10" - UC_RISCV_REG_S11 = UC_RISCV_REG_X27, // "s11" - UC_RISCV_REG_T3 = UC_RISCV_REG_X28, // "t3" - UC_RISCV_REG_T4 = UC_RISCV_REG_X29, // "t4" - UC_RISCV_REG_T5 = UC_RISCV_REG_X30, // "t5" - UC_RISCV_REG_T6 = UC_RISCV_REG_X31, // "t6" + UC_RISCV_REG_ZERO = UC_RISCV_REG_X0, // "zero" + UC_RISCV_REG_RA = UC_RISCV_REG_X1, // "ra" + UC_RISCV_REG_SP = UC_RISCV_REG_X2, // "sp" + UC_RISCV_REG_GP = UC_RISCV_REG_X3, // "gp" + UC_RISCV_REG_TP = UC_RISCV_REG_X4, // "tp" + UC_RISCV_REG_T0 = UC_RISCV_REG_X5, // "t0" + UC_RISCV_REG_T1 = UC_RISCV_REG_X6, // "t1" + UC_RISCV_REG_T2 = UC_RISCV_REG_X7, // "t2" + UC_RISCV_REG_S0 = UC_RISCV_REG_X8, // "s0" + UC_RISCV_REG_FP = UC_RISCV_REG_X8, // "fp" + UC_RISCV_REG_S1 = UC_RISCV_REG_X9, // "s1" + UC_RISCV_REG_A0 = UC_RISCV_REG_X10, // "a0" + UC_RISCV_REG_A1 = UC_RISCV_REG_X11, // "a1" + UC_RISCV_REG_A2 = UC_RISCV_REG_X12, // "a2" + UC_RISCV_REG_A3 = UC_RISCV_REG_X13, // "a3" + UC_RISCV_REG_A4 = UC_RISCV_REG_X14, // "a4" + UC_RISCV_REG_A5 = UC_RISCV_REG_X15, // "a5" + UC_RISCV_REG_A6 = UC_RISCV_REG_X16, // "a6" + UC_RISCV_REG_A7 = UC_RISCV_REG_X17, // "a7" + UC_RISCV_REG_S2 = UC_RISCV_REG_X18, // "s2" + UC_RISCV_REG_S3 = UC_RISCV_REG_X19, // "s3" + UC_RISCV_REG_S4 = UC_RISCV_REG_X20, // "s4" + UC_RISCV_REG_S5 = UC_RISCV_REG_X21, // "s5" + UC_RISCV_REG_S6 = UC_RISCV_REG_X22, // "s6" + UC_RISCV_REG_S7 = UC_RISCV_REG_X23, // "s7" + UC_RISCV_REG_S8 = UC_RISCV_REG_X24, // "s8" + UC_RISCV_REG_S9 = UC_RISCV_REG_X25, // "s9" + UC_RISCV_REG_S10 = UC_RISCV_REG_X26, // "s10" + UC_RISCV_REG_S11 = UC_RISCV_REG_X27, // "s11" + UC_RISCV_REG_T3 = UC_RISCV_REG_X28, // "t3" + UC_RISCV_REG_T4 = UC_RISCV_REG_X29, // "t4" + UC_RISCV_REG_T5 = UC_RISCV_REG_X30, // "t5" + UC_RISCV_REG_T6 = UC_RISCV_REG_X31, // "t6" - UC_RISCV_REG_FT0 = UC_RISCV_REG_F0, // "ft0" - UC_RISCV_REG_FT1 = UC_RISCV_REG_F1, // "ft1" - UC_RISCV_REG_FT2 = UC_RISCV_REG_F2, // "ft2" - UC_RISCV_REG_FT3 = UC_RISCV_REG_F3, // "ft3" - UC_RISCV_REG_FT4 = UC_RISCV_REG_F4, // "ft4" - UC_RISCV_REG_FT5 = UC_RISCV_REG_F5, // "ft5" - UC_RISCV_REG_FT6 = UC_RISCV_REG_F6, // "ft6" - UC_RISCV_REG_FT7 = UC_RISCV_REG_F7, // "ft7" - UC_RISCV_REG_FS0 = UC_RISCV_REG_F8, // "fs0" - UC_RISCV_REG_FS1 = UC_RISCV_REG_F9, // "fs1" + UC_RISCV_REG_FT0 = UC_RISCV_REG_F0, // "ft0" + UC_RISCV_REG_FT1 = UC_RISCV_REG_F1, // "ft1" + UC_RISCV_REG_FT2 = UC_RISCV_REG_F2, // "ft2" + UC_RISCV_REG_FT3 = UC_RISCV_REG_F3, // "ft3" + UC_RISCV_REG_FT4 = UC_RISCV_REG_F4, // "ft4" + UC_RISCV_REG_FT5 = UC_RISCV_REG_F5, // "ft5" + UC_RISCV_REG_FT6 = UC_RISCV_REG_F6, // "ft6" + UC_RISCV_REG_FT7 = UC_RISCV_REG_F7, // "ft7" + UC_RISCV_REG_FS0 = UC_RISCV_REG_F8, // "fs0" + UC_RISCV_REG_FS1 = UC_RISCV_REG_F9, // "fs1" - UC_RISCV_REG_FA0 = UC_RISCV_REG_F10, // "fa0" - UC_RISCV_REG_FA1 = UC_RISCV_REG_F11, // "fa1" - UC_RISCV_REG_FA2 = UC_RISCV_REG_F12, // "fa2" - UC_RISCV_REG_FA3 = UC_RISCV_REG_F13, // "fa3" - UC_RISCV_REG_FA4 = UC_RISCV_REG_F14, // "fa4" - UC_RISCV_REG_FA5 = UC_RISCV_REG_F15, // "fa5" - UC_RISCV_REG_FA6 = UC_RISCV_REG_F16, // "fa6" - UC_RISCV_REG_FA7 = UC_RISCV_REG_F17, // "fa7" - UC_RISCV_REG_FS2 = UC_RISCV_REG_F18, // "fs2" - UC_RISCV_REG_FS3 = UC_RISCV_REG_F19, // "fs3" - UC_RISCV_REG_FS4 = UC_RISCV_REG_F20, // "fs4" - UC_RISCV_REG_FS5 = UC_RISCV_REG_F21, // "fs5" - UC_RISCV_REG_FS6 = UC_RISCV_REG_F22, // "fs6" - UC_RISCV_REG_FS7 = UC_RISCV_REG_F23, // "fs7" - UC_RISCV_REG_FS8 = UC_RISCV_REG_F24, // "fs8" - UC_RISCV_REG_FS9 = UC_RISCV_REG_F25, // "fs9" - UC_RISCV_REG_FS10 = UC_RISCV_REG_F26, // "fs10" - UC_RISCV_REG_FS11 = UC_RISCV_REG_F27, // "fs11" - UC_RISCV_REG_FT8 = UC_RISCV_REG_F28, // "ft8" - UC_RISCV_REG_FT9 = UC_RISCV_REG_F29, // "ft9" - UC_RISCV_REG_FT10 = UC_RISCV_REG_F30, // "ft10" - UC_RISCV_REG_FT11 = UC_RISCV_REG_F31, // "ft11" + UC_RISCV_REG_FA0 = UC_RISCV_REG_F10, // "fa0" + UC_RISCV_REG_FA1 = UC_RISCV_REG_F11, // "fa1" + UC_RISCV_REG_FA2 = UC_RISCV_REG_F12, // "fa2" + UC_RISCV_REG_FA3 = UC_RISCV_REG_F13, // "fa3" + UC_RISCV_REG_FA4 = UC_RISCV_REG_F14, // "fa4" + UC_RISCV_REG_FA5 = UC_RISCV_REG_F15, // "fa5" + UC_RISCV_REG_FA6 = UC_RISCV_REG_F16, // "fa6" + UC_RISCV_REG_FA7 = UC_RISCV_REG_F17, // "fa7" + UC_RISCV_REG_FS2 = UC_RISCV_REG_F18, // "fs2" + UC_RISCV_REG_FS3 = UC_RISCV_REG_F19, // "fs3" + UC_RISCV_REG_FS4 = UC_RISCV_REG_F20, // "fs4" + UC_RISCV_REG_FS5 = UC_RISCV_REG_F21, // "fs5" + UC_RISCV_REG_FS6 = UC_RISCV_REG_F22, // "fs6" + UC_RISCV_REG_FS7 = UC_RISCV_REG_F23, // "fs7" + UC_RISCV_REG_FS8 = UC_RISCV_REG_F24, // "fs8" + UC_RISCV_REG_FS9 = UC_RISCV_REG_F25, // "fs9" + UC_RISCV_REG_FS10 = UC_RISCV_REG_F26, // "fs10" + UC_RISCV_REG_FS11 = UC_RISCV_REG_F27, // "fs11" + UC_RISCV_REG_FT8 = UC_RISCV_REG_F28, // "ft8" + UC_RISCV_REG_FT9 = UC_RISCV_REG_F29, // "ft9" + UC_RISCV_REG_FT10 = UC_RISCV_REG_F30, // "ft10" + UC_RISCV_REG_FT11 = UC_RISCV_REG_F31, // "ft11" } uc_riscv_reg; #ifdef __cplusplus diff --git a/include/unicorn/sparc.h b/include/unicorn/sparc.h index 08e05386..1bed80ae 100644 --- a/include/unicorn/sparc.h +++ b/include/unicorn/sparc.h @@ -16,9 +16,45 @@ extern "C" { #undef sparc #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif +typedef enum uc_cpu_sparc { + UC_CPU_SPARC_FUJITSU_MB86904 = 0, + UC_CPU_SPARC_FUJITSU_MB86907, + UC_CPU_SPARC_TI_MICROSPARC_I, + UC_CPU_SPARC_TI_MICROSPARC_II, + UC_CPU_SPARC_TI_MICROSPARC_IIEP, + UC_CPU_SPARC_TI_SUPERSPARC_40, + UC_CPU_SPARC_TI_SUPERSPARC_50, + UC_CPU_SPARC_TI_SUPERSPARC_51, + UC_CPU_SPARC_TI_SUPERSPARC_60, + UC_CPU_SPARC_TI_SUPERSPARC_61, + UC_CPU_SPARC_TI_SUPERSPARC_II, + UC_CPU_SPARC_LEON2, + UC_CPU_SPARC_LEON3 +} uc_cpu_sparc; + +typedef enum uc_cpu_sparc64 { + UC_CPU_SPARC64_FUJITSU = 0, + UC_CPU_SPARC64_FUJITSU_III, + UC_CPU_SPARC64_FUJITSU_IV, + UC_CPU_SPARC64_FUJITSU_V, + UC_CPU_SPARC64_TI_ULTRASPARC_I, + UC_CPU_SPARC64_TI_ULTRASPARC_II, + UC_CPU_SPARC64_TI_ULTRASPARC_III, + UC_CPU_SPARC64_TI_ULTRASPARC_IIE, + UC_CPU_SPARC64_SUN_ULTRASPARC_III, + UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU, + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII, + UC_CPU_SPARC64_SUN_ULTRASPARC_IV, + UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS, + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS, + UC_CPU_SPARC64_SUN_ULTRASPARC_T1, + UC_CPU_SPARC64_SUN_ULTRASPARC_T2, + UC_CPU_SPARC64_NEC_ULTRASPARC_I, +} uc_cpu_sparc64; + //> SPARC registers typedef enum uc_sparc_reg { UC_SPARC_REG_INVALID = 0, @@ -71,7 +107,7 @@ typedef enum uc_sparc_reg { UC_SPARC_REG_F58, UC_SPARC_REG_F60, UC_SPARC_REG_F62, - UC_SPARC_REG_FCC0, // Floating condition codes + UC_SPARC_REG_FCC0, // Floating condition codes UC_SPARC_REG_FCC1, UC_SPARC_REG_FCC2, UC_SPARC_REG_FCC3, @@ -91,7 +127,7 @@ typedef enum uc_sparc_reg { UC_SPARC_REG_I5, UC_SPARC_REG_FP, UC_SPARC_REG_I7, - UC_SPARC_REG_ICC, // Integer condition codes + UC_SPARC_REG_ICC, // Integer condition codes UC_SPARC_REG_L0, UC_SPARC_REG_L1, UC_SPARC_REG_L2, @@ -114,9 +150,9 @@ typedef enum uc_sparc_reg { UC_SPARC_REG_XCC, // pseudo register - UC_SPARC_REG_PC, // program counter register + UC_SPARC_REG_PC, // program counter register - UC_SPARC_REG_ENDING, // <-- mark the end of the list of registers + UC_SPARC_REG_ENDING, // <-- mark the end of the list of registers // extras UC_SPARC_REG_O6 = UC_SPARC_REG_SP, diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 239ff064..48e8cb1b 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -42,11 +42,11 @@ typedef size_t uc_hook; #endif #ifdef _MSC_VER -#pragma warning(disable:4201) -#pragma warning(disable:4100) +#pragma warning(disable : 4201) +#pragma warning(disable : 4100) #ifdef UNICORN_SHARED #define UNICORN_EXPORT __declspec(dllexport) -#else // defined(UNICORN_STATIC) +#else // defined(UNICORN_STATIC) #define UNICORN_EXPORT #endif #else @@ -62,7 +62,8 @@ typedef size_t uc_hook; #elif defined(_MSC_VER) #define UNICORN_DEPRECATED __declspec(deprecated) #else -#pragma message("WARNING: You need to implement UNICORN_DEPRECATED for this compiler") +#pragma message( \ + "WARNING: You need to implement UNICORN_DEPRECATED for this compiler") #define UNICORN_DEPRECATED #endif @@ -75,7 +76,6 @@ typedef size_t uc_hook; #define UC_VERSION_MINOR UC_API_MINOR #define UC_VERSION_EXTRA 0 - /* Macro to create combined version which can be compared to result of uc_version() API. @@ -90,14 +90,14 @@ typedef size_t uc_hook; // Architecture type typedef enum uc_arch { - UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) - UC_ARCH_ARM64, // ARM-64, also called AArch64 - UC_ARCH_MIPS, // Mips architecture - UC_ARCH_X86, // X86 architecture (including x86 & x86-64) - UC_ARCH_PPC, // PowerPC architecture - UC_ARCH_SPARC, // Sparc architecture - UC_ARCH_M68K, // M68K architecture - UC_ARCH_RISCV, // RISCV architecture + UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) + UC_ARCH_ARM64, // ARM-64, also called AArch64 + UC_ARCH_MIPS, // Mips architecture + UC_ARCH_X86, // X86 architecture (including x86 & x86-64) + UC_ARCH_PPC, // PowerPC architecture + UC_ARCH_SPARC, // Sparc architecture + UC_ARCH_M68K, // M68K architecture + UC_ARCH_RISCV, // RISCV architecture UC_ARCH_MAX, } uc_arch; @@ -107,41 +107,42 @@ typedef enum uc_mode { UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode // arm / arm64 - UC_MODE_ARM = 0, // ARM mode - UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) - UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series - UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) + UC_MODE_ARM = 0, // ARM mode + UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) + UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series + UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) // arm (32bit) cpu types - UC_MODE_ARM926 = 1 << 7, // ARM926 CPU type - UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type - UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type + UC_MODE_ARM926 = 1 << 7, // ARM926 CPU type + UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type + UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type // mips - UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported) - UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported) - UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported) - UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA - UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA + UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported) + UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported) + UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported) + UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA + UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA // x86 / x64 - UC_MODE_16 = 1 << 1, // 16-bit mode - UC_MODE_32 = 1 << 2, // 32-bit mode - UC_MODE_64 = 1 << 3, // 64-bit mode + UC_MODE_16 = 1 << 1, // 16-bit mode + UC_MODE_32 = 1 << 2, // 32-bit mode + UC_MODE_64 = 1 << 3, // 64-bit mode - // ppc - UC_MODE_PPC32 = 1 << 2, // 32-bit mode - UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) - UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) + // ppc + UC_MODE_PPC32 = 1 << 2, // 32-bit mode + UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) + UC_MODE_QPX = + 1 << 4, // Quad Processing eXtensions mode (currently unsupported) // sparc - UC_MODE_SPARC32 = 1 << 2, // 32-bit mode - UC_MODE_SPARC64 = 1 << 3, // 64-bit mode - UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported) + UC_MODE_SPARC32 = 1 << 2, // 32-bit mode + UC_MODE_SPARC64 = 1 << 3, // 64-bit mode + UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported) // riscv - UC_MODE_RISCV32 = 1 << 2, // 32-bit mode - UC_MODE_RISCV64 = 1 << 3, // 64-bit mode + UC_MODE_RISCV32 = 1 << 2, // 32-bit mode + UC_MODE_RISCV64 = 1 << 3, // 64-bit mode // m68k } uc_mode; @@ -149,39 +150,48 @@ typedef enum uc_mode { // All type of errors encountered by Unicorn API. // These are values returned by uc_errno() typedef enum uc_err { - UC_ERR_OK = 0, // No error: everything was fine - UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate() - UC_ERR_ARCH, // Unsupported architecture: uc_open() - UC_ERR_HANDLE, // Invalid handle - UC_ERR_MODE, // Invalid/unsupported mode: uc_open() - UC_ERR_VERSION, // Unsupported version (bindings) - UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: uc_emu_start() - UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: uc_emu_start() - UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: uc_emu_start() - UC_ERR_HOOK, // Invalid hook type: uc_hook_add() - UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start() - UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() - UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start() - UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start() - UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start() - UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API) + UC_ERR_OK = 0, // No error: everything was fine + UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate() + UC_ERR_ARCH, // Unsupported architecture: uc_open() + UC_ERR_HANDLE, // Invalid handle + UC_ERR_MODE, // Invalid/unsupported mode: uc_open() + UC_ERR_VERSION, // Unsupported version (bindings) + UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: + // uc_emu_start() + UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: + // uc_emu_start() + UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: + // uc_emu_start() + UC_ERR_HOOK, // Invalid hook type: uc_hook_add() + UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: + // uc_emu_start() + UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() + UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: + // uc_emu_start() + UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: + // uc_emu_start() + UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: + // uc_emu_start() + UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific + // function API) UC_ERR_READ_UNALIGNED, // Unaligned read - UC_ERR_WRITE_UNALIGNED, // Unaligned write - UC_ERR_FETCH_UNALIGNED, // Unaligned fetch - UC_ERR_HOOK_EXIST, // hook for this event already existed - UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() - UC_ERR_EXCEPTION, // Unhandled CPU exception + UC_ERR_WRITE_UNALIGNED, // Unaligned write + UC_ERR_FETCH_UNALIGNED, // Unaligned fetch + UC_ERR_HOOK_EXIST, // hook for this event already existed + UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() + UC_ERR_EXCEPTION, // Unhandled CPU exception } uc_err; - /* Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK) @address: address where the code is being executed - @size: size of machine instruction(s) being executed, or 0 when size is unknown + @size: size of machine instruction(s) being executed, or 0 when size is + unknown @user_data: user data passed to tracing APIs. */ -typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, void *user_data); +typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data); /* Callback function for tracing interrupts (for uc_hook_intr()) @@ -189,14 +199,16 @@ typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, @intno: interrupt number @user_data: user data passed to tracing APIs. */ -typedef void (*uc_cb_hookintr_t)(uc_engine *uc, uint32_t intno, void *user_data); +typedef void (*uc_cb_hookintr_t)(uc_engine *uc, uint32_t intno, + void *user_data); /* Callback function for tracing invalid instructions @user_data: user data passed to tracing APIs. - @return: return true to continue, or false to stop program (due to invalid instruction). + @return: return true to continue, or false to stop program (due to invalid + instruction). */ typedef bool (*uc_cb_hookinsn_invalid_t)(uc_engine *uc, void *user_data); @@ -207,7 +219,8 @@ typedef bool (*uc_cb_hookinsn_invalid_t)(uc_engine *uc, void *user_data); @size: data size (1/2/4) to be read from this port @user_data: user data passed to tracing APIs. */ -typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void *user_data); +typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, + void *user_data); /* Callback function for OUT instruction of X86 @@ -216,7 +229,24 @@ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void @size: data size (1/2/4) to be written to this port @value: data value to be written to this port */ -typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data); +typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, + uint32_t value, void *user_data); + +// Represent a TranslationBlock. +typedef struct uc_tb { + uint64_t pc; + uint16_t icount; + uint16_t size; +} uc_tb; + +/* + Callback function for new edges between translation blocks. + + @cur_tb: Current TB which is to be generated. + @prev_tb: The previous TB. +*/ +typedef void (*uc_hook_edge_gen_t)(uc_engine *uc, uc_tb *cur_tb, uc_tb *prev_tb, + void *user_data); /* Callback function for MMIO read @@ -225,7 +255,8 @@ typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_ @size: data size to read @user_data: user data passed to uc_mmio_map() */ -typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, unsigned size, void *user_data); +typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, + unsigned size, void *user_data); /* Callback function for MMIO write @@ -235,28 +266,30 @@ typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, unsigned s @value: data value to be written @user_data: user data passed to uc_mmio_map() */ -typedef void (*uc_cb_mmio_write_t)(uc_engine *uc, uint64_t offset, unsigned size, uint64_t value, void *user_data); - +typedef void (*uc_cb_mmio_write_t)(uc_engine *uc, uint64_t offset, + unsigned size, uint64_t value, + void *user_data); // All type of memory accesses for UC_HOOK_MEM_* typedef enum uc_mem_type { - UC_MEM_READ = 16, // Memory is read from - UC_MEM_WRITE, // Memory is written to - UC_MEM_FETCH, // Memory is fetched - UC_MEM_READ_UNMAPPED, // Unmapped memory is read from - UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to - UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched - UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory - UC_MEM_READ_PROT, // Read from read protected, but mapped, memory - UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory - UC_MEM_READ_AFTER, // Memory is read from (successful access) + UC_MEM_READ = 16, // Memory is read from + UC_MEM_WRITE, // Memory is written to + UC_MEM_FETCH, // Memory is fetched + UC_MEM_READ_UNMAPPED, // Unmapped memory is read from + UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to + UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched + UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory + UC_MEM_READ_PROT, // Read from read protected, but mapped, memory + UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory + UC_MEM_READ_AFTER, // Memory is read from (successful access) } uc_mem_type; // All type of hooks for uc_hook_add() API. typedef enum uc_hook_type { // Hook all interrupt/syscall events UC_HOOK_INTR = 1 << 0, - // Hook a particular instruction - only a very small subset of instructions supported here + // Hook a particular instruction - only a very small subset of instructions + // supported here UC_HOOK_INSN = 1 << 1, // Hook a range of code UC_HOOK_CODE = 1 << 2, @@ -285,24 +318,38 @@ typedef enum uc_hook_type { UC_HOOK_MEM_READ_AFTER = 1 << 13, // Hook invalid instructions exceptions. UC_HOOK_INSN_INVALID = 1 << 14, + // Hook on new edge generation. Could be useful in program analysis. + // + // NOTE: This is different from UC_HOOK_BLOCK in 2 ways: + // 1. The hook is called before executing code. + // 2. The hook is only called when generation is triggered. + UC_HOOK_EDGE_GENERATED = 1 << 15 } uc_hook_type; // Hook type for all events of unmapped memory access -#define UC_HOOK_MEM_UNMAPPED (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + UC_HOOK_MEM_FETCH_UNMAPPED) +#define UC_HOOK_MEM_UNMAPPED \ + (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + \ + UC_HOOK_MEM_FETCH_UNMAPPED) // Hook type for all events of illegal protected memory access -#define UC_HOOK_MEM_PROT (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT) +#define UC_HOOK_MEM_PROT \ + (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT) // Hook type for all events of illegal read memory access -#define UC_HOOK_MEM_READ_INVALID (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED) +#define UC_HOOK_MEM_READ_INVALID \ + (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED) // Hook type for all events of illegal write memory access -#define UC_HOOK_MEM_WRITE_INVALID (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED) +#define UC_HOOK_MEM_WRITE_INVALID \ + (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED) // Hook type for all events of illegal fetch memory access -#define UC_HOOK_MEM_FETCH_INVALID (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED) +#define UC_HOOK_MEM_FETCH_INVALID \ + (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED) // Hook type for all events of illegal memory access #define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT) // Hook type for all events of valid memory access -// NOTE: UC_HOOK_MEM_READ is triggered before UC_HOOK_MEM_READ_PROT and UC_HOOK_MEM_READ_UNMAPPED, so -// this hook may technically trigger on some invalid reads. -#define UC_HOOK_MEM_VALID (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH) +// NOTE: UC_HOOK_MEM_READ is triggered before UC_HOOK_MEM_READ_PROT and +// UC_HOOK_MEM_READ_UNMAPPED, so +// this hook may technically trigger on some invalid reads. +#define UC_HOOK_MEM_VALID \ + (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH) /* Callback function for hooking memory (READ, WRITE & FETCH) @@ -314,7 +361,8 @@ typedef enum uc_hook_type { @user_data: user data passed to tracing APIs */ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data); + uint64_t address, int size, int64_t value, + void *user_data); /* Callback function for handling invalid memory access events (UNMAPPED and @@ -326,21 +374,24 @@ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type, @value: value of data being written to memory, or irrelevant if type = READ. @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 - memory is made accessible with the correct permissions during the hook. + @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 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, - the memory should be uc_mem_map()-ed with the correct permissions, and the - instruction will then read or write to the address as it was supposed to. + In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED + callback, the memory should be uc_mem_map()-ed with the correct permissions, + and the instruction will then read or write to the address as it was supposed + to. - In the event of a UC_MEM_FETCH_UNMAPPED callback, the memory can be mapped - in as executable, in which case execution will resume from the fetched address. - The instruction pointer may be written to in order to change where execution resumes, - but the fetch must succeed if execution is to resume. + In the event of a UC_MEM_FETCH_UNMAPPED callback, the memory can be + mapped in as executable, in which case execution will resume from the fetched + address. The instruction pointer may be written to in order to change where + execution resumes, but the fetch must succeed if execution is to resume. */ typedef bool (*uc_cb_eventmem_t)(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data); + uint64_t address, int size, int64_t value, + void *user_data); /* Memory region mapped by uc_mem_map() and uc_mem_map_ptr() @@ -357,10 +408,116 @@ typedef enum uc_query_type { // Dynamically query current hardware mode. UC_QUERY_MODE = 1, UC_QUERY_PAGE_SIZE, // query pagesize of engine - UC_QUERY_ARCH, // query architecture of engine (for ARM to query Thumb mode) - UC_QUERY_TIMEOUT, // query if emulation stops due to timeout (indicated if result = True) + UC_QUERY_ARCH, // query architecture of engine (for ARM to query Thumb mode) + UC_QUERY_TIMEOUT, // query if emulation stops due to timeout (indicated if + // result = True) } uc_query_type; +// The implementation of uc_ctl is like what Linux ioctl does but slightly +// different. +// +// A uc_control_type passed to uc_ctl is constructed as: +// +// R/W NR Reserved Type +// [ ] [ ] [ ] [ ] +// 31 30 29 26 25 16 15 0 +// +// @R/W: Whether the operation is a read or write access. +// @NR: Number of arguments. +// @Reserved: Should be zero, reserved for future extension. +// @Type: Taken from uc_control_type enum. +// +// See the helper macros below. + +// No input and output arguments. +#define UC_CTL_IO_NONE (0) +// The arguments are used for input. +#define UC_CTL_IO_WRITE (1) +// The arguments are used for ouput. +#define UC_CTL_IO_READ (2) +// The arguments include both input and output arugments. +#define UC_CTL_IO_READ_WRITE (UC_CTL_IO_WRITE | UC_CTL_IO_READ) + +#define UC_CTL(type, nr, rw) ((type) | ((nr) << 26) | ((rw) << 30)) +#define UC_CTL_NONE(type, nr) UC_CTL(type, nr, UC_CTL_IO_NONE) +#define UC_CTL_READ(type, nr) UC_CTL(type, nr, UC_CTL_IO_READ) +#define UC_CTL_WRITE(type, nr) UC_CTL(type, nr, UC_CTL_IO_WRITE) +#define UC_CTL_READ_WRITE(type, nr) UC_CTL(type, nr, UC_CTL_IO_READ_WRITE) + +// All type of controls for uc_ctl API. +// The controls are organized in a tree level. +// If a control don't have `Set` or `Get` for @args, it means it's r/o or w/o. +typedef enum uc_control_type { + // Current mode. + // Read: @args = (int*) + UC_CTL_UC_MODE = 0, + // Curent page size. + // Write: @args = (uint32_t) + // Read: @args = (uint32_t*) + UC_CTL_UC_PAGE_SIZE, + // Current arch. + // Read: @args = (int*) + UC_CTL_UC_ARCH, + // Current timeout. + // Read: @args = (uint64_t*) + UC_CTL_UC_TIMEOUT, + // Enable multiple exists. + // Without this control, reading/setting exists won't work. + // This is for API backward compatibility. + // Write: @args = (int) + UC_CTL_UC_USE_EXITS, + // The number of current exists. + // Read: @args = (size_t*) + UC_CTL_UC_EXITS_CNT, + // Current exists. + // Write: @args = (uint64_t* exists, size_t len) + // @len = UC_CTL_UC_EXITS_CNT + // Read: @args = (uint64_t* exists, size_t len) + // @len = UC_CTL_UC_EXITS_CNT + UC_CTL_UC_EXITS, + + // Set the cpu model of uc. + // Note this option can only be set before any Unicorn + // API is called except for uc_open. + // Write: @args = (int) + // Read: @args = (int) + UC_CTL_CPU_MODEL, + // Request a tb cache at a specific address + // Read: @args = (uint64_t, uc_tb*) + UC_CTL_TB_REQUEST_CACHE, + // Invalidate a tb cache at a specific address + // Read: @args = (uint64_t) + UC_CTL_TB_REMOVE_CACHE + +} uc_control_type; + +#define uc_ctl_get_mode(uc, mode) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_MODE, 1), (mode)) +#define uc_ctl_get_page_size(uc, ptr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1), (ptr)) +#define uc_ctl_set_page_size(uc, page_size) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_PAGE_SIZE, 1), (page_size)) +#define uc_ctl_get_arch(uc, arch) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_ARCH, 1), (arch)) +#define uc_ctl_get_timeout(uc, ptr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_TIMEOUT, 1), (ptr)) +#define uc_ctl_exits_enabled(uc, enabled) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_USE_EXITS, 1), (enabled)) +#define uc_ctl_get_exists_cnt(uc, ptr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_EXITS_CNT, 1), (ptr)) +#define uc_ctl_get_exists(uc, buffer, len) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_EXITS, 2), (buffer), (len)) +#define uc_ctl_set_exists(uc, buffer, len) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_EXITS, 2), (buffer), (len)) +#define uc_ctl_get_cpu_model(uc, model) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_CPU_MODEL, 1), (model)) +#define uc_ctl_set_cpu_model(uc, model) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CPU_MODEL, 1), (model)) +#define uc_ctl_remove_cache(uc, address) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REMOVE_CACHE, 1), (address)) +#define uc_ctl_request_cache(uc, address, tb) \ + uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_REQUEST_CACHE, 2), (address), (tb)) + // Opaque storage for CPU context, used with uc_context_*() struct uc_context; typedef struct uc_context uc_context; @@ -385,7 +542,6 @@ typedef struct uc_context uc_context; UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor); - /* Determine if the given architecture is supported by this library. @@ -396,7 +552,6 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor); UNICORN_EXPORT bool uc_arch_supported(uc_arch arch); - /* Create new instance of unicorn engine. @@ -439,6 +594,20 @@ uc_err uc_close(uc_engine *uc); UNICORN_EXPORT uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result); +/* + Control internal states of engine. + + Also see uc_ctl_* macro helpers for easy use. + + @uc: handle returned by uc_open() + @option: control type. + @args: See uc_control_type for details about variadic arguments. + + @return: error code of uc_err enum type (UC_ERR_*, see above) +*/ +UNICORN_EXPORT +uc_err uc_ctl(uc_engine *uc, uc_control_type option, ...); + /* Report the last error number when some API function fails. Like glibc's errno, uc_errno might not retain its old value once accessed. @@ -499,7 +668,8 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value); for detailed error). */ UNICORN_EXPORT -uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, int count); +uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, + int count); /* Read multiple register values. @@ -529,7 +699,8 @@ uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size); +uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, + size_t size); /* Read a range of bytes in memory. @@ -566,7 +737,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); for detailed error). */ UNICORN_EXPORT -uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count); +uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, + uint64_t timeout, size_t count); /* Stop emulation (which was started by uc_emu_start() API. @@ -585,15 +757,17 @@ uc_err uc_emu_stop(uc_engine *uc); The callback will be run when the hook event is hit. @uc: handle returned by uc_open() - @hh: hook handle returned from this registration. To be used in uc_hook_del() API + @hh: hook handle returned from this registration. To be used in uc_hook_del() + API @type: hook type, refer to uc_hook_type enum @callback: callback to be run when instruction is hit @user_data: user-defined data. This will be passed to callback function in its last argument @user_data @begin: start address of the area where the callback is in effect (inclusive) @end: end address of the area where the callback is in effect (inclusive) - NOTE 1: the callback is called only if related address is in range [@begin, @end] - NOTE 2: if @begin > @end, callback is called whenever this hook type is triggered + NOTE 1: the callback is called only if related address is in range [@begin, + @end] NOTE 2: if @begin > @end, callback is called whenever this hook type is + triggered @...: variable arguments (depending on @type) NOTE: if @type = UC_HOOK_INSN, this is the instruction ID. currently, only x86 in, out, syscall, sysenter, cpuid are supported. @@ -603,7 +777,7 @@ uc_err uc_emu_stop(uc_engine *uc); */ UNICORN_EXPORT uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, - void *user_data, uint64_t begin, uint64_t end, ...); + void *user_data, uint64_t begin, uint64_t end, ...); /* Unregister (remove) a hook callback. @@ -621,11 +795,11 @@ UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh); typedef enum uc_prot { - UC_PROT_NONE = 0, - UC_PROT_READ = 1, - UC_PROT_WRITE = 2, - UC_PROT_EXEC = 4, - UC_PROT_ALL = 7, + UC_PROT_NONE = 0, + UC_PROT_READ = 1, + UC_PROT_WRITE = 2, + UC_PROT_EXEC = 4, + UC_PROT_ALL = 7, } uc_prot; /* @@ -634,12 +808,14 @@ typedef enum uc_prot { @uc: handle returned by uc_open() @address: starting address of the new memory region to be mapped in. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the new memory region to be mapped in. - This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be a multiple of 4KB, or this will return with UC_ERR_ARG + error. @perms: Permissions for the newly mapped region. - This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, - or this will return with UC_ERR_ARG error. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | + UC_PROT_EXEC, or this will return with UC_ERR_ARG error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). @@ -653,21 +829,25 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); @uc: handle returned by uc_open() @address: starting address of the new memory region to be mapped in. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the new memory region to be mapped in. - This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be a multiple of 4KB, or this will return with UC_ERR_ARG + error. @perms: Permissions for the newly mapped region. - This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, - or this will return with UC_ERR_ARG error. - @ptr: pointer to host memory backing the newly mapped memory. This host memory is - expected to be of equal or larger size than provided, and be mapped with at - least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | + UC_PROT_EXEC, or this will return with UC_ERR_ARG error. + @ptr: pointer to host memory backing the newly mapped memory. This host memory + is expected to be an equal or larger size than provided, and be mapped with at + least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is + undefined. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr); +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, void *ptr); /* Map MMIO in for emulation. @@ -675,15 +855,16 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per @uc: handle returned by uc_open() @address: starting address of the new MMIO region to be mapped in. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the new MMIO region to be mapped in. This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. @read_cb: function for handling reads from this MMIO region. - @user_data_read: user-defined data. This will be passed to @read_cb function in its - last argument @user_data + @user_data_read: user-defined data. This will be passed to @read_cb function in + its last argument @user_data @write_cb: function for handling writes to this MMIO region. - @user_data_write: user-defined data. This will be passed to @write_cb function in its - last argument @user_data + @user_data_write: user-defined data. This will be passed to @write_cb function + in its last argument @user_data @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ @@ -698,9 +879,11 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, @uc: handle returned by uc_open() @address: starting address of the memory region to be unmapped. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the memory region to be modified. - This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be a multiple of 4KB, or this will return with UC_ERR_ARG + error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). @@ -714,18 +897,21 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); @uc: handle returned by uc_open() @address: starting address of the memory region to be modified. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the memory region to be modified. - This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be a multiple of 4KB, or this will return with UC_ERR_ARG + error. @perms: New permissions for the mapped region. - This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, - or this will return with UC_ERR_ARG error. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | + UC_PROT_EXEC, or this will return with UC_ERR_ARG error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); +uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms); /* Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr() @@ -763,9 +949,9 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context); /* Free the memory allocated by uc_mem_regions. - WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc should - be freed by uc_context_free(). Calling uc_free() may still work, but the result - is **undefined**. + WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc + should be freed by uc_context_free(). Calling uc_free() may still work, but + the result is **undefined**. @mem: memory allocated by uc_mem_regions (returned in *regions). @@ -827,7 +1013,8 @@ uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value); for detailed error). */ UNICORN_EXPORT -uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, int count); +uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, + int count); /* Read multiple register values from a context. @@ -841,7 +1028,8 @@ uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, for detailed error). */ UNICORN_EXPORT -uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int count); +uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, + int count); /* Restore the current CPU context from a saved copy. @@ -849,7 +1037,8 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int co state saved by uc_context_save(). @uc: handle returned by uc_open() - @context: handle returned by uc_context_alloc that has been used with uc_context_save + @context: handle returned by uc_context_alloc that has been used with + uc_context_save @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). @@ -857,10 +1046,9 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int co UNICORN_EXPORT uc_err uc_context_restore(uc_engine *uc, uc_context *context); - /* - Return the size needed to store the cpu context. Can be used to allocate a buffer - to contain the cpu context and directly call uc_context_save. + Return the size needed to store the cpu context. Can be used to allocate a + buffer to contain the cpu context and directly call uc_context_save. @uc: handle returned by uc_open() @@ -869,7 +1057,6 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context); UNICORN_EXPORT size_t uc_context_size(uc_engine *uc); - /* Free the context allocated by uc_context_alloc(). diff --git a/include/unicorn/x86.h b/include/unicorn/x86.h index 9533a72f..f91ce057 100644 --- a/include/unicorn/x86.h +++ b/include/unicorn/x86.h @@ -13,17 +13,58 @@ extern "C" { #include "platform.h" +typedef enum uc_cpu_x86 { + UC_CPU_X86_QEMU64 = 0, + UC_CPU_X86_PHENOM, + UC_CPU_X86_CORE2DUO, + UC_CPU_X86_KVM64, + UC_CPU_X86_QEMU32, + UC_CPU_X86_KVM32, + UC_CPU_X86_COREDUO, + UC_CPU_X86_486, + UC_CPU_X86_PENTIUM, + UC_CPU_X86_PENTIUM2, + UC_CPU_X86_PENTIUM3, + UC_CPU_X86_ATHLON, + UC_CPU_X86_N270, + UC_CPU_X86_CONROE, + UC_CPU_X86_PENRYN, + UC_CPU_X86_NEHALEM, + UC_CPU_X86_WESTMERE, + UC_CPU_X86_SANDYBRIDGE, + UC_CPU_X86_IVYBRIDGE, + UC_CPU_X86_HASWELL, + UC_CPU_X86_BROADWELL, + UC_CPU_X86_SKYLAKE_CLIENT, + UC_CPU_X86_SKYLAKE_SERVER, + UC_CPU_X86_CASCADELAKE_SERVER, + UC_CPU_X86_COOPERLAKE, + UC_CPU_X86_ICELAKE_CLIENT, + UC_CPU_X86_ICELAKE_SERVER, + UC_CPU_X86_DENVERTON, + UC_CPU_X86_SNOWRIDGE, + UC_CPU_X86_KNIGHTSMILL, + UC_CPU_X86_OPTERON_G1, + UC_CPU_X86_OPTERON_G2, + UC_CPU_X86_OPTERON_G3, + UC_CPU_X86_OPTERON_G4, + UC_CPU_X86_OPTERON_G5, + UC_CPU_X86_EPYC, + UC_CPU_X86_DHYANA, + UC_CPU_X86_EPYC_ROME +} uc_cpu_x86; + // Memory-Management Register for instructions IDTR, GDTR, LDTR, TR. // Borrow from SegmentCache in qemu/target-i386/cpu.h typedef struct uc_x86_mmr { - uint16_t selector; /* not used by GDTR and IDTR */ - uint64_t base; /* handle 32 or 64 bit CPUs */ + uint16_t selector; /* not used by GDTR and IDTR */ + uint64_t base; /* handle 32 or 64 bit CPUs */ uint32_t limit; - uint32_t flags; /* not used by GDTR and IDTR */ + uint32_t flags; /* not used by GDTR and IDTR */ } uc_x86_mmr; -// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the register ID) in -// call to uc_reg_write/uc_reg_read() to manipulate MSRs. +// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the +// register ID) in call to uc_reg_write/uc_reg_read() to manipulate MSRs. typedef struct uc_x86_msr { uint32_t rid; // MSR id uint64_t value; // MSR value @@ -35,62 +76,241 @@ typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data); //> X86 registers typedef enum uc_x86_reg { - UC_X86_REG_INVALID = 0, - UC_X86_REG_AH, UC_X86_REG_AL, UC_X86_REG_AX, UC_X86_REG_BH, UC_X86_REG_BL, - UC_X86_REG_BP, UC_X86_REG_BPL, UC_X86_REG_BX, UC_X86_REG_CH, UC_X86_REG_CL, - UC_X86_REG_CS, UC_X86_REG_CX, UC_X86_REG_DH, UC_X86_REG_DI, UC_X86_REG_DIL, - UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP, - UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS, - UC_X86_REG_EIP, UC_X86_REG_ES, UC_X86_REG_ESI, UC_X86_REG_ESP, - UC_X86_REG_FPSW, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_IP, UC_X86_REG_RAX, - UC_X86_REG_RBP, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDI, UC_X86_REG_RDX, - UC_X86_REG_RIP, UC_X86_REG_RSI, UC_X86_REG_RSP, UC_X86_REG_SI, - UC_X86_REG_SIL, UC_X86_REG_SP, UC_X86_REG_SPL, UC_X86_REG_SS, UC_X86_REG_CR0, - UC_X86_REG_CR1, UC_X86_REG_CR2, UC_X86_REG_CR3, UC_X86_REG_CR4, UC_X86_REG_CR8, - UC_X86_REG_DR0, UC_X86_REG_DR1, UC_X86_REG_DR2, UC_X86_REG_DR3, UC_X86_REG_DR4, - UC_X86_REG_DR5, UC_X86_REG_DR6, UC_X86_REG_DR7, UC_X86_REG_FP0, UC_X86_REG_FP1, - UC_X86_REG_FP2, UC_X86_REG_FP3, - UC_X86_REG_FP4, UC_X86_REG_FP5, UC_X86_REG_FP6, UC_X86_REG_FP7, - UC_X86_REG_K0, UC_X86_REG_K1, UC_X86_REG_K2, UC_X86_REG_K3, UC_X86_REG_K4, - UC_X86_REG_K5, UC_X86_REG_K6, UC_X86_REG_K7, UC_X86_REG_MM0, UC_X86_REG_MM1, - UC_X86_REG_MM2, UC_X86_REG_MM3, UC_X86_REG_MM4, UC_X86_REG_MM5, UC_X86_REG_MM6, - UC_X86_REG_MM7, UC_X86_REG_R8, UC_X86_REG_R9, UC_X86_REG_R10, UC_X86_REG_R11, - UC_X86_REG_R12, UC_X86_REG_R13, UC_X86_REG_R14, UC_X86_REG_R15, - UC_X86_REG_ST0, UC_X86_REG_ST1, UC_X86_REG_ST2, UC_X86_REG_ST3, - UC_X86_REG_ST4, UC_X86_REG_ST5, UC_X86_REG_ST6, UC_X86_REG_ST7, - UC_X86_REG_XMM0, UC_X86_REG_XMM1, UC_X86_REG_XMM2, UC_X86_REG_XMM3, UC_X86_REG_XMM4, - UC_X86_REG_XMM5, UC_X86_REG_XMM6, UC_X86_REG_XMM7, UC_X86_REG_XMM8, UC_X86_REG_XMM9, - UC_X86_REG_XMM10, UC_X86_REG_XMM11, UC_X86_REG_XMM12, UC_X86_REG_XMM13, UC_X86_REG_XMM14, - UC_X86_REG_XMM15, UC_X86_REG_XMM16, UC_X86_REG_XMM17, UC_X86_REG_XMM18, UC_X86_REG_XMM19, - UC_X86_REG_XMM20, UC_X86_REG_XMM21, UC_X86_REG_XMM22, UC_X86_REG_XMM23, UC_X86_REG_XMM24, - UC_X86_REG_XMM25, UC_X86_REG_XMM26, UC_X86_REG_XMM27, UC_X86_REG_XMM28, UC_X86_REG_XMM29, - UC_X86_REG_XMM30, UC_X86_REG_XMM31, UC_X86_REG_YMM0, UC_X86_REG_YMM1, UC_X86_REG_YMM2, - UC_X86_REG_YMM3, UC_X86_REG_YMM4, UC_X86_REG_YMM5, UC_X86_REG_YMM6, UC_X86_REG_YMM7, - UC_X86_REG_YMM8, UC_X86_REG_YMM9, UC_X86_REG_YMM10, UC_X86_REG_YMM11, UC_X86_REG_YMM12, - UC_X86_REG_YMM13, UC_X86_REG_YMM14, UC_X86_REG_YMM15, UC_X86_REG_YMM16, UC_X86_REG_YMM17, - UC_X86_REG_YMM18, UC_X86_REG_YMM19, UC_X86_REG_YMM20, UC_X86_REG_YMM21, UC_X86_REG_YMM22, - UC_X86_REG_YMM23, UC_X86_REG_YMM24, UC_X86_REG_YMM25, UC_X86_REG_YMM26, UC_X86_REG_YMM27, - UC_X86_REG_YMM28, UC_X86_REG_YMM29, UC_X86_REG_YMM30, UC_X86_REG_YMM31, UC_X86_REG_ZMM0, - UC_X86_REG_ZMM1, UC_X86_REG_ZMM2, UC_X86_REG_ZMM3, UC_X86_REG_ZMM4, UC_X86_REG_ZMM5, - UC_X86_REG_ZMM6, UC_X86_REG_ZMM7, UC_X86_REG_ZMM8, UC_X86_REG_ZMM9, UC_X86_REG_ZMM10, - UC_X86_REG_ZMM11, UC_X86_REG_ZMM12, UC_X86_REG_ZMM13, UC_X86_REG_ZMM14, UC_X86_REG_ZMM15, - UC_X86_REG_ZMM16, UC_X86_REG_ZMM17, UC_X86_REG_ZMM18, UC_X86_REG_ZMM19, UC_X86_REG_ZMM20, - UC_X86_REG_ZMM21, UC_X86_REG_ZMM22, UC_X86_REG_ZMM23, UC_X86_REG_ZMM24, UC_X86_REG_ZMM25, - UC_X86_REG_ZMM26, UC_X86_REG_ZMM27, UC_X86_REG_ZMM28, UC_X86_REG_ZMM29, UC_X86_REG_ZMM30, - UC_X86_REG_ZMM31, UC_X86_REG_R8B, UC_X86_REG_R9B, UC_X86_REG_R10B, UC_X86_REG_R11B, - UC_X86_REG_R12B, UC_X86_REG_R13B, UC_X86_REG_R14B, UC_X86_REG_R15B, UC_X86_REG_R8D, - UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D, - UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W, - UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W, - UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW, - UC_X86_REG_FPTAG, + UC_X86_REG_INVALID = 0, + UC_X86_REG_AH, + UC_X86_REG_AL, + UC_X86_REG_AX, + UC_X86_REG_BH, + UC_X86_REG_BL, + UC_X86_REG_BP, + UC_X86_REG_BPL, + UC_X86_REG_BX, + UC_X86_REG_CH, + UC_X86_REG_CL, + UC_X86_REG_CS, + UC_X86_REG_CX, + UC_X86_REG_DH, + UC_X86_REG_DI, + UC_X86_REG_DIL, + UC_X86_REG_DL, + UC_X86_REG_DS, + UC_X86_REG_DX, + UC_X86_REG_EAX, + UC_X86_REG_EBP, + UC_X86_REG_EBX, + UC_X86_REG_ECX, + UC_X86_REG_EDI, + UC_X86_REG_EDX, + UC_X86_REG_EFLAGS, + UC_X86_REG_EIP, + UC_X86_REG_ES, + UC_X86_REG_ESI, + UC_X86_REG_ESP, + UC_X86_REG_FPSW, + UC_X86_REG_FS, + UC_X86_REG_GS, + UC_X86_REG_IP, + UC_X86_REG_RAX, + UC_X86_REG_RBP, + UC_X86_REG_RBX, + UC_X86_REG_RCX, + UC_X86_REG_RDI, + UC_X86_REG_RDX, + UC_X86_REG_RIP, + UC_X86_REG_RSI, + UC_X86_REG_RSP, + UC_X86_REG_SI, + UC_X86_REG_SIL, + UC_X86_REG_SP, + UC_X86_REG_SPL, + UC_X86_REG_SS, + UC_X86_REG_CR0, + UC_X86_REG_CR1, + UC_X86_REG_CR2, + UC_X86_REG_CR3, + UC_X86_REG_CR4, + UC_X86_REG_CR8, + UC_X86_REG_DR0, + UC_X86_REG_DR1, + UC_X86_REG_DR2, + UC_X86_REG_DR3, + UC_X86_REG_DR4, + UC_X86_REG_DR5, + UC_X86_REG_DR6, + UC_X86_REG_DR7, + UC_X86_REG_FP0, + UC_X86_REG_FP1, + UC_X86_REG_FP2, + UC_X86_REG_FP3, + UC_X86_REG_FP4, + UC_X86_REG_FP5, + UC_X86_REG_FP6, + UC_X86_REG_FP7, + UC_X86_REG_K0, + UC_X86_REG_K1, + UC_X86_REG_K2, + UC_X86_REG_K3, + UC_X86_REG_K4, + UC_X86_REG_K5, + UC_X86_REG_K6, + UC_X86_REG_K7, + UC_X86_REG_MM0, + UC_X86_REG_MM1, + UC_X86_REG_MM2, + UC_X86_REG_MM3, + UC_X86_REG_MM4, + UC_X86_REG_MM5, + UC_X86_REG_MM6, + UC_X86_REG_MM7, + UC_X86_REG_R8, + UC_X86_REG_R9, + UC_X86_REG_R10, + UC_X86_REG_R11, + UC_X86_REG_R12, + UC_X86_REG_R13, + UC_X86_REG_R14, + UC_X86_REG_R15, + UC_X86_REG_ST0, + UC_X86_REG_ST1, + UC_X86_REG_ST2, + UC_X86_REG_ST3, + UC_X86_REG_ST4, + UC_X86_REG_ST5, + UC_X86_REG_ST6, + UC_X86_REG_ST7, + UC_X86_REG_XMM0, + UC_X86_REG_XMM1, + UC_X86_REG_XMM2, + UC_X86_REG_XMM3, + UC_X86_REG_XMM4, + UC_X86_REG_XMM5, + UC_X86_REG_XMM6, + UC_X86_REG_XMM7, + UC_X86_REG_XMM8, + UC_X86_REG_XMM9, + UC_X86_REG_XMM10, + UC_X86_REG_XMM11, + UC_X86_REG_XMM12, + UC_X86_REG_XMM13, + UC_X86_REG_XMM14, + UC_X86_REG_XMM15, + UC_X86_REG_XMM16, + UC_X86_REG_XMM17, + UC_X86_REG_XMM18, + UC_X86_REG_XMM19, + UC_X86_REG_XMM20, + UC_X86_REG_XMM21, + UC_X86_REG_XMM22, + UC_X86_REG_XMM23, + UC_X86_REG_XMM24, + UC_X86_REG_XMM25, + UC_X86_REG_XMM26, + UC_X86_REG_XMM27, + UC_X86_REG_XMM28, + UC_X86_REG_XMM29, + UC_X86_REG_XMM30, + UC_X86_REG_XMM31, + UC_X86_REG_YMM0, + UC_X86_REG_YMM1, + UC_X86_REG_YMM2, + UC_X86_REG_YMM3, + UC_X86_REG_YMM4, + UC_X86_REG_YMM5, + UC_X86_REG_YMM6, + UC_X86_REG_YMM7, + UC_X86_REG_YMM8, + UC_X86_REG_YMM9, + UC_X86_REG_YMM10, + UC_X86_REG_YMM11, + UC_X86_REG_YMM12, + UC_X86_REG_YMM13, + UC_X86_REG_YMM14, + UC_X86_REG_YMM15, + UC_X86_REG_YMM16, + UC_X86_REG_YMM17, + UC_X86_REG_YMM18, + UC_X86_REG_YMM19, + UC_X86_REG_YMM20, + UC_X86_REG_YMM21, + UC_X86_REG_YMM22, + UC_X86_REG_YMM23, + UC_X86_REG_YMM24, + UC_X86_REG_YMM25, + UC_X86_REG_YMM26, + UC_X86_REG_YMM27, + UC_X86_REG_YMM28, + UC_X86_REG_YMM29, + UC_X86_REG_YMM30, + UC_X86_REG_YMM31, + UC_X86_REG_ZMM0, + UC_X86_REG_ZMM1, + UC_X86_REG_ZMM2, + UC_X86_REG_ZMM3, + UC_X86_REG_ZMM4, + UC_X86_REG_ZMM5, + UC_X86_REG_ZMM6, + UC_X86_REG_ZMM7, + UC_X86_REG_ZMM8, + UC_X86_REG_ZMM9, + UC_X86_REG_ZMM10, + UC_X86_REG_ZMM11, + UC_X86_REG_ZMM12, + UC_X86_REG_ZMM13, + UC_X86_REG_ZMM14, + UC_X86_REG_ZMM15, + UC_X86_REG_ZMM16, + UC_X86_REG_ZMM17, + UC_X86_REG_ZMM18, + UC_X86_REG_ZMM19, + UC_X86_REG_ZMM20, + UC_X86_REG_ZMM21, + UC_X86_REG_ZMM22, + UC_X86_REG_ZMM23, + UC_X86_REG_ZMM24, + UC_X86_REG_ZMM25, + UC_X86_REG_ZMM26, + UC_X86_REG_ZMM27, + UC_X86_REG_ZMM28, + UC_X86_REG_ZMM29, + UC_X86_REG_ZMM30, + UC_X86_REG_ZMM31, + UC_X86_REG_R8B, + UC_X86_REG_R9B, + UC_X86_REG_R10B, + UC_X86_REG_R11B, + UC_X86_REG_R12B, + UC_X86_REG_R13B, + UC_X86_REG_R14B, + UC_X86_REG_R15B, + UC_X86_REG_R8D, + UC_X86_REG_R9D, + UC_X86_REG_R10D, + UC_X86_REG_R11D, + UC_X86_REG_R12D, + UC_X86_REG_R13D, + UC_X86_REG_R14D, + UC_X86_REG_R15D, + UC_X86_REG_R8W, + UC_X86_REG_R9W, + UC_X86_REG_R10W, + UC_X86_REG_R11W, + UC_X86_REG_R12W, + UC_X86_REG_R13W, + UC_X86_REG_R14W, + UC_X86_REG_R15W, + UC_X86_REG_IDTR, + UC_X86_REG_GDTR, + UC_X86_REG_LDTR, + UC_X86_REG_TR, + UC_X86_REG_FPCW, + UC_X86_REG_FPTAG, UC_X86_REG_MSR, // Model-Specific Register UC_X86_REG_MXCSR, UC_X86_REG_FS_BASE, // Base regs for x86_64 UC_X86_REG_GS_BASE, UC_X86_REG_FLAGS, UC_X86_REG_RFLAGS, - UC_X86_REG_ENDING // <-- mark the end of the list of registers + UC_X86_REG_ENDING // <-- mark the end of the list of registers } uc_x86_reg; //> X86 instructions diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 75d71514..1ef7fd53 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64 #define use_idiv_instructions use_idiv_instructions_aarch64 #define arm_arch arm_arch_aarch64 #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index ee750153..25c3c8a2 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64eb #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64eb #define use_idiv_instructions use_idiv_instructions_aarch64eb #define arm_arch arm_arch_aarch64eb #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64eb diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index 79bcdd13..99a17273 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -245,6 +245,10 @@ static inline TranslationBlock *tb_find(CPUState *cpu, TranslationBlock *tb; target_ulong cs_base, pc; uint32_t flags; + uc_tb cur_tb, prev_tb; + uc_engine *uc = cpu->uc; + struct list_item *cur; + struct hook *hook; tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask); if (tb == NULL) { @@ -265,6 +269,23 @@ static inline TranslationBlock *tb_find(CPUState *cpu, if (last_tb) { tb_add_jump(last_tb, tb_exit, tb); } + + UC_TB_COPY(&cur_tb, tb); + + if (last_tb) { + UC_TB_COPY(&prev_tb, last_tb); + for (cur = uc->hook[UC_HOOK_EDGE_GENERATED_IDX].head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + if (hook->to_delete) { + continue; + } + + if (HOOK_BOUND_CHECK(hook, (uint64_t)tb->pc)) { + ((uc_hook_edge_gen_t)hook->callback)(uc, &cur_tb, &prev_tb, hook->user_data); + } + } + } + return tb; } diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index 79434101..b9f3c272 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -980,6 +980,81 @@ static void tb_htable_init(struct uc_struct *uc) qht_init(&uc->tcg_ctx->tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode); } + +static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t len) +{ + tb_page_addr_t start, end; + + // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) + start = get_page_addr_code(uc->cpu->env_ptr, start_addr) & (target_ulong)(-1); + + // For 32bit target. + end = (start + len) & (target_ulong)(-1); + + // We get a wrap? + if (start > end) { + return; + } + + tb_invalidate_phys_range(uc, start, end); +} + +static uc_err uc_gen_tb(struct uc_struct *uc, uint64_t addr, uc_tb *out_tb) +{ + TranslationBlock *tb; + target_ulong cs_base, pc; + CPUState *cpu = uc->cpu; + CPUArchState *env = (CPUArchState *)cpu->env_ptr; + uint32_t flags; + uint32_t hash; + uint32_t cflags = cpu->cflags_next_tb; + + if (cflags == -1) { + cflags = curr_cflags(); + } + + cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); + + // Unicorn: Our hack here. + pc = addr; + + hash = tb_jmp_cache_hash_func(env->uc, pc); + tb = cpu->tb_jmp_cache[hash]; + + cflags &= ~CF_CLUSTER_MASK; + cflags |= cpu->cluster_index << CF_CLUSTER_SHIFT; + + if (unlikely(!(tb && + tb->pc == pc && + tb->cs_base == cs_base && + tb->flags == flags && + tb->trace_vcpu_dstate == *cpu->trace_dstate && + (tb_cflags(tb) & (CF_HASH_MASK | CF_INVALID)) == cflags))) { + + tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags); + cpu->tb_jmp_cache[hash] = tb; + + if (tb == NULL) { + mmap_lock(); + tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); + mmap_unlock(); + /* We add the TB in the virtual pc hash table for the fast lookup */ + cpu->tb_jmp_cache[hash] = tb; + } + } + + // If we still couldn't generate a TB, it must be out of memory. + if (tb == NULL) { + return UC_ERR_NOMEM; + } + + if (out_tb != NULL) { + UC_TB_COPY(out_tb, tb); + } + + return UC_ERR_OK; +} + /* Must be called before using the QEMU cpus. 'tb_size' is the size (in bytes) allocated to the translation buffer. Zero means default size. */ @@ -1000,6 +1075,9 @@ void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size) tcg_prologue_init(uc->tcg_ctx); /* cpu_interrupt_handler is not used in uc1 */ uc->l1_map = g_malloc0(sizeof(void *) * V_L1_MAX_SIZE); + /* Invalidate / Cache TBs */ + uc->uc_invalidate_tb = uc_invalidate_tb; + uc->uc_gen_tb = uc_gen_tb; } /* call with @p->lock held */ @@ -1753,7 +1831,8 @@ void tb_invalidate_phys_range(struct uc_struct *uc, ram_addr_t start, ram_addr_t pages = page_collection_lock(uc, start, end); for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - start < end; + //start < end; Unicorn: Fix possible wrap around + (intptr_t)(end - start) > 0; start = next, next += TARGET_PAGE_SIZE) { PageDesc *pd = page_find(uc, start >> TARGET_PAGE_BITS); tb_page_addr_t bound = MIN(next, end); diff --git a/qemu/accel/tcg/translate-all.h b/qemu/accel/tcg/translate-all.h index 71be1d41..30ce55d1 100644 --- a/qemu/accel/tcg/translate-all.h +++ b/qemu/accel/tcg/translate-all.h @@ -30,6 +30,7 @@ void tb_invalidate_phys_page_fast(struct uc_struct *uc, struct page_collection * tb_page_addr_t start, int len, uintptr_t retaddr); void tb_invalidate_phys_page_range(struct uc_struct *uc, tb_page_addr_t start, tb_page_addr_t end); +void tb_invalidate_phys_range(struct uc_struct *uc, ram_addr_t start, ram_addr_t end); void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr); #endif /* TRANSLATE_ALL_H */ diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 0fca28a9..9ed272fd 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -58,7 +58,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Unicorn: early check to see if the address of this block is * the "run until" address. */ - if (tb->pc == cpu->uc->addr_end) { + if (uc_addr_is_exit(uc, tb->pc)) { // This should catch that instruction is at the end // and generate appropriate halting code. gen_tb_start(tcg_ctx, db->tb); diff --git a/qemu/arm.h b/qemu/arm.h index d3cc372d..545a9ca6 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _arm #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_arm #define use_idiv_instructions use_idiv_instructions_arm #define arm_arch arm_arch_arm #define tb_target_set_jmp_target tb_target_set_jmp_target_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 0a51a80d..988dab96 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _armeb #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_armeb #define use_idiv_instructions use_idiv_instructions_armeb #define arm_arch arm_arch_armeb #define tb_target_set_jmp_target tb_target_set_jmp_target_armeb diff --git a/qemu/m68k.h b/qemu/m68k.h index cb3d430b..81472490 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _m68k #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_m68k #define use_idiv_instructions use_idiv_instructions_m68k #define arm_arch arm_arch_m68k #define tb_target_set_jmp_target tb_target_set_jmp_target_m68k diff --git a/qemu/mips.h b/qemu/mips.h index a2b78379..cd1cccb4 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mips #define use_idiv_instructions use_idiv_instructions_mips #define arm_arch arm_arch_mips #define tb_target_set_jmp_target tb_target_set_jmp_target_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9faef36b..e56c5f1f 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mips64 #define use_idiv_instructions use_idiv_instructions_mips64 #define arm_arch arm_arch_mips64 #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 6f748b36..8e3bdbfe 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64el #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mips64el #define use_idiv_instructions use_idiv_instructions_mips64el #define arm_arch arm_arch_mips64el #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index a4831183..1c1660f3 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mipsel #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mipsel #define use_idiv_instructions use_idiv_instructions_mipsel #define arm_arch arm_arch_mipsel #define tb_target_set_jmp_target tb_target_set_jmp_target_mipsel diff --git a/qemu/ppc.h b/qemu/ppc.h index 8cb9ea3e..87a216a3 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_ppc #define use_idiv_instructions use_idiv_instructions_ppc #define arm_arch arm_arch_ppc #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc diff --git a/qemu/ppc64.h b/qemu/ppc64.h index 1d055072..d4f27146 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_ppc64 #define use_idiv_instructions use_idiv_instructions_ppc64 #define arm_arch arm_arch_ppc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc64 diff --git a/qemu/riscv32.h b/qemu/riscv32.h index df9eed70..57795e38 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv32 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_riscv32 #define use_idiv_instructions use_idiv_instructions_riscv32 #define arm_arch arm_arch_riscv32 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index c41e7178..4b19f2c9 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_riscv64 #define use_idiv_instructions use_idiv_instructions_riscv64 #define arm_arch arm_arch_riscv64 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv64 diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index f983f634..25568fac 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -27,6 +27,7 @@ #include "qemu/bitmap.h" #include "tcg/tcg.h" #include "exec/tb-hash.h" +#include "accel/tcg/translate-all.h" #include "uc_priv.h" @@ -170,6 +171,28 @@ void cpu_stop_current(struct uc_struct *uc) } } + + +static inline gboolean uc_exit_invalidate_iter(gpointer key, gpointer val, gpointer data) +{ + uint64_t exit = *((uint64_t*)key); + uc_engine *uc = (uc_engine*)data; + + if (exit != 0) { + // Unicorn: Why addr - 1? + // + // 0: INC ecx + // 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) + // + // While tb_invalidate_phys_range invalides [start, end) + // + // This function is designed to used with g_tree_foreach + uc->uc_invalidate_tb(uc, exit - 1, 1); + } + + return false; +} + void resume_all_vcpus(struct uc_struct* uc) { CPUState *cpu = uc->cpu; @@ -185,15 +208,11 @@ void resume_all_vcpus(struct uc_struct* uc) } } - // clear the cache of the addr_end address, since the generated code + // clear the cache of the exits address, since the generated code // at that address is to exit emulation, but not for the instruction there. // if we dont do this, next time we cannot emulate at that address - TranslationBlock *tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(uc, uc->addr_end)]; - if (tb) { - qht_remove(&uc->tcg_ctx->tb_ctx.htable, tb, tb->hash); - tb_flush_jmp_cache(cpu, uc->addr_end); - } + g_tree_foreach(uc->exits, uc_exit_invalidate_iter, (void*)uc); cpu->created = false; } diff --git a/qemu/sparc.h b/qemu/sparc.h index 741e7565..ecb8c6c2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_sparc #define use_idiv_instructions use_idiv_instructions_sparc #define arm_arch arm_arch_sparc #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 5262a11b..22d1ea35 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_sparc64 #define use_idiv_instructions use_idiv_instructions_sparc64 #define arm_arch arm_arch_sparc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc64 diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index a9eb1ca0..914b382b 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -14637,7 +14637,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUARMState *env = cpu->env_ptr; // Unicorn: end address tells us to stop emulation - if (dcbase->pc_next == dc->uc->addr_end) { + if (uc_addr_is_exit(dc->uc, dcbase->pc_next)) { // imitate WFI instruction to halt emulation dcbase->is_jmp = DISAS_WFI; } else { diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 742a55fd..efdfc4b4 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11421,7 +11421,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } // Unicorn: end address tells us to stop emulation - if (dcbase->pc_next == dc->uc->addr_end) { + if (uc_addr_is_exit(dc->uc, dcbase->pc_next)) { // imitate WFI instruction to halt emulation dcbase->is_jmp = DISAS_WFI; } else { @@ -11499,7 +11499,7 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } // Unicorn: end address tells us to stop emulation - if (dcbase->pc_next == uc->addr_end) { + if (uc_addr_is_exit(uc, dcbase->pc_next)) { // imitate WFI instruction to halt emulation dcbase->is_jmp = DISAS_WFI; return; diff --git a/qemu/target/arm/unicorn.h b/qemu/target/arm/unicorn.h index be5e23fc..270444bd 100644 --- a/qemu/target/arm/unicorn.h +++ b/qemu/target/arm/unicorn.h @@ -5,26 +5,38 @@ #define UC_QEMU_TARGET_ARM_H // functions to read & write registers -int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); -int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); +int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void arm_reg_reset(struct uc_struct *uc); void arm64_reg_reset(struct uc_struct *uc); -void arm_uc_init(struct uc_struct* uc); -void armeb_uc_init(struct uc_struct* uc); +void arm_uc_init(struct uc_struct *uc); +void armeb_uc_init(struct uc_struct *uc); -void arm64_uc_init(struct uc_struct* uc); -void arm64eb_uc_init(struct uc_struct* uc); +void arm64_uc_init(struct uc_struct *uc); +void arm64eb_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/arm/unicorn_aarch64.c b/qemu/target/arm/unicorn_aarch64.c index 14361f1c..872ed08a 100644 --- a/qemu/target/arm/unicorn_aarch64.c +++ b/qemu/target/arm/unicorn_aarch64.c @@ -17,7 +17,7 @@ static void arm64_set_pc(struct uc_struct *uc, uint64_t address) ((CPUARMState *)uc->cpu->env_ptr)->pc = address; } -static void arm64_release(void* ctx) +static void arm64_release(void *ctx) { int i; TCGContext *tcg_ctx = (TCGContext *)ctx; @@ -38,11 +38,13 @@ static void arm64_release(void* ctx) g_free(fast->table); } - QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } - QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } @@ -98,73 +100,78 @@ static void reg_read(CPUARMState *env, unsigned int regid, void *value) } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { *(int32_t *)value = READ_DWORD(env->xregs[regid - UC_ARM64_REG_W0]); } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { // FIXME - float64 *dst = (float64*) value; + float64 *dst = (float64 *)value; uint32_t reg_index = regid - UC_ARM64_REG_Q0; dst[0] = env->vfp.zregs[reg_index].d[0]; dst[1] = env->vfp.zregs[reg_index].d[1]; } else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { - *(float64*)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0]; + *(float64 *)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0]; } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { - *(int32_t*)value = READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]); + *(int32_t *)value = + READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]); } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { - *(int16_t*)value = READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]); + *(int16_t *)value = + READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]); } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { - *(int8_t*)value = READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]); + *(int8_t *)value = + READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]); } else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) { - *(uint64_t*)value = env->elr_el[regid - UC_ARM64_REG_ELR_EL0]; + *(uint64_t *)value = env->elr_el[regid - UC_ARM64_REG_ELR_EL0]; } else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) { - *(uint64_t*)value = env->sp_el[regid - UC_ARM64_REG_SP_EL0]; + *(uint64_t *)value = env->sp_el[regid - UC_ARM64_REG_SP_EL0]; } else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) { - *(uint64_t*)value = env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0]; + *(uint64_t *)value = env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0]; } else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) { - *(uint64_t*)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0]; - } else if (regid >= UC_ARM64_REG_VBAR_EL0 && regid <= UC_ARM64_REG_VBAR_EL3) { - *(uint64_t*)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0]; + *(uint64_t *)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0]; + } else if (regid >= UC_ARM64_REG_VBAR_EL0 && + regid <= UC_ARM64_REG_VBAR_EL3) { + *(uint64_t *)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0]; } else { - switch(regid) { - default: break; - case UC_ARM64_REG_CPACR_EL1: - // *(uint32_t *)value = env->cp15.c1_coproc; - break; - case UC_ARM64_REG_TPIDR_EL0: - // *(int64_t *)value = env->cp15.tpidr_el0; - break; - case UC_ARM64_REG_TPIDRRO_EL0: - // *(int64_t *)value = env->cp15.tpidrro_el0; - break; - case UC_ARM64_REG_TPIDR_EL1: - // *(int64_t *)value = env->cp15.tpidr_el1; - break; - case UC_ARM64_REG_X29: - *(int64_t *)value = env->xregs[29]; - break; - case UC_ARM64_REG_X30: - *(int64_t *)value = env->xregs[30]; - break; - case UC_ARM64_REG_PC: - *(uint64_t *)value = env->pc; - break; - case UC_ARM64_REG_SP: - *(int64_t *)value = env->xregs[31]; - break; - case UC_ARM64_REG_NZCV: - *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; - break; - case UC_ARM64_REG_PSTATE: - *(uint32_t *)value = pstate_read(env); - break; - case UC_ARM64_REG_TTBR0_EL1: - // *(uint64_t *)value = env->cp15.ttbr0_el1; - break; - case UC_ARM64_REG_TTBR1_EL1: - // *(uint64_t *)value = env->cp15.ttbr1_el1; - break; - case UC_ARM64_REG_PAR_EL1: - // *(uint64_t *)value = env->cp15.par_el1; - break; - case UC_ARM64_REG_MAIR_EL1: - // *(uint64_t *)value = env->cp15.mair_el1; - break; + switch (regid) { + default: + break; + case UC_ARM64_REG_CPACR_EL1: + // *(uint32_t *)value = env->cp15.c1_coproc; + break; + case UC_ARM64_REG_TPIDR_EL0: + // *(int64_t *)value = env->cp15.tpidr_el0; + break; + case UC_ARM64_REG_TPIDRRO_EL0: + // *(int64_t *)value = env->cp15.tpidrro_el0; + break; + case UC_ARM64_REG_TPIDR_EL1: + // *(int64_t *)value = env->cp15.tpidr_el1; + break; + case UC_ARM64_REG_X29: + *(int64_t *)value = env->xregs[29]; + break; + case UC_ARM64_REG_X30: + *(int64_t *)value = env->xregs[30]; + break; + case UC_ARM64_REG_PC: + *(uint64_t *)value = env->pc; + break; + case UC_ARM64_REG_SP: + *(int64_t *)value = env->xregs[31]; + break; + case UC_ARM64_REG_NZCV: + *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; + break; + case UC_ARM64_REG_PSTATE: + *(uint32_t *)value = pstate_read(env); + break; + case UC_ARM64_REG_TTBR0_EL1: + // *(uint64_t *)value = env->cp15.ttbr0_el1; + break; + case UC_ARM64_REG_TTBR1_EL1: + // *(uint64_t *)value = env->cp15.ttbr1_el1; + break; + case UC_ARM64_REG_PAR_EL1: + // *(uint64_t *)value = env->cp15.par_el1; + break; + case UC_ARM64_REG_MAIR_EL1: + // *(uint64_t *)value = env->cp15.mair_el1; + break; } } @@ -181,82 +188,88 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value) } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { WRITE_DWORD(env->xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value); } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { - float64 *src = (float64*) value; + float64 *src = (float64 *)value; uint32_t reg_index = regid - UC_ARM64_REG_Q0; env->vfp.zregs[reg_index].d[0] = src[0]; env->vfp.zregs[reg_index].d[1] = src[1]; } else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { - env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = * (float64*) value; + env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = *(float64 *)value; } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { - WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0], *(int32_t*) value); + WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0], + *(int32_t *)value); } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { - WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0], *(int16_t*) value); + WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0], + *(int16_t *)value); } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { - WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0], *(int8_t*) value); + WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0], + *(int8_t *)value); } else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) { - env->elr_el[regid - UC_ARM64_REG_ELR_EL0] = *(uint64_t*)value; + env->elr_el[regid - UC_ARM64_REG_ELR_EL0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) { - env->sp_el[regid - UC_ARM64_REG_SP_EL0] = *(uint64_t*)value; + env->sp_el[regid - UC_ARM64_REG_SP_EL0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) { - env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0] = *(uint64_t*)value; + env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) { - env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t*)value; - } else if (regid >= UC_ARM64_REG_VBAR_EL0 && regid <= UC_ARM64_REG_VBAR_EL3) { - env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t*)value; + env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t *)value; + } else if (regid >= UC_ARM64_REG_VBAR_EL0 && + regid <= UC_ARM64_REG_VBAR_EL3) { + env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t *)value; } else { - switch(regid) { - default: break; - case UC_ARM64_REG_CPACR_EL1: - //env->cp15.c1_coproc = *(uint32_t *)value; - break; - case UC_ARM64_REG_TPIDR_EL0: - //env->cp15.tpidr_el0 = *(uint64_t *)value; - break; - case UC_ARM64_REG_TPIDRRO_EL0: - //env->cp15.tpidrro_el0 = *(uint64_t *)value; - break; - case UC_ARM64_REG_TPIDR_EL1: - //env->cp15.tpidr_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_X29: - env->xregs[29] = *(uint64_t *)value; - break; - case UC_ARM64_REG_X30: - env->xregs[30] = *(uint64_t *)value; - break; - case UC_ARM64_REG_PC: - env->pc = *(uint64_t *)value; - break; - case UC_ARM64_REG_SP: - env->xregs[31] = *(uint64_t *)value; - break; - case UC_ARM64_REG_NZCV: - //cpsr_write(env, *(uint32_t *)value, CPSR_NZCV); - break; - case UC_ARM64_REG_PSTATE: - pstate_write(env, *(uint32_t *)value); - break; - case UC_ARM64_REG_TTBR0_EL1: - //env->cp15.ttbr0_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_TTBR1_EL1: - //env->cp15.ttbr1_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_PAR_EL1: - //env->cp15.par_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_MAIR_EL1: - //env->cp15.mair_el1 = *(uint64_t *)value; - break; + switch (regid) { + default: + break; + case UC_ARM64_REG_CPACR_EL1: + // env->cp15.c1_coproc = *(uint32_t *)value; + break; + case UC_ARM64_REG_TPIDR_EL0: + // env->cp15.tpidr_el0 = *(uint64_t *)value; + break; + case UC_ARM64_REG_TPIDRRO_EL0: + // env->cp15.tpidrro_el0 = *(uint64_t *)value; + break; + case UC_ARM64_REG_TPIDR_EL1: + // env->cp15.tpidr_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_X29: + env->xregs[29] = *(uint64_t *)value; + break; + case UC_ARM64_REG_X30: + env->xregs[30] = *(uint64_t *)value; + break; + case UC_ARM64_REG_PC: + env->pc = *(uint64_t *)value; + break; + case UC_ARM64_REG_SP: + env->xregs[31] = *(uint64_t *)value; + break; + case UC_ARM64_REG_NZCV: + // cpsr_write(env, *(uint32_t *)value, CPSR_NZCV); + break; + case UC_ARM64_REG_PSTATE: + pstate_write(env, *(uint32_t *)value); + break; + case UC_ARM64_REG_TTBR0_EL1: + // env->cp15.ttbr0_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_TTBR1_EL1: + // env->cp15.ttbr1_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_PAR_EL1: + // env->cp15.par_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_MAIR_EL1: + // env->cp15.mair_el1 = *(uint64_t *)value; + break; } } return; } -int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { - CPUARMState *env= &(ARM_CPU(uc->cpu)->env); + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { @@ -268,16 +281,17 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co return 0; } -int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) +int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUARMState *env= &(ARM_CPU(uc->cpu)->env); + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_ARM64_REG_PC){ + if (regid == UC_ARM64_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -289,12 +303,14 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else -int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { - CPUARMState *env= (CPUARMState *)ctx->data; + CPUARMState *env = (CPUARMState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -308,12 +324,14 @@ int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **va DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else -int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { - CPUARMState *env= (CPUARMState *)ctx->data; + CPUARMState *env = (CPUARMState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -339,9 +357,9 @@ static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -void arm64eb_uc_init(struct uc_struct* uc) +void arm64eb_uc_init(struct uc_struct *uc) #else -void arm64_uc_init(struct uc_struct* uc) +void arm64_uc_init(struct uc_struct *uc) #endif { uc->reg_read = arm64_reg_read; diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index e582691f..299f129f 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -23,7 +23,7 @@ static void arm_release(void *ctx) { int i; TCGContext *tcg_ctx = (TCGContext *)ctx; - ARMCPU* cpu = (ARMCPU *)tcg_ctx->uc->cpu; + ARMCPU *cpu = (ARMCPU *)tcg_ctx->uc->cpu; CPUTLBDesc *d = cpu->neg.tlb.d; CPUTLBDescFast *f = cpu->neg.tlb.f; CPUTLBDesc *desc; @@ -40,11 +40,13 @@ static void arm_release(void *ctx) g_free(fast->table); } - QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } - QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } @@ -120,7 +122,8 @@ static uint32_t v7m_mrs_xpsr(CPUARMState *env, uint32_t reg) return xpsr_read(env) & mask; } -static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask, uint32_t reg, uint32_t val) +static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask, uint32_t reg, + uint32_t val) { uint32_t xpsrmask = 0; @@ -150,85 +153,86 @@ static void reg_read(CPUARMState *env, unsigned int regid, void *value) *(int32_t *)value = env->regs[regid - UC_ARM_REG_R0]; } else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) { uint32_t reg_index = regid - UC_ARM_REG_D0; - *(float64 *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1]; + *(float64 *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1]; } else { - switch(regid) { - case UC_ARM_REG_APSR: - if (arm_feature(env, ARM_FEATURE_M)) { - *(int32_t *)value = v7m_mrs_xpsr(env, 0); - } else { - *(int32_t *)value = cpsr_read(env) & (CPSR_NZCV | CPSR_Q | CPSR_GE); - } - break; - case UC_ARM_REG_APSR_NZCV: - *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; - break; - case UC_ARM_REG_CPSR: - *(int32_t *)value = cpsr_read(env); - break; - case UC_ARM_REG_SPSR: - *(int32_t *)value = env->spsr; - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - *(int32_t *)value = env->regs[13]; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - *(int32_t *)value = env->regs[14]; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - *(int32_t *)value = env->regs[15]; - break; - case UC_ARM_REG_C1_C0_2: - *(int32_t *)value = env->cp15.cpacr_el1; - break; - case UC_ARM_REG_C13_C0_3: - *(int32_t *)value = env->cp15.tpidrro_el[0]; - break; - case UC_ARM_REG_FPEXC: - *(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC]; - break; - case UC_ARM_REG_IPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 5); - break; - case UC_ARM_REG_MSP: - *(uint32_t *)value = helper_v7m_mrs(env, 8); - break; - case UC_ARM_REG_PSP: - *(uint32_t *)value = helper_v7m_mrs(env, 9); - break; - case UC_ARM_REG_IAPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 1); - break; - case UC_ARM_REG_EAPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 2); - break; - case UC_ARM_REG_XPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 3); - break; - case UC_ARM_REG_EPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 6); - break; - case UC_ARM_REG_IEPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 7); - break; - case UC_ARM_REG_PRIMASK: - *(uint32_t *)value = helper_v7m_mrs(env, 16); - break; - case UC_ARM_REG_BASEPRI: - *(uint32_t *)value = helper_v7m_mrs(env, 17); - break; - case UC_ARM_REG_BASEPRI_MAX: - *(uint32_t *)value = helper_v7m_mrs(env, 18); - break; - case UC_ARM_REG_FAULTMASK: - *(uint32_t *)value = helper_v7m_mrs(env, 19); - break; - case UC_ARM_REG_CONTROL: - *(uint32_t *)value = helper_v7m_mrs(env, 20); - break; + switch (regid) { + case UC_ARM_REG_APSR: + if (arm_feature(env, ARM_FEATURE_M)) { + *(int32_t *)value = v7m_mrs_xpsr(env, 0); + } else { + *(int32_t *)value = + cpsr_read(env) & (CPSR_NZCV | CPSR_Q | CPSR_GE); + } + break; + case UC_ARM_REG_APSR_NZCV: + *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; + break; + case UC_ARM_REG_CPSR: + *(int32_t *)value = cpsr_read(env); + break; + case UC_ARM_REG_SPSR: + *(int32_t *)value = env->spsr; + break; + // case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + *(int32_t *)value = env->regs[13]; + break; + // case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + *(int32_t *)value = env->regs[14]; + break; + // case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + *(int32_t *)value = env->regs[15]; + break; + case UC_ARM_REG_C1_C0_2: + *(int32_t *)value = env->cp15.cpacr_el1; + break; + case UC_ARM_REG_C13_C0_3: + *(int32_t *)value = env->cp15.tpidrro_el[0]; + break; + case UC_ARM_REG_FPEXC: + *(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC]; + break; + case UC_ARM_REG_IPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 5); + break; + case UC_ARM_REG_MSP: + *(uint32_t *)value = helper_v7m_mrs(env, 8); + break; + case UC_ARM_REG_PSP: + *(uint32_t *)value = helper_v7m_mrs(env, 9); + break; + case UC_ARM_REG_IAPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 1); + break; + case UC_ARM_REG_EAPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 2); + break; + case UC_ARM_REG_XPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 3); + break; + case UC_ARM_REG_EPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 6); + break; + case UC_ARM_REG_IEPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 7); + break; + case UC_ARM_REG_PRIMASK: + *(uint32_t *)value = helper_v7m_mrs(env, 16); + break; + case UC_ARM_REG_BASEPRI: + *(uint32_t *)value = helper_v7m_mrs(env, 17); + break; + case UC_ARM_REG_BASEPRI_MAX: + *(uint32_t *)value = helper_v7m_mrs(env, 18); + break; + case UC_ARM_REG_FAULTMASK: + *(uint32_t *)value = helper_v7m_mrs(env, 19); + break; + case UC_ARM_REG_CONTROL: + *(uint32_t *)value = helper_v7m_mrs(env, 20); + break; } } @@ -243,125 +247,127 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value) uint32_t reg_index = regid - UC_ARM_REG_D0; env->vfp.zregs[reg_index / 2].d[reg_index & 1] = *(float64 *)value; } else { - switch(regid) { - case UC_ARM_REG_APSR: - if (!arm_feature(env, ARM_FEATURE_M)) { - cpsr_write(env, *(uint32_t *)value, (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteRaw); - } else { - // Same with UC_ARM_REG_APSR_NZCVQ - v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); - } - break; - case UC_ARM_REG_APSR_NZCV: - cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw); - break; - case UC_ARM_REG_CPSR: - cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteRaw); - break; - case UC_ARM_REG_SPSR: - env->spsr = *(uint32_t *)value; - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - env->regs[13] = *(uint32_t *)value; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - env->regs[14] = *(uint32_t *)value; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - env->pc = (*(uint32_t *)value & ~1); - env->thumb = (*(uint32_t *)value & 1); - env->uc->thumb = (*(uint32_t *)value & 1); - env->regs[15] = (*(uint32_t *)value & ~1); - break; + switch (regid) { + case UC_ARM_REG_APSR: + if (!arm_feature(env, ARM_FEATURE_M)) { + cpsr_write(env, *(uint32_t *)value, + (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteRaw); + } else { + // Same with UC_ARM_REG_APSR_NZCVQ + v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); + } + break; + case UC_ARM_REG_APSR_NZCV: + cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw); + break; + case UC_ARM_REG_CPSR: + cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteRaw); + break; + case UC_ARM_REG_SPSR: + env->spsr = *(uint32_t *)value; + break; + // case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + env->regs[13] = *(uint32_t *)value; + break; + // case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + env->regs[14] = *(uint32_t *)value; + break; + // case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + env->pc = (*(uint32_t *)value & ~1); + env->thumb = (*(uint32_t *)value & 1); + env->uc->thumb = (*(uint32_t *)value & 1); + env->regs[15] = (*(uint32_t *)value & ~1); + break; // case UC_ARM_REG_C1_C0_2: // env->cp15.c1_coproc = *(int32_t *)value; // break; - case UC_ARM_REG_C13_C0_3: - env->cp15.tpidrro_el[0] = *(int32_t *)value; - break; - case UC_ARM_REG_FPEXC: - env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value; - break; - case UC_ARM_REG_IPSR: - v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value); - break; - case UC_ARM_REG_MSP: - helper_v7m_msr(env, 8, *(uint32_t *)value); - break; - case UC_ARM_REG_PSP: - helper_v7m_msr(env, 9, *(uint32_t *)value); - break; - case UC_ARM_REG_CONTROL: - helper_v7m_msr(env, 20, *(uint32_t *)value); - break; - case UC_ARM_REG_EPSR: - v7m_msr_xpsr(env, 0b1000, 6, *(uint32_t *)value); - break; - case UC_ARM_REG_IEPSR: - v7m_msr_xpsr(env, 0b1000, 7, *(uint32_t *)value); - break; - case UC_ARM_REG_PRIMASK: - helper_v7m_msr(env, 16, *(uint32_t *)value); - break; - case UC_ARM_REG_BASEPRI: - helper_v7m_msr(env, 17, *(uint32_t *)value); - break; - case UC_ARM_REG_BASEPRI_MAX: - helper_v7m_msr(env, 18, *(uint32_t *)value); - break; - case UC_ARM_REG_FAULTMASK: - helper_v7m_msr(env, 19, *(uint32_t *)value); - break; - case UC_ARM_REG_APSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); - break; - case UC_ARM_REG_APSR_G: - v7m_msr_xpsr(env, 0b0100, 0, *(uint32_t *)value); - break; - case UC_ARM_REG_APSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 0, *(uint32_t *)value); - break; - case UC_ARM_REG_IAPSR: - case UC_ARM_REG_IAPSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 1, *(uint32_t *)value); - break; - case UC_ARM_REG_IAPSR_G: - v7m_msr_xpsr(env, 0b0100, 1, *(uint32_t *)value); - break; - case UC_ARM_REG_IAPSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 1, *(uint32_t *)value); - break; - case UC_ARM_REG_EAPSR: - case UC_ARM_REG_EAPSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 2, *(uint32_t *)value); - break; - case UC_ARM_REG_EAPSR_G: - v7m_msr_xpsr(env, 0b0100, 2, *(uint32_t *)value); - break; - case UC_ARM_REG_EAPSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 2, *(uint32_t *)value); - break; - case UC_ARM_REG_XPSR: - case UC_ARM_REG_XPSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 3, *(uint32_t *)value); - break; - case UC_ARM_REG_XPSR_G: - v7m_msr_xpsr(env, 0b0100, 3, *(uint32_t *)value); - break; - case UC_ARM_REG_XPSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 3, *(uint32_t *)value); - break; + case UC_ARM_REG_C13_C0_3: + env->cp15.tpidrro_el[0] = *(int32_t *)value; + break; + case UC_ARM_REG_FPEXC: + env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value; + break; + case UC_ARM_REG_IPSR: + v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value); + break; + case UC_ARM_REG_MSP: + helper_v7m_msr(env, 8, *(uint32_t *)value); + break; + case UC_ARM_REG_PSP: + helper_v7m_msr(env, 9, *(uint32_t *)value); + break; + case UC_ARM_REG_CONTROL: + helper_v7m_msr(env, 20, *(uint32_t *)value); + break; + case UC_ARM_REG_EPSR: + v7m_msr_xpsr(env, 0b1000, 6, *(uint32_t *)value); + break; + case UC_ARM_REG_IEPSR: + v7m_msr_xpsr(env, 0b1000, 7, *(uint32_t *)value); + break; + case UC_ARM_REG_PRIMASK: + helper_v7m_msr(env, 16, *(uint32_t *)value); + break; + case UC_ARM_REG_BASEPRI: + helper_v7m_msr(env, 17, *(uint32_t *)value); + break; + case UC_ARM_REG_BASEPRI_MAX: + helper_v7m_msr(env, 18, *(uint32_t *)value); + break; + case UC_ARM_REG_FAULTMASK: + helper_v7m_msr(env, 19, *(uint32_t *)value); + break; + case UC_ARM_REG_APSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); + break; + case UC_ARM_REG_APSR_G: + v7m_msr_xpsr(env, 0b0100, 0, *(uint32_t *)value); + break; + case UC_ARM_REG_APSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 0, *(uint32_t *)value); + break; + case UC_ARM_REG_IAPSR: + case UC_ARM_REG_IAPSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 1, *(uint32_t *)value); + break; + case UC_ARM_REG_IAPSR_G: + v7m_msr_xpsr(env, 0b0100, 1, *(uint32_t *)value); + break; + case UC_ARM_REG_IAPSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 1, *(uint32_t *)value); + break; + case UC_ARM_REG_EAPSR: + case UC_ARM_REG_EAPSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 2, *(uint32_t *)value); + break; + case UC_ARM_REG_EAPSR_G: + v7m_msr_xpsr(env, 0b0100, 2, *(uint32_t *)value); + break; + case UC_ARM_REG_EAPSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 2, *(uint32_t *)value); + break; + case UC_ARM_REG_XPSR: + case UC_ARM_REG_XPSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 3, *(uint32_t *)value); + break; + case UC_ARM_REG_XPSR_G: + v7m_msr_xpsr(env, 0b0100, 3, *(uint32_t *)value); + break; + case UC_ARM_REG_XPSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 3, *(uint32_t *)value); + break; } } return; } -int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; @@ -375,7 +381,8 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) +int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUArchState *env = &(ARM_CPU(uc->cpu)->env); int i; @@ -384,7 +391,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_ARM_REG_R15){ + if (regid == UC_ARM_REG_R15) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -396,9 +403,11 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else -int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { CPUARMState *env = (CPUARMState *)ctx->data; @@ -415,9 +424,11 @@ int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else -int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { CPUARMState *env = (CPUARMState *)ctx->data; @@ -434,33 +445,35 @@ int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* cons static bool arm_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case EXCP_UDEF: - case EXCP_YIELD: - return true; - case EXCP_INVSTATE: - uc->invalid_error = UC_ERR_EXCEPTION; - return true; + switch (intno) { + default: + return false; + case EXCP_UDEF: + case EXCP_YIELD: + return true; + case EXCP_INVSTATE: + uc->invalid_error = UC_ERR_EXCEPTION; + return true; } } -static uc_err arm_query(struct uc_struct *uc, uc_query_type type, size_t *result) +static uc_err arm_query(struct uc_struct *uc, uc_query_type type, + size_t *result) { CPUState *mycpu = uc->cpu; uint32_t mode; - switch(type) { - case UC_QUERY_MODE: - // zero out ARM/THUMB mode - mode = uc->mode & ~(UC_MODE_ARM | UC_MODE_THUMB); - // THUMB mode or ARM MOde - mode |= ((ARM_CPU(mycpu)->env.thumb != 0)? UC_MODE_THUMB : UC_MODE_ARM); - *result = mode; - return UC_ERR_OK; - default: - return UC_ERR_ARG; + switch (type) { + case UC_QUERY_MODE: + // zero out ARM/THUMB mode + mode = uc->mode & ~(UC_MODE_ARM | UC_MODE_THUMB); + // THUMB mode or ARM MOde + mode |= + ((ARM_CPU(mycpu)->env.thumb != 0) ? UC_MODE_THUMB : UC_MODE_ARM); + *result = mode; + return UC_ERR_OK; + default: + return UC_ERR_ARG; } } @@ -477,9 +490,9 @@ static int arm_cpus_init(struct uc_struct *uc, const char *cpu_model) } #ifdef TARGET_WORDS_BIGENDIAN -void armeb_uc_init(struct uc_struct* uc) +void armeb_uc_init(struct uc_struct *uc) #else -void arm_uc_init(struct uc_struct* uc) +void arm_uc_init(struct uc_struct *uc) #endif { uc->reg_read = arm_reg_read; diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index cf148c4b..8616b12f 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4765,7 +4765,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; // Unicorn: end address tells us to stop emulation - if (s->pc == s->uc->addr_end) { + if (uc_addr_is_exit(env->uc, s->pc)) { // imitate the HLT instruction gen_update_cc_op(s); gen_jmp_im(s, pc_start - s->cs_base); diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index eef1e471..404f8444 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -6,18 +6,18 @@ #include "sysemu/cpus.h" #include "cpu.h" #include "unicorn_common.h" -#include /* needed for uc_x86_mmr */ +#include /* needed for uc_x86_mmr */ #include "unicorn.h" -#define FPST(n) (env->fpregs[(env->fpstt + (n)) & 7].d) +#define FPST(n) (env->fpregs[(env->fpstt + (n)) & 7].d) #define X86_NON_CS_FLAGS (DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK) static void load_seg_16_helper(CPUX86State *env, int seg, uint32_t selector) { - cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, X86_NON_CS_FLAGS); + cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, + X86_NON_CS_FLAGS); } - void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f); floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper); @@ -28,7 +28,7 @@ static void x86_set_pc(struct uc_struct *uc, uint64_t address) { if (uc->mode == UC_MODE_16) { int16_t cs = (uint16_t)X86_CPU(uc->cpu)->env.segs[R_CS].selector; - ((CPUX86State *)uc->cpu->env_ptr)->eip = address - cs*16; + ((CPUX86State *)uc->cpu->env_ptr)->eip = address - cs * 16; } else ((CPUX86State *)uc->cpu->env_ptr)->eip = address; } @@ -59,11 +59,16 @@ void x86_reg_reset(struct uc_struct *uc) { CPUArchState *env = uc->cpu->env_ptr; - env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH; - env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_AES | CPUID_EXT_CX16; + env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | + CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH; + env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | + CPUID_EXT_SSE42 | CPUID_EXT_AES | + CPUID_EXT_CX16; env->features[FEAT_8000_0001_EDX] = CPUID_EXT2_3DNOW | CPUID_EXT2_RDTSCP; - env->features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_SKINIT | CPUID_EXT3_CR8LEG; - env->features[FEAT_7_0_EBX] = CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP; + env->features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | + CPUID_EXT3_SKINIT | CPUID_EXT3_CR8LEG; + env->features[FEAT_7_0_EBX] = CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | + CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP; memset(env->regs, 0, sizeof(env->regs)); memset(env->segs, 0, sizeof(env->segs)); @@ -81,7 +86,7 @@ void x86_reg_reset(struct uc_struct *uc) env->fpstt = 0; /* top of stack index */ env->fpus = 0; env->fpuc = 0; - memset(env->fptags, 0, sizeof(env->fptags)); /* 0 = valid, 1 = empty */ + memset(env->fptags, 0, sizeof(env->fptags)); /* 0 = valid, 1 = empty */ env->mxcsr = 0; memset(env->xmm_regs, 0, sizeof(env->xmm_regs)); @@ -129,43 +134,44 @@ void x86_reg_reset(struct uc_struct *uc) // TODO: reset other registers in CPUX86State qemu/target-i386/cpu.h // properly initialize internal setup for each mode - switch(uc->mode) { - default: - break; - case UC_MODE_16: - env->hflags = 0; - env->cr[0] = 0; - //undo the damage done by the memset of env->segs above - //for R_CS, not quite the same as x86_cpu_reset - cpu_x86_load_seg_cache(env, R_CS, 0, 0, 0xffff, - DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | + switch (uc->mode) { + default: + break; + case UC_MODE_16: + env->hflags = 0; + env->cr[0] = 0; + // undo the damage done by the memset of env->segs above + // for R_CS, not quite the same as x86_cpu_reset + cpu_x86_load_seg_cache(env, R_CS, 0, 0, 0xffff, + DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); - //remainder yields same state as x86_cpu_reset - load_seg_16_helper(env, R_DS, 0); - load_seg_16_helper(env, R_ES, 0); - load_seg_16_helper(env, R_SS, 0); - load_seg_16_helper(env, R_FS, 0); - load_seg_16_helper(env, R_GS, 0); + // remainder yields same state as x86_cpu_reset + load_seg_16_helper(env, R_DS, 0); + load_seg_16_helper(env, R_ES, 0); + load_seg_16_helper(env, R_SS, 0); + load_seg_16_helper(env, R_FS, 0); + load_seg_16_helper(env, R_GS, 0); - break; - case UC_MODE_32: - env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_OSFXSR_MASK; - cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode - break; - case UC_MODE_64: - env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_LMA_MASK | HF_OSFXSR_MASK; - env->hflags &= ~(HF_ADDSEG_MASK); - env->efer |= MSR_EFER_LMA | MSR_EFER_LME; // extended mode activated - cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode - /* If we are operating in 64bit mode then add the Long Mode flag - * to the CPUID feature flag - */ - env->features[FEAT_8000_0001_EDX] |= CPUID_EXT2_LM; - break; + break; + case UC_MODE_32: + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_OSFXSR_MASK; + cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode + break; + case UC_MODE_64: + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | + HF_LMA_MASK | HF_OSFXSR_MASK; + env->hflags &= ~(HF_ADDSEG_MASK); + env->efer |= MSR_EFER_LMA | MSR_EFER_LME; // extended mode activated + cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode + /* If we are operating in 64bit mode then add the Long Mode flag + * to the CPUID feature flag + */ + env->features[FEAT_8000_0001_EDX] |= CPUID_EXT2_LM; + break; } } -static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) +static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) { uint64_t ecx = env->regs[R_ECX]; uint64_t eax = env->regs[R_EAX]; @@ -175,14 +181,14 @@ static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) helper_rdmsr(env); msr->value = ((uint32_t)env->regs[R_EAX]) | - ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); + ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); env->regs[R_EAX] = eax; env->regs[R_ECX] = ecx; env->regs[R_EDX] = edx; - /* The implementation doesn't throw exception or return an error if there is one, so - * we will return 0. */ + /* The implementation doesn't throw exception or return an error if there is + * one, so we will return 0. */ return 0; } @@ -201,1258 +207,1249 @@ static int x86_msr_write(CPUX86State *env, uc_x86_msr *msr) env->regs[R_EAX] = eax; env->regs[R_EDX] = edx; - /* The implementation doesn't throw exception or return an error if there is one, so - * we will return 0. */ + /* The implementation doesn't throw exception or return an error if there is + * one, so we will return 0. */ return 0; } -static void reg_read(CPUX86State *env, unsigned int regid, void *value, uc_mode mode) +static void reg_read(CPUX86State *env, unsigned int regid, void *value, + uc_mode mode) { - switch(regid) { - default: - break; - case UC_X86_REG_FP0: - case UC_X86_REG_FP1: - case UC_X86_REG_FP2: - case UC_X86_REG_FP3: - case UC_X86_REG_FP4: - case UC_X86_REG_FP5: - case UC_X86_REG_FP6: - case UC_X86_REG_FP7: - { - floatx80 reg = env->fpregs[regid - UC_X86_REG_FP0].d; - cpu_get_fp80(value, (uint16_t*)((char*)value+sizeof(uint64_t)), reg); - } - return; - case UC_X86_REG_FPSW: - { - uint16_t fpus = env->fpus; - fpus = fpus & ~0x3800; - fpus |= ( env->fpstt & 0x7 ) << 11; - *(uint16_t*) value = fpus; - } - return; - case UC_X86_REG_FPCW: - *(uint16_t*) value = env->fpuc; - return; - case UC_X86_REG_FPTAG: - { - #define EXPD(fp) (fp.l.upper & 0x7fff) - #define MANTD(fp) (fp.l.lower) - #define MAXEXPD 0x7fff - int fptag, exp, i; - uint64_t mant; - CPU_LDoubleU tmp; - fptag = 0; - for (i = 7; i >= 0; i--) { - fptag <<= 2; - if (env->fptags[i]) { - fptag |= 3; - } else { - tmp.d = env->fpregs[i].d; - exp = EXPD(tmp); - mant = MANTD(tmp); - if (exp == 0 && mant == 0) { - /* zero */ - fptag |= 1; - } else if (exp == 0 || exp == MAXEXPD - || (mant & (1LL << 63)) == 0) { - /* NaNs, infinity, denormal */ - fptag |= 2; - } - } + switch (regid) { + default: + break; + case UC_X86_REG_FP0: + case UC_X86_REG_FP1: + case UC_X86_REG_FP2: + case UC_X86_REG_FP3: + case UC_X86_REG_FP4: + case UC_X86_REG_FP5: + case UC_X86_REG_FP6: + case UC_X86_REG_FP7: { + floatx80 reg = env->fpregs[regid - UC_X86_REG_FP0].d; + cpu_get_fp80(value, (uint16_t *)((char *)value + sizeof(uint64_t)), + reg); + } + return; + case UC_X86_REG_FPSW: { + uint16_t fpus = env->fpus; + fpus = fpus & ~0x3800; + fpus |= (env->fpstt & 0x7) << 11; + *(uint16_t *)value = fpus; + } + return; + case UC_X86_REG_FPCW: + *(uint16_t *)value = env->fpuc; + return; + case UC_X86_REG_FPTAG: { +#define EXPD(fp) (fp.l.upper & 0x7fff) +#define MANTD(fp) (fp.l.lower) +#define MAXEXPD 0x7fff + int fptag, exp, i; + uint64_t mant; + CPU_LDoubleU tmp; + fptag = 0; + for (i = 7; i >= 0; i--) { + fptag <<= 2; + if (env->fptags[i]) { + fptag |= 3; + } else { + tmp.d = env->fpregs[i].d; + exp = EXPD(tmp); + mant = MANTD(tmp); + if (exp == 0 && mant == 0) { + /* zero */ + fptag |= 1; + } else if (exp == 0 || exp == MAXEXPD || + (mant & (1LL << 63)) == 0) { + /* NaNs, infinity, denormal */ + fptag |= 2; } - *(uint16_t*) value = fptag; - } - return; - case UC_X86_REG_XMM0: - case UC_X86_REG_XMM1: - case UC_X86_REG_XMM2: - case UC_X86_REG_XMM3: - case UC_X86_REG_XMM4: - case UC_X86_REG_XMM5: - case UC_X86_REG_XMM6: - case UC_X86_REG_XMM7: - { - float64 *dst = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - dst[0] = reg->_d[0]; - dst[1] = reg->_d[1]; - return; - } - case UC_X86_REG_ST0: - case UC_X86_REG_ST1: - case UC_X86_REG_ST2: - case UC_X86_REG_ST3: - case UC_X86_REG_ST4: - case UC_X86_REG_ST5: - case UC_X86_REG_ST6: - case UC_X86_REG_ST7: - { - // value must be big enough to keep 80 bits (10 bytes) - memcpy(value, &FPST(regid - UC_X86_REG_ST0), 10); - return; - } - case UC_X86_REG_YMM0: - case UC_X86_REG_YMM1: - case UC_X86_REG_YMM2: - case UC_X86_REG_YMM3: - case UC_X86_REG_YMM4: - case UC_X86_REG_YMM5: - case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: - { - float64 *dst = (float64*)value; - XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - dst[0] = lo_reg->_d[0]; - dst[1] = lo_reg->_d[1]; - dst[2] = hi_reg->_d[0]; - dst[3] = hi_reg->_d[1]; - return; } + } + *(uint16_t *)value = fptag; + } + return; + case UC_X86_REG_XMM0: + case UC_X86_REG_XMM1: + case UC_X86_REG_XMM2: + case UC_X86_REG_XMM3: + case UC_X86_REG_XMM4: + case UC_X86_REG_XMM5: + case UC_X86_REG_XMM6: + case UC_X86_REG_XMM7: { + float64 *dst = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->_d[0]; + dst[1] = reg->_d[1]; + return; + } + case UC_X86_REG_ST0: + case UC_X86_REG_ST1: + case UC_X86_REG_ST2: + case UC_X86_REG_ST3: + case UC_X86_REG_ST4: + case UC_X86_REG_ST5: + case UC_X86_REG_ST6: + case UC_X86_REG_ST7: { + // value must be big enough to keep 80 bits (10 bytes) + memcpy(value, &FPST(regid - UC_X86_REG_ST0), 10); + return; + } + case UC_X86_REG_YMM0: + case UC_X86_REG_YMM1: + case UC_X86_REG_YMM2: + case UC_X86_REG_YMM3: + case UC_X86_REG_YMM4: + case UC_X86_REG_YMM5: + case UC_X86_REG_YMM6: + case UC_X86_REG_YMM7: + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: { + float64 *dst = (float64 *)value; + XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; + XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; + dst[0] = lo_reg->_d[0]; + dst[1] = lo_reg->_d[1]; + dst[2] = hi_reg->_d[0]; + dst[3] = hi_reg->_d[1]; + return; + } } - switch(mode) { + switch (mode) { + default: + break; + case UC_MODE_16: + switch (regid) { default: break; - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - *(int16_t *)value = env->segs[R_ES].selector; - return; - case UC_X86_REG_SS: - *(int16_t *)value = env->segs[R_SS].selector; - return; - case UC_X86_REG_DS: - *(int16_t *)value = env->segs[R_DS].selector; - return; - case UC_X86_REG_FS: - *(int16_t *)value = env->segs[R_FS].selector; - return; - case UC_X86_REG_GS: - *(int16_t *)value = env->segs[R_GS].selector; - return; - case UC_X86_REG_FS_BASE: - *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; - return; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - *(int32_t *)value = env->cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - *(int32_t *)value = env->dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_FLAGS: - *(int16_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EAX: - *(int32_t *)value = env->regs[R_EAX]; - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); - break; - case UC_X86_REG_EBX: - *(int32_t *)value = env->regs[R_EBX]; - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); - break; - case UC_X86_REG_ECX: - *(int32_t *)value = env->regs[R_ECX]; - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); - break; - case UC_X86_REG_EDX: - *(int32_t *)value = env->regs[R_EDX]; - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); - break; - case UC_X86_REG_ESP: - *(int32_t *)value = env->regs[R_ESP]; - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(env->regs[R_ESP]); - break; - case UC_X86_REG_EBP: - *(int32_t *)value = env->regs[R_EBP]; - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(env->regs[R_EBP]); - break; - case UC_X86_REG_ESI: - *(int32_t *)value = env->regs[R_ESI]; - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(env->regs[R_ESI]); - break; - case UC_X86_REG_EDI: - *(int32_t *)value = env->regs[R_EDI]; - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(env->regs[R_EDI]); - break; - case UC_X86_REG_EIP: - *(int32_t *)value = env->eip; - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(env->eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = env->ldt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; - ((uc_x86_mmr *)value)->flags = env->ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = env->tr.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; - ((uc_x86_mmr *)value)->flags = env->tr.flags; - break; - case UC_X86_REG_MSR: - x86_msr_read(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - *(uint32_t *)value = env->mxcsr; - break; - case UC_X86_REG_FS_BASE: - *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; - break; - } + case UC_X86_REG_ES: + *(int16_t *)value = env->segs[R_ES].selector; + return; + case UC_X86_REG_SS: + *(int16_t *)value = env->segs[R_SS].selector; + return; + case UC_X86_REG_DS: + *(int16_t *)value = env->segs[R_DS].selector; + return; + case UC_X86_REG_FS: + *(int16_t *)value = env->segs[R_FS].selector; + return; + case UC_X86_REG_GS: + *(int16_t *)value = env->segs[R_GS].selector; + return; + case UC_X86_REG_FS_BASE: + *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; + return; + } + // fall-thru + case UC_MODE_32: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + *(int32_t *)value = env->cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + *(int32_t *)value = env->dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_FLAGS: + *(int16_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EAX: + *(int32_t *)value = env->regs[R_EAX]; + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); + break; + case UC_X86_REG_EBX: + *(int32_t *)value = env->regs[R_EBX]; + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); + break; + case UC_X86_REG_ECX: + *(int32_t *)value = env->regs[R_ECX]; + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); + break; + case UC_X86_REG_EDX: + *(int32_t *)value = env->regs[R_EDX]; + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); + break; + case UC_X86_REG_ESP: + *(int32_t *)value = env->regs[R_ESP]; + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(env->regs[R_ESP]); + break; + case UC_X86_REG_EBP: + *(int32_t *)value = env->regs[R_EBP]; + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(env->regs[R_EBP]); + break; + case UC_X86_REG_ESI: + *(int32_t *)value = env->regs[R_ESI]; + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(env->regs[R_ESI]); + break; + case UC_X86_REG_EDI: + *(int32_t *)value = env->regs[R_EDI]; + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(env->regs[R_EDI]); + break; + case UC_X86_REG_EIP: + *(int32_t *)value = env->eip; + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(env->eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = env->ldt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; + ((uc_x86_mmr *)value)->flags = env->ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = env->tr.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; + ((uc_x86_mmr *)value)->flags = env->tr.flags; + break; + case UC_X86_REG_MSR: + x86_msr_read(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + *(uint32_t *)value = env->mxcsr; + break; + case UC_X86_REG_FS_BASE: + *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; + break; + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - *(int64_t *)value = env->dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_FLAGS: - *(int16_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_RFLAGS: - *(int64_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_RAX: - *(uint64_t *)value = env->regs[R_EAX]; - break; - case UC_X86_REG_EAX: - *(int32_t *)value = READ_DWORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); - break; - case UC_X86_REG_RBX: - *(uint64_t *)value = env->regs[R_EBX]; - break; - case UC_X86_REG_EBX: - *(int32_t *)value = READ_DWORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); - break; - case UC_X86_REG_RCX: - *(uint64_t *)value = env->regs[R_ECX]; - break; - case UC_X86_REG_ECX: - *(int32_t *)value = READ_DWORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); - break; - case UC_X86_REG_RDX: - *(uint64_t *)value = env->regs[R_EDX]; - break; - case UC_X86_REG_EDX: - *(int32_t *)value = READ_DWORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); - break; - case UC_X86_REG_RSP: - *(uint64_t *)value = env->regs[R_ESP]; - break; - case UC_X86_REG_ESP: - *(int32_t *)value = READ_DWORD(env->regs[R_ESP]); - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(env->regs[R_ESP]); - break; - case UC_X86_REG_SPL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ESP]); - break; - case UC_X86_REG_RBP: - *(uint64_t *)value = env->regs[R_EBP]; - break; - case UC_X86_REG_EBP: - *(int32_t *)value = READ_DWORD(env->regs[R_EBP]); - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(env->regs[R_EBP]); - break; - case UC_X86_REG_BPL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBP]); - break; - case UC_X86_REG_RSI: - *(uint64_t *)value = env->regs[R_ESI]; - break; - case UC_X86_REG_ESI: - *(int32_t *)value = READ_DWORD(env->regs[R_ESI]); - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(env->regs[R_ESI]); - break; - case UC_X86_REG_SIL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ESI]); - break; - case UC_X86_REG_RDI: - *(uint64_t *)value = env->regs[R_EDI]; - break; - case UC_X86_REG_EDI: - *(int32_t *)value = READ_DWORD(env->regs[R_EDI]); - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(env->regs[R_EDI]); - break; - case UC_X86_REG_DIL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDI]); - break; - case UC_X86_REG_RIP: - *(uint64_t *)value = env->eip; - break; - case UC_X86_REG_EIP: - *(int32_t *)value = READ_DWORD(env->eip); - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(env->eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; - break; - case UC_X86_REG_R8: - *(int64_t *)value = READ_QWORD(env->regs[8]); - break; - case UC_X86_REG_R8D: - *(int32_t *)value = READ_DWORD(env->regs[8]); - break; - case UC_X86_REG_R8W: - *(int16_t *)value = READ_WORD(env->regs[8]); - break; - case UC_X86_REG_R8B: - *(int8_t *)value = READ_BYTE_L(env->regs[8]); - break; - case UC_X86_REG_R9: - *(int64_t *)value = READ_QWORD(env->regs[9]); - break; - case UC_X86_REG_R9D: - *(int32_t *)value = READ_DWORD(env->regs[9]); - break; - case UC_X86_REG_R9W: - *(int16_t *)value = READ_WORD(env->regs[9]); - break; - case UC_X86_REG_R9B: - *(int8_t *)value = READ_BYTE_L(env->regs[9]); - break; - case UC_X86_REG_R10: - *(int64_t *)value = READ_QWORD(env->regs[10]); - break; - case UC_X86_REG_R10D: - *(int32_t *)value = READ_DWORD(env->regs[10]); - break; - case UC_X86_REG_R10W: - *(int16_t *)value = READ_WORD(env->regs[10]); - break; - case UC_X86_REG_R10B: - *(int8_t *)value = READ_BYTE_L(env->regs[10]); - break; - case UC_X86_REG_R11: - *(int64_t *)value = READ_QWORD(env->regs[11]); - break; - case UC_X86_REG_R11D: - *(int32_t *)value = READ_DWORD(env->regs[11]); - break; - case UC_X86_REG_R11W: - *(int16_t *)value = READ_WORD(env->regs[11]); - break; - case UC_X86_REG_R11B: - *(int8_t *)value = READ_BYTE_L(env->regs[11]); - break; - case UC_X86_REG_R12: - *(int64_t *)value = READ_QWORD(env->regs[12]); - break; - case UC_X86_REG_R12D: - *(int32_t *)value = READ_DWORD(env->regs[12]); - break; - case UC_X86_REG_R12W: - *(int16_t *)value = READ_WORD(env->regs[12]); - break; - case UC_X86_REG_R12B: - *(int8_t *)value = READ_BYTE_L(env->regs[12]); - break; - case UC_X86_REG_R13: - *(int64_t *)value = READ_QWORD(env->regs[13]); - break; - case UC_X86_REG_R13D: - *(int32_t *)value = READ_DWORD(env->regs[13]); - break; - case UC_X86_REG_R13W: - *(int16_t *)value = READ_WORD(env->regs[13]); - break; - case UC_X86_REG_R13B: - *(int8_t *)value = READ_BYTE_L(env->regs[13]); - break; - case UC_X86_REG_R14: - *(int64_t *)value = READ_QWORD(env->regs[14]); - break; - case UC_X86_REG_R14D: - *(int32_t *)value = READ_DWORD(env->regs[14]); - break; - case UC_X86_REG_R14W: - *(int16_t *)value = READ_WORD(env->regs[14]); - break; - case UC_X86_REG_R14B: - *(int8_t *)value = READ_BYTE_L(env->regs[14]); - break; - case UC_X86_REG_R15: - *(int64_t *)value = READ_QWORD(env->regs[15]); - break; - case UC_X86_REG_R15D: - *(int32_t *)value = READ_DWORD(env->regs[15]); - break; - case UC_X86_REG_R15W: - *(int16_t *)value = READ_WORD(env->regs[15]); - break; - case UC_X86_REG_R15B: - *(int8_t *)value = READ_BYTE_L(env->regs[15]); - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; - ((uc_x86_mmr *)value)->base = env->idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; - ((uc_x86_mmr *)value)->base = env->gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = env->ldt.limit; - ((uc_x86_mmr *)value)->base = env->ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; - ((uc_x86_mmr *)value)->flags = env->ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = env->tr.limit; - ((uc_x86_mmr *)value)->base = env->tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; - ((uc_x86_mmr *)value)->flags = env->tr.flags; - break; - case UC_X86_REG_MSR: - x86_msr_read(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - *(uint32_t *)value = env->mxcsr; - break; - case UC_X86_REG_XMM8: - case UC_X86_REG_XMM9: - case UC_X86_REG_XMM10: - case UC_X86_REG_XMM11: - case UC_X86_REG_XMM12: - case UC_X86_REG_XMM13: - case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: - { - float64 *dst = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - dst[0] = reg->_d[0]; - dst[1] = reg->_d[1]; - break; - } - case UC_X86_REG_FS_BASE: - *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; - break; - case UC_X86_REG_GS_BASE: - *(uint64_t *)value = (uint64_t)env->segs[R_GS].base; - break; - } + case UC_MODE_64: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + *(int64_t *)value = env->dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_FLAGS: + *(int16_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_RFLAGS: + *(int64_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_RAX: + *(uint64_t *)value = env->regs[R_EAX]; + break; + case UC_X86_REG_EAX: + *(int32_t *)value = READ_DWORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); + break; + case UC_X86_REG_RBX: + *(uint64_t *)value = env->regs[R_EBX]; + break; + case UC_X86_REG_EBX: + *(int32_t *)value = READ_DWORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); + break; + case UC_X86_REG_RCX: + *(uint64_t *)value = env->regs[R_ECX]; + break; + case UC_X86_REG_ECX: + *(int32_t *)value = READ_DWORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); + break; + case UC_X86_REG_RDX: + *(uint64_t *)value = env->regs[R_EDX]; + break; + case UC_X86_REG_EDX: + *(int32_t *)value = READ_DWORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); + break; + case UC_X86_REG_RSP: + *(uint64_t *)value = env->regs[R_ESP]; + break; + case UC_X86_REG_ESP: + *(int32_t *)value = READ_DWORD(env->regs[R_ESP]); + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(env->regs[R_ESP]); + break; + case UC_X86_REG_SPL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ESP]); + break; + case UC_X86_REG_RBP: + *(uint64_t *)value = env->regs[R_EBP]; + break; + case UC_X86_REG_EBP: + *(int32_t *)value = READ_DWORD(env->regs[R_EBP]); + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(env->regs[R_EBP]); + break; + case UC_X86_REG_BPL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBP]); + break; + case UC_X86_REG_RSI: + *(uint64_t *)value = env->regs[R_ESI]; + break; + case UC_X86_REG_ESI: + *(int32_t *)value = READ_DWORD(env->regs[R_ESI]); + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(env->regs[R_ESI]); + break; + case UC_X86_REG_SIL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ESI]); + break; + case UC_X86_REG_RDI: + *(uint64_t *)value = env->regs[R_EDI]; + break; + case UC_X86_REG_EDI: + *(int32_t *)value = READ_DWORD(env->regs[R_EDI]); + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(env->regs[R_EDI]); + break; + case UC_X86_REG_DIL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDI]); + break; + case UC_X86_REG_RIP: + *(uint64_t *)value = env->eip; + break; + case UC_X86_REG_EIP: + *(int32_t *)value = READ_DWORD(env->eip); + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(env->eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; + break; + case UC_X86_REG_R8: + *(int64_t *)value = READ_QWORD(env->regs[8]); + break; + case UC_X86_REG_R8D: + *(int32_t *)value = READ_DWORD(env->regs[8]); + break; + case UC_X86_REG_R8W: + *(int16_t *)value = READ_WORD(env->regs[8]); + break; + case UC_X86_REG_R8B: + *(int8_t *)value = READ_BYTE_L(env->regs[8]); + break; + case UC_X86_REG_R9: + *(int64_t *)value = READ_QWORD(env->regs[9]); + break; + case UC_X86_REG_R9D: + *(int32_t *)value = READ_DWORD(env->regs[9]); + break; + case UC_X86_REG_R9W: + *(int16_t *)value = READ_WORD(env->regs[9]); + break; + case UC_X86_REG_R9B: + *(int8_t *)value = READ_BYTE_L(env->regs[9]); + break; + case UC_X86_REG_R10: + *(int64_t *)value = READ_QWORD(env->regs[10]); + break; + case UC_X86_REG_R10D: + *(int32_t *)value = READ_DWORD(env->regs[10]); + break; + case UC_X86_REG_R10W: + *(int16_t *)value = READ_WORD(env->regs[10]); + break; + case UC_X86_REG_R10B: + *(int8_t *)value = READ_BYTE_L(env->regs[10]); + break; + case UC_X86_REG_R11: + *(int64_t *)value = READ_QWORD(env->regs[11]); + break; + case UC_X86_REG_R11D: + *(int32_t *)value = READ_DWORD(env->regs[11]); + break; + case UC_X86_REG_R11W: + *(int16_t *)value = READ_WORD(env->regs[11]); + break; + case UC_X86_REG_R11B: + *(int8_t *)value = READ_BYTE_L(env->regs[11]); + break; + case UC_X86_REG_R12: + *(int64_t *)value = READ_QWORD(env->regs[12]); + break; + case UC_X86_REG_R12D: + *(int32_t *)value = READ_DWORD(env->regs[12]); + break; + case UC_X86_REG_R12W: + *(int16_t *)value = READ_WORD(env->regs[12]); + break; + case UC_X86_REG_R12B: + *(int8_t *)value = READ_BYTE_L(env->regs[12]); + break; + case UC_X86_REG_R13: + *(int64_t *)value = READ_QWORD(env->regs[13]); + break; + case UC_X86_REG_R13D: + *(int32_t *)value = READ_DWORD(env->regs[13]); + break; + case UC_X86_REG_R13W: + *(int16_t *)value = READ_WORD(env->regs[13]); + break; + case UC_X86_REG_R13B: + *(int8_t *)value = READ_BYTE_L(env->regs[13]); + break; + case UC_X86_REG_R14: + *(int64_t *)value = READ_QWORD(env->regs[14]); + break; + case UC_X86_REG_R14D: + *(int32_t *)value = READ_DWORD(env->regs[14]); + break; + case UC_X86_REG_R14W: + *(int16_t *)value = READ_WORD(env->regs[14]); + break; + case UC_X86_REG_R14B: + *(int8_t *)value = READ_BYTE_L(env->regs[14]); + break; + case UC_X86_REG_R15: + *(int64_t *)value = READ_QWORD(env->regs[15]); + break; + case UC_X86_REG_R15D: + *(int32_t *)value = READ_DWORD(env->regs[15]); + break; + case UC_X86_REG_R15W: + *(int16_t *)value = READ_WORD(env->regs[15]); + break; + case UC_X86_REG_R15B: + *(int8_t *)value = READ_BYTE_L(env->regs[15]); + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; + ((uc_x86_mmr *)value)->base = env->idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; + ((uc_x86_mmr *)value)->base = env->gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = env->ldt.limit; + ((uc_x86_mmr *)value)->base = env->ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; + ((uc_x86_mmr *)value)->flags = env->ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = env->tr.limit; + ((uc_x86_mmr *)value)->base = env->tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; + ((uc_x86_mmr *)value)->flags = env->tr.flags; + break; + case UC_X86_REG_MSR: + x86_msr_read(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + *(uint32_t *)value = env->mxcsr; + break; + case UC_X86_REG_XMM8: + case UC_X86_REG_XMM9: + case UC_X86_REG_XMM10: + case UC_X86_REG_XMM11: + case UC_X86_REG_XMM12: + case UC_X86_REG_XMM13: + case UC_X86_REG_XMM14: + case UC_X86_REG_XMM15: { + float64 *dst = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->_d[0]; + dst[1] = reg->_d[1]; + break; + } + case UC_X86_REG_FS_BASE: + *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; + break; + case UC_X86_REG_GS_BASE: + *(uint64_t *)value = (uint64_t)env->segs[R_GS].base; + break; + } + break; #endif } return; } -static int reg_write(CPUX86State *env, unsigned int regid, const void *value, uc_mode mode) +static int reg_write(CPUX86State *env, unsigned int regid, const void *value, + uc_mode mode) { int ret; - - switch(regid) { - default: - break; - case UC_X86_REG_FP0: - case UC_X86_REG_FP1: - case UC_X86_REG_FP2: - case UC_X86_REG_FP3: - case UC_X86_REG_FP4: - case UC_X86_REG_FP5: - case UC_X86_REG_FP6: - case UC_X86_REG_FP7: - { - uint64_t mant = *(uint64_t*) value; - uint16_t upper = *(uint16_t*) ((char*)value + sizeof(uint64_t)); - env->fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); - } - return 0; - case UC_X86_REG_FPSW: - { - uint16_t fpus = *(uint16_t*) value; - env->fpus = fpus & ~0x3800; - env->fpstt = (fpus >> 11) & 0x7; - } - return 0; - case UC_X86_REG_FPCW: - cpu_set_fpuc(env, *(uint16_t *)value); - return 0; - case UC_X86_REG_FPTAG: - { - int i; - uint16_t fptag = *(uint16_t*) value; - for (i = 0; i < 8; i++) { - env->fptags[i] = ((fptag & 3) == 3); - fptag >>= 2; - } - return 0; - } - break; - case UC_X86_REG_XMM0: - case UC_X86_REG_XMM1: - case UC_X86_REG_XMM2: - case UC_X86_REG_XMM3: - case UC_X86_REG_XMM4: - case UC_X86_REG_XMM5: - case UC_X86_REG_XMM6: - case UC_X86_REG_XMM7: - { - float64 *src = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - reg->_d[0] = src[0]; - reg->_d[1] = src[1]; - return 0; - } - case UC_X86_REG_ST0: - case UC_X86_REG_ST1: - case UC_X86_REG_ST2: - case UC_X86_REG_ST3: - case UC_X86_REG_ST4: - case UC_X86_REG_ST5: - case UC_X86_REG_ST6: - case UC_X86_REG_ST7: - { - // value must be big enough to keep 80 bits (10 bytes) - memcpy(&FPST(regid - UC_X86_REG_ST0), value, 10); - return 0; - } - case UC_X86_REG_YMM0: - case UC_X86_REG_YMM1: - case UC_X86_REG_YMM2: - case UC_X86_REG_YMM3: - case UC_X86_REG_YMM4: - case UC_X86_REG_YMM5: - case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: - { - float64 *src = (float64*)value; - XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - lo_reg->_d[0] = src[0]; - lo_reg->_d[1] = src[1]; - hi_reg->_d[0] = src[2]; - hi_reg->_d[1] = src[3]; - return 0; - } + switch (regid) { + default: + break; + case UC_X86_REG_FP0: + case UC_X86_REG_FP1: + case UC_X86_REG_FP2: + case UC_X86_REG_FP3: + case UC_X86_REG_FP4: + case UC_X86_REG_FP5: + case UC_X86_REG_FP6: + case UC_X86_REG_FP7: { + uint64_t mant = *(uint64_t *)value; + uint16_t upper = *(uint16_t *)((char *)value + sizeof(uint64_t)); + env->fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); + } + return 0; + case UC_X86_REG_FPSW: { + uint16_t fpus = *(uint16_t *)value; + env->fpus = fpus & ~0x3800; + env->fpstt = (fpus >> 11) & 0x7; + } + return 0; + case UC_X86_REG_FPCW: + cpu_set_fpuc(env, *(uint16_t *)value); + return 0; + case UC_X86_REG_FPTAG: { + int i; + uint16_t fptag = *(uint16_t *)value; + for (i = 0; i < 8; i++) { + env->fptags[i] = ((fptag & 3) == 3); + fptag >>= 2; + } + + return 0; + } break; + case UC_X86_REG_XMM0: + case UC_X86_REG_XMM1: + case UC_X86_REG_XMM2: + case UC_X86_REG_XMM3: + case UC_X86_REG_XMM4: + case UC_X86_REG_XMM5: + case UC_X86_REG_XMM6: + case UC_X86_REG_XMM7: { + float64 *src = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->_d[0] = src[0]; + reg->_d[1] = src[1]; + return 0; + } + case UC_X86_REG_ST0: + case UC_X86_REG_ST1: + case UC_X86_REG_ST2: + case UC_X86_REG_ST3: + case UC_X86_REG_ST4: + case UC_X86_REG_ST5: + case UC_X86_REG_ST6: + case UC_X86_REG_ST7: { + // value must be big enough to keep 80 bits (10 bytes) + memcpy(&FPST(regid - UC_X86_REG_ST0), value, 10); + return 0; + } + case UC_X86_REG_YMM0: + case UC_X86_REG_YMM1: + case UC_X86_REG_YMM2: + case UC_X86_REG_YMM3: + case UC_X86_REG_YMM4: + case UC_X86_REG_YMM5: + case UC_X86_REG_YMM6: + case UC_X86_REG_YMM7: + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: { + float64 *src = (float64 *)value; + XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; + XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; + lo_reg->_d[0] = src[0]; + lo_reg->_d[1] = src[1]; + hi_reg->_d[0] = src[2]; + hi_reg->_d[1] = src[3]; + return 0; + } } - switch(mode) { + switch (mode) { + default: + break; + + case UC_MODE_16: + switch (regid) { default: break; - - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - load_seg_16_helper(env, R_ES, *(uint16_t *)value); - return 0; - case UC_X86_REG_SS: - load_seg_16_helper(env, R_SS, *(uint16_t *)value); - return 0; - case UC_X86_REG_DS: - load_seg_16_helper(env, R_DS, *(uint16_t *)value); - return 0; - case UC_X86_REG_FS: - load_seg_16_helper(env, R_FS, *(uint16_t *)value); - return 0; - case UC_X86_REG_GS: - load_seg_16_helper(env, R_GS, *(uint16_t *)value); - return 0; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - env->dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; - break; - case UC_X86_REG_FLAGS: - cpu_load_eflags(env, *(uint16_t*)value, -1); - break; - case UC_X86_REG_EFLAGS: - cpu_load_eflags(env, *(uint32_t *)value, -1); - break; - case UC_X86_REG_EAX: - env->regs[R_EAX] = *(uint32_t *)value; - break; - case UC_X86_REG_AX: - WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_EBX: - env->regs[R_EBX] = *(uint32_t *)value; - break; - case UC_X86_REG_BX: - WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_ECX: - env->regs[R_ECX] = *(uint32_t *)value; - break; - case UC_X86_REG_CX: - WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_EDX: - env->regs[R_EDX] = *(uint32_t *)value; - break; - case UC_X86_REG_DX: - WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_ESP: - env->regs[R_ESP] = *(uint32_t *)value; - break; - case UC_X86_REG_SP: - WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_EBP: - env->regs[R_EBP] = *(uint32_t *)value; - break; - case UC_X86_REG_BP: - WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_ESI: - env->regs[R_ESI] = *(uint32_t *)value; - break; - case UC_X86_REG_SI: - WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_EDI: - env->regs[R_EDI] = *(uint32_t *)value; - break; - case UC_X86_REG_DI: - WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_EIP: - env->eip = *(uint32_t *)value; - break; - case UC_X86_REG_IP: - env->eip = *(uint16_t *)value; - break; - case UC_X86_REG_CS: - ret = uc_check_cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); - break; - case UC_X86_REG_DS: - ret = uc_check_cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); - break; - case UC_X86_REG_SS: - ret = uc_check_cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); - break; - case UC_X86_REG_ES: - ret = uc_check_cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); - break; - case UC_X86_REG_FS: - ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_IDTR: - env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->idt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - env->ldt.limit = ((uc_x86_mmr *)value)->limit; - env->ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; - env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - env->tr.limit = ((uc_x86_mmr *)value)->limit; - env->tr.base = (uint32_t)((uc_x86_mmr *)value)->base; - env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->tr.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_MSR: - x86_msr_write(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - cpu_set_mxcsr(env, *(uint32_t *)value); - break; - /* - // Don't think base registers are a "thing" on x86 - case UC_X86_REG_FS_BASE: - env->segs[R_FS].base = *(uint32_t *)value; - continue; - case UC_X86_REG_GS_BASE: - env->segs[R_GS].base = *(uint32_t *)value; - continue; - */ - } + case UC_X86_REG_ES: + load_seg_16_helper(env, R_ES, *(uint16_t *)value); + return 0; + case UC_X86_REG_SS: + load_seg_16_helper(env, R_SS, *(uint16_t *)value); + return 0; + case UC_X86_REG_DS: + load_seg_16_helper(env, R_DS, *(uint16_t *)value); + return 0; + case UC_X86_REG_FS: + load_seg_16_helper(env, R_FS, *(uint16_t *)value); + return 0; + case UC_X86_REG_GS: + load_seg_16_helper(env, R_GS, *(uint16_t *)value); + return 0; + } + // fall-thru + case UC_MODE_32: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + env->dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; + break; + case UC_X86_REG_FLAGS: + cpu_load_eflags(env, *(uint16_t *)value, -1); + break; + case UC_X86_REG_EFLAGS: + cpu_load_eflags(env, *(uint32_t *)value, -1); + break; + case UC_X86_REG_EAX: + env->regs[R_EAX] = *(uint32_t *)value; + break; + case UC_X86_REG_AX: + WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_EBX: + env->regs[R_EBX] = *(uint32_t *)value; + break; + case UC_X86_REG_BX: + WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_ECX: + env->regs[R_ECX] = *(uint32_t *)value; + break; + case UC_X86_REG_CX: + WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_EDX: + env->regs[R_EDX] = *(uint32_t *)value; + break; + case UC_X86_REG_DX: + WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_ESP: + env->regs[R_ESP] = *(uint32_t *)value; + break; + case UC_X86_REG_SP: + WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_EBP: + env->regs[R_EBP] = *(uint32_t *)value; + break; + case UC_X86_REG_BP: + WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_ESI: + env->regs[R_ESI] = *(uint32_t *)value; + break; + case UC_X86_REG_SI: + WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_EDI: + env->regs[R_EDI] = *(uint32_t *)value; + break; + case UC_X86_REG_DI: + WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_EIP: + env->eip = *(uint32_t *)value; + break; + case UC_X86_REG_IP: + env->eip = *(uint16_t *)value; + break; + case UC_X86_REG_CS: + ret = uc_check_cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); + break; + case UC_X86_REG_DS: + ret = uc_check_cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); + break; + case UC_X86_REG_SS: + ret = uc_check_cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); + break; + case UC_X86_REG_ES: + ret = uc_check_cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); + break; + case UC_X86_REG_FS: + ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_IDTR: + env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->idt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + env->ldt.limit = ((uc_x86_mmr *)value)->limit; + env->ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; + env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + env->tr.limit = ((uc_x86_mmr *)value)->limit; + env->tr.base = (uint32_t)((uc_x86_mmr *)value)->base; + env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->tr.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_MSR: + x86_msr_write(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + cpu_set_mxcsr(env, *(uint32_t *)value); + break; + /* + // Don't think base registers are a "thing" on x86 + case UC_X86_REG_FS_BASE: + env->segs[R_FS].base = *(uint32_t *)value; + continue; + case UC_X86_REG_GS_BASE: + env->segs[R_GS].base = *(uint32_t *)value; + continue; + */ + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - env->dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; - break; - case UC_X86_REG_FLAGS: - cpu_load_eflags(env, *(uint16_t*)value, -1); - break; - case UC_X86_REG_EFLAGS: - cpu_load_eflags(env, *(uint32_t *)value, -1); - break; - case UC_X86_REG_RFLAGS: - cpu_load_eflags(env, *(uint64_t *)value, -1); - break; - case UC_X86_REG_RAX: - env->regs[R_EAX] = *(uint64_t *)value; - break; - case UC_X86_REG_EAX: - WRITE_DWORD(env->regs[R_EAX], *(uint32_t *)value); - break; - case UC_X86_REG_AX: - WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_RBX: - env->regs[R_EBX] = *(uint64_t *)value; - break; - case UC_X86_REG_EBX: - WRITE_DWORD(env->regs[R_EBX], *(uint32_t *)value); - break; - case UC_X86_REG_BX: - WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_RCX: - env->regs[R_ECX] = *(uint64_t *)value; - break; - case UC_X86_REG_ECX: - WRITE_DWORD(env->regs[R_ECX], *(uint32_t *)value); - break; - case UC_X86_REG_CX: - WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_RDX: - env->regs[R_EDX] = *(uint64_t *)value; - break; - case UC_X86_REG_EDX: - WRITE_DWORD(env->regs[R_EDX], *(uint32_t *)value); - break; - case UC_X86_REG_DX: - WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_RSP: - env->regs[R_ESP] = *(uint64_t *)value; - break; - case UC_X86_REG_ESP: - WRITE_DWORD(env->regs[R_ESP], *(uint32_t *)value); - break; - case UC_X86_REG_SP: - WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_SPL: - WRITE_BYTE_L(env->regs[R_ESP], *(uint8_t *)value); - break; - case UC_X86_REG_RBP: - env->regs[R_EBP] = *(uint64_t *)value; - break; - case UC_X86_REG_EBP: - WRITE_DWORD(env->regs[R_EBP], *(uint32_t *)value); - break; - case UC_X86_REG_BP: - WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_BPL: - WRITE_BYTE_L(env->regs[R_EBP], *(uint8_t *)value); - break; - case UC_X86_REG_RSI: - env->regs[R_ESI] = *(uint64_t *)value; - break; - case UC_X86_REG_ESI: - WRITE_DWORD(env->regs[R_ESI], *(uint32_t *)value); - break; - case UC_X86_REG_SI: - WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_SIL: - WRITE_BYTE_L(env->regs[R_ESI], *(uint8_t *)value); - break; - case UC_X86_REG_RDI: - env->regs[R_EDI] = *(uint64_t *)value; - break; - case UC_X86_REG_EDI: - WRITE_DWORD(env->regs[R_EDI], *(uint32_t *)value); - break; - case UC_X86_REG_DI: - WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_DIL: - WRITE_BYTE_L(env->regs[R_EDI], *(uint8_t *)value); - break; - case UC_X86_REG_RIP: - env->eip = *(uint64_t *)value; - break; - case UC_X86_REG_EIP: - env->eip = *(uint32_t *)value; - break; - case UC_X86_REG_IP: - WRITE_WORD(env->eip, *(uint16_t *)value); - break; - case UC_X86_REG_CS: - env->segs[R_CS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_DS: - env->segs[R_DS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_SS: - env->segs[R_SS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_ES: - env->segs[R_ES].selector = *(uint16_t *)value; - break; - case UC_X86_REG_FS: - ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_R8: - env->regs[8] = *(uint64_t *)value; - break; - case UC_X86_REG_R8D: - WRITE_DWORD(env->regs[8], *(uint32_t *)value); - break; - case UC_X86_REG_R8W: - WRITE_WORD(env->regs[8], *(uint16_t *)value); - break; - case UC_X86_REG_R8B: - WRITE_BYTE_L(env->regs[8], *(uint8_t *)value); - break; - case UC_X86_REG_R9: - env->regs[9] = *(uint64_t *)value; - break; - case UC_X86_REG_R9D: - WRITE_DWORD(env->regs[9], *(uint32_t *)value); - break; - case UC_X86_REG_R9W: - WRITE_WORD(env->regs[9], *(uint16_t *)value); - break; - case UC_X86_REG_R9B: - WRITE_BYTE_L(env->regs[9], *(uint8_t *)value); - break; - case UC_X86_REG_R10: - env->regs[10] = *(uint64_t *)value; - break; - case UC_X86_REG_R10D: - WRITE_DWORD(env->regs[10], *(uint32_t *)value); - break; - case UC_X86_REG_R10W: - WRITE_WORD(env->regs[10], *(uint16_t *)value); - break; - case UC_X86_REG_R10B: - WRITE_BYTE_L(env->regs[10], *(uint8_t *)value); - break; - case UC_X86_REG_R11: - env->regs[11] = *(uint64_t *)value; - break; - case UC_X86_REG_R11D: - WRITE_DWORD(env->regs[11], *(uint32_t *)value); - break; - case UC_X86_REG_R11W: - WRITE_WORD(env->regs[11], *(uint16_t *)value); - break; - case UC_X86_REG_R11B: - WRITE_BYTE_L(env->regs[11], *(uint8_t *)value); - break; - case UC_X86_REG_R12: - env->regs[12] = *(uint64_t *)value; - break; - case UC_X86_REG_R12D: - WRITE_DWORD(env->regs[12], *(uint32_t *)value); - break; - case UC_X86_REG_R12W: - WRITE_WORD(env->regs[12], *(uint16_t *)value); - break; - case UC_X86_REG_R12B: - WRITE_BYTE_L(env->regs[12], *(uint8_t *)value); - break; - case UC_X86_REG_R13: - env->regs[13] = *(uint64_t *)value; - break; - case UC_X86_REG_R13D: - WRITE_DWORD(env->regs[13], *(uint32_t *)value); - break; - case UC_X86_REG_R13W: - WRITE_WORD(env->regs[13], *(uint16_t *)value); - break; - case UC_X86_REG_R13B: - WRITE_BYTE_L(env->regs[13], *(uint8_t *)value); - break; - case UC_X86_REG_R14: - env->regs[14] = *(uint64_t *)value; - break; - case UC_X86_REG_R14D: - WRITE_DWORD(env->regs[14], *(uint32_t *)value); - break; - case UC_X86_REG_R14W: - WRITE_WORD(env->regs[14], *(uint16_t *)value); - break; - case UC_X86_REG_R14B: - WRITE_BYTE_L(env->regs[14], *(uint8_t *)value); - break; - case UC_X86_REG_R15: - env->regs[15] = *(uint64_t *)value; - break; - case UC_X86_REG_R15D: - WRITE_DWORD(env->regs[15], *(uint32_t *)value); - break; - case UC_X86_REG_R15W: - WRITE_WORD(env->regs[15], *(uint16_t *)value); - break; - case UC_X86_REG_R15B: - WRITE_BYTE_L(env->regs[15], *(uint8_t *)value); - break; - case UC_X86_REG_IDTR: - env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->idt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->gdt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - env->ldt.limit = ((uc_x86_mmr *)value)->limit; - env->ldt.base = ((uc_x86_mmr *)value)->base; - env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - env->tr.limit = ((uc_x86_mmr *)value)->limit; - env->tr.base = ((uc_x86_mmr *)value)->base; - env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->tr.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_MSR: - x86_msr_write(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - cpu_set_mxcsr(env, *(uint32_t *)value); - break; - case UC_X86_REG_XMM8: - case UC_X86_REG_XMM9: - case UC_X86_REG_XMM10: - case UC_X86_REG_XMM11: - case UC_X86_REG_XMM12: - case UC_X86_REG_XMM13: - case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: - { - float64 *src = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - reg->_d[0] = src[0]; - reg->_d[1] = src[1]; - break; - } - case UC_X86_REG_FS_BASE: - env->segs[R_FS].base = *(uint64_t *)value; - return 0; - case UC_X86_REG_GS_BASE: - env->segs[R_GS].base = *(uint64_t *)value; - return 0; - } + case UC_MODE_64: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + env->dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; + break; + case UC_X86_REG_FLAGS: + cpu_load_eflags(env, *(uint16_t *)value, -1); + break; + case UC_X86_REG_EFLAGS: + cpu_load_eflags(env, *(uint32_t *)value, -1); + break; + case UC_X86_REG_RFLAGS: + cpu_load_eflags(env, *(uint64_t *)value, -1); + break; + case UC_X86_REG_RAX: + env->regs[R_EAX] = *(uint64_t *)value; + break; + case UC_X86_REG_EAX: + WRITE_DWORD(env->regs[R_EAX], *(uint32_t *)value); + break; + case UC_X86_REG_AX: + WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_RBX: + env->regs[R_EBX] = *(uint64_t *)value; + break; + case UC_X86_REG_EBX: + WRITE_DWORD(env->regs[R_EBX], *(uint32_t *)value); + break; + case UC_X86_REG_BX: + WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_RCX: + env->regs[R_ECX] = *(uint64_t *)value; + break; + case UC_X86_REG_ECX: + WRITE_DWORD(env->regs[R_ECX], *(uint32_t *)value); + break; + case UC_X86_REG_CX: + WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_RDX: + env->regs[R_EDX] = *(uint64_t *)value; + break; + case UC_X86_REG_EDX: + WRITE_DWORD(env->regs[R_EDX], *(uint32_t *)value); + break; + case UC_X86_REG_DX: + WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_RSP: + env->regs[R_ESP] = *(uint64_t *)value; + break; + case UC_X86_REG_ESP: + WRITE_DWORD(env->regs[R_ESP], *(uint32_t *)value); + break; + case UC_X86_REG_SP: + WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_SPL: + WRITE_BYTE_L(env->regs[R_ESP], *(uint8_t *)value); + break; + case UC_X86_REG_RBP: + env->regs[R_EBP] = *(uint64_t *)value; + break; + case UC_X86_REG_EBP: + WRITE_DWORD(env->regs[R_EBP], *(uint32_t *)value); + break; + case UC_X86_REG_BP: + WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_BPL: + WRITE_BYTE_L(env->regs[R_EBP], *(uint8_t *)value); + break; + case UC_X86_REG_RSI: + env->regs[R_ESI] = *(uint64_t *)value; + break; + case UC_X86_REG_ESI: + WRITE_DWORD(env->regs[R_ESI], *(uint32_t *)value); + break; + case UC_X86_REG_SI: + WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_SIL: + WRITE_BYTE_L(env->regs[R_ESI], *(uint8_t *)value); + break; + case UC_X86_REG_RDI: + env->regs[R_EDI] = *(uint64_t *)value; + break; + case UC_X86_REG_EDI: + WRITE_DWORD(env->regs[R_EDI], *(uint32_t *)value); + break; + case UC_X86_REG_DI: + WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_DIL: + WRITE_BYTE_L(env->regs[R_EDI], *(uint8_t *)value); + break; + case UC_X86_REG_RIP: + env->eip = *(uint64_t *)value; + break; + case UC_X86_REG_EIP: + env->eip = *(uint32_t *)value; + break; + case UC_X86_REG_IP: + WRITE_WORD(env->eip, *(uint16_t *)value); + break; + case UC_X86_REG_CS: + env->segs[R_CS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_DS: + env->segs[R_DS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_SS: + env->segs[R_SS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_ES: + env->segs[R_ES].selector = *(uint16_t *)value; + break; + case UC_X86_REG_FS: + ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_R8: + env->regs[8] = *(uint64_t *)value; + break; + case UC_X86_REG_R8D: + WRITE_DWORD(env->regs[8], *(uint32_t *)value); + break; + case UC_X86_REG_R8W: + WRITE_WORD(env->regs[8], *(uint16_t *)value); + break; + case UC_X86_REG_R8B: + WRITE_BYTE_L(env->regs[8], *(uint8_t *)value); + break; + case UC_X86_REG_R9: + env->regs[9] = *(uint64_t *)value; + break; + case UC_X86_REG_R9D: + WRITE_DWORD(env->regs[9], *(uint32_t *)value); + break; + case UC_X86_REG_R9W: + WRITE_WORD(env->regs[9], *(uint16_t *)value); + break; + case UC_X86_REG_R9B: + WRITE_BYTE_L(env->regs[9], *(uint8_t *)value); + break; + case UC_X86_REG_R10: + env->regs[10] = *(uint64_t *)value; + break; + case UC_X86_REG_R10D: + WRITE_DWORD(env->regs[10], *(uint32_t *)value); + break; + case UC_X86_REG_R10W: + WRITE_WORD(env->regs[10], *(uint16_t *)value); + break; + case UC_X86_REG_R10B: + WRITE_BYTE_L(env->regs[10], *(uint8_t *)value); + break; + case UC_X86_REG_R11: + env->regs[11] = *(uint64_t *)value; + break; + case UC_X86_REG_R11D: + WRITE_DWORD(env->regs[11], *(uint32_t *)value); + break; + case UC_X86_REG_R11W: + WRITE_WORD(env->regs[11], *(uint16_t *)value); + break; + case UC_X86_REG_R11B: + WRITE_BYTE_L(env->regs[11], *(uint8_t *)value); + break; + case UC_X86_REG_R12: + env->regs[12] = *(uint64_t *)value; + break; + case UC_X86_REG_R12D: + WRITE_DWORD(env->regs[12], *(uint32_t *)value); + break; + case UC_X86_REG_R12W: + WRITE_WORD(env->regs[12], *(uint16_t *)value); + break; + case UC_X86_REG_R12B: + WRITE_BYTE_L(env->regs[12], *(uint8_t *)value); + break; + case UC_X86_REG_R13: + env->regs[13] = *(uint64_t *)value; + break; + case UC_X86_REG_R13D: + WRITE_DWORD(env->regs[13], *(uint32_t *)value); + break; + case UC_X86_REG_R13W: + WRITE_WORD(env->regs[13], *(uint16_t *)value); + break; + case UC_X86_REG_R13B: + WRITE_BYTE_L(env->regs[13], *(uint8_t *)value); + break; + case UC_X86_REG_R14: + env->regs[14] = *(uint64_t *)value; + break; + case UC_X86_REG_R14D: + WRITE_DWORD(env->regs[14], *(uint32_t *)value); + break; + case UC_X86_REG_R14W: + WRITE_WORD(env->regs[14], *(uint16_t *)value); + break; + case UC_X86_REG_R14B: + WRITE_BYTE_L(env->regs[14], *(uint8_t *)value); + break; + case UC_X86_REG_R15: + env->regs[15] = *(uint64_t *)value; + break; + case UC_X86_REG_R15D: + WRITE_DWORD(env->regs[15], *(uint32_t *)value); + break; + case UC_X86_REG_R15W: + WRITE_WORD(env->regs[15], *(uint16_t *)value); + break; + case UC_X86_REG_R15B: + WRITE_BYTE_L(env->regs[15], *(uint8_t *)value); + break; + case UC_X86_REG_IDTR: + env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->idt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->gdt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + env->ldt.limit = ((uc_x86_mmr *)value)->limit; + env->ldt.base = ((uc_x86_mmr *)value)->base; + env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + env->tr.limit = ((uc_x86_mmr *)value)->limit; + env->tr.base = ((uc_x86_mmr *)value)->base; + env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->tr.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_MSR: + x86_msr_write(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + cpu_set_mxcsr(env, *(uint32_t *)value); + break; + case UC_X86_REG_XMM8: + case UC_X86_REG_XMM9: + case UC_X86_REG_XMM10: + case UC_X86_REG_XMM11: + case UC_X86_REG_XMM12: + case UC_X86_REG_XMM13: + case UC_X86_REG_XMM14: + case UC_X86_REG_XMM15: { + float64 *src = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->_d[0] = src[0]; + reg->_d[1] = src[1]; + break; + } + case UC_X86_REG_FS_BASE: + env->segs[R_FS].base = *(uint64_t *)value; + return 0; + case UC_X86_REG_GS_BASE: + env->segs[R_GS].base = *(uint64_t *)value; + return 0; + } + break; #endif } return 0; } -int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; @@ -1466,9 +1463,10 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUX86State* env = &(X86_CPU(uc->cpu)->env); + CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; int ret; @@ -1476,37 +1474,37 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i unsigned int regid = regs[i]; const void *value = vals[i]; ret = reg_write(env, regid, value, uc->mode); - if (ret){ + if (ret) { return ret; } - switch(uc->mode) { + switch (uc->mode) { + default: + break; + case UC_MODE_32: + switch (regid) { default: break; - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - } + case UC_X86_REG_EIP: + case UC_X86_REG_IP: + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_RIP: - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - } + case UC_MODE_64: + switch (regid) { + default: + break; + case UC_X86_REG_RIP: + case UC_X86_REG_EIP: + case UC_X86_REG_IP: + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } #endif } } @@ -1515,7 +1513,8 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i } DEFAULT_VISIBILITY -int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { CPUX86State *env = (CPUX86State *)ctx->data; int i; @@ -1530,7 +1529,8 @@ int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals } DEFAULT_VISIBILITY -int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { CPUX86State *env = (CPUX86State *)ctx->data; int i; @@ -1540,7 +1540,7 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *cons unsigned int regid = regs[i]; const void *value = vals[i]; ret = reg_write(env, regid, value, ctx->mode); - if (ret){ + if (ret) { return ret; } } @@ -1550,22 +1550,20 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *cons static bool x86_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case EXCP06_ILLOP: - return true; + switch (intno) { + default: + return false; + case EXCP06_ILLOP: + return true; } } static bool x86_insn_hook_validate(uint32_t insn_enum) { - //for x86 we can only hook IN, OUT, and SYSCALL - if (insn_enum != UC_X86_INS_IN - && insn_enum != UC_X86_INS_OUT - && insn_enum != UC_X86_INS_SYSCALL - && insn_enum != UC_X86_INS_SYSENTER - && insn_enum != UC_X86_INS_CPUID) { + // for x86 we can only hook IN, OUT, and SYSCALL + if (insn_enum != UC_X86_INS_IN && insn_enum != UC_X86_INS_OUT && + insn_enum != UC_X86_INS_SYSCALL && insn_enum != UC_X86_INS_SYSENTER && + insn_enum != UC_X86_INS_CPUID) { return false; } return true; @@ -1585,7 +1583,7 @@ static int x86_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void x86_uc_init(struct uc_struct* uc) +void x86_uc_init(struct uc_struct *uc) { uc->reg_read = x86_reg_read; uc->reg_write = x86_reg_write; diff --git a/qemu/target/i386/unicorn.h b/qemu/target/i386/unicorn.h index b07be9d2..7c456cfb 100644 --- a/qemu/target/i386/unicorn.h +++ b/qemu/target/i386/unicorn.h @@ -6,12 +6,16 @@ #define UC_QEMU_TARGET_I386_H // functions to read & write registers -int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); -int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); +int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void x86_reg_reset(struct uc_struct *uc); -void x86_uc_init(struct uc_struct* uc); +void x86_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 323eff44..c447a905 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6326,7 +6326,7 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) uint16_t insn; // Unicorn: end address tells us to stop emulation - if (dc->pc == uc->addr_end) { + if (uc_addr_is_exit(uc, dc->pc)) { gen_exception(dc, dc->pc, EXCP_HLT); return; } diff --git a/qemu/target/m68k/unicorn.c b/qemu/target/m68k/unicorn.c index 1b9c5b14..72ce6ce5 100644 --- a/qemu/target/m68k/unicorn.c +++ b/qemu/target/m68k/unicorn.c @@ -15,7 +15,7 @@ static void m68k_set_pc(struct uc_struct *uc, uint64_t address) ((CPUM68KState *)uc->cpu->env_ptr)->pc = address; } -static void m68k_release(void* ctx) +static void m68k_release(void *ctx) { int i; TCGContext *tcg_ctx = (TCGContext *)ctx; @@ -51,11 +51,12 @@ static void reg_read(CPUM68KState *env, unsigned int regid, void *value) else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) *(int32_t *)value = env->dregs[regid - UC_M68K_REG_D0]; else { - switch(regid) { - default: break; - case UC_M68K_REG_PC: - *(int32_t *)value = env->pc; - break; + switch (regid) { + default: + break; + case UC_M68K_REG_PC: + *(int32_t *)value = env->pc; + break; } } @@ -69,18 +70,20 @@ static void reg_write(CPUM68KState *env, unsigned int regid, const void *value) else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) env->dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value; else { - switch(regid) { - default: break; - case UC_M68K_REG_PC: - env->pc = *(uint32_t *)value; - break; + switch (regid) { + default: + break; + case UC_M68K_REG_PC: + env->pc = *(uint32_t *)value; + break; } } } -int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { - CPUM68KState* env = &(M68K_CPU(uc->cpu)->env); + CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { @@ -92,16 +95,17 @@ int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou return 0; } -int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUM68KState* env = &(M68K_CPU(uc->cpu)->env); + CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if (regid == UC_M68K_REG_PC){ + if (regid == UC_M68K_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -112,9 +116,10 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, } DEFAULT_VISIBILITY -int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { - CPUM68KState* env = (CPUM68KState* )ctx->data; + CPUM68KState *env = (CPUM68KState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -127,9 +132,10 @@ int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **val } DEFAULT_VISIBILITY -int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { - CPUM68KState* env = (CPUM68KState* )ctx->data; + CPUM68KState *env = (CPUM68KState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -153,7 +159,7 @@ static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void m68k_uc_init(struct uc_struct* uc) +void m68k_uc_init(struct uc_struct *uc) { uc->release = m68k_release; uc->reg_read = m68k_reg_read; diff --git a/qemu/target/m68k/unicorn.h b/qemu/target/m68k/unicorn.h index 2eeeaae8..ebd5c310 100644 --- a/qemu/target/m68k/unicorn.h +++ b/qemu/target/m68k/unicorn.h @@ -5,12 +5,16 @@ #define UC_QEMU_TARGET_M68K_H // functions to read & write registers -int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); -int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); +int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void m68k_reg_reset(struct uc_struct *uc); -void m68k_uc_init(struct uc_struct* uc); +void m68k_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 97e680a3..e9fceaf9 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30932,7 +30932,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) is_slot = ctx->hflags & MIPS_HFLAG_BMASK; // Unicorn: end address tells us to stop emulation - if (ctx->base.pc_next == uc->addr_end) { + if (uc_addr_is_exit(uc, ctx->base.pc_next)) { // raise a special interrupt to quit gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); ctx->base.is_jmp = DISAS_NORETURN; diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index 2c9dae5f..c2840828 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -37,7 +37,6 @@ static void mips_set_pc(struct uc_struct *uc, uint64_t address) ((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address; } - static void mips_release(void *ctx) { int i; @@ -75,20 +74,21 @@ static void reg_read(CPUMIPSState *env, unsigned int regid, void *value) if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) *(mipsreg_t *)value = env->active_tc.gpr[regid - UC_MIPS_REG_0]; else { - switch(regid) { - default: break; - case UC_MIPS_REG_PC: - *(mipsreg_t *)value = env->active_tc.PC; - break; - case UC_MIPS_REG_CP0_CONFIG3: - *(mipsreg_t *)value = env->CP0_Config3; - break; - case UC_MIPS_REG_CP0_STATUS: - *(mipsreg_t *)value = env->CP0_Status; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; - break; + switch (regid) { + default: + break; + case UC_MIPS_REG_PC: + *(mipsreg_t *)value = env->active_tc.PC; + break; + case UC_MIPS_REG_CP0_CONFIG3: + *(mipsreg_t *)value = env->CP0_Config3; + break; + case UC_MIPS_REG_CP0_STATUS: + *(mipsreg_t *)value = env->CP0_Status; + break; + case UC_MIPS_REG_CP0_USERLOCAL: + *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; + break; } } @@ -100,31 +100,33 @@ static void reg_write(CPUMIPSState *env, unsigned int regid, const void *value) if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) env->active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value; else { - switch(regid) { - default: break; - case UC_MIPS_REG_PC: - env->active_tc.PC = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_CONFIG3: - env->CP0_Config3 = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_STATUS: - // TODO: ALL CP0 REGS - // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf - // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf - env->CP0_Status = *(mipsreg_t *)value; - compute_hflags(env); - break; - case UC_MIPS_REG_CP0_USERLOCAL: - env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; - break; + switch (regid) { + default: + break; + case UC_MIPS_REG_PC: + env->active_tc.PC = *(mipsreg_t *)value; + break; + case UC_MIPS_REG_CP0_CONFIG3: + env->CP0_Config3 = *(mipsreg_t *)value; + break; + case UC_MIPS_REG_CP0_STATUS: + // TODO: ALL CP0 REGS + // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf + // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf + env->CP0_Status = *(mipsreg_t *)value; + compute_hflags(env); + break; + case UC_MIPS_REG_CP0_USERLOCAL: + env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; + break; } } return; } -int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); int i; @@ -138,7 +140,8 @@ int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou return 0; } -int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); int i; @@ -147,7 +150,7 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_MIPS_REG_PC){ + if (regid == UC_MIPS_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -160,15 +163,19 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, DEFAULT_VISIBILITY #ifdef TARGET_MIPS64 #ifdef TARGET_WORDS_BIGENDIAN - int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else - int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif #else // if TARGET_MIPS #ifdef TARGET_WORDS_BIGENDIAN - int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else - int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif #endif { @@ -187,15 +194,19 @@ DEFAULT_VISIBILITY DEFAULT_VISIBILITY #ifdef TARGET_MIPS64 #ifdef TARGET_WORDS_BIGENDIAN - int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else - int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif #else // if TARGET_MIPS #ifdef TARGET_WORDS_BIGENDIAN - int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else - int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif #endif { @@ -226,15 +237,15 @@ static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_MIPS64 #ifdef TARGET_WORDS_BIGENDIAN - void mips64_uc_init(struct uc_struct* uc) +void mips64_uc_init(struct uc_struct *uc) #else - void mips64el_uc_init(struct uc_struct* uc) +void mips64el_uc_init(struct uc_struct *uc) #endif #else // if TARGET_MIPS #ifdef TARGET_WORDS_BIGENDIAN - void mips_uc_init(struct uc_struct* uc) +void mips_uc_init(struct uc_struct *uc) #else - void mipsel_uc_init(struct uc_struct* uc) +void mipsel_uc_init(struct uc_struct *uc) #endif #endif { diff --git a/qemu/target/mips/unicorn.h b/qemu/target/mips/unicorn.h index 6179a3c3..5a806522 100644 --- a/qemu/target/mips/unicorn.h +++ b/qemu/target/mips/unicorn.h @@ -5,22 +5,32 @@ #define UC_QEMU_TARGET_MIPS_H // functions to read & write registers -int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void mips_reg_reset(struct uc_struct *uc); -void mips_uc_init(struct uc_struct* uc); -void mipsel_uc_init(struct uc_struct* uc); -void mips64_uc_init(struct uc_struct* uc); -void mips64el_uc_init(struct uc_struct* uc); +void mips_uc_init(struct uc_struct *uc); +void mipsel_uc_init(struct uc_struct *uc); +void mips64_uc_init(struct uc_struct *uc); +void mips64el_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 8cfebab2..fec05d19 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7626,7 +7626,7 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); // Unicorn: end address tells us to stop emulation - if (ctx->base.pc_next == uc->addr_end) { + if (uc_addr_is_exit(uc, ctx->base.pc_next)) { gen_wait(ctx); return; } diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index 66b7da7d..99438c27 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -18,14 +18,14 @@ typedef uint32_t ppcreg_t; static uint64_t ppc_mem_redirect(uint64_t address) { -/* // kseg0 range masks off high address bit - if (address >= 0x80000000 && address <= 0x9fffffff) - return address & 0x7fffffff; + /* // kseg0 range masks off high address bit + if (address >= 0x80000000 && address <= 0x9fffffff) + return address & 0x7fffffff; - // kseg1 range masks off top 3 address bits - if (address >= 0xa0000000 && address <= 0xbfffffff) { - return address & 0x1fffffff; - }*/ + // kseg1 range masks off top 3 address bits + if (address >= 0xa0000000 && address <= 0xbfffffff) { + return address & 0x1fffffff; + }*/ // no redirect return address; @@ -59,12 +59,12 @@ static void ppc_release(void *ctx) for (i = 0; i < 32; i++) { g_free(tcg_ctx->cpu_gpr[i]); } -// g_free(tcg_ctx->cpu_PC); + // g_free(tcg_ctx->cpu_PC); g_free(tcg_ctx->btarget); g_free(tcg_ctx->bcond); g_free(tcg_ctx->cpu_dspctrl); -// g_free(tcg_ctx->tb_ctx.tbs); + // g_free(tcg_ctx->tb_ctx.tbs); ppc_cpu_instance_finalize(tcg_ctx->uc->cpu); ppc_cpu_unrealize(tcg_ctx->uc->cpu); @@ -84,17 +84,18 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value) if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) *(ppcreg_t *)value = env->gpr[regid - UC_PPC_REG_0]; else { - switch(regid) { - default: break; - case UC_PPC_REG_PC: - *(ppcreg_t *)value = env->nip; - break; -/* case UC_PPC_REG_CP0_CONFIG3: - *(mipsreg_t *)value = env->CP0_Config3; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; - break; */ + switch (regid) { + default: + break; + case UC_PPC_REG_PC: + *(ppcreg_t *)value = env->nip; + break; + /* case UC_PPC_REG_CP0_CONFIG3: + *(mipsreg_t *)value = env->CP0_Config3; + break; + case UC_MIPS_REG_CP0_USERLOCAL: + *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; + break; */ } } @@ -106,24 +107,26 @@ static void reg_write(CPUPPCState *env, unsigned int regid, const void *value) if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) env->gpr[regid - UC_PPC_REG_0] = *(ppcreg_t *)value; else { - switch(regid) { - default: break; - case UC_PPC_REG_PC: - env->nip = *(ppcreg_t *)value; - break; -/* case UC_MIPS_REG_CP0_CONFIG3: - env->CP0_Config3 = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; - break; */ + switch (regid) { + default: + break; + case UC_PPC_REG_PC: + env->nip = *(ppcreg_t *)value; + break; + /* case UC_MIPS_REG_CP0_CONFIG3: + env->CP0_Config3 = *(mipsreg_t *)value; + break; + case UC_MIPS_REG_CP0_USERLOCAL: + env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; + break; */ } } return; } -int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); int i; @@ -137,7 +140,8 @@ int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); int i; @@ -158,9 +162,11 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i DEFAULT_VISIBILITY #ifdef TARGET_PPC64 -int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else -int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { CPUPPCState *env = (CPUPPCState *)ctx->data; @@ -177,9 +183,11 @@ int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals DEFAULT_VISIBILITY #ifdef TARGET_PPC64 -int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else -int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { CPUPPCState *env = (CPUPPCState *)ctx->data; @@ -208,9 +216,9 @@ static int ppc_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_PPC64 -void ppc64_uc_init(struct uc_struct* uc) +void ppc64_uc_init(struct uc_struct *uc) #else -void ppc_uc_init(struct uc_struct* uc) +void ppc_uc_init(struct uc_struct *uc) #endif { uc->reg_read = ppc_reg_read; diff --git a/qemu/target/ppc/unicorn.h b/qemu/target/ppc/unicorn.h index ef3bcf6e..2afaa3a0 100644 --- a/qemu/target/ppc/unicorn.h +++ b/qemu/target/ppc/unicorn.h @@ -5,16 +5,22 @@ #define UC_QEMU_TARGET_PPC_H // functions to read & write registers -int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void ppc_reg_reset(struct uc_struct *uc); -void ppc_uc_init(struct uc_struct* uc); -void ppc64_uc_init(struct uc_struct* uc); +void ppc_uc_init(struct uc_struct *uc); +void ppc64_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 7aa55188..e256958f 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -850,7 +850,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) bool insn_hook = false; // Unicorn: end address tells us to stop emulation - if (ctx->base.pc_next == ctx->uc->addr_end) { + if (uc_addr_is_exit(uc, ctx->base.pc_next)) { // Unicorn: We have to exit current execution here. dcbase->is_jmp = DISAS_UC_EXIT; } else { @@ -899,6 +899,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *ctx = container_of(dcbase, DisasContext, base); + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; switch (ctx->base.is_jmp) { case DISAS_TOO_MANY: @@ -907,6 +908,7 @@ static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) case DISAS_NORETURN: break; case DISAS_UC_EXIT: + tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc, ctx->base.pc_next); gen_helper_uc_riscv_exit(ctx->uc->tcg_ctx, ctx->uc->tcg_ctx->cpu_env); break; default: diff --git a/qemu/target/riscv/unicorn.c b/qemu/target/riscv/unicorn.c index 4bf9f2b7..c66a5c9a 100644 --- a/qemu/target/riscv/unicorn.c +++ b/qemu/target/riscv/unicorn.c @@ -36,99 +36,97 @@ static void riscv_release(void *ctx) } } -void riscv_reg_reset(struct uc_struct *uc) -{ -} +void riscv_reg_reset(struct uc_struct *uc) {} static void reg_read(CPURISCVState *env, unsigned int regid, void *value) { - switch(regid) { - case UC_RISCV_REG_X0: - case UC_RISCV_REG_X1: - case UC_RISCV_REG_X2: - case UC_RISCV_REG_X3: - case UC_RISCV_REG_X4: - case UC_RISCV_REG_X5: - case UC_RISCV_REG_X6: - case UC_RISCV_REG_X7: - case UC_RISCV_REG_X8: - case UC_RISCV_REG_X9: - case UC_RISCV_REG_X10: - case UC_RISCV_REG_X11: - case UC_RISCV_REG_X12: - case UC_RISCV_REG_X13: - case UC_RISCV_REG_X14: - case UC_RISCV_REG_X15: - case UC_RISCV_REG_X16: - case UC_RISCV_REG_X17: - case UC_RISCV_REG_X18: - case UC_RISCV_REG_X19: - case UC_RISCV_REG_X20: - case UC_RISCV_REG_X21: - case UC_RISCV_REG_X22: - case UC_RISCV_REG_X23: - case UC_RISCV_REG_X24: - case UC_RISCV_REG_X25: - case UC_RISCV_REG_X26: - case UC_RISCV_REG_X27: - case UC_RISCV_REG_X28: - case UC_RISCV_REG_X29: - case UC_RISCV_REG_X30: - case UC_RISCV_REG_X31: + switch (regid) { + case UC_RISCV_REG_X0: + case UC_RISCV_REG_X1: + case UC_RISCV_REG_X2: + case UC_RISCV_REG_X3: + case UC_RISCV_REG_X4: + case UC_RISCV_REG_X5: + case UC_RISCV_REG_X6: + case UC_RISCV_REG_X7: + case UC_RISCV_REG_X8: + case UC_RISCV_REG_X9: + case UC_RISCV_REG_X10: + case UC_RISCV_REG_X11: + case UC_RISCV_REG_X12: + case UC_RISCV_REG_X13: + case UC_RISCV_REG_X14: + case UC_RISCV_REG_X15: + case UC_RISCV_REG_X16: + case UC_RISCV_REG_X17: + case UC_RISCV_REG_X18: + case UC_RISCV_REG_X19: + case UC_RISCV_REG_X20: + case UC_RISCV_REG_X21: + case UC_RISCV_REG_X22: + case UC_RISCV_REG_X23: + case UC_RISCV_REG_X24: + case UC_RISCV_REG_X25: + case UC_RISCV_REG_X26: + case UC_RISCV_REG_X27: + case UC_RISCV_REG_X28: + case UC_RISCV_REG_X29: + case UC_RISCV_REG_X30: + case UC_RISCV_REG_X31: #ifdef TARGET_RISCV64 - *(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; + *(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; #else - *(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; + *(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; #endif - break; - case UC_RISCV_REG_PC: + break; + case UC_RISCV_REG_PC: #ifdef TARGET_RISCV64 - *(int64_t *)value = env->pc; + *(int64_t *)value = env->pc; #else - *(int32_t *)value = env->pc; + *(int32_t *)value = env->pc; #endif - break; + break; - case UC_RISCV_REG_F0: // "ft0" - case UC_RISCV_REG_F1: // "ft1" - case UC_RISCV_REG_F2: // "ft2" - case UC_RISCV_REG_F3: // "ft3" - case UC_RISCV_REG_F4: // "ft4" - case UC_RISCV_REG_F5: // "ft5" - case UC_RISCV_REG_F6: // "ft6" - case UC_RISCV_REG_F7: // "ft7" - case UC_RISCV_REG_F8: // "fs0" - case UC_RISCV_REG_F9: // "fs1" - case UC_RISCV_REG_F10: // "fa0" - case UC_RISCV_REG_F11: // "fa1" - case UC_RISCV_REG_F12: // "fa2" - case UC_RISCV_REG_F13: // "fa3" - case UC_RISCV_REG_F14: // "fa4" - case UC_RISCV_REG_F15: // "fa5" - case UC_RISCV_REG_F16: // "fa6" - case UC_RISCV_REG_F17: // "fa7" - case UC_RISCV_REG_F18: // "fs2" - case UC_RISCV_REG_F19: // "fs3" - case UC_RISCV_REG_F20: // "fs4" - case UC_RISCV_REG_F21: // "fs5" - case UC_RISCV_REG_F22: // "fs6" - case UC_RISCV_REG_F23: // "fs7" - case UC_RISCV_REG_F24: // "fs8" - case UC_RISCV_REG_F25: // "fs9" - case UC_RISCV_REG_F26: // "fs10" - case UC_RISCV_REG_F27: // "fs11" - case UC_RISCV_REG_F28: // "ft8" - case UC_RISCV_REG_F29: // "ft9" - case UC_RISCV_REG_F30: // "ft10" - case UC_RISCV_REG_F31: // "ft11" + case UC_RISCV_REG_F0: // "ft0" + case UC_RISCV_REG_F1: // "ft1" + case UC_RISCV_REG_F2: // "ft2" + case UC_RISCV_REG_F3: // "ft3" + case UC_RISCV_REG_F4: // "ft4" + case UC_RISCV_REG_F5: // "ft5" + case UC_RISCV_REG_F6: // "ft6" + case UC_RISCV_REG_F7: // "ft7" + case UC_RISCV_REG_F8: // "fs0" + case UC_RISCV_REG_F9: // "fs1" + case UC_RISCV_REG_F10: // "fa0" + case UC_RISCV_REG_F11: // "fa1" + case UC_RISCV_REG_F12: // "fa2" + case UC_RISCV_REG_F13: // "fa3" + case UC_RISCV_REG_F14: // "fa4" + case UC_RISCV_REG_F15: // "fa5" + case UC_RISCV_REG_F16: // "fa6" + case UC_RISCV_REG_F17: // "fa7" + case UC_RISCV_REG_F18: // "fs2" + case UC_RISCV_REG_F19: // "fs3" + case UC_RISCV_REG_F20: // "fs4" + case UC_RISCV_REG_F21: // "fs5" + case UC_RISCV_REG_F22: // "fs6" + case UC_RISCV_REG_F23: // "fs7" + case UC_RISCV_REG_F24: // "fs8" + case UC_RISCV_REG_F25: // "fs9" + case UC_RISCV_REG_F26: // "fs10" + case UC_RISCV_REG_F27: // "fs11" + case UC_RISCV_REG_F28: // "ft8" + case UC_RISCV_REG_F29: // "ft9" + case UC_RISCV_REG_F30: // "ft10" + case UC_RISCV_REG_F31: // "ft11" #ifdef TARGET_RISCV64 - *(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; + *(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; #else - *(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; + *(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; #endif - break; - default: - break; + break; + default: + break; } return; @@ -136,96 +134,97 @@ static void reg_read(CPURISCVState *env, unsigned int regid, void *value) static void reg_write(CPURISCVState *env, unsigned int regid, const void *value) { - switch(regid) { - case UC_RISCV_REG_X0: - case UC_RISCV_REG_X1: - case UC_RISCV_REG_X2: - case UC_RISCV_REG_X3: - case UC_RISCV_REG_X4: - case UC_RISCV_REG_X5: - case UC_RISCV_REG_X6: - case UC_RISCV_REG_X7: - case UC_RISCV_REG_X8: - case UC_RISCV_REG_X9: - case UC_RISCV_REG_X10: - case UC_RISCV_REG_X11: - case UC_RISCV_REG_X12: - case UC_RISCV_REG_X13: - case UC_RISCV_REG_X14: - case UC_RISCV_REG_X15: - case UC_RISCV_REG_X16: - case UC_RISCV_REG_X17: - case UC_RISCV_REG_X18: - case UC_RISCV_REG_X19: - case UC_RISCV_REG_X20: - case UC_RISCV_REG_X21: - case UC_RISCV_REG_X22: - case UC_RISCV_REG_X23: - case UC_RISCV_REG_X24: - case UC_RISCV_REG_X25: - case UC_RISCV_REG_X26: - case UC_RISCV_REG_X27: - case UC_RISCV_REG_X28: - case UC_RISCV_REG_X29: - case UC_RISCV_REG_X30: - case UC_RISCV_REG_X31: + switch (regid) { + case UC_RISCV_REG_X0: + case UC_RISCV_REG_X1: + case UC_RISCV_REG_X2: + case UC_RISCV_REG_X3: + case UC_RISCV_REG_X4: + case UC_RISCV_REG_X5: + case UC_RISCV_REG_X6: + case UC_RISCV_REG_X7: + case UC_RISCV_REG_X8: + case UC_RISCV_REG_X9: + case UC_RISCV_REG_X10: + case UC_RISCV_REG_X11: + case UC_RISCV_REG_X12: + case UC_RISCV_REG_X13: + case UC_RISCV_REG_X14: + case UC_RISCV_REG_X15: + case UC_RISCV_REG_X16: + case UC_RISCV_REG_X17: + case UC_RISCV_REG_X18: + case UC_RISCV_REG_X19: + case UC_RISCV_REG_X20: + case UC_RISCV_REG_X21: + case UC_RISCV_REG_X22: + case UC_RISCV_REG_X23: + case UC_RISCV_REG_X24: + case UC_RISCV_REG_X25: + case UC_RISCV_REG_X26: + case UC_RISCV_REG_X27: + case UC_RISCV_REG_X28: + case UC_RISCV_REG_X29: + case UC_RISCV_REG_X30: + case UC_RISCV_REG_X31: #ifdef TARGET_RISCV64 - env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value; + env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value; #else - env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value; + env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value; #endif - break; - case UC_RISCV_REG_PC: + break; + case UC_RISCV_REG_PC: #ifdef TARGET_RISCV64 - env->pc = *(uint64_t *)value; + env->pc = *(uint64_t *)value; #else - env->pc = *(uint32_t *)value; + env->pc = *(uint32_t *)value; #endif - break; - case UC_RISCV_REG_F0: // "ft0" - case UC_RISCV_REG_F1: // "ft1" - case UC_RISCV_REG_F2: // "ft2" - case UC_RISCV_REG_F3: // "ft3" - case UC_RISCV_REG_F4: // "ft4" - case UC_RISCV_REG_F5: // "ft5" - case UC_RISCV_REG_F6: // "ft6" - case UC_RISCV_REG_F7: // "ft7" - case UC_RISCV_REG_F8: // "fs0" - case UC_RISCV_REG_F9: // "fs1" - case UC_RISCV_REG_F10: // "fa0" - case UC_RISCV_REG_F11: // "fa1" - case UC_RISCV_REG_F12: // "fa2" - case UC_RISCV_REG_F13: // "fa3" - case UC_RISCV_REG_F14: // "fa4" - case UC_RISCV_REG_F15: // "fa5" - case UC_RISCV_REG_F16: // "fa6" - case UC_RISCV_REG_F17: // "fa7" - case UC_RISCV_REG_F18: // "fs2" - case UC_RISCV_REG_F19: // "fs3" - case UC_RISCV_REG_F20: // "fs4" - case UC_RISCV_REG_F21: // "fs5" - case UC_RISCV_REG_F22: // "fs6" - case UC_RISCV_REG_F23: // "fs7" - case UC_RISCV_REG_F24: // "fs8" - case UC_RISCV_REG_F25: // "fs9" - case UC_RISCV_REG_F26: // "fs10" - case UC_RISCV_REG_F27: // "fs11" - case UC_RISCV_REG_F28: // "ft8" - case UC_RISCV_REG_F29: // "ft9" - case UC_RISCV_REG_F30: // "ft10" - case UC_RISCV_REG_F31: // "ft11" + break; + case UC_RISCV_REG_F0: // "ft0" + case UC_RISCV_REG_F1: // "ft1" + case UC_RISCV_REG_F2: // "ft2" + case UC_RISCV_REG_F3: // "ft3" + case UC_RISCV_REG_F4: // "ft4" + case UC_RISCV_REG_F5: // "ft5" + case UC_RISCV_REG_F6: // "ft6" + case UC_RISCV_REG_F7: // "ft7" + case UC_RISCV_REG_F8: // "fs0" + case UC_RISCV_REG_F9: // "fs1" + case UC_RISCV_REG_F10: // "fa0" + case UC_RISCV_REG_F11: // "fa1" + case UC_RISCV_REG_F12: // "fa2" + case UC_RISCV_REG_F13: // "fa3" + case UC_RISCV_REG_F14: // "fa4" + case UC_RISCV_REG_F15: // "fa5" + case UC_RISCV_REG_F16: // "fa6" + case UC_RISCV_REG_F17: // "fa7" + case UC_RISCV_REG_F18: // "fs2" + case UC_RISCV_REG_F19: // "fs3" + case UC_RISCV_REG_F20: // "fs4" + case UC_RISCV_REG_F21: // "fs5" + case UC_RISCV_REG_F22: // "fs6" + case UC_RISCV_REG_F23: // "fs7" + case UC_RISCV_REG_F24: // "fs8" + case UC_RISCV_REG_F25: // "fs9" + case UC_RISCV_REG_F26: // "fs10" + case UC_RISCV_REG_F27: // "fs11" + case UC_RISCV_REG_F28: // "ft8" + case UC_RISCV_REG_F29: // "ft9" + case UC_RISCV_REG_F30: // "ft10" + case UC_RISCV_REG_F31: // "ft11" #ifdef TARGET_RISCV64 - env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value; + env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value; #else - env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value; + env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value; #endif - break; - default: - break; + break; + default: + break; } } -int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); int i; @@ -239,7 +238,8 @@ int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co return 0; } -int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); int i; @@ -248,11 +248,11 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_RISCV_REG_PC){ + if (regid == UC_RISCV_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); - } + } } return 0; @@ -260,10 +260,12 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, DEFAULT_VISIBILITY #ifdef TARGET_RISCV32 -int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else - /* TARGET_RISCV64 */ -int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +/* TARGET_RISCV64 */ +int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { CPURISCVState *env = (CPURISCVState *)ctx->data; @@ -280,10 +282,12 @@ int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void ** DEFAULT_VISIBILITY #ifdef TARGET_RISCV32 -int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else - /* TARGET_RISCV64 */ -int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +/* TARGET_RISCV64 */ +int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { CPURISCVState *env = (CPURISCVState *)ctx->data; @@ -301,14 +305,14 @@ int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void * static bool riscv_stop_interrupt(struct uc_struct *uc, int intno) { // detect stop exception - switch(intno){ - default: - return false; - case RISCV_EXCP_UNICORN_END: - return true; - case RISCV_EXCP_BREAKPOINT: - uc->invalid_error = UC_ERR_EXCEPTION; - return true; + switch (intno) { + default: + return false; + case RISCV_EXCP_UNICORN_END: + return true; + case RISCV_EXCP_BREAKPOINT: + uc->invalid_error = UC_ERR_EXCEPTION; + return true; } } @@ -332,10 +336,10 @@ static int riscv_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_RISCV32 -void riscv32_uc_init(struct uc_struct* uc) +void riscv32_uc_init(struct uc_struct *uc) #else - /* TARGET_RISCV64 */ -void riscv64_uc_init(struct uc_struct* uc) +/* TARGET_RISCV64 */ +void riscv64_uc_init(struct uc_struct *uc) #endif { uc->reg_read = riscv_reg_read; diff --git a/qemu/target/riscv/unicorn.h b/qemu/target/riscv/unicorn.h index 58371737..6add9369 100644 --- a/qemu/target/riscv/unicorn.h +++ b/qemu/target/riscv/unicorn.h @@ -6,16 +6,22 @@ #define UC_QEMU_TARGET_RISCV_H // functions to read & write registers -int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void riscv_reg_reset(struct uc_struct *uc); -void riscv32_uc_init(struct uc_struct* uc); -void riscv64_uc_init(struct uc_struct* uc); +void riscv32_uc_init(struct uc_struct *uc); +void riscv64_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index c6f3d9cd..8c2a8b40 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5951,7 +5951,7 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) unsigned int insn; // Unicorn: end address tells us to stop emulation - if (dc->pc == uc->addr_end) { + if (uc_addr_is_exit(uc, dc->pc)) { #ifndef TARGET_SPARC64 gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); #endif diff --git a/qemu/target/sparc/unicorn.c b/qemu/target/sparc/unicorn.c index aad52ebb..4733ac99 100644 --- a/qemu/target/sparc/unicorn.c +++ b/qemu/target/sparc/unicorn.c @@ -10,11 +10,11 @@ static bool sparc_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case TT_ILL_INSN: - return true; + switch (intno) { + default: + return false; + case TT_ILL_INSN: + return true; } } @@ -63,15 +63,16 @@ static void reg_read(CPUSPARCState *env, unsigned int regid, void *value) else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) *(int32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0]; else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) - *(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0]; + *(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0]; else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - *(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0]; + *(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0]; else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - *(int32_t *)value = env->pc; - break; + switch (regid) { + default: + break; + case UC_SPARC_REG_PC: + *(int32_t *)value = env->pc; + break; } } @@ -87,21 +88,23 @@ static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value) else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value; else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value; + env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value; else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - env->pc = *(uint32_t *)value; - env->npc = *(uint32_t *)value + 4; - break; + switch (regid) { + default: + break; + case UC_SPARC_REG_PC: + env->pc = *(uint32_t *)value; + env->npc = *(uint32_t *)value + 4; + break; } } return; } -int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; @@ -115,7 +118,8 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co return 0; } -int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; @@ -124,7 +128,7 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if( regid == UC_SPARC_REG_PC){ + if (regid == UC_SPARC_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -136,7 +140,8 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, } DEFAULT_VISIBILITY -int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; int i; @@ -151,7 +156,8 @@ int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **va } DEFAULT_VISIBILITY -int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; int i; @@ -177,7 +183,7 @@ static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void sparc_uc_init(struct uc_struct* uc) +void sparc_uc_init(struct uc_struct *uc) { uc->release = sparc_release; uc->reg_read = sparc_reg_read; diff --git a/qemu/target/sparc/unicorn.h b/qemu/target/sparc/unicorn.h index 2e90e0e3..1f9818aa 100644 --- a/qemu/target/sparc/unicorn.h +++ b/qemu/target/sparc/unicorn.h @@ -5,16 +5,22 @@ #define UC_QEMU_TARGET_SPARC_H // functions to read & write registers -int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void sparc_reg_reset(struct uc_struct *uc); -void sparc_uc_init(struct uc_struct* uc); -void sparc64_uc_init(struct uc_struct* uc); +void sparc_uc_init(struct uc_struct *uc); +void sparc64_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/x86_64.h b/qemu/x86_64.h index a1896af7..d0d3fba0 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _x86_64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_x86_64 #define use_idiv_instructions use_idiv_instructions_x86_64 #define arm_arch arm_arch_x86_64 #define tb_target_set_jmp_target tb_target_set_jmp_target_x86_64 diff --git a/samples/mem_apis.c b/samples/mem_apis.c index 767e6aec..57756f3c 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -14,24 +14,24 @@ 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. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ #define __STDC_FORMAT_MACROS - #include #include #include #include #include - static int insts_executed; // callback for tracing instructions, detect HLT and terminate emulation -static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, + void *user_data) { uint8_t opcode; unsigned char buf[256]; @@ -39,61 +39,81 @@ static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_da insts_executed++; if (uc_mem_read(uc, addr, buf, size) != UC_ERR_OK) { - printf("not ok - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); + printf("not ok - uc_mem_read fail during hook_code callback, addr: " + "0x%" PRIx64 "\n", + addr); if (uc_emu_stop(uc) != UC_ERR_OK) { - printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); + printf("not ok - uc_emu_stop fail during hook_code callback, addr: " + "0x%" PRIx64 "\n", + addr); _exit(-1); } } opcode = buf[0]; switch (opcode) { - case 0x41: // inc ecx - if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { - printf("not ok - uc_mem_protect fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); - _exit(-1); - } - break; - case 0x42: // inc edx - if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) { - printf("not ok - uc_mem_unmap fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); - _exit(-1); - } - break; - case 0xf4: // hlt - if (uc_emu_stop(uc) != UC_ERR_OK) { - printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); - _exit(-1); - } - break; - default: // all others - break; + case 0x41: // inc ecx + if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { + printf("not ok - uc_mem_protect fail during hook_code callback, " + "addr: 0x%" PRIx64 "\n", + addr); + _exit(-1); + } + break; + case 0x42: // inc edx + if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) { + printf("not ok - uc_mem_unmap fail during hook_code callback, " + "addr: 0x%" PRIx64 "\n", + addr); + _exit(-1); + } + break; + case 0xf4: // hlt + if (uc_emu_stop(uc) != UC_ERR_OK) { + printf("not ok - uc_emu_stop fail during hook_code callback, addr: " + "0x%" PRIx64 "\n", + addr); + _exit(-1); + } + break; + default: // all others + break; } } // callback for tracing invalid memory access (READ/WRITE/EXEC) -static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, - uint64_t addr, int size, int64_t value, void *user_data) +static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t addr, + int size, int64_t value, void *user_data) { - switch(type) { - default: - printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr); - return false; - case UC_MEM_READ_UNMAPPED: - printf("not ok - Read from invalid memory at 0x%"PRIx64 ", data size = %u\n", addr, size); - return false; - case UC_MEM_WRITE_UNMAPPED: - printf("not ok - Write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); - return false; - case UC_MEM_FETCH_PROT: - printf("not ok - Fetch from non-executable memory at 0x%"PRIx64 "\n", addr); - return false; - case UC_MEM_WRITE_PROT: - printf("not ok - Write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); - return false; - case UC_MEM_READ_PROT: - printf("not ok - Read from non-readable memory at 0x%"PRIx64 ", data size = %u\n", addr, size); - return false; + switch (type) { + default: + printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, + addr); + return false; + case UC_MEM_READ_UNMAPPED: + printf("not ok - Read from invalid memory at 0x%" PRIx64 + ", data size = %u\n", + addr, size); + return false; + case UC_MEM_WRITE_UNMAPPED: + printf("not ok - Write to invalid memory at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + addr, size, value); + return false; + case UC_MEM_FETCH_PROT: + printf("not ok - Fetch from non-executable memory at 0x%" PRIx64 "\n", + addr); + return false; + case UC_MEM_WRITE_PROT: + printf("not ok - Write to non-writeable memory at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + addr, size, value); + return false; + case UC_MEM_READ_PROT: + printf("not ok - Read from non-readable memory at 0x%" PRIx64 + ", data size = %u\n", + addr, size); + return false; } } @@ -107,7 +127,8 @@ static void do_nx_demo(bool cause_fault) insts_executed = 0; printf("===================================\n"); - printf("# Example of marking memory NX (%s)\n", cause_fault ? "faulting" : "non-faulting"); + printf("# Example of marking memory NX (%s)\n", + cause_fault ? "faulting" : "non-faulting"); // Initialize emulator in X86-32bit mode err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); @@ -129,14 +150,16 @@ static void do_nx_demo(bool cause_fault) page2: @2000 jmp page1 */ - memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax - memcpy(code_buf + 0x1000 - 5, "\xe9\x00\x10\x00\x00", 5); // jump to 0x102000 + memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax + memcpy(code_buf + 0x1000 - 5, "\xe9\x00\x10\x00\x00", + 5); // jump to 0x102000 memcpy(code_buf + 0x2000, "\xe9\xfb\xef\xff\xff", 5); // jump to 0x101000 - code_buf[0x1fff] = 0xf4; //hlt + code_buf[0x1fff] = 0xf4; // hlt if (cause_fault) { - // insert instruction to trigger U_PROT_EXEC change (see hook_code function) - code_buf[0x1000] = 0x41; // inc ecx at page1 + // insert instruction to trigger U_PROT_EXEC change (see hook_code + // function) + code_buf[0x1000] = 0x41; // inc ecx at page1 } // write machine code to be emulated to memory @@ -146,9 +169,10 @@ static void do_nx_demo(bool cause_fault) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != + UC_ERR_OK || + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1, + 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -157,7 +181,8 @@ static void do_nx_demo(bool cause_fault) printf("BEGINNING EXECUTION\n"); err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0); if (err != UC_ERR_OK) { - printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err)); + printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, + uc_strerror(err)); printf("FAILED EXECUTION\n"); } else { printf("SUCCESSFUL EXECUTION\n"); @@ -212,11 +237,12 @@ static void do_perms_demo(bool change_perms) */ memcpy(code_buf, WRITE_DEMO, sizeof(WRITE_DEMO) - 1); memset(code_buf + sizeof(WRITE_DEMO) - 1, 0x90, 1000); - code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt + code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt if (change_perms) { - // write protect memory area [0x101000, 0x101fff]. see hook_code function - code_buf[0] = 0x41; // inc ecx + // write protect memory area [0x101000, 0x101fff]. see hook_code + // function + code_buf[0] = 0x41; // inc ecx } // write machine code to be emulated to memory @@ -226,10 +252,10 @@ static void do_perms_demo(bool change_perms) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, - UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != + UC_ERR_OK || + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1, + 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -239,7 +265,8 @@ static void do_perms_demo(bool change_perms) err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0); if (err != UC_ERR_OK) { printf("FAILED EXECUTION\n"); - printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err)); + printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, + uc_strerror(err)); } else { printf("SUCCESSFUL EXECUTION\n"); } @@ -253,11 +280,11 @@ static void perms_test() { printf("Permissions demo - step 1: show that area is writeable\n"); do_perms_demo(false); - printf("Permissions demo - step 2: show that code fails when memory marked unwriteable\n"); + printf("Permissions demo - step 2: show that code fails when memory marked " + "unwriteable\n"); do_perms_demo(true); } - static void do_unmap_demo(bool do_unmap) { uc_engine *uc; @@ -290,11 +317,11 @@ static void do_unmap_demo(bool do_unmap) */ memcpy(code_buf, WRITE_DEMO, sizeof(WRITE_DEMO) - 1); memset(code_buf + sizeof(WRITE_DEMO) - 1, 0x90, 1000); - code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt + code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt if (do_unmap) { // unmap memory area [0x101000, 0x101fff]. see hook_code function - code_buf[0] = 0x42; // inc edx (see hook_code function) + code_buf[0] = 0x42; // inc edx (see hook_code function) } // write machine code to be emulated to memory @@ -304,10 +331,10 @@ static void do_unmap_demo(bool do_unmap) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, - UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != + UC_ERR_OK || + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1, + 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -317,7 +344,8 @@ static void do_unmap_demo(bool do_unmap) err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0); if (err != UC_ERR_OK) { printf("FAILED EXECUTION\n"); - printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err)); + printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, + uc_strerror(err)); } else { printf("SUCCESSFUL EXECUTION\n"); } @@ -331,7 +359,8 @@ static void unmap_test() { printf("Unmap demo - step 1: show that area is writeable\n"); do_unmap_demo(false); - printf("Unmap demo - step 2: show that code fails when memory is unmapped\n"); + printf( + "Unmap demo - step 2: show that code fails when memory is unmapped\n"); do_unmap_demo(true); } diff --git a/samples/sample_arm.c b/samples/sample_arm.c index bda2d0b0..ac25e598 100644 --- a/samples/sample_arm.c +++ b/samples/sample_arm.c @@ -6,29 +6,37 @@ #include #include - // code to be emulated // #define ARM_CODE "\x37\x00\xa0\xe3" // mov r0, #0x37 #define ARM_CODE "\x00\xf0\x20\xe3" // nop -// #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3 +// #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, +// r2, r3 #define THUMB_CODE "\x83\xb0" // sub sp, #0xc -#define ARM_THUM_COND_CODE "\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov r2, #0x4d' +#define ARM_THUM_COND_CODE \ + "\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov + // r2, #0x4d' // code to be emulated -#define ARM_CODE_EB "\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3 -#define THUMB_CODE_EB "\xb0\x83" // sub sp, #0xc +#define ARM_CODE_EB \ + "\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3 +#define THUMB_CODE_EB "\xb0\x83" // sub sp, #0xc // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_arm(void) @@ -37,18 +45,18 @@ static void test_arm(void) uc_err err; uc_hook trace1, trace2; - int r0 = 0x1234; // R0 register - int r2 = 0x6789; // R1 register - int r3 = 0x3333; // R2 register - int r1; // R1 register + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register printf("Emulate ARM code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -71,7 +79,7 @@ static void test_arm(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -93,15 +101,15 @@ static void test_thumb(void) uc_err err; uc_hook trace1, trace2; - int sp = 0x1234; // R0 register + int sp = 0x1234; // R0 register printf("Emulate THUMB code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -123,7 +131,7 @@ static void test_thumb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. // Note we start at ADDRESS | 1 to indicate THUMB mode. - err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -143,18 +151,18 @@ static void test_armeb(void) uc_err err; uc_hook trace1, trace2; - int r0 = 0x1234; // R0 register - int r2 = 0x6789; // R1 register - int r3 = 0x3333; // R2 register - int r1; // R1 register + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register printf("Emulate ARM Big-Endian code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -177,7 +185,7 @@ static void test_armeb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE_EB) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE_EB) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -199,15 +207,15 @@ static void test_thumbeb(void) uc_err err; uc_hook trace1, trace2; - int sp = 0x1234; // R0 register + int sp = 0x1234; // R0 register printf("Emulate THUMB Big-Endian code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -229,7 +237,8 @@ static void test_thumbeb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. // Note we start at ADDRESS | 1 to indicate THUMB mode. - err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE_EB) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE_EB) - 1, 0, + 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -257,8 +266,8 @@ static void test_thumb_mrs(void) // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -288,14 +297,15 @@ static void test_thumb_mrs(void) uc_reg_read(uc, UC_ARM_REG_PC, &pc); printf(">>> PC = 0x%x\n", pc); - if (pc != ADDRESS + 4){ + if (pc != ADDRESS + 4) { printf("Error, PC was 0x%x, expected was 0x%x.\n", pc, ADDRESS + 4); } uc_close(uc); } -static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_out) +static void test_thumb_ite_internal(bool step, uint32_t *r2_out, + uint32_t *r3_out) { uc_engine *uc; uc_err err; @@ -305,14 +315,15 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); - uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE, sizeof(ARM_THUM_COND_CODE) - 1); + uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE, + sizeof(ARM_THUM_COND_CODE) - 1); uc_reg_write(uc, UC_ARM_REG_SP, &sp); @@ -320,16 +331,19 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou uc_reg_write(uc, UC_ARM_REG_R3, &r3); if (!step) { - err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS | 1, + ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } } else { int i, addr = ADDRESS; for (i = 0; i < sizeof(ARM_THUM_COND_CODE) / 2; i++) { - err = uc_emu_start(uc, addr | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1); + err = uc_emu_start(uc, addr | 1, + ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1); if (err) { - printf("Failed on uc_emu_start() with error returned: %u\n", err); + printf("Failed on uc_emu_start() with error returned: %u\n", + err); } uc_reg_read(uc, UC_ARM_REG_PC, &addr); } @@ -344,13 +358,13 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou *r3_out = r3; } -static void test_thumb_ite() +static void test_thumb_ite() { uint32_t r2, r3; uint32_t step_r2, step_r3; printf("Emulate a THUMB ITE block as a whole or per instruction.\n"); - + // Run once. printf("Running the entire binary.\n"); test_thumb_ite_internal(false, &r2, &r3); diff --git a/samples/sample_arm64.c b/samples/sample_arm64.c index 74ea4e05..ba09b77a 100644 --- a/samples/sample_arm64.c +++ b/samples/sample_arm64.c @@ -6,48 +6,53 @@ #include #include - // code to be emulated -#define ARM64_CODE "\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13], #0 -//#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13]; ldrb w15, [x13] +#define ARM64_CODE \ + "\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13], + // #0 +//#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13]; +// ldrb w15, [x13] #define ARM64_CODE_EB ARM64_CODE // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_arm64_mem_fetch(void) { - uc_engine* uc; + uc_engine *uc; uc_err err; uint64_t x1, sp, x0; // msr x0, CurrentEL - unsigned char shellcode0[4] = { - 64, 66, 56, 213 - }; + unsigned char shellcode0[4] = {64, 66, 56, 213}; // .text:00000000004002C0 LDR X1, [SP,#arg_0] - unsigned char shellcode[4] = { - 0xE1, 0x03, 0x40, 0xF9 - }; + unsigned char shellcode[4] = {0xE1, 0x03, 0x40, 0xF9}; unsigned shellcode_address = 0x4002C0; uint64_t data_address = 0x10000000000000; - printf(">>> Emulate ARM64 fetching stack data from high address %"PRIx64"\n", data_address); + printf(">>> Emulate ARM64 fetching stack data from high address %" PRIx64 + "\n", + data_address); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -60,16 +65,16 @@ static void test_arm64_mem_fetch(void) uc_mem_write(uc, shellcode_address, shellcode0, 4); uc_mem_write(uc, shellcode_address + 4, shellcode, 4); - err = uc_emu_start(uc, shellcode_address, shellcode_address+4, 0, 0); + err = uc_emu_start(uc, shellcode_address, shellcode_address + 4, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } x0 = 0; uc_reg_read(uc, UC_ARM64_REG_X0, &x0); - printf(">>> x0(Exception Level)=%"PRIx64"\n", x0>>2); + printf(">>> x0(Exception Level)=%" PRIx64 "\n", x0 >> 2); - err = uc_emu_start(uc, shellcode_address+4, shellcode_address+8, 0, 0); + err = uc_emu_start(uc, shellcode_address + 4, shellcode_address + 8, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -87,17 +92,17 @@ static void test_arm64(void) uc_err err; uc_hook trace1, trace2; - int64_t x11 = 0x12345678; // X11 register - int64_t x13 = 0x10000 + 0x8; // X13 register - int64_t x15 = 0x33; // X15 register + int64_t x11 = 0x12345678; // X11 register + int64_t x13 = 0x10000 + 0x8; // X13 register + int64_t x15 = 0x33; // X15 register printf("Emulate ARM64 code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -120,7 +125,7 @@ static void test_arm64(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -141,17 +146,17 @@ static void test_arm64eb(void) uc_err err; uc_hook trace1, trace2; - int64_t x11 = 0x12345678; // X11 register - int64_t x13 = 0x10000 + 0x8; // X13 register - int64_t x15 = 0x33; // X15 register + int64_t x11 = 0x12345678; // X11 register + int64_t x13 = 0x10000 + 0x8; // X13 register + int64_t x15 = 0x33; // X15 register printf("Emulate ARM64 Big-Endian code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -174,7 +179,7 @@ static void test_arm64eb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE_EB) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE_EB) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -190,7 +195,7 @@ static void test_arm64eb(void) } int main(int argc, char **argv, char **envp) -{ +{ test_arm64_mem_fetch(); test_arm64(); diff --git a/samples/sample_batch_reg.c b/samples/sample_batch_reg.c index b1b51b6d..8b5736f4 100644 --- a/samples/sample_batch_reg.c +++ b/samples/sample_batch_reg.c @@ -2,17 +2,15 @@ #include #include +int syscall_abi[] = {UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI, + UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, + UC_X86_REG_R9}; -int syscall_abi[] = { - UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, - UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9 -}; +uint64_t vals[7] = {200, 10, 11, 12, 13, 14, 15}; -uint64_t vals[7] = { 200, 10, 11, 12, 13, 14, 15 }; - -// This part of the API is less... clean... because Unicorn supports arbitrary register types. -// So the least intrusive solution is passing individual pointers. -// On the plus side, you only need to make this pointer array once. +// This part of the API is less... clean... because Unicorn supports arbitrary +// register types. So the least intrusive solution is passing individual +// pointers. On the plus side, you only need to make this pointer array once. void *ptrs[7]; void uc_perror(const char *func, uc_err err) @@ -22,8 +20,12 @@ void uc_perror(const char *func, uc_err err) #define BASE 0x10000 -// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov r9, 6; syscall -#define CODE "\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05" +// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov +// r9, 6; syscall +#define CODE \ + "\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02" \ + "\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49" \ + "\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05" void hook_syscall(uc_engine *uc, void *user_data) { @@ -34,7 +36,8 @@ void hook_syscall(uc_engine *uc, void *user_data) printf("syscall: {"); for (i = 0; i < 7; i++) { - if (i != 0) printf(", "); + if (i != 0) + printf(", "); printf("%" PRIu64, vals[i]); } @@ -80,7 +83,8 @@ int main() printf("reg_read_batch = {"); for (i = 0; i < 7; i++) { - if (i != 0) printf(", "); + if (i != 0) + printf(", "); printf("%" PRIu64, vals[i]); } @@ -90,7 +94,8 @@ int main() printf("\n"); printf("running syscall shellcode\n"); - if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL))) { + if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1, + 0, UC_X86_INS_SYSCALL))) { uc_perror("uc_hook_add", err); return 1; } diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c new file mode 100644 index 00000000..3e63c4f6 --- /dev/null +++ b/samples/sample_ctl.c @@ -0,0 +1,286 @@ +/* Unicorn Emulator Engine */ +/* By Lazymio(@wtdcode), 2021 */ + +/* Sample code to demonstrate how to use uc_ctl */ + +#include +#include +#include + +// code to be emulated + +// INC ecx; DEC edx; PXOR xmm0, xmm1 +#define X86_CODE32 "\x41\x4a" +// cmp eax, 0; +// jg lb; +// inc eax; +// nop; +// lb: +// inc ebx; +// nop; +#define X86_JUMP_CODE "\x83\xf8\x00\x7f\x02\x40\x90\x43\x90" + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void test_uc_ctl_read(void) +{ + uc_engine *uc; + uc_err err; + int mode, arch; + uint32_t pagesize; + uint64_t timeout; + + printf("Reading some properties by uc_ctl.\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // Let's query some properties by uc_ctl. + // Note uc_ctl_* is just tiny macro wrappers for uc_ctl(). + err = uc_ctl_get_mode(uc, &mode); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_get_arch(uc, &arch); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_get_timeout(uc, &timeout); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_get_page_size(uc, &pagesize); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + printf(">>> mode = %d, arch = %d, timeout=%" PRIu64 ", pagesize=%" PRIu32 + "\n", + mode, arch, timeout, pagesize); + + uc_close(uc); +} + +static void trace_new_edge(uc_engine *uc, uc_tb *cur, uc_tb *prev, void *data) +{ + printf(">>> Getting a new edge from 0x%" PRIx64 " to 0x%" PRIx64 ".\n", + prev->pc + prev->size - 1, cur->pc); +} + +void test_uc_ctl_exits() +{ + uc_engine *uc; + uc_err err; + uc_hook h; + int r_eax, r_ebx; + uint64_t exits[] = {ADDRESS + 6, ADDRESS + 8}; + + printf("Using multiple exits by uc_ctl.\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + err = uc_mem_map(uc, ADDRESS, 0x1000, UC_PROT_ALL); + if (err) { + printf("Failed on uc_mem_map() with error returned: %u\n", err); + return; + } + + // Write our code to the memory. + err = uc_mem_write(uc, ADDRESS, X86_JUMP_CODE, sizeof(X86_JUMP_CODE) - 1); + if (err) { + printf("Failed on uc_mem_write() with error returned: %u\n", err); + return; + } + + // We trace if any new edge is generated. + err = uc_hook_add(uc, &h, UC_HOOK_EDGE_GENERATED, trace_new_edge, NULL, 0, + -1); + if (err) { + printf("Failed on uc_hook_add() with error returned: %u\n", err); + return; + } + + // Enable multiple exits. + err = uc_ctl_exits_enabled(uc, true); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_set_exists(uc, exits, 2); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + // This should stop at ADDRESS + 6 and increase eax, even thouhg we don't + // provide an exit. + err = uc_emu_start(uc, ADDRESS, 0, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + return; + } + + err = uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + err = uc_reg_read(uc, UC_X86_REG_EBX, &r_ebx); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + printf(">>> eax = %" PRId32 " and ebx = %" PRId32 + " after the first emulation\n", + r_eax, r_ebx); + + // This should stop at ADDRESS + 8, even thouhg we don't provide an exit. + err = uc_emu_start(uc, ADDRESS, 0, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + return; + } + + err = uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + err = uc_reg_read(uc, UC_X86_REG_EBX, &r_ebx); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + printf(">>> eax = %" PRId32 " and ebx = %" PRId32 + " after the second emulation\n", + r_eax, r_ebx); + + uc_close(uc); +} + +#define TB_COUNT (8) +#define TCG_MAX_INSNS (512) // from tcg.h +#define CODE_LEN TB_COUNT *TCG_MAX_INSNS + +double time_emulation(uc_engine *uc, uint64_t start, uint64_t end) +{ + time_t t1, t2; + + t1 = clock(); + + uc_emu_start(uc, start, end, 0, 0); + + t2 = clock(); + + return (t2 - t1) * 1000.0 / CLOCKS_PER_SEC; +} + +static void test_uc_ctl_tb_cache() +{ + uc_engine *uc; + uc_err err; + uc_tb tb; + uc_hook h; + char code[CODE_LEN]; + double standard, cached, evicted; + + printf("Controling the TB cache in a finer granularity by uc_ctl.\n"); + + // Fill the code buffer with NOP. + memset(code, 0x90, CODE_LEN); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + err = uc_mem_map(uc, ADDRESS, 0x10000, UC_PROT_ALL); + if (err) { + printf("Failed on uc_mem_map() with error returned: %u\n", err); + return; + } + + // Write our code to the memory. + err = uc_mem_write(uc, ADDRESS, code, sizeof(code) - 1); + if (err) { + printf("Failed on uc_mem_write() with error returned: %u\n", err); + return; + } + + // We trace if any new edge is generated. + // Note: In this sample, there is only **one** basic block while muliple + // translation blocks is generated due to QEMU tcg buffer limit. In this + // case, we don't consider it as a new edge. + err = uc_hook_add(uc, &h, UC_HOOK_EDGE_GENERATED, trace_new_edge, NULL, 0, + -1); + if (err) { + printf("Failed on uc_hook_add() with error returned: %u\n", err); + return; + } + + // Do emulation without any cache. + standard = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1); + + // Now we request cache for all TBs. + for (int i = 0; i < TB_COUNT; i++) { + err = uc_ctl_request_cache(uc, ADDRESS + i * TCG_MAX_INSNS, &tb); + printf(">>> TB is cached at 0x%" PRIx64 " which has %" PRIu16 + " instructions with %" PRIu16 " bytes.\n", + tb.pc, tb.icount, tb.size); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + } + + // Do emulation with all TB cached. + cached = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1); + + // Now we clear cache for all TBs. + for (int i = 0; i < TB_COUNT; i++) { + err = uc_ctl_remove_cache(uc, ADDRESS + i * TCG_MAX_INSNS); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + } + + // Do emulation with all TB cache evicted. + evicted = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1); + + printf(">>> Run time: First time: %f, Cached: %f, Cache evicted: %f\n", + standard, cached, evicted); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + test_uc_ctl_read(); + printf("====================\n"); + test_uc_ctl_exits(); + printf("====================\n"); + test_uc_ctl_tb_cache(); + + return 0; +} diff --git a/samples/sample_m68k.c b/samples/sample_m68k.c index 49e47e5b..ed58f9fe 100644 --- a/samples/sample_m68k.c +++ b/samples/sample_m68k.c @@ -6,21 +6,25 @@ #include #include - // code to be emulated #define M68K_CODE "\x76\xed" // movq #-19, %d3 // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_m68k(void) @@ -29,34 +33,34 @@ static void test_m68k(void) uc_hook trace1, trace2; uc_err err; - int d0 = 0x0000; // d0 data register - int d1 = 0x0000; // d1 data register - int d2 = 0x0000; // d2 data register - int d3 = 0x0000; // d3 data register - int d4 = 0x0000; // d4 data register - int d5 = 0x0000; // d5 data register - int d6 = 0x0000; // d6 data register - int d7 = 0x0000; // d7 data register + int d0 = 0x0000; // d0 data register + int d1 = 0x0000; // d1 data register + int d2 = 0x0000; // d2 data register + int d3 = 0x0000; // d3 data register + int d4 = 0x0000; // d4 data register + int d5 = 0x0000; // d5 data register + int d6 = 0x0000; // d6 data register + int d7 = 0x0000; // d7 data register - int a0 = 0x0000; // a0 address register - int a1 = 0x0000; // a1 address register - int a2 = 0x0000; // a2 address register - int a3 = 0x0000; // a3 address register - int a4 = 0x0000; // a4 address register - int a5 = 0x0000; // a5 address register - int a6 = 0x0000; // a6 address register - int a7 = 0x0000; // a6 address register + int a0 = 0x0000; // a0 address register + int a1 = 0x0000; // a1 address register + int a2 = 0x0000; // a2 address register + int a3 = 0x0000; // a3 address register + int a4 = 0x0000; // a4 address register + int a5 = 0x0000; // a5 address register + int a6 = 0x0000; // a6 address register + int a7 = 0x0000; // a6 address register - int pc = 0x0000; // program counter - int sr = 0x0000; // status register + int pc = 0x0000; // program counter + int sr = 0x0000; // status register printf("Emulate M68K code\n"); // Initialize emulator in M68K mode err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -96,7 +100,7 @@ static void test_m68k(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } diff --git a/samples/sample_mips.c b/samples/sample_mips.c index ef26af11..3bcafafd 100644 --- a/samples/sample_mips.c +++ b/samples/sample_mips.c @@ -6,7 +6,6 @@ #include #include - // code to be emulated #define MIPS_CODE_EB "\x34\x21\x34\x56" // ori $at, $at, 0x3456; #define MIPS_CODE_EL "\x56\x34\x21\x34" // ori $at, $at, 0x3456; @@ -14,14 +13,19 @@ // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_mips_eb(void) @@ -30,15 +34,15 @@ static void test_mips_eb(void) uc_err err; uc_hook trace1, trace2; - int r1 = 0x6789; // R1 register + int r1 = 0x6789; // R1 register printf("Emulate MIPS code (big-endian)\n"); // Initialize emulator in MIPS mode err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -61,7 +65,8 @@ static void test_mips_eb(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, + uc_strerror(err)); } // now print out some registers @@ -79,7 +84,7 @@ static void test_mips_el(void) uc_err err; uc_hook trace1, trace2; - int r1 = 0x6789; // R1 register + int r1 = 0x6789; // R1 register printf("===========================\n"); printf("Emulate MIPS code (little-endian)\n"); @@ -87,8 +92,8 @@ static void test_mips_el(void) // Initialize emulator in MIPS mode err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -111,7 +116,8 @@ static void test_mips_el(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, + uc_strerror(err)); } // now print out some registers diff --git a/samples/sample_ppc.c b/samples/sample_ppc.c index 12dbbd3f..cd09ae5e 100644 --- a/samples/sample_ppc.c +++ b/samples/sample_ppc.c @@ -6,22 +6,25 @@ #include #include - // code to be emulated #define PPC_CODE "\x7F\x46\x1A\x14" // add r26, r6, r3 // memory address where emulation starts #define ADDRESS 0x10000 - -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_ppc(void) @@ -30,17 +33,17 @@ static void test_ppc(void) uc_err err; uc_hook trace1, trace2; - int r3 = 0x1234; // R3 register - int r6 = 0x6789; // R6 register - int r26 = 0x8877; // R26 register (result) + int r3 = 0x1234; // R3 register + int r6 = 0x6789; // R6 register + int r26 = 0x8877; // R26 register (result) printf("Emulate PPC code\n"); // Initialize emulator in PPC mode - err = uc_open(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN , &uc); + err = uc_open(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -63,7 +66,7 @@ static void test_ppc(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(PPC_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(PPC_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); return; @@ -79,7 +82,6 @@ static void test_ppc(void) uc_close(uc); } - int main(int argc, char **argv, char **envp) { test_ppc(); diff --git a/samples/sample_riscv.c b/samples/sample_riscv.c index 73bdf98d..6e36f53a 100644 --- a/samples/sample_riscv.c +++ b/samples/sample_riscv.c @@ -5,7 +5,6 @@ #include #include - // code to be emulated #if 0 $ cstool riscv64 1305100093850502 @@ -15,23 +14,30 @@ $ cstool riscv64 1305100093850502 //#define RISCV_CODE "\x13\x05\x10\x00\x93\x85\x05\x02\x93\x85\x05\x02" #define RISCV_CODE "\x13\x05\x10\x00\x93\x85\x05\x02" - // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } -static void hook_code3(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code3(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); if (address == ADDRESS) { printf("stop emulation\n"); uc_emu_stop(uc); @@ -52,8 +58,8 @@ static void test_riscv(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -106,8 +112,8 @@ static void test_riscv2(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -171,8 +177,8 @@ static void test_riscv3(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -226,8 +232,8 @@ static void test_riscv_step(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -297,8 +303,8 @@ static void test_riscv_timeout(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -365,8 +371,8 @@ static void test_riscv_sd64(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -401,13 +407,14 @@ static void test_riscv_sd64(void) } static bool hook_memalloc(uc_engine *uc, uc_mem_type type, uint64_t address, - int size, int64_t value, void *user_data) + int size, int64_t value, void *user_data) { uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL; int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000; - printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 "), block size = 0x%x (0x%x)\n", - address, algined_address, size, aligned_size); + printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 + "), block size = 0x%x (0x%x)\n", + address, algined_address, size, aligned_size); uc_mem_map(uc, algined_address, aligned_size, UC_PROT_ALL); @@ -439,7 +446,8 @@ static void test_recover_from_illegal(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // auto-allocate memory on access - uc_hook_add(uc, &mem_alloc, UC_HOOK_MEM_UNMAPPED, hook_memalloc, NULL, 1, 0); + uc_hook_add(uc, &mem_alloc, UC_HOOK_MEM_UNMAPPED, hook_memalloc, NULL, 1, + 0); // tracing all basic blocks with customized callback uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); @@ -469,8 +477,8 @@ static void test_recover_from_illegal(void) uc_reg_read(uc, UC_RISCV_REG_A0, &a0); uc_reg_read(uc, UC_RISCV_REG_A1, &a1); - printf(">>> A0 = 0x%"PRIx64 "\n", a0); - printf(">>> A1 = 0x%"PRIx64 "\n", a1); + printf(">>> A0 = 0x%" PRIx64 "\n", a0); + printf(">>> A1 = 0x%" PRIx64 "\n", a1); uc_close(uc); } @@ -495,8 +503,8 @@ static void test_riscv_func_return(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -527,7 +535,9 @@ static void test_riscv_func_return(void) uc_reg_read(uc, UC_RISCV_REG_PC, &pc); if (pc != ra) { - printf("Error after execution: PC is: 0x%"PRIx64 ", expected was 0x%"PRIx64 "\n", pc, ra); + printf("Error after execution: PC is: 0x%" PRIx64 + ", expected was 0x%" PRIx64 "\n", + pc, ra); if (pc == 0x10000) { printf(" PC did not change during execution\n"); } @@ -551,7 +561,9 @@ static void test_riscv_func_return(void) uc_reg_read(uc, UC_RISCV_REG_PC, &pc); if (pc != ra) { - printf("Error after execution: PC is: 0x%"PRIx64 ", expected was 0x%"PRIx64 "\n", pc, ra); + printf("Error after execution: PC is: 0x%" PRIx64 + ", expected was 0x%" PRIx64 "\n", + pc, ra); if (pc == 0x10004) { printf(" PC did not change during execution\n"); } diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 04c2a359..f7609282 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -6,7 +6,6 @@ #include #include - // code to be emulated #define SPARC_CODE "\x86\x00\x40\x02" // add %g1, %g2, %g3; //#define SPARC_CODE "\xbb\x70\x00\x00" // illegal code @@ -14,14 +13,19 @@ // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_sparc(void) @@ -30,17 +34,17 @@ static void test_sparc(void) uc_err err; uc_hook trace1, trace2; - int g1 = 0x1230; // G1 register - int g2 = 0x6789; // G2 register - int g3 = 0x5555; // G3 register + int g1 = 0x1230; // G1 register + int g2 = 0x6789; // G2 register + int g3 = 0x5555; // G3 register printf("Emulate SPARC code\n"); // Initialize emulator in Sparc mode - err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN, &uc); + err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32 | UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -65,8 +69,8 @@ static void test_sparc(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, + uc_strerror(err)); } // now print out some registers diff --git a/samples/sample_x86.c b/samples/sample_x86.c index 6732e076..3b9d280f 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -6,27 +6,45 @@ #include #include - // code to be emulated -#define X86_CODE32 "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1 -#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop -// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41" +#define X86_CODE32 \ + "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1 +#define X86_CODE32_JUMP \ + "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop +// #define X86_CODE32_SELF +// "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41" //#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx; #define X86_CODE32_LOOP "\x41\x4a\xeb\xfe" // INC ecx; DEC edx; JMP self-loop -#define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx -#define X86_CODE32_MEM_READ "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx -#define X86_CODE32_MEM_READ_IN_TB "\x40\x8b\x1d\x00\x00\x10\x00\x42" // inc eax; mov ebx, [0x100000]; inc edx +#define X86_CODE32_MEM_WRITE \ + "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC + // edx +#define X86_CODE32_MEM_READ \ + "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx +#define X86_CODE32_MEM_READ_IN_TB \ + "\x40\x8b\x1d\x00\x00\x10\x00\x42" // inc eax; mov ebx, [0x100000]; inc edx -#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx -#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx -#define X86_CODE32_INC "\x40" // INC eax +#define X86_CODE32_JMP_INVALID \ + "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx +#define X86_CODE32_INOUT \ + "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, + // AL; INC ebx +#define X86_CODE32_INC "\x40" // INC eax -//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash -//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" -#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" -#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al +//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 +//\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // +//<== still crash #define X86_CODE64 +//"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" +#define X86_CODE64 \ + "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90" \ + "\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A" \ + "\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5" \ + "\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E" \ + "\x09\x3C\x59" +#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al #define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL -#define X86_MMIO_CODE "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" // mov [0x20004], ecx; mov ecx, [0x20004] +#define X86_MMIO_CODE \ + "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" // mov [0x20004], ecx; + // mov ecx, [0x20004] /* * 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6 * 0x1003 dw 0x3ea98b13 @@ -37,16 +55,21 @@ #define ADDRESS 0x1000000 // callback for tracing basic blocks -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } // callback for tracing instruction -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { int eflags; - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); printf(">>> --- EFLAGS is 0x%x\n", eflags); @@ -57,13 +80,16 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user } // callback for tracing instruction -static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { uint64_t rip; uc_reg_read(uc, UC_X86_REG_RIP, &rip); - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); - printf(">>> RIP is 0x%"PRIx64 "\n", rip); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); + printf(">>> RIP is 0x%" PRIx64 "\n", rip); // Uncomment below code to stop the emulation using uc_emu_stop() // if (address == 0x1000009) @@ -71,44 +97,48 @@ static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *us } // callback for tracing memory access (READ or WRITE) -static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data) +static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void *user_data) { - switch(type) { - default: - // return false to indicate we want to stop emulation - return false; - case UC_MEM_WRITE_UNMAPPED: - printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", - address, size, value); - // map this memory in with 2MB in size - uc_mem_map(uc, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL); - // return true to indicate we want to continue - return true; + switch (type) { + default: + // return false to indicate we want to stop emulation + return false; + case UC_MEM_WRITE_UNMAPPED: + printf(">>> Missing memory is being WRITE at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + address, size, value); + // map this memory in with 2MB in size + uc_mem_map(uc, 0xaaaa0000, 2 * 1024 * 1024, UC_PROT_ALL); + // return true to indicate we want to continue + return true; } } // dummy callback static bool hook_mem_invalid_dummy(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data) + uint64_t address, int size, int64_t value, + void *user_data) { // stop emulation return false; } -static void hook_mem64(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data) +static void hook_mem64(uc_engine *uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void *user_data) { - switch(type) { - default: break; - case UC_MEM_READ: - printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n", - address, size); - break; - case UC_MEM_WRITE: - printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", - address, size, value); - break; + switch (type) { + default: + break; + case UC_MEM_READ: + printf(">>> Memory is being READ at 0x%" PRIx64 ", data size = %u\n", + address, size); + break; + case UC_MEM_WRITE: + printf(">>> Memory is being WRITE at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + address, size, value); + break; } } @@ -120,47 +150,50 @@ static uint32_t hook_in(uc_engine *uc, uint32_t port, int size, void *user_data) uc_reg_read(uc, UC_X86_REG_EIP, &eip); - printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size, eip); + printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size, + eip); - switch(size) { - default: - return 0; // should never reach this - case 1: - // read 1 byte to AL - return 0xf1; - case 2: - // read 2 byte to AX - return 0xf2; - break; - case 4: - // read 4 byte to EAX - return 0xf4; + switch (size) { + default: + return 0; // should never reach this + case 1: + // read 1 byte to AL + return 0xf1; + case 2: + // read 2 byte to AX + return 0xf2; + break; + case 4: + // read 4 byte to EAX + return 0xf4; } } // callback for OUT instruction (X86). -static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data) +static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, + void *user_data) { uint32_t tmp = 0; uint32_t eip; uc_reg_read(uc, UC_X86_REG_EIP, &eip); - printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n", port, size, value, eip); + printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n", + port, size, value, eip); // confirm that value is indeed the value of AL/AX/EAX - switch(size) { - default: - return; // should never reach this - case 1: - uc_reg_read(uc, UC_X86_REG_AL, &tmp); - break; - case 2: - uc_reg_read(uc, UC_X86_REG_AX, &tmp); - break; - case 4: - uc_reg_read(uc, UC_X86_REG_EAX, &tmp); - break; + switch (size) { + default: + return; // should never reach this + case 1: + uc_reg_read(uc, UC_X86_REG_AL, &tmp); + break; + case 2: + uc_reg_read(uc, UC_X86_REG_AX, &tmp); + break; + case 4: + uc_reg_read(uc, UC_X86_REG_EAX, &tmp); + break; } printf("--- register value = 0x%x\n", tmp); @@ -176,17 +209,18 @@ static void hook_syscall(uc_engine *uc, void *user_data) rax = 0x200; uc_reg_write(uc, UC_X86_REG_RAX, &rax); } else - printf("ERROR: was not expecting rax=0x%"PRIx64 " in syscall\n", rax); + printf("ERROR: was not expecting rax=0x%" PRIx64 " in syscall\n", rax); } static bool hook_memalloc(uc_engine *uc, uc_mem_type type, uint64_t address, - int size, int64_t value, void *user_data) + int size, int64_t value, void *user_data) { uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL; int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000; - printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 "), block size = 0x%x (0x%x)\n", - address, algined_address, size, aligned_size); + printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 + "), block size = 0x%x (0x%x)\n", + address, algined_address, size, aligned_size); uc_mem_map(uc, algined_address, aligned_size, UC_PROT_ALL); @@ -206,8 +240,8 @@ static void test_miss_code(void) uc_err err; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("Emulate i386 code - missing code\n"); @@ -231,8 +265,8 @@ static void test_miss_code(void) // emulate machine code, without having the code in yet err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -253,8 +287,8 @@ static void test_i386(void) uint32_t tmp; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register // XMM0 and XMM1 registers, low qword then high qword uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607}; uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070}; @@ -292,8 +326,8 @@ static void test_i386(void) // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -304,7 +338,7 @@ static void test_i386(void) uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0); printf(">>> ECX = 0x%x\n", r_ecx); printf(">>> EDX = 0x%x\n", r_edx); - printf(">>> XMM0 = 0x%.16"PRIx64"%.16"PRIx64"\n", r_xmm0[1], r_xmm0[0]); + printf(">>> XMM0 = 0x%.16" PRIx64 "%.16" PRIx64 "\n", r_xmm0[1], r_xmm0[0]); // read from memory if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp))) @@ -323,8 +357,8 @@ static void test_i386_map_ptr(void) uc_hook trace1, trace2; void *mem; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code - use uc_mem_map_ptr()\n"); @@ -364,8 +398,8 @@ static void test_i386_map_ptr(void) // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -407,7 +441,7 @@ static void test_i386_jump(void) // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, X86_CODE32_JUMP, - sizeof(X86_CODE32_JUMP) - 1)) { + sizeof(X86_CODE32_JUMP) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -419,10 +453,11 @@ static void test_i386_jump(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0); + err = + uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } printf(">>> Emulation done. Below is the CPU context\n"); @@ -436,8 +471,8 @@ static void test_i386_loop(void) uc_engine *uc; uc_err err; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that loop forever\n"); @@ -453,7 +488,8 @@ static void test_i386_loop(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_LOOP, + sizeof(X86_CODE32_LOOP) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -464,10 +500,11 @@ static void test_i386_loop(void) // emulate machine code in 2 seconds, so we can quit even // if the code loops - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, 2 * UC_SECOND_SCALE, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, + 2 * UC_SECOND_SCALE, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -488,8 +525,8 @@ static void test_i386_invalid_mem_read(void) uc_err err; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that read from invalid memory\n"); @@ -505,7 +542,8 @@ static void test_i386_invalid_mem_read(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ, sizeof(X86_CODE32_MEM_READ) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ, + sizeof(X86_CODE32_MEM_READ) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -521,10 +559,11 @@ static void test_i386_invalid_mem_read(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, + 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -546,8 +585,8 @@ static void test_i386_invalid_mem_write(void) uc_hook trace1, trace2, trace3; uint32_t tmp; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that write to invalid memory\n"); @@ -563,7 +602,8 @@ static void test_i386_invalid_mem_write(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE, + sizeof(X86_CODE32_MEM_WRITE) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -579,13 +619,16 @@ static void test_i386_invalid_mem_write(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // intercept invalid memory events - uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL, 1, 0); + uc_hook_add(uc, &trace3, + UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, + hook_mem_invalid, NULL, 1, 0); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, + 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -617,8 +660,8 @@ static void test_i386_jump_invalid(void) uc_err err; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that jumps to invalid memory\n"); @@ -634,7 +677,8 @@ static void test_i386_jump_invalid(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_JMP_INVALID, sizeof(X86_CODE32_JMP_INVALID) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_JMP_INVALID, + sizeof(X86_CODE32_JMP_INVALID) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -650,10 +694,11 @@ static void test_i386_jump_invalid(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, + ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -673,9 +718,8 @@ static void test_i386_inout(void) uc_err err; uc_hook trace1, trace2, trace3, trace4; - - int r_eax = 0x1234; // EAX register - int r_ecx = 0x6789; // ECX register + int r_eax = 0x1234; // EAX register + int r_ecx = 0x6789; // ECX register printf("===================================\n"); printf("Emulate i386 code with IN/OUT instructions\n"); @@ -691,7 +735,8 @@ static void test_i386_inout(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_INOUT, + sizeof(X86_CODE32_INOUT) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -709,13 +754,15 @@ static void test_i386_inout(void) // uc IN instruction uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, 1, 0, UC_X86_INS_IN); // uc OUT instruction - uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, UC_X86_INS_OUT); + uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, + UC_X86_INS_OUT); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0); + err = + uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -736,7 +783,7 @@ static void test_i386_context_save(void) uc_context *context; uc_err err; - int r_eax = 0x1; // EAX register + int r_eax = 0x1; // EAX register printf("===================================\n"); printf("Save/restore CPU context in opaque blob\n"); @@ -765,8 +812,8 @@ static void test_i386_context_save(void) err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -795,8 +842,8 @@ static void test_i386_context_save(void) err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -830,7 +877,8 @@ static void test_i386_context_save(void) } // now print out some registers - printf(">>> CPU context restored with modification. Below is the CPU context\n"); + printf(">>> CPU context restored with modification. Below is the CPU " + "context\n"); uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); printf(">>> EAX = 0x%x\n", r_eax); @@ -928,7 +976,6 @@ static void test_x86_64(void) int64_t rsp = ADDRESS + 0x200000; - printf("Emulate x86_64 code\n"); // Initialize emulator in X86-64bit mode @@ -969,7 +1016,8 @@ static void test_x86_64(void) uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instructions in the range [ADDRESS, ADDRESS+20] - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS, ADDRESS+20); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS, + ADDRESS + 20); // tracing all memory WRITE access (with @begin > @end) uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, 1, 0); @@ -981,8 +1029,8 @@ static void test_x86_64(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -1043,23 +1091,26 @@ static void test_x86_64_syscall(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE64_SYSCALL, sizeof(X86_CODE64_SYSCALL) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE64_SYSCALL, + sizeof(X86_CODE64_SYSCALL) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } // hook interrupts for syscall - uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL); + uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, + UC_X86_INS_SYSCALL); // initialize machine registers uc_reg_write(uc, UC_X86_REG_RAX, &rax); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, + 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -1109,8 +1160,8 @@ static void test_x86_16(void) // finishing all the code. err = uc_emu_start(uc, 0, sizeof(X86_CODE16) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -1131,12 +1182,13 @@ static void test_i386_invalid_mem_read_in_tb(void) uc_err err; uc_hook trace1; - int r_eax = 0x1234; // EAX register - int r_edx = 0x7890; // EDX register + int r_eax = 0x1234; // EAX register + int r_edx = 0x7890; // EDX register int r_eip = 0; printf("===================================\n"); - printf("Emulate i386 code that read invalid memory in the middle of a TB\n"); + printf( + "Emulate i386 code that read invalid memory in the middle of a TB\n"); // Initialize emulator in X86-32bit mode err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); @@ -1149,7 +1201,8 @@ static void test_i386_invalid_mem_read_in_tb(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ_IN_TB, sizeof(X86_CODE32_MEM_READ_IN_TB) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ_IN_TB, + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -1159,13 +1212,15 @@ static void test_i386_invalid_mem_read_in_tb(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // Add a dummy callback. - uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ, hook_mem_invalid_dummy, NULL, 1, 0); - + uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ, hook_mem_invalid_dummy, NULL, 1, + 0); + // Let it crash by design. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, + ADDRESS + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1, 0, 0); if (err) { printf("uc_emu_start() failed BY DESIGN with error returned %u: %s\n", - err, uc_strerror(err)); + err, uc_strerror(err)); } printf(">>> Emulation done. Below is the CPU context\n"); @@ -1174,21 +1229,24 @@ static void test_i386_invalid_mem_read_in_tb(void) printf(">>> EIP = 0x%x\n", r_eip); if (r_eip != ADDRESS + 1) { - printf(">>> ERROR: Wrong PC 0x%x when reading unmapped memory in the middle of TB!\n", r_eip); + printf(">>> ERROR: Wrong PC 0x%x when reading unmapped memory in the " + "middle of TB!\n", + r_eip); } else { - printf(">>> The PC is correct after reading unmapped memory in the middle of TB.\n"); + printf(">>> The PC is correct after reading unmapped memory in the " + "middle of TB.\n"); } uc_close(uc); } -static void test_i386_smc_xor() +static void test_i386_smc_xor() { uc_engine *uc; uc_err err; - uint32_t r_edi = ADDRESS; // ECX register - uint32_t r_eax = 0xbc4177e6; // EDX register + uint32_t r_edi = ADDRESS; // ECX register + uint32_t r_eax = 0xbc4177e6; // EDX register uint32_t result; printf("===================================\n"); @@ -1216,15 +1274,15 @@ static void test_i386_smc_xor() // **Important Note** // - // Since SMC code will cause TB regeneration, the XOR in fact would executed - // twice (the first execution won't take effect.). Thus, if you would like to - // use count to control the emulation, the count should be set to 2. + // Since SMC code will cause TB regeneration, the XOR in fact would executed + // twice (the first execution won't take effect.). Thus, if you would like + // to use count to control the emulation, the count should be set to 2. // // err = uc_emu_start(uc, ADDRESS, ADDRESS + 3, 0, 0); err = uc_emu_start(uc, ADDRESS, 0, 0, 2); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } printf(">>> Emulation done. Below is the result.\n"); @@ -1232,30 +1290,38 @@ static void test_i386_smc_xor() uc_mem_read(uc, ADDRESS + 3, (void *)&result, 4); if (result == (0x3ea98b13 ^ 0xbc4177e6)) { - printf(">>> SMC emulation is correct. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", result); + printf(">>> SMC emulation is correct. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", + result); } else { - printf(">>> SMC emulation is wrong. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", result); + printf(">>> SMC emulation is wrong. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", + result); } uc_close(uc); } -static uint64_t mmio_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) +static uint64_t mmio_read_callback(uc_engine *uc, uint64_t offset, + unsigned size, void *user_data) { - printf(">>> Read IO memory at offset 0x%"PRIu64" with 0x%"PRIu32" bytes and return 0x19260817\n", offset, size); + printf(">>> Read IO memory at offset 0x%" PRIu64 " with 0x%" PRIu32 + " bytes and return 0x19260817\n", + offset, size); // The value returned here would be written to ecx. return 0x19260817; } -static void mmio_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) +static void mmio_write_callback(uc_engine *uc, uint64_t offset, unsigned size, + uint64_t value, void *user_data) { - printf(">>> Write value 0x%"PRIu64" to IO memory at offset 0x%"PRIu64" with 0x%"PRIu32" bytes\n", value, offset, size); + printf(">>> Write value 0x%" PRIu64 " to IO memory at offset 0x%" PRIu64 + " with 0x%" PRIu32 " bytes\n", + value, offset, size); return; } static void test_i386_mmio() { - uc_engine* uc; + uc_engine *uc; int r_ecx = 0xdeadbeef; uc_err err; @@ -1283,7 +1349,8 @@ static void test_i386_mmio() return; } - err = uc_mmio_map(uc, 0x20000, 0x4000, mmio_read_callback, NULL, mmio_write_callback, NULL); + err = uc_mmio_map(uc, 0x20000, 0x4000, mmio_read_callback, NULL, + mmio_write_callback, NULL); if (err) { printf("Failed on uc_mmio_map() with error returned: %u\n", err); return; @@ -1314,8 +1381,7 @@ int main(int argc, char **argv, char **envp) if (argc == 2) { if (!strcmp(argv[1], "-16")) { test_x86_16(); - } - else if (!strcmp(argv[1], "-32")) { + } else if (!strcmp(argv[1], "-32")) { test_miss_code(); test_i386(); test_i386_map_ptr(); @@ -1326,17 +1392,14 @@ int main(int argc, char **argv, char **envp) test_i386_invalid_mem_read(); test_i386_invalid_mem_write(); test_i386_jump_invalid(); - //test_i386_invalid_c6c7(); - } - else if (!strcmp(argv[1], "-64")) { + // test_i386_invalid_c6c7(); + } else if (!strcmp(argv[1], "-64")) { test_x86_64(); test_x86_64_syscall(); - } - else if (!strcmp(argv[1], "-h")) { + } else if (!strcmp(argv[1], "-h")) { printf("Syntax: %s <-16|-32|-64>\n", argv[0]); } - } - else { + } else { test_x86_16(); test_miss_code(); test_i386(); @@ -1348,7 +1411,7 @@ int main(int argc, char **argv, char **envp) test_i386_invalid_mem_read(); test_i386_invalid_mem_write(); test_i386_jump_invalid(); - //test_i386_invalid_c6c7(); + // test_i386_invalid_c6c7(); test_x86_64(); test_x86_64_syscall(); test_i386_invalid_mem_read_in_tb(); diff --git a/samples/sample_x86_32_gdt_and_seg_regs.c b/samples/sample_x86_32_gdt_and_seg_regs.c index e6023f8e..1ffd8892 100644 --- a/samples/sample_x86_32_gdt_and_seg_regs.c +++ b/samples/sample_x86_32_gdt_and_seg_regs.c @@ -26,62 +26,64 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #pragma pack(push, 1) struct SegmentDescriptor { - union { - struct { + union { + struct { #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned short limit0; - unsigned short base0; - unsigned char base1; - unsigned char type:4; - unsigned char system:1; /* S flag */ - unsigned char dpl:2; - unsigned char present:1; /* P flag */ - unsigned char limit1:4; - unsigned char avail:1; - unsigned char is_64_code:1; /* L flag */ - unsigned char db:1; /* DB flag */ - unsigned char granularity:1; /* G flag */ - unsigned char base2; + unsigned short limit0; + unsigned short base0; + unsigned char base1; + unsigned char type : 4; + unsigned char system : 1; /* S flag */ + unsigned char dpl : 2; + unsigned char present : 1; /* P flag */ + unsigned char limit1 : 4; + unsigned char avail : 1; + unsigned char is_64_code : 1; /* L flag */ + unsigned char db : 1; /* DB flag */ + unsigned char granularity : 1; /* G flag */ + unsigned char base2; #else - unsigned char base2; - unsigned char granularity:1; /* G flag */ - unsigned char db:1; /* DB flag */ - unsigned char is_64_code:1; /* L flag */ - unsigned char avail:1; - unsigned char limit1:4; - unsigned char present:1; /* P flag */ - unsigned char dpl:2; - unsigned char system:1; /* S flag */ - unsigned char type:4; - unsigned char base1; - unsigned short base0; - unsigned short limit0; + unsigned char base2; + unsigned char granularity : 1; /* G flag */ + unsigned char db : 1; /* DB flag */ + unsigned char is_64_code : 1; /* L flag */ + unsigned char avail : 1; + unsigned char limit1 : 4; + unsigned char present : 1; /* P flag */ + unsigned char dpl : 2; + unsigned char system : 1; /* S flag */ + unsigned char type : 4; + unsigned char base1; + unsigned short base0; + unsigned short limit0; #endif - }; - uint64_t desc; - }; + }; + uint64_t desc; + }; }; #pragma pack(pop) -#define SEGBASE(d) ((uint32_t)((((d).desc >> 16) & 0xffffff) | (((d).desc >> 32) & 0xff000000))) +#define SEGBASE(d) \ + ((uint32_t)((((d).desc >> 16) & 0xffffff) | \ + (((d).desc >> 32) & 0xff000000))) #define SEGLIMIT(d) ((d).limit0 | (((unsigned int)(d).limit1) << 16)) /** * Assert that err matches expect */ -#define uc_assert_err(expect, err) \ -do { \ - uc_err __err = err; \ - if (__err != expect) { \ - fprintf(stderr, "%s", uc_strerror(__err)); \ - exit(1); \ - } \ -} while (0) +#define uc_assert_err(expect, err) \ + do { \ + uc_err __err = err; \ + if (__err != expect) { \ + fprintf(stderr, "%s", uc_strerror(__err)); \ + exit(1); \ + } \ + } while (0) /** * Assert that err is UC_ERR_OK */ -#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err) +#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err) /** * Assert that err is anything but UC_ERR_OK @@ -90,55 +92,61 @@ do { \ * as this serves to document which errors a function will return * in various scenarios. */ -#define uc_assert_fail(err) \ -do { \ - uc_err __err = err; \ - if (__err == UC_ERR_OK) { \ - fprintf(stderr, "%s", uc_strerror(__err)); \ - exit(1); \ - } \ -} while (0) +#define uc_assert_fail(err) \ + do { \ + uc_err __err = err; \ + if (__err == UC_ERR_OK) { \ + fprintf(stderr, "%s", uc_strerror(__err)); \ + exit(1); \ + } \ + } while (0) -#define OK(x) uc_assert_success(x) +#define OK(x) uc_assert_success(x) /******************************************************************************/ -static void hook_mem(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) +static void hook_mem(uc_engine *uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void *user_data) { - switch(type) { - case UC_MEM_WRITE: - printf("mem write at 0x%"PRIx64 ", size = %u, value = 0x%"PRIx64 "\n", address, size, value); - break; - default: break; + switch (type) { + case UC_MEM_WRITE: + printf("mem write at 0x%" PRIx64 ", size = %u, value = 0x%" PRIx64 "\n", + address, size, value); + break; + default: + break; } } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf("Executing at 0x%"PRIx64 ", ilen = 0x%x\n", address, size); + printf("Executing at 0x%" PRIx64 ", ilen = 0x%x\n", address, size); } -//VERY basic descriptor init function, sets many fields to user space sane defaults -static void init_descriptor(struct SegmentDescriptor *desc, uint32_t base, uint32_t limit, uint8_t is_code) +// VERY basic descriptor init function, sets many fields to user space sane +// defaults +static void init_descriptor(struct SegmentDescriptor *desc, uint32_t base, + uint32_t limit, uint8_t is_code) { - desc->desc = 0; //clear the descriptor + desc->desc = 0; // clear the descriptor desc->base0 = base & 0xffff; desc->base1 = (base >> 16) & 0xff; desc->base2 = base >> 24; if (limit > 0xfffff) { - //need Giant granularity + // need Giant granularity limit >>= 12; desc->granularity = 1; } desc->limit0 = limit & 0xffff; desc->limit1 = limit >> 16; - //some sane defaults + // some sane defaults desc->dpl = 3; desc->present = 1; - desc->db = 1; //32 bit + desc->db = 1; // 32 bit desc->type = is_code ? 0xb : 3; - desc->system = 1; //code or data + desc->system = 1; // code or data } /* @@ -149,7 +157,7 @@ static void hex_dump(unsigned char *ptr, unsigned int len) if (i != 0 && (i & 0xf) == 0) { fprintf(stderr, "\n"); } - fprintf(stderr, "%02hhx", ptr[i]); + fprintf(stderr, "%02hhx", ptr[i]); } fprintf(stderr, "\n"); } @@ -163,7 +171,7 @@ static void gdt_demo() uint8_t buf[128]; uc_x86_mmr gdtr; int i; - + /* bits 32 @@ -174,29 +182,33 @@ static void gdt_demo() mov dword [fs:4], 0x89abcdef */ - const uint8_t code[] = "\x68\x67\x45\x23\x01\x68\xef\xcd\xab\x89\x64\xc7\x05\x00\x00\x00\x00\x67\x45\x23\x01\x64\xc7\x05\x04\x00\x00\x00\xef\xcd\xab\x89"; + const uint8_t code[] = + "\x68\x67\x45\x23\x01\x68\xef\xcd\xab\x89\x64\xc7\x05\x00\x00\x00\x00" + "\x67\x45\x23\x01\x64\xc7\x05\x04\x00\x00\x00\xef\xcd\xab\x89"; const uint64_t code_address = 0x1000000; const uint64_t stack_address = 0x120000; const uint64_t gdt_address = 0xc0000000; const uint64_t fs_address = 0x7efdd000; - struct SegmentDescriptor *gdt = (struct SegmentDescriptor*)calloc(31, sizeof(struct SegmentDescriptor)); + struct SegmentDescriptor *gdt = (struct SegmentDescriptor *)calloc( + 31, sizeof(struct SegmentDescriptor)); - int r_esp = (int)stack_address + 0x1000; // initial esp + int r_esp = (int)stack_address + 0x1000; // initial esp int r_cs = 0x73; - int r_ss = 0x88; //ring 0 + int r_ss = 0x88; // ring 0 int r_ds = 0x7b; int r_es = 0x7b; int r_fs = 0x83; - gdtr.base = gdt_address; + gdtr.base = gdt_address; gdtr.limit = 31 * sizeof(struct SegmentDescriptor) - 1; - init_descriptor(&gdt[14], 0, 0xfffff000, 1); //code segment - init_descriptor(&gdt[15], 0, 0xfffff000, 0); //data segment - init_descriptor(&gdt[16], 0x7efdd000, 0xfff, 0); //one page data segment simulate fs - init_descriptor(&gdt[17], 0, 0xfffff000, 0); //ring 0 data - gdt[17].dpl = 0; //set descriptor privilege level + init_descriptor(&gdt[14], 0, 0xfffff000, 1); // code segment + init_descriptor(&gdt[15], 0, 0xfffff000, 0); // data segment + init_descriptor(&gdt[16], 0x7efdd000, 0xfff, + 0); // one page data segment simulate fs + init_descriptor(&gdt[17], 0, 0xfffff000, 0); // ring 0 data + gdt[17].dpl = 0; // set descriptor privilege level /* fprintf(stderr, "GDT: \n"); @@ -207,9 +219,11 @@ static void gdt_demo() err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); uc_assert_success(err); - uc_hook_add(uc, &hook1, UC_HOOK_CODE, hook_code, NULL, code_address, code_address + sizeof(code) - 1); + uc_hook_add(uc, &hook1, UC_HOOK_CODE, hook_code, NULL, code_address, + code_address + sizeof(code) - 1); - err = uc_hook_add(uc, &hook2, UC_HOOK_MEM_WRITE, hook_mem, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &hook2, UC_HOOK_MEM_WRITE, hook_mem, NULL, + (uint64_t)1, (uint64_t)0); uc_assert_success(err); // map 1 page of code for this emulation @@ -224,12 +238,13 @@ static void gdt_demo() err = uc_mem_map(uc, gdt_address, 0x10000, UC_PROT_WRITE | UC_PROT_READ); uc_assert_success(err); - //set up a GDT BEFORE you manipulate any segment registers + // set up a GDT BEFORE you manipulate any segment registers err = uc_reg_write(uc, UC_X86_REG_GDTR, &gdtr); uc_assert_success(err); // write gdt to be emulated to memory - err = uc_mem_write(uc, gdt_address, gdt, 31 * sizeof(struct SegmentDescriptor)); + err = uc_mem_write(uc, gdt_address, gdt, + 31 * sizeof(struct SegmentDescriptor)); uc_assert_success(err); // map 1 page for FS @@ -237,7 +252,7 @@ static void gdt_demo() uc_assert_success(err); // write machine code to be emulated to memory - err = uc_mem_write(uc, code_address, code, sizeof(code)-1); + err = uc_mem_write(uc, code_address, code, sizeof(code) - 1); uc_assert_success(err); // initialize machine registers @@ -245,7 +260,8 @@ static void gdt_demo() uc_assert_success(err); // when setting SS, need rpl == cpl && dpl == cpl - // emulator starts with cpl == 0, so we need a dpl 0 descriptor and rpl 0 selector + // emulator starts with cpl == 0, so we need a dpl 0 descriptor and rpl 0 + // selector err = uc_reg_write(uc, UC_X86_REG_SS, &r_ss); uc_assert_success(err); @@ -259,7 +275,7 @@ static void gdt_demo() uc_assert_success(err); // emulate machine code in infinite time - err = uc_emu_start(uc, code_address, code_address+sizeof(code)-1, 0, 0); + err = uc_emu_start(uc, code_address, code_address + sizeof(code) - 1, 0, 0); uc_assert_success(err); // read from memory diff --git a/samples/shellcode.c b/samples/shellcode.c index e0a72c75..9094dc07 100644 --- a/samples/shellcode.c +++ b/samples/shellcode.c @@ -6,23 +6,31 @@ #include #include - // code to be emulated -#define X86_CODE32 "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f" +#define X86_CODE32 \ + "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd" \ + "\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c" \ + "\x6f" -#define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41" +#define X86_CODE32_SELF \ + "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89" \ + "\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31" \ + "\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3" \ + "\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41" // memory address where emulation starts #define ADDRESS 0x1000000 -#define MIN(a, b) (a < b? a : b) +#define MIN(a, b) (a < b ? a : b) // callback for tracing instruction -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { int r_eip; uint8_t tmp[16]; - printf("Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf("Tracing instruction at 0x%" PRIx64 ", instruction size = 0x%x\n", + address, size); uc_reg_read(uc, UC_X86_REG_EIP, &r_eip); printf("*** EIP = %x ***: ", r_eip); @@ -30,7 +38,7 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user size = MIN(sizeof(tmp), size); if (!uc_mem_read(uc, address, tmp, size)) { uint32_t i; - for (i=0; i>> 0x%x: interrupt 0x%x, EAX = 0x%x\n", r_eip, intno, r_eax); - break; - case 1: // sys_exit - printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno); - uc_emu_stop(uc); - break; - case 4: // sys_write - // ECX = buffer address - uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); + switch (r_eax) { + default: + printf(">>> 0x%x: interrupt 0x%x, EAX = 0x%x\n", r_eip, intno, r_eax); + break; + case 1: // sys_exit + printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno); + uc_emu_stop(uc); + break; + case 4: // sys_write + // ECX = buffer address + uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); - // EDX = buffer size - uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); + // EDX = buffer size + uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); - // read the buffer in - size = MIN(sizeof(buffer)-1, r_edx); + // read the buffer in + size = MIN(sizeof(buffer) - 1, r_edx); - if (!uc_mem_read(uc, r_ecx, buffer, size)) { - buffer[size] = '\0'; - printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n", - r_eip, intno, r_ecx, r_edx, buffer); - } else { - printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u (cannot get content)\n", - r_eip, intno, r_ecx, r_edx); - } - break; + if (!uc_mem_read(uc, r_ecx, buffer, size)) { + buffer[size] = '\0'; + printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = " + "%u, content = '%s'\n", + r_eip, intno, r_ecx, r_edx, buffer); + } else { + printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = " + "%u (cannot get content)\n", + r_eip, intno, r_ecx, r_edx); + } + break; } } @@ -88,7 +98,7 @@ static void test_i386(void) uc_err err; uc_hook trace1, trace2; - int r_esp = ADDRESS + 0x200000; // ESP register + int r_esp = ADDRESS + 0x200000; // ESP register printf("Emulate i386 code\n"); @@ -103,7 +113,8 @@ static void test_i386(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_SELF, + sizeof(X86_CODE32_SELF) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -120,11 +131,13 @@ static void test_i386(void) printf("\n>>> Start tracing this Linux code\n"); // emulate machine code in infinite time - // err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, 12); <--- emulate only 12 instructions - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0); + // err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, + // 12); <--- emulate only 12 instructions + err = + uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } printf("\n>>> Emulation done.\n"); @@ -137,8 +150,7 @@ int main(int argc, char **argv, char **envp) if (argc == 2) { if (!strcmp(argv[1], "-32")) { test_i386(); - } - else if (!strcmp(argv[1], "-h")) { + } else if (!strcmp(argv[1], "-h")) { printf("Syntax: %s <-32|-64>\n", argv[0]); } } else { diff --git a/symbols.sh b/symbols.sh index 19997fb4..a30c0f90 100755 --- a/symbols.sh +++ b/symbols.sh @@ -4,6 +4,7 @@ CMD_PATH=$(realpath $0) SOURCE_DIR=$(dirname ${CMD_PATH}) COMMON_SYMBOLS=" +tb_invalidate_phys_range \ use_idiv_instructions \ arm_arch \ tb_target_set_jmp_target \ diff --git a/tests/unit/acutest.h b/tests/unit/acutest.h index 376748bd..6b4d596d 100644 --- a/tests/unit/acutest.h +++ b/tests/unit/acutest.h @@ -27,7 +27,6 @@ #ifndef ACUTEST_H #define ACUTEST_H - /************************ *** Public interface *** ************************/ @@ -59,8 +58,7 @@ * * Note the list has to be ended with a zeroed record. */ -#define TEST_LIST const struct acutest_test_ acutest_list_[] - +#define TEST_LIST const struct acutest_test_ acutest_list_[] /* Macros for testing whether an unit test succeeds or fails. These macros * can be used arbitrarily in functions implementing the unit tests. @@ -81,9 +79,9 @@ * TEST_CHECK(ptr->member2 > 200); * } */ -#define TEST_CHECK_(cond,...) acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__) -#define TEST_CHECK(cond) acutest_check_((cond), __FILE__, __LINE__, "%s", #cond) - +#define TEST_CHECK_(cond, ...) \ + acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) acutest_check_((cond), __FILE__, __LINE__, "%s", #cond) /* These macros are the same as TEST_CHECK_ and TEST_CHECK except that if the * condition fails, the currently executed unit test is immediately aborted. @@ -100,17 +98,16 @@ * effects to the outside world (e.g. communicating with some server, inserting * into a database etc.). */ -#define TEST_ASSERT_(cond,...) \ +#define TEST_ASSERT_(cond, ...) \ do { \ - if(!acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ + if (!acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ acutest_abort_(); \ - } while(0) + } while (0) #define TEST_ASSERT(cond) \ do { \ - if(!acutest_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ + if (!acutest_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ acutest_abort_(); \ - } while(0) - + } while (0) #ifdef __cplusplus /* Macros to verify that the code (the 1st argument) throws exception of given @@ -134,15 +131,16 @@ try { \ code; \ msg_ = "No exception thrown."; \ - } catch(exctype const&) { \ - exc_ok_= true; \ - } catch(...) { \ + } catch (exctype const &) { \ + exc_ok_ = true; \ + } catch (...) { \ msg_ = "Unexpected exception thrown."; \ } \ - acutest_check_(exc_ok_, __FILE__, __LINE__, #code " throws " #exctype);\ - if(msg_ != NULL) \ + acutest_check_(exc_ok_, __FILE__, __LINE__, \ + #code " throws " #exctype); \ + if (msg_ != NULL) \ acutest_message_("%s", msg_); \ - } while(0) + } while (0) #define TEST_EXCEPTION_(code, exctype, ...) \ do { \ bool exc_ok_ = false; \ @@ -150,17 +148,16 @@ try { \ code; \ msg_ = "No exception thrown."; \ - } catch(exctype const&) { \ - exc_ok_= true; \ - } catch(...) { \ + } catch (exctype const &) { \ + exc_ok_ = true; \ + } catch (...) { \ msg_ = "Unexpected exception thrown."; \ } \ acutest_check_(exc_ok_, __FILE__, __LINE__, __VA_ARGS__); \ - if(msg_ != NULL) \ + if (msg_ != NULL) \ acutest_message_("%s", msg_); \ - } while(0) -#endif /* #ifdef __cplusplus */ - + } while (0) +#endif /* #ifdef __cplusplus */ /* Sometimes it is useful to split execution of more complex unit tests to some * smaller parts and associate those parts with some names. @@ -180,18 +177,16 @@ * implicitly the previous one. To end the test case explicitly (e.g. to end * the last test case after exiting the loop), you may use TEST_CASE(NULL). */ -#define TEST_CASE_(...) acutest_case_(__VA_ARGS__) -#define TEST_CASE(name) acutest_case_("%s", name) - +#define TEST_CASE_(...) acutest_case_(__VA_ARGS__) +#define TEST_CASE(name) acutest_case_("%s", name) /* Maximal output per TEST_CASE call. Longer messages are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_CASE_MAXSIZE - #define TEST_CASE_MAXSIZE 64 +#define TEST_CASE_MAXSIZE 64 #endif - /* printf-like macro for outputting an extra information about a failure. * * Intended use is to output some computed output versus the expected value, @@ -213,17 +208,15 @@ * The macro can deal with multi-line output fairly well. It also automatically * adds a final new-line if there is none present. */ -#define TEST_MSG(...) acutest_message_(__VA_ARGS__) - +#define TEST_MSG(...) acutest_message_(__VA_ARGS__) /* Maximal output per TEST_MSG call. Longer messages are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_MSG_MAXSIZE - #define TEST_MSG_MAXSIZE 1024 +#define TEST_MSG_MAXSIZE 1024 #endif - /* Macro for dumping a block of memory. * * Its intended use is very similar to what TEST_MSG is for, but instead of @@ -235,16 +228,15 @@ * TEST_DUMP("Expected:", addr_expected, size_expected); * TEST_DUMP("Produced:", addr_produced, size_produced); */ -#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size) +#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size) /* Maximal output per TEST_DUMP call (in bytes to dump). Longer blocks are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_DUMP_MAXSIZE - #define TEST_DUMP_MAXSIZE 1024 +#define TEST_DUMP_MAXSIZE 1024 #endif - /* Common test initialiation/clean-up * * In some test suites, it may be needed to perform some sort of the same @@ -258,14 +250,13 @@ * Examples of various ways how to use the macro TEST_INIT: * * #define TEST_INIT my_init_func(); - * #define TEST_INIT my_init_func() // Works even without the semicolon - * #define TEST_INIT setlocale(LC_ALL, NULL); - * #define TEST_INIT { setlocale(LC_ALL, NULL); my_init_func(); } + * #define TEST_INIT my_init_func() // Works even without the + * semicolon #define TEST_INIT setlocale(LC_ALL, NULL); #define TEST_INIT + * { setlocale(LC_ALL, NULL); my_init_func(); } * * TEST_FINI is to be used in the same way. */ - /********************** *** Implementation *** **********************/ @@ -280,76 +271,76 @@ #include #if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) - #define ACUTEST_UNIX_ 1 - #include - #include - #include - #include - #include - #include - #include +#define ACUTEST_UNIX_ 1 +#include +#include +#include +#include +#include +#include +#include - #if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC - #define ACUTEST_HAS_POSIX_TIMER_ 1 - #endif +#if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC +#define ACUTEST_HAS_POSIX_TIMER_ 1 +#endif #endif #if defined(_gnu_linux_) || defined(__linux__) - #define ACUTEST_LINUX_ 1 - #include - #include +#define ACUTEST_LINUX_ 1 +#include +#include #endif #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) - #define ACUTEST_WIN_ 1 - #include - #include +#define ACUTEST_WIN_ 1 +#include +#include #endif #if defined(__APPLE__) - #define ACUTEST_MACOS_ - #include - #include - #include - #include - #include +#define ACUTEST_MACOS_ +#include +#include +#include +#include +#include #endif #ifdef __cplusplus - #include +#include #endif #ifdef __has_include - #if __has_include() - #include - #endif +#if __has_include() +#include +#endif #endif -/* Enable the use of the non-standard keyword __attribute__ to silence warnings under some compilers */ +/* Enable the use of the non-standard keyword __attribute__ to silence warnings + * under some compilers */ #if defined(__GNUC__) || defined(__clang__) - #define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr)) +#define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr)) #else - #define ACUTEST_ATTRIBUTE_(attr) +#define ACUTEST_ATTRIBUTE_(attr) #endif /* Note our global private identifiers end with '_' to mitigate risk of clash * with the unit tests implementation. */ #ifdef __cplusplus - extern "C" { +extern "C" { #endif #ifdef _MSC_VER - /* In the multi-platform code like ours, we cannot use the non-standard - * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of - * standard sprintf(). Hence, lets disable the warning C4996. */ - #pragma warning(push) - #pragma warning(disable: 4996) +/* In the multi-platform code like ours, we cannot use the non-standard + * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of + * standard sprintf(). Hence, lets disable the warning C4996. */ +#pragma warning(push) +#pragma warning(disable : 4996) #endif - struct acutest_test_ { - const char* name; + const char *name; void (*func)(void); }; @@ -366,18 +357,17 @@ enum { extern const struct acutest_test_ acutest_list_[]; -int acutest_check_(int cond, const char* file, int line, const char* fmt, ...); -void acutest_case_(const char* fmt, ...); -void acutest_message_(const char* fmt, ...); -void acutest_dump_(const char* title, const void* addr, size_t size); +int acutest_check_(int cond, const char *file, int line, const char *fmt, ...); +void acutest_case_(const char *fmt, ...); +void acutest_message_(const char *fmt, ...); +void acutest_dump_(const char *title, const void *addr, size_t size); void acutest_abort_(void) ACUTEST_ATTRIBUTE_(noreturn); - #ifndef TEST_NO_MAIN -static char* acutest_argv0_ = NULL; +static char *acutest_argv0_ = NULL; static size_t acutest_list_size_ = 0; -static struct acutest_test_data_* acutest_test_data_ = NULL; +static struct acutest_test_data_ *acutest_test_data_ = NULL; static size_t acutest_count_ = 0; static int acutest_no_exec_ = -1; static int acutest_no_summary_ = 0; @@ -392,7 +382,7 @@ static FILE *acutest_xml_output_ = NULL; static int acutest_stat_failed_units_ = 0; static int acutest_stat_run_units_ = 0; -static const struct acutest_test_* acutest_current_test_ = NULL; +static const struct acutest_test_ *acutest_current_test_ = NULL; static int acutest_current_index_ = 0; static char acutest_case_name_[TEST_CASE_MAXSIZE] = ""; static int acutest_test_already_logged_ = 0; @@ -405,132 +395,116 @@ static int acutest_timer_ = 0; static int acutest_abort_has_jmp_buf_ = 0; static jmp_buf acutest_abort_jmp_buf_; - -static void -acutest_cleanup_(void) +static void acutest_cleanup_(void) { - free((void*) acutest_test_data_); + free((void *)acutest_test_data_); } -static void ACUTEST_ATTRIBUTE_(noreturn) -acutest_exit_(int exit_code) +static void ACUTEST_ATTRIBUTE_(noreturn) acutest_exit_(int exit_code) { acutest_cleanup_(); exit(exit_code); } #if defined ACUTEST_WIN_ - typedef LARGE_INTEGER acutest_timer_type_; - static LARGE_INTEGER acutest_timer_freq_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +typedef LARGE_INTEGER acutest_timer_type_; +static LARGE_INTEGER acutest_timer_freq_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - static void - acutest_timer_init_(void) - { - QueryPerformanceFrequency(´st_timer_freq_); - } +static void acutest_timer_init_(void) +{ + QueryPerformanceFrequency(´st_timer_freq_); +} - static void - acutest_timer_get_time_(LARGE_INTEGER* ts) - { - QueryPerformanceCounter(ts); - } +static void acutest_timer_get_time_(LARGE_INTEGER *ts) +{ + QueryPerformanceCounter(ts); +} - static double - acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) - { - double duration = (double)(end.QuadPart - start.QuadPart); - duration /= (double)acutest_timer_freq_.QuadPart; - return duration; - } +static double acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) +{ + double duration = (double)(end.QuadPart - start.QuadPart); + duration /= (double)acutest_timer_freq_.QuadPart; + return duration; +} - static void - acutest_timer_print_diff_(void) - { - printf("%.6lf secs", acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); - } +static void acutest_timer_print_diff_(void) +{ + printf("%.6lf secs", + acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); +} #elif defined ACUTEST_HAS_POSIX_TIMER_ - static clockid_t acutest_timer_id_; - typedef struct timespec acutest_timer_type_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +static clockid_t acutest_timer_id_; +typedef struct timespec acutest_timer_type_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - static void - acutest_timer_init_(void) - { - if(acutest_timer_ == 1) - acutest_timer_id_ = CLOCK_MONOTONIC; - else if(acutest_timer_ == 2) - acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; - } +static void acutest_timer_init_(void) +{ + if (acutest_timer_ == 1) + acutest_timer_id_ = CLOCK_MONOTONIC; + else if (acutest_timer_ == 2) + acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; +} - static void - acutest_timer_get_time_(struct timespec* ts) - { - clock_gettime(acutest_timer_id_, ts); - } +static void acutest_timer_get_time_(struct timespec *ts) +{ + clock_gettime(acutest_timer_id_, ts); +} - static double - acutest_timer_diff_(struct timespec start, struct timespec end) - { - double endns; - double startns; +static double acutest_timer_diff_(struct timespec start, struct timespec end) +{ + double endns; + double startns; - endns = end.tv_sec; - endns *= 1e9; - endns += end.tv_nsec; + endns = end.tv_sec; + endns *= 1e9; + endns += end.tv_nsec; - startns = start.tv_sec; - startns *= 1e9; - startns += start.tv_nsec; + startns = start.tv_sec; + startns *= 1e9; + startns += start.tv_nsec; - return ((endns - startns)/ 1e9); - } + return ((endns - startns) / 1e9); +} - static void - acutest_timer_print_diff_(void) - { - printf("%.6lf secs", - acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); - } +static void acutest_timer_print_diff_(void) +{ + printf("%.6lf secs", + acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); +} #else - typedef int acutest_timer_type_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +typedef int acutest_timer_type_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - void - acutest_timer_init_(void) - {} +void acutest_timer_init_(void) {} - static void - acutest_timer_get_time_(int* ts) - { - (void) ts; - } +static void acutest_timer_get_time_(int *ts) +{ + (void)ts; +} - static double - acutest_timer_diff_(int start, int end) - { - (void) start; - (void) end; - return 0.0; - } +static double acutest_timer_diff_(int start, int end) +{ + (void)start; + (void)end; + return 0.0; +} - static void - acutest_timer_print_diff_(void) - {} +static void acutest_timer_print_diff_(void) {} #endif -#define ACUTEST_COLOR_DEFAULT_ 0 -#define ACUTEST_COLOR_GREEN_ 1 -#define ACUTEST_COLOR_RED_ 2 -#define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 3 -#define ACUTEST_COLOR_GREEN_INTENSIVE_ 4 -#define ACUTEST_COLOR_RED_INTENSIVE_ 5 +#define ACUTEST_COLOR_DEFAULT_ 0 +#define ACUTEST_COLOR_GREEN_ 1 +#define ACUTEST_COLOR_RED_ 2 +#define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 3 +#define ACUTEST_COLOR_GREEN_INTENSIVE_ 4 +#define ACUTEST_COLOR_RED_INTENSIVE_ 5 -static int ACUTEST_ATTRIBUTE_(format (printf, 2, 3)) -acutest_colored_printf_(int color, const char* fmt, ...) +static int ACUTEST_ATTRIBUTE_(format(printf, 2, 3)) + acutest_colored_printf_(int color, const char *fmt, ...) { va_list args; char buffer[256]; @@ -539,22 +513,34 @@ acutest_colored_printf_(int color, const char* fmt, ...) va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); - buffer[sizeof(buffer)-1] = '\0'; + buffer[sizeof(buffer) - 1] = '\0'; - if(!acutest_colorize_) { + if (!acutest_colorize_) { return printf("%s", buffer); } #if defined ACUTEST_UNIX_ { - const char* col_str; - switch(color) { - case ACUTEST_COLOR_GREEN_: col_str = "\033[0;32m"; break; - case ACUTEST_COLOR_RED_: col_str = "\033[0;31m"; break; - case ACUTEST_COLOR_GREEN_INTENSIVE_: col_str = "\033[1;32m"; break; - case ACUTEST_COLOR_RED_INTENSIVE_: col_str = "\033[1;31m"; break; - case ACUTEST_COLOR_DEFAULT_INTENSIVE_: col_str = "\033[1m"; break; - default: col_str = "\033[0m"; break; + const char *col_str; + switch (color) { + case ACUTEST_COLOR_GREEN_: + col_str = "\033[0;32m"; + break; + case ACUTEST_COLOR_RED_: + col_str = "\033[0;31m"; + break; + case ACUTEST_COLOR_GREEN_INTENSIVE_: + col_str = "\033[1;32m"; + break; + case ACUTEST_COLOR_RED_INTENSIVE_: + col_str = "\033[1;31m"; + break; + case ACUTEST_COLOR_DEFAULT_INTENSIVE_: + col_str = "\033[1m"; + break; + default: + col_str = "\033[0m"; + break; } printf("%s", col_str); n = printf("%s", buffer); @@ -570,15 +556,28 @@ acutest_colored_printf_(int color, const char* fmt, ...) h = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(h, &info); - switch(color) { - case ACUTEST_COLOR_GREEN_: attr = FOREGROUND_GREEN; break; - case ACUTEST_COLOR_RED_: attr = FOREGROUND_RED; break; - case ACUTEST_COLOR_GREEN_INTENSIVE_: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; - case ACUTEST_COLOR_RED_INTENSIVE_: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break; - case ACUTEST_COLOR_DEFAULT_INTENSIVE_: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; - default: attr = 0; break; + switch (color) { + case ACUTEST_COLOR_GREEN_: + attr = FOREGROUND_GREEN; + break; + case ACUTEST_COLOR_RED_: + attr = FOREGROUND_RED; + break; + case ACUTEST_COLOR_GREEN_INTENSIVE_: + attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; + case ACUTEST_COLOR_RED_INTENSIVE_: + attr = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + case ACUTEST_COLOR_DEFAULT_INTENSIVE_: + attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_INTENSITY; + break; + default: + attr = 0; + break; } - if(attr != 0) + if (attr != 0) SetConsoleTextAttribute(h, attr); n = printf("%s", buffer); SetConsoleTextAttribute(h, info.wAttributes); @@ -590,48 +589,50 @@ acutest_colored_printf_(int color, const char* fmt, ...) #endif } -static void -acutest_begin_test_line_(const struct acutest_test_* test) +static void acutest_begin_test_line_(const struct acutest_test_ *test) { - if(!acutest_tap_) { - if(acutest_verbose_level_ >= 3) { - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s:\n", test->name); + if (!acutest_tap_) { + if (acutest_verbose_level_ >= 3) { + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Test %s:\n", test->name); acutest_test_already_logged_++; - } else if(acutest_verbose_level_ >= 1) { + } else if (acutest_verbose_level_ >= 1) { int n; char spaces[48]; - n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s... ", test->name); + n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Test %s... ", test->name); memset(spaces, ' ', sizeof(spaces)); - if(n < (int) sizeof(spaces)) - printf("%.*s", (int) sizeof(spaces) - n, spaces); + if (n < (int)sizeof(spaces)) + printf("%.*s", (int)sizeof(spaces) - n, spaces); } else { acutest_test_already_logged_ = 1; } } } -static void -acutest_finish_test_line_(int result) +static void acutest_finish_test_line_(int result) { - if(acutest_tap_) { - const char* str = (result == 0) ? "ok" : "not ok"; + if (acutest_tap_) { + const char *str = (result == 0) ? "ok" : "not ok"; - printf("%s %d - %s\n", str, acutest_current_index_ + 1, acutest_current_test_->name); + printf("%s %d - %s\n", str, acutest_current_index_ + 1, + acutest_current_test_->name); - if(result == 0 && acutest_timer_) { + if (result == 0 && acutest_timer_) { printf("# Duration: "); acutest_timer_print_diff_(); printf("\n"); } } else { - int color = (result == 0) ? ACUTEST_COLOR_GREEN_INTENSIVE_ : ACUTEST_COLOR_RED_INTENSIVE_; - const char* str = (result == 0) ? "OK" : "FAILED"; + int color = (result == 0) ? ACUTEST_COLOR_GREEN_INTENSIVE_ + : ACUTEST_COLOR_RED_INTENSIVE_; + const char *str = (result == 0) ? "OK" : "FAILED"; printf("[ "); acutest_colored_printf_(color, "%s", str); printf(" ]"); - if(result == 0 && acutest_timer_) { + if (result == 0 && acutest_timer_) { printf(" "); acutest_timer_print_diff_(); } @@ -640,37 +641,36 @@ acutest_finish_test_line_(int result) } } -static void -acutest_line_indent_(int level) +static void acutest_line_indent_(int level) { static const char spaces[] = " "; int n = level * 2; - if(acutest_tap_ && n > 0) { + if (acutest_tap_ && n > 0) { n--; printf("#"); } - while(n > 16) { + while (n > 16) { printf("%s", spaces); n -= 16; } printf("%.*s", n, spaces); } -int ACUTEST_ATTRIBUTE_(format (printf, 4, 5)) -acutest_check_(int cond, const char* file, int line, const char* fmt, ...) +int ACUTEST_ATTRIBUTE_(format(printf, 4, 5)) + acutest_check_(int cond, const char *file, int line, const char *fmt, ...) { const char *result_str; int result_color; int verbose_level; - if(cond) { + if (cond) { result_str = "ok"; result_color = ACUTEST_COLOR_GREEN_; verbose_level = 3; } else { - if(!acutest_test_already_logged_ && acutest_current_test_ != NULL) + if (!acutest_test_already_logged_ && acutest_current_test_ != NULL) acutest_finish_test_line_(-1); result_str = "failed"; @@ -680,30 +680,31 @@ acutest_check_(int cond, const char* file, int line, const char* fmt, ...) acutest_test_already_logged_++; } - if(acutest_verbose_level_ >= verbose_level) { + if (acutest_verbose_level_ >= verbose_level) { va_list args; - if(!acutest_case_already_logged_ && acutest_case_name_[0]) { + if (!acutest_case_already_logged_ && acutest_case_name_[0]) { acutest_line_indent_(1); - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", acutest_case_name_); + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Case %s:\n", acutest_case_name_); acutest_test_already_logged_++; acutest_case_already_logged_++; } acutest_line_indent_(acutest_case_name_[0] ? 2 : 1); - if(file != NULL) { + if (file != NULL) { #ifdef ACUTEST_WIN_ - const char* lastsep1 = strrchr(file, '\\'); - const char* lastsep2 = strrchr(file, '/'); - if(lastsep1 == NULL) - lastsep1 = file-1; - if(lastsep2 == NULL) - lastsep2 = file-1; + const char *lastsep1 = strrchr(file, '\\'); + const char *lastsep2 = strrchr(file, '/'); + if (lastsep1 == NULL) + lastsep1 = file - 1; + if (lastsep2 == NULL) + lastsep2 = file - 1; file = (lastsep1 > lastsep2 ? lastsep1 : lastsep2) + 1; #else - const char* lastsep = strrchr(file, '/'); - if(lastsep != NULL) - file = lastsep+1; + const char *lastsep = strrchr(file, '/'); + if (lastsep != NULL) + file = lastsep + 1; #endif printf("%s:%d: Check ", file, line); } @@ -722,20 +723,20 @@ acutest_check_(int cond, const char* file, int line, const char* fmt, ...) return !acutest_cond_failed_; } -void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_case_(const char* fmt, ...) +void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_case_(const char *fmt, ...) { va_list args; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; - if(acutest_case_name_[0]) { + if (acutest_case_name_[0]) { acutest_case_already_logged_ = 0; acutest_case_name_[0] = '\0'; } - if(fmt == NULL) + if (fmt == NULL) return; va_start(args, fmt); @@ -743,90 +744,90 @@ acutest_case_(const char* fmt, ...) va_end(args); acutest_case_name_[sizeof(acutest_case_name_) - 1] = '\0'; - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", acutest_case_name_); + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", + acutest_case_name_); acutest_test_already_logged_++; acutest_case_already_logged_++; } } -void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_message_(const char* fmt, ...) +void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_message_(const char *fmt, ...) { char buffer[TEST_MSG_MAXSIZE]; - char* line_beg; - char* line_end; + char *line_beg; + char *line_end; va_list args; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; /* We allow extra message only when something is already wrong in the * current test. */ - if(acutest_current_test_ == NULL || !acutest_cond_failed_) + if (acutest_current_test_ == NULL || !acutest_cond_failed_) return; va_start(args, fmt); vsnprintf(buffer, TEST_MSG_MAXSIZE, fmt, args); va_end(args); - buffer[TEST_MSG_MAXSIZE-1] = '\0'; + buffer[TEST_MSG_MAXSIZE - 1] = '\0'; line_beg = buffer; - while(1) { + while (1) { line_end = strchr(line_beg, '\n'); - if(line_end == NULL) + if (line_end == NULL) break; acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); printf("%.*s\n", (int)(line_end - line_beg), line_beg); line_beg = line_end + 1; } - if(line_beg[0] != '\0') { + if (line_beg[0] != '\0') { acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); printf("%s\n", line_beg); } } -void -acutest_dump_(const char* title, const void* addr, size_t size) +void acutest_dump_(const char *title, const void *addr, size_t size) { static const size_t BYTES_PER_LINE = 16; size_t line_beg; size_t truncate = 0; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; /* We allow extra message only when something is already wrong in the * current test. */ - if(acutest_current_test_ == NULL || !acutest_cond_failed_) + if (acutest_current_test_ == NULL || !acutest_cond_failed_) return; - if(size > TEST_DUMP_MAXSIZE) { + if (size > TEST_DUMP_MAXSIZE) { truncate = size - TEST_DUMP_MAXSIZE; size = TEST_DUMP_MAXSIZE; } acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); - printf((title[strlen(title)-1] == ':') ? "%s\n" : "%s:\n", title); + printf((title[strlen(title) - 1] == ':') ? "%s\n" : "%s:\n", title); - for(line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { + for (line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { size_t line_end = line_beg + BYTES_PER_LINE; size_t off; acutest_line_indent_(acutest_case_name_[0] ? 4 : 3); printf("%08lx: ", (unsigned long)line_beg); - for(off = line_beg; off < line_end; off++) { - if(off < size) - printf(" %02x", ((const unsigned char*)addr)[off]); + for (off = line_beg; off < line_end; off++) { + if (off < size) + printf(" %02x", ((const unsigned char *)addr)[off]); else printf(" "); } printf(" "); - for(off = line_beg; off < line_end; off++) { - unsigned char byte = ((const unsigned char*)addr)[off]; - if(off < size) + for (off = line_beg; off < line_end; off++) { + unsigned char byte = ((const unsigned char *)addr)[off]; + if (off < size) printf("%c", (iscntrl(byte) ? '.' : byte)); else break; @@ -835,135 +836,128 @@ acutest_dump_(const char* title, const void* addr, size_t size) printf("\n"); } - if(truncate > 0) { + if (truncate > 0) { acutest_line_indent_(acutest_case_name_[0] ? 4 : 3); - printf(" ... (and more %u bytes)\n", (unsigned) truncate); + printf(" ... (and more %u bytes)\n", (unsigned)truncate); } } /* This is called just before each test */ -static void -acutest_init_(const char *test_name) +static void acutest_init_(const char *test_name) { #ifdef TEST_INIT - TEST_INIT - ; /* Allow for a single unterminated function call */ + TEST_INIT; /* Allow for a single unterminated function call */ #endif /* Suppress any warnings about unused variable. */ - (void) test_name; + (void)test_name; } /* This is called after each test */ -static void -acutest_fini_(const char *test_name) +static void acutest_fini_(const char *test_name) { #ifdef TEST_FINI - TEST_FINI - ; /* Allow for a single unterminated function call */ + TEST_FINI; /* Allow for a single unterminated function call */ #endif /* Suppress any warnings about unused variable. */ - (void) test_name; + (void)test_name; } -void -acutest_abort_(void) +void acutest_abort_(void) { - if(acutest_abort_has_jmp_buf_) { + if (acutest_abort_has_jmp_buf_) { longjmp(acutest_abort_jmp_buf_, 1); } else { - if(acutest_current_test_ != NULL) + if (acutest_current_test_ != NULL) acutest_fini_(acutest_current_test_->name); abort(); } } -static void -acutest_list_names_(void) +static void acutest_list_names_(void) { - const struct acutest_test_* test; + const struct acutest_test_ *test; printf("Unit tests:\n"); - for(test = ´st_list_[0]; test->func != NULL; test++) + for (test = ´st_list_[0]; test->func != NULL; test++) printf(" %s\n", test->name); } -static void -acutest_remember_(int i) +static void acutest_remember_(int i) { - if(acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_) + if (acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_) return; acutest_test_data_[i].flags |= ACUTEST_FLAG_RUN_; acutest_count_++; } -static void -acutest_set_success_(int i, int success) +static void acutest_set_success_(int i, int success) { - acutest_test_data_[i].flags |= success ? ACUTEST_FLAG_SUCCESS_ : ACUTEST_FLAG_FAILURE_; + acutest_test_data_[i].flags |= + success ? ACUTEST_FLAG_SUCCESS_ : ACUTEST_FLAG_FAILURE_; } -static void -acutest_set_duration_(int i, double duration) +static void acutest_set_duration_(int i, double duration) { acutest_test_data_[i].duration = duration; } -static int -acutest_name_contains_word_(const char* name, const char* pattern) +static int acutest_name_contains_word_(const char *name, const char *pattern) { static const char word_delim[] = " \t-_/.,:;"; - const char* substr; + const char *substr; size_t pattern_len; pattern_len = strlen(pattern); substr = strstr(name, pattern); - while(substr != NULL) { - int starts_on_word_boundary = (substr == name || strchr(word_delim, substr[-1]) != NULL); - int ends_on_word_boundary = (substr[pattern_len] == '\0' || strchr(word_delim, substr[pattern_len]) != NULL); + while (substr != NULL) { + int starts_on_word_boundary = + (substr == name || strchr(word_delim, substr[-1]) != NULL); + int ends_on_word_boundary = + (substr[pattern_len] == '\0' || + strchr(word_delim, substr[pattern_len]) != NULL); - if(starts_on_word_boundary && ends_on_word_boundary) + if (starts_on_word_boundary && ends_on_word_boundary) return 1; - substr = strstr(substr+1, pattern); + substr = strstr(substr + 1, pattern); } return 0; } -static int -acutest_lookup_(const char* pattern) +static int acutest_lookup_(const char *pattern) { int i; int n = 0; /* Try exact match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(strcmp(acutest_list_[i].name, pattern) == 0) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (strcmp(acutest_list_[i].name, pattern) == 0) { acutest_remember_(i); n++; break; } } - if(n > 0) + if (n > 0) return n; /* Try word match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(acutest_name_contains_word_(acutest_list_[i].name, pattern)) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (acutest_name_contains_word_(acutest_list_[i].name, pattern)) { acutest_remember_(i); n++; } } - if(n > 0) + if (n > 0) return n; /* Try relaxed match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(strstr(acutest_list_[i].name, pattern) != NULL) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (strstr(acutest_list_[i].name, pattern) != NULL) { acutest_remember_(i); n++; } @@ -972,21 +966,20 @@ acutest_lookup_(const char* pattern) return n; } - /* Called if anything goes bad in Acutest, or if the unit test ends in other * way then by normal returning from its function (e.g. exception or some * abnormal child process termination). */ -static void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_error_(const char* fmt, ...) +static void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_error_(const char *fmt, ...) { - if(acutest_verbose_level_ == 0) + if (acutest_verbose_level_ == 0) return; - if(acutest_verbose_level_ >= 2) { + if (acutest_verbose_level_ >= 2) { va_list args; acutest_line_indent_(1); - if(acutest_verbose_level_ >= 3) + if (acutest_verbose_level_ >= 3) acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "ERROR: "); va_start(args, fmt); vprintf(fmt, args); @@ -994,14 +987,13 @@ acutest_error_(const char* fmt, ...) printf("\n"); } - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { printf("\n"); } } /* Call directly the given test unit function. */ -static int -acutest_do_run_(const struct acutest_test_* test, int index) +static int acutest_do_run_(const struct acutest_test_ *test, int index) { int status = -1; @@ -1022,9 +1014,9 @@ acutest_do_run_(const struct acutest_test_* test, int index) fflush(stdout); fflush(stderr); - if(!acutest_worker_) { + if (!acutest_worker_) { acutest_abort_has_jmp_buf_ = 1; - if(setjmp(acutest_abort_jmp_buf_) != 0) { + if (setjmp(acutest_abort_jmp_buf_) != 0) { acutest_was_aborted_ = 1; goto aborted; } @@ -1032,56 +1024,58 @@ acutest_do_run_(const struct acutest_test_* test, int index) acutest_timer_get_time_(´st_timer_start_); test->func(); -aborted: + aborted: acutest_abort_has_jmp_buf_ = 0; acutest_timer_get_time_(´st_timer_end_); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); - if(acutest_test_failures_ == 0) { - acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS: "); + if (acutest_test_failures_ == 0) { + acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, + "SUCCESS: "); printf("All conditions have passed.\n"); - if(acutest_timer_) { + if (acutest_timer_) { acutest_line_indent_(1); printf("Duration: "); acutest_timer_print_diff_(); printf("\n"); } } else { - acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); - if(!acutest_was_aborted_) { + acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, + "FAILED: "); + if (!acutest_was_aborted_) { printf("%d condition%s %s failed.\n", - acutest_test_failures_, - (acutest_test_failures_ == 1) ? "" : "s", - (acutest_test_failures_ == 1) ? "has" : "have"); + acutest_test_failures_, + (acutest_test_failures_ == 1) ? "" : "s", + (acutest_test_failures_ == 1) ? "has" : "have"); } else { printf("Aborted.\n"); } } printf("\n"); - } else if(acutest_verbose_level_ >= 1 && acutest_test_failures_ == 0) { + } else if (acutest_verbose_level_ >= 1 && acutest_test_failures_ == 0) { acutest_finish_test_line_(0); } status = (acutest_test_failures_ == 0) ? 0 : -1; #ifdef __cplusplus - } catch(std::exception& e) { - const char* what = e.what(); + } catch (std::exception &e) { + const char *what = e.what(); acutest_check_(0, NULL, 0, "Threw std::exception"); - if(what != NULL) + if (what != NULL) acutest_message_("std::exception::what(): %s", what); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); printf("C++ exception.\n\n"); } - } catch(...) { + } catch (...) { acutest_check_(0, NULL, 0, "Threw an exception"); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); printf("C++ exception.\n\n"); @@ -1099,8 +1093,8 @@ aborted: /* Trigger the unit test. If possible (and not suppressed) it starts a child * process who calls acutest_do_run_(), otherwise it calls acutest_do_run_() * directly. */ -static void -acutest_run_(const struct acutest_test_* test, int index, int master_index) +static void acutest_run_(const struct acutest_test_ *test, int index, + int master_index) { int failed = 1; acutest_timer_type_ start, end; @@ -1109,7 +1103,7 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) acutest_test_already_logged_ = 0; acutest_timer_get_time_(&start); - if(!acutest_no_exec_) { + if (!acutest_no_exec_) { #if defined(ACUTEST_UNIX_) @@ -1121,10 +1115,10 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) fflush(stderr); pid = fork(); - if(pid == (pid_t)-1) { + if (pid == (pid_t)-1) { acutest_error_("Cannot fork. %s [%d]", strerror(errno), errno); failed = 1; - } else if(pid == 0) { + } else if (pid == 0) { /* Child: Do the test. */ acutest_worker_ = 1; failed = (acutest_do_run_(test, index) != 0); @@ -1132,29 +1126,54 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) } else { /* Parent: Wait until child terminates and analyze its exit code. */ waitpid(pid, &exit_code, 0); - if(WIFEXITED(exit_code)) { - switch(WEXITSTATUS(exit_code)) { - case 0: failed = 0; break; /* test has passed. */ - case 1: /* noop */ break; /* "normal" failure. */ - default: acutest_error_("Unexpected exit code [%d]", WEXITSTATUS(exit_code)); + if (WIFEXITED(exit_code)) { + switch (WEXITSTATUS(exit_code)) { + case 0: + failed = 0; + break; /* test has passed. */ + case 1: /* noop */ + break; /* "normal" failure. */ + default: + acutest_error_("Unexpected exit code [%d]", + WEXITSTATUS(exit_code)); } - } else if(WIFSIGNALED(exit_code)) { + } else if (WIFSIGNALED(exit_code)) { char tmp[32]; - const char* signame; - switch(WTERMSIG(exit_code)) { - case SIGINT: signame = "SIGINT"; break; - case SIGHUP: signame = "SIGHUP"; break; - case SIGQUIT: signame = "SIGQUIT"; break; - case SIGABRT: signame = "SIGABRT"; break; - case SIGKILL: signame = "SIGKILL"; break; - case SIGSEGV: signame = "SIGSEGV"; break; - case SIGILL: signame = "SIGILL"; break; - case SIGTERM: signame = "SIGTERM"; break; - default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break; + const char *signame; + switch (WTERMSIG(exit_code)) { + case SIGINT: + signame = "SIGINT"; + break; + case SIGHUP: + signame = "SIGHUP"; + break; + case SIGQUIT: + signame = "SIGQUIT"; + break; + case SIGABRT: + signame = "SIGABRT"; + break; + case SIGKILL: + signame = "SIGKILL"; + break; + case SIGSEGV: + signame = "SIGSEGV"; + break; + case SIGILL: + signame = "SIGILL"; + break; + case SIGTERM: + signame = "SIGTERM"; + break; + default: + sprintf(tmp, "signal %d", WTERMSIG(exit_code)); + signame = tmp; + break; } acutest_error_("Test interrupted by %s.", signame); } else { - acutest_error_("Test ended in an unexpected way [%d].", exit_code); + acutest_error_("Test ended in an unexpected way [%d].", + exit_code); } } @@ -1167,29 +1186,38 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) /* Windows has no fork(). So we propagate all info into the child * through a command line arguments. */ - _snprintf(buffer, sizeof(buffer)-1, - "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d --color=%s -- \"%s\"", - acutest_argv0_, index, acutest_timer_ ? "--time" : "", - acutest_tap_ ? "--tap" : "", acutest_verbose_level_, - acutest_colorize_ ? "always" : "never", - test->name); + _snprintf(buffer, sizeof(buffer) - 1, + "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d " + "--color=%s -- \"%s\"", + acutest_argv0_, index, acutest_timer_ ? "--time" : "", + acutest_tap_ ? "--tap" : "", acutest_verbose_level_, + acutest_colorize_ ? "always" : "never", test->name); memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(STARTUPINFO); - if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { + if (CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, + &startupInfo, &processInfo)) { WaitForSingleObject(processInfo.hProcess, INFINITE); GetExitCodeProcess(processInfo.hProcess, &exitCode); CloseHandle(processInfo.hThread); CloseHandle(processInfo.hProcess); failed = (exitCode != 0); - if(exitCode > 1) { - switch(exitCode) { - case 3: acutest_error_("Aborted."); break; - case 0xC0000005: acutest_error_("Access violation."); break; - default: acutest_error_("Test ended in an unexpected way [%lu].", exitCode); break; + if (exitCode > 1) { + switch (exitCode) { + case 3: + acutest_error_("Aborted."); + break; + case 0xC0000005: + acutest_error_("Access violation."); + break; + default: + acutest_error_("Test ended in an unexpected way [%lu].", + exitCode); + break; } } } else { - acutest_error_("Cannot create unit test subprocess [%ld].", GetLastError()); + acutest_error_("Cannot create unit test subprocess [%ld].", + GetLastError()); failed = 1; } @@ -1209,7 +1237,7 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) acutest_current_test_ = NULL; acutest_stat_run_units_++; - if(failed) + if (failed) acutest_stat_failed_units_++; acutest_set_success_(master_index, !failed); @@ -1218,12 +1246,13 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) #if defined(ACUTEST_WIN_) /* Callback for SEH events. */ -static LONG CALLBACK -acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) +static LONG CALLBACK acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) { acutest_check_(0, NULL, 0, "Unhandled SEH exception"); - acutest_message_("Exception code: 0x%08lx", ptrs->ExceptionRecord->ExceptionCode); - acutest_message_("Exception address: 0x%p", ptrs->ExceptionRecord->ExceptionAddress); + acutest_message_("Exception code: 0x%08lx", + ptrs->ExceptionRecord->ExceptionCode); + acutest_message_("Exception address: 0x%p", + ptrs->ExceptionRecord->ExceptionAddress); fflush(stdout); fflush(stderr); @@ -1232,38 +1261,37 @@ acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) } #endif +#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 +#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 -#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 -#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 - -#define ACUTEST_CMDLINE_OPTID_NONE_ 0 -#define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) -#define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) -#define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) +#define ACUTEST_CMDLINE_OPTID_NONE_ 0 +#define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) +#define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) +#define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) typedef struct acutest_test_CMDLINE_OPTION_ { char shortname; - const char* longname; + const char *longname; int id; unsigned flags; } ACUTEST_CMDLINE_OPTION_; -static int -acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_* options, - const char* arggroup, - int (*callback)(int /*optval*/, const char* /*arg*/)) +static int acutest_cmdline_handle_short_opt_group_( + const ACUTEST_CMDLINE_OPTION_ *options, const char *arggroup, + int (*callback)(int /*optval*/, const char * /*arg*/)) { - const ACUTEST_CMDLINE_OPTION_* opt; + const ACUTEST_CMDLINE_OPTION_ *opt; int i; int ret = 0; - for(i = 0; arggroup[i] != '\0'; i++) { - for(opt = options; opt->id != 0; opt++) { - if(arggroup[i] == opt->shortname) + for (i = 0; arggroup[i] != '\0'; i++) { + for (opt = options; opt->id != 0; opt++) { + if (arggroup[i] == opt->shortname) break; } - if(opt->id != 0 && !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + if (opt->id != 0 && + !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { ret = callback(opt->id, NULL); } else { /* Unknown option. */ @@ -1271,106 +1299,116 @@ acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_* options, badoptname[0] = '-'; badoptname[1] = arggroup[i]; badoptname[2] = '\0'; - ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_ : ACUTEST_CMDLINE_OPTID_UNKNOWN_), - badoptname); + ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_ + : ACUTEST_CMDLINE_OPTID_UNKNOWN_), + badoptname); } - if(ret != 0) + if (ret != 0) break; } return ret; } -#define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32 +#define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32 -static int -acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** argv, - int (*callback)(int /*optval*/, const char* /*arg*/)) +static int acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_ *options, + int argc, char **argv, + int (*callback)(int /*optval*/, + const char * /*arg*/)) { - const ACUTEST_CMDLINE_OPTION_* opt; - char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_+1]; + const ACUTEST_CMDLINE_OPTION_ *opt; + char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_ + 1]; int after_doubledash = 0; int i = 1; int ret = 0; auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_] = '\0'; - while(i < argc) { - if(after_doubledash || strcmp(argv[i], "-") == 0) { + while (i < argc) { + if (after_doubledash || strcmp(argv[i], "-") == 0) { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); - } else if(strcmp(argv[i], "--") == 0) { - /* End of options. All the remaining members are non-option arguments. */ + } else if (strcmp(argv[i], "--") == 0) { + /* End of options. All the remaining members are non-option + * arguments. */ after_doubledash = 1; - } else if(argv[i][0] != '-') { + } else if (argv[i][0] != '-') { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); } else { - for(opt = options; opt->id != 0; opt++) { - if(opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { + for (opt = options; opt->id != 0; opt++) { + if (opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { size_t len = strlen(opt->longname); - if(strncmp(argv[i]+2, opt->longname, len) == 0) { + if (strncmp(argv[i] + 2, opt->longname, len) == 0) { /* Regular long option. */ - if(argv[i][2+len] == '\0') { + if (argv[i][2 + len] == '\0') { /* with no argument provided. */ - if(!(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) + if (!(opt->flags & + ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) ret = callback(opt->id, NULL); else - ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + ret = callback( + ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); break; - } else if(argv[i][2+len] == '=') { + } else if (argv[i][2 + len] == '=') { /* with an argument provided. */ - if(opt->flags & (ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ | ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { - ret = callback(opt->id, argv[i]+2+len+1); + if (opt->flags & + (ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ | + ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + ret = callback(opt->id, argv[i] + 2 + len + 1); } else { sprintf(auxbuf, "--%s", opt->longname); - ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, auxbuf); + ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, + auxbuf); } break; } else { continue; } } - } else if(opt->shortname != '\0' && argv[i][0] == '-') { - if(argv[i][1] == opt->shortname) { + } else if (opt->shortname != '\0' && argv[i][0] == '-') { + if (argv[i][1] == opt->shortname) { /* Regular short option. */ - if(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_) { - if(argv[i][2] != '\0') - ret = callback(opt->id, argv[i]+2); - else if(i+1 < argc) + if (opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_) { + if (argv[i][2] != '\0') + ret = callback(opt->id, argv[i] + 2); + else if (i + 1 < argc) ret = callback(opt->id, argv[++i]); else - ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + ret = callback( + ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); break; } else { ret = callback(opt->id, NULL); /* There might be more (argument-less) short options * grouped together. */ - if(ret == 0 && argv[i][2] != '\0') - ret = acutest_cmdline_handle_short_opt_group_(options, argv[i]+2, callback); + if (ret == 0 && argv[i][2] != '\0') + ret = acutest_cmdline_handle_short_opt_group_( + options, argv[i] + 2, callback); break; } } } } - if(opt->id == 0) { /* still not handled? */ - if(argv[i][0] != '-') { + if (opt->id == 0) { /* still not handled? */ + if (argv[i][0] != '-') { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); } else { /* Unknown option. */ - char* badoptname = argv[i]; + char *badoptname = argv[i]; - if(strncmp(badoptname, "--", 2) == 0) { + if (strncmp(badoptname, "--", 2) == 0) { /* Strip any argument from the long option. */ - char* assignment = strchr(badoptname, '='); - if(assignment != NULL) { + char *assignment = strchr(badoptname, '='); + if (assignment != NULL) { size_t len = assignment - badoptname; - if(len > ACUTEST_CMDLINE_AUXBUF_SIZE_) + if (len > ACUTEST_CMDLINE_AUXBUF_SIZE_) len = ACUTEST_CMDLINE_AUXBUF_SIZE_; strncpy(auxbuf, badoptname, len); auxbuf[len] = '\0'; @@ -1383,7 +1421,7 @@ acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** a } } - if(ret != 0) + if (ret != 0) return ret; i++; } @@ -1391,28 +1429,34 @@ acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** a return ret; } -static void -acutest_help_(void) +static void acutest_help_(void) { printf("Usage: %s [options] [test...]\n", acutest_argv0_); printf("\n"); - printf("Run the specified unit tests; or if the option '--skip' is used, run all\n"); - printf("tests in the suite but those listed. By default, if no tests are specified\n"); + printf("Run the specified unit tests; or if the option '--skip' is used, " + "run all\n"); + printf("tests in the suite but those listed. By default, if no tests are " + "specified\n"); printf("on the command line, all unit tests in the suite are run.\n"); printf("\n"); printf("Options:\n"); - printf(" -s, --skip Execute all unit tests but the listed ones\n"); - printf(" --exec[=WHEN] If supported, execute unit tests as child processes\n"); - printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf( + " -s, --skip Execute all unit tests but the listed ones\n"); + printf(" --exec[=WHEN] If supported, execute unit tests as child " + "processes\n"); + printf(" (WHEN is one of 'auto', 'always', " + "'never')\n"); printf(" -E, --no-exec Same as --exec=never\n"); #if defined ACUTEST_WIN_ printf(" -t, --time Measure test duration\n"); #elif defined ACUTEST_HAS_POSIX_TIMER_ printf(" -t, --time Measure test duration (real time)\n"); - printf(" --time=TIMER Measure test duration, using given timer\n"); + printf( + " --time=TIMER Measure test duration, using given timer\n"); printf(" (TIMER is one of 'real', 'cpu')\n"); #endif - printf(" --no-summary Suppress printing of test results summary\n"); + printf( + " --no-summary Suppress printing of test results summary\n"); printf(" --tap Produce TAP-compliant output\n"); printf(" (See https://testanything.org/)\n"); printf(" -x, --xml-output=FILE Enable XUnit output to the given file\n"); @@ -1420,213 +1464,232 @@ acutest_help_(void) printf(" -v, --verbose Make output more verbose\n"); printf(" --verbose=LEVEL Set verbose level to LEVEL:\n"); printf(" 0 ... Be silent\n"); - printf(" 1 ... Output one line per test (and summary)\n"); - printf(" 2 ... As 1 and failed conditions (this is default)\n"); - printf(" 3 ... As 1 and all conditions (and extended summary)\n"); + printf(" 1 ... Output one line per test (and " + "summary)\n"); + printf(" 2 ... As 1 and failed conditions (this " + "is default)\n"); + printf(" 3 ... As 1 and all conditions (and " + "extended summary)\n"); printf(" -q, --quiet Same as --verbose=0\n"); printf(" --color[=WHEN] Enable colorized output\n"); - printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" (WHEN is one of 'auto', 'always', " + "'never')\n"); printf(" --no-color Same as --color=never\n"); printf(" -h, --help Display this help and exit\n"); - if(acutest_list_size_ < 16) { + if (acutest_list_size_ < 16) { printf("\n"); acutest_list_names_(); } } static const ACUTEST_CMDLINE_OPTION_ acutest_cmdline_options_[] = { - { 's', "skip", 's', 0 }, - { 0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 'E', "no-exec", 'E', 0 }, + {'s', "skip", 's', 0}, + {0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {'E', "no-exec", 'E', 0}, #if defined ACUTEST_WIN_ - { 't', "time", 't', 0 }, - { 0, "timer", 't', 0 }, /* kept for compatibility */ + {'t', "time", 't', 0}, + {0, "timer", 't', 0}, /* kept for compatibility */ #elif defined ACUTEST_HAS_POSIX_TIMER_ - { 't', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 0, "timer", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, /* kept for compatibility */ + {'t', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {0, "timer", 't', + ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, /* kept for compatibility */ #endif - { 0, "no-summary", 'S', 0 }, - { 0, "tap", 'T', 0 }, - { 'l', "list", 'l', 0 }, - { 'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 'q', "quiet", 'q', 0 }, - { 0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 0, "no-color", 'C', 0 }, - { 'h', "help", 'h', 0 }, - { 0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, /* internal */ - { 'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, - { 0, NULL, 0, 0 } -}; + {0, "no-summary", 'S', 0}, + {0, "tap", 'T', 0}, + {'l', "list", 'l', 0}, + {'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {'q', "quiet", 'q', 0}, + {0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {0, "no-color", 'C', 0}, + {'h', "help", 'h', 0}, + {0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, /* internal */ + {'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, + {0, NULL, 0, 0}}; -static int -acutest_cmdline_callback_(int id, const char* arg) +static int acutest_cmdline_callback_(int id, const char *arg) { - switch(id) { - case 's': - acutest_skip_mode_ = 1; - break; + switch (id) { + case 's': + acutest_skip_mode_ = 1; + break; - case 'e': - if(arg == NULL || strcmp(arg, "always") == 0) { - acutest_no_exec_ = 0; - } else if(strcmp(arg, "never") == 0) { - acutest_no_exec_ = 1; - } else if(strcmp(arg, "auto") == 0) { - /*noop*/ - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --exec.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case 'E': + case 'e': + if (arg == NULL || strcmp(arg, "always") == 0) { + acutest_no_exec_ = 0; + } else if (strcmp(arg, "never") == 0) { acutest_no_exec_ = 1; - break; + } else if (strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --exec.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + } + break; - case 't': -#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ - if(arg == NULL || strcmp(arg, "real") == 0) { - acutest_timer_ = 1; - #ifndef ACUTEST_WIN_ - } else if(strcmp(arg, "cpu") == 0) { - acutest_timer_ = 2; - #endif - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --time.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } + case 'E': + acutest_no_exec_ = 1; + break; + + case 't': +#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ + if (arg == NULL || strcmp(arg, "real") == 0) { + acutest_timer_ = 1; +#ifndef ACUTEST_WIN_ + } else if (strcmp(arg, "cpu") == 0) { + acutest_timer_ = 2; #endif - break; + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --time.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + } +#endif + break; - case 'S': - acutest_no_summary_ = 1; - break; + case 'S': + acutest_no_summary_ = 1; + break; - case 'T': - acutest_tap_ = 1; - break; + case 'T': + acutest_tap_ = 1; + break; - case 'l': - acutest_list_names_(); - acutest_exit_(0); - break; + case 'l': + acutest_list_names_(); + acutest_exit_(0); + break; - case 'v': - acutest_verbose_level_ = (arg != NULL ? atoi(arg) : acutest_verbose_level_+1); - break; + case 'v': + acutest_verbose_level_ = + (arg != NULL ? atoi(arg) : acutest_verbose_level_ + 1); + break; - case 'q': - acutest_verbose_level_ = 0; - break; + case 'q': + acutest_verbose_level_ = 0; + break; - case 'c': - if(arg == NULL || strcmp(arg, "always") == 0) { - acutest_colorize_ = 1; - } else if(strcmp(arg, "never") == 0) { - acutest_colorize_ = 0; - } else if(strcmp(arg, "auto") == 0) { - /*noop*/ - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --color.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case 'C': + case 'c': + if (arg == NULL || strcmp(arg, "always") == 0) { + acutest_colorize_ = 1; + } else if (strcmp(arg, "never") == 0) { acutest_colorize_ = 0; - break; - - case 'h': - acutest_help_(); - acutest_exit_(0); - break; - - case 'w': - acutest_worker_ = 1; - acutest_worker_index_ = atoi(arg); - break; - case 'x': - acutest_xml_output_ = fopen(arg, "w"); - if (!acutest_xml_output_) { - fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); - acutest_exit_(2); - } - break; - - case 0: - if(acutest_lookup_(arg) == 0) { - fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --list' for list of unit tests.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case ACUTEST_CMDLINE_OPTID_UNKNOWN_: - fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); + } else if (strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --color.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); acutest_exit_(2); - break; + } + break; - case ACUTEST_CMDLINE_OPTID_MISSINGARG_: - fprintf(stderr, "The command line option '%s' requires an argument.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - break; + case 'C': + acutest_colorize_ = 0; + break; - case ACUTEST_CMDLINE_OPTID_BOGUSARG_: - fprintf(stderr, "The command line option '%s' does not expect an argument.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); + case 'h': + acutest_help_(); + acutest_exit_(0); + break; + + case 'w': + acutest_worker_ = 1; + acutest_worker_index_ = atoi(arg); + break; + case 'x': + acutest_xml_output_ = fopen(arg, "w"); + if (!acutest_xml_output_) { + fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); acutest_exit_(2); - break; + } + break; + + case 0: + if (acutest_lookup_(arg) == 0) { + fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, + arg); + fprintf(stderr, "Try '%s --list' for list of unit tests.\n", + acutest_argv0_); + acutest_exit_(2); + } + break; + + case ACUTEST_CMDLINE_OPTID_UNKNOWN_: + fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; + + case ACUTEST_CMDLINE_OPTID_MISSINGARG_: + fprintf(stderr, "The command line option '%s' requires an argument.\n", + arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; + + case ACUTEST_CMDLINE_OPTID_BOGUSARG_: + fprintf(stderr, + "The command line option '%s' does not expect an argument.\n", + arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; } return 0; } - #ifdef ACUTEST_LINUX_ -static int -acutest_is_tracer_present_(void) +static int acutest_is_tracer_present_(void) { /* Must be large enough so the line 'TracerPid: ${PID}' can fit in. */ static const int OVERLAP = 32; - char buf[256+OVERLAP+1]; + char buf[256 + OVERLAP + 1]; int tracer_present = 0; int fd; size_t n_read = 0; fd = open("/proc/self/status", O_RDONLY); - if(fd == -1) + if (fd == -1) return 0; - while(1) { + while (1) { static const char pattern[] = "TracerPid:"; - const char* field; + const char *field; - while(n_read < sizeof(buf) - 1) { + while (n_read < sizeof(buf) - 1) { ssize_t n; n = read(fd, buf + n_read, sizeof(buf) - 1 - n_read); - if(n <= 0) + if (n <= 0) break; n_read += n; } buf[n_read] = '\0'; field = strstr(buf, pattern); - if(field != NULL && field < buf + sizeof(buf) - OVERLAP) { - pid_t tracer_pid = (pid_t) atoi(field + sizeof(pattern) - 1); + if (field != NULL && field < buf + sizeof(buf) - OVERLAP) { + pid_t tracer_pid = (pid_t)atoi(field + sizeof(pattern) - 1); tracer_present = (tracer_pid != 0); break; } - if(n_read == sizeof(buf)-1) { - memmove(buf, buf + sizeof(buf)-1 - OVERLAP, OVERLAP); + if (n_read == sizeof(buf) - 1) { + memmove(buf, buf + sizeof(buf) - 1 - OVERLAP, OVERLAP); n_read = OVERLAP; } else { break; @@ -1639,8 +1702,7 @@ acutest_is_tracer_present_(void) #endif #ifdef ACUTEST_MACOS_ -static bool -acutest_AmIBeingDebugged(void) +static bool acutest_AmIBeingDebugged(void) { int junk; int mib[4]; @@ -1664,12 +1726,11 @@ acutest_AmIBeingDebugged(void) assert(junk == 0); // We're being debugged if the P_TRACED flag is set. - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + return ((info.kp_proc.p_flag & P_TRACED) != 0); } #endif -int -main(int argc, char** argv) +int main(int argc, char **argv) { int i; @@ -1678,28 +1739,30 @@ main(int argc, char** argv) #if defined ACUTEST_UNIX_ acutest_colorize_ = isatty(STDOUT_FILENO); #elif defined ACUTEST_WIN_ - #if defined _BORLANDC_ +#if defined _BORLANDC_ acutest_colorize_ = isatty(_fileno(stdout)); - #else +#else acutest_colorize_ = _isatty(_fileno(stdout)); - #endif +#endif #else acutest_colorize_ = 0; #endif /* Count all test units */ acutest_list_size_ = 0; - for(i = 0; acutest_list_[i].func != NULL; i++) + for (i = 0; acutest_list_[i].func != NULL; i++) acutest_list_size_++; - acutest_test_data_ = (struct acutest_test_data_*)calloc(acutest_list_size_, sizeof(struct acutest_test_data_)); - if(acutest_test_data_ == NULL) { + acutest_test_data_ = (struct acutest_test_data_ *)calloc( + acutest_list_size_, sizeof(struct acutest_test_data_)); + if (acutest_test_data_ == NULL) { fprintf(stderr, "Out of memory.\n"); acutest_exit_(2); } /* Parse options */ - acutest_cmdline_read_(acutest_cmdline_options_, argc, argv, acutest_cmdline_callback_); + acutest_cmdline_read_(acutest_cmdline_options_, argc, argv, + acutest_cmdline_callback_); /* Initialize the proper timer. */ acutest_timer_init_(); @@ -1712,83 +1775,89 @@ main(int argc, char** argv) #endif /* By default, we want to run all tests. */ - if(acutest_count_ == 0) { - for(i = 0; acutest_list_[i].func != NULL; i++) + if (acutest_count_ == 0) { + for (i = 0; acutest_list_[i].func != NULL; i++) acutest_remember_(i); } /* Guess whether we want to run unit tests as child processes. */ - if(acutest_no_exec_ < 0) { + if (acutest_no_exec_ < 0) { acutest_no_exec_ = 0; - if(acutest_count_ <= 1) { + if (acutest_count_ <= 1) { acutest_no_exec_ = 1; } else { #ifdef ACUTEST_WIN_ - if(IsDebuggerPresent()) + if (IsDebuggerPresent()) acutest_no_exec_ = 1; #endif #ifdef ACUTEST_LINUX_ - if(acutest_is_tracer_present_()) + if (acutest_is_tracer_present_()) acutest_no_exec_ = 1; #endif #ifdef ACUTEST_MACOS_ - if(acutest_AmIBeingDebugged()) + if (acutest_AmIBeingDebugged()) acutest_no_exec_ = 1; #endif #ifdef RUNNING_ON_VALGRIND - /* RUNNING_ON_VALGRIND is provided by optionally included */ - if(RUNNING_ON_VALGRIND) + /* RUNNING_ON_VALGRIND is provided by optionally included + * */ + if (RUNNING_ON_VALGRIND) acutest_no_exec_ = 1; #endif } } - if(acutest_tap_) { + if (acutest_tap_) { /* TAP requires we know test result ("ok", "not ok") before we output * anything about the test, and this gets problematic for larger verbose * levels. */ - if(acutest_verbose_level_ > 2) + if (acutest_verbose_level_ > 2) acutest_verbose_level_ = 2; /* TAP harness should provide some summary. */ acutest_no_summary_ = 1; - if(!acutest_worker_) - printf("1..%d\n", (int) acutest_count_); + if (!acutest_worker_) + printf("1..%d\n", (int)acutest_count_); } int index = acutest_worker_index_; - for(i = 0; acutest_list_[i].func != NULL; i++) { + for (i = 0; acutest_list_[i].func != NULL; i++) { int run = (acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_); if (acutest_skip_mode_) /* Run all tests except those listed. */ run = !run; - if(run) + if (run) acutest_run_(´st_list_[i], index++, i); } /* Write a summary */ - if(!acutest_no_summary_ && acutest_verbose_level_ >= 1) { - if(acutest_verbose_level_ >= 3) { - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Summary:\n"); + if (!acutest_no_summary_ && acutest_verbose_level_ >= 1) { + if (acutest_verbose_level_ >= 3) { + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Summary:\n"); - printf(" Count of all unit tests: %4d\n", (int) acutest_list_size_); - printf(" Count of run unit tests: %4d\n", acutest_stat_run_units_); - printf(" Count of failed unit tests: %4d\n", acutest_stat_failed_units_); - printf(" Count of skipped unit tests: %4d\n", (int) acutest_list_size_ - acutest_stat_run_units_); + printf(" Count of all unit tests: %4d\n", + (int)acutest_list_size_); + printf(" Count of run unit tests: %4d\n", + acutest_stat_run_units_); + printf(" Count of failed unit tests: %4d\n", + acutest_stat_failed_units_); + printf(" Count of skipped unit tests: %4d\n", + (int)acutest_list_size_ - acutest_stat_run_units_); } - if(acutest_stat_failed_units_ == 0) { + if (acutest_stat_failed_units_ == 0) { acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS:"); printf(" All unit tests have passed.\n"); } else { acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED:"); printf(" %d of %d unit tests %s failed.\n", - acutest_stat_failed_units_, acutest_stat_run_units_, - (acutest_stat_failed_units_ == 1) ? "has" : "have"); + acutest_stat_failed_units_, acutest_stat_run_units_, + (acutest_stat_failed_units_ == 1) ? "has" : "have"); } - if(acutest_verbose_level_ >= 3) + if (acutest_verbose_level_ >= 3) printf("\n"); } @@ -1801,16 +1870,23 @@ main(int argc, char** argv) #else const char *suite_name = argv[0]; #endif - fprintf(acutest_xml_output_, "\n"); - fprintf(acutest_xml_output_, "\n", - suite_name, (int)acutest_list_size_, acutest_stat_failed_units_, acutest_stat_failed_units_, - (int)acutest_list_size_ - acutest_stat_run_units_); - for(i = 0; acutest_list_[i].func != NULL; i++) { + fprintf(acutest_xml_output_, + "\n"); + fprintf(acutest_xml_output_, + "\n", + suite_name, (int)acutest_list_size_, acutest_stat_failed_units_, + acutest_stat_failed_units_, + (int)acutest_list_size_ - acutest_stat_run_units_); + for (i = 0; acutest_list_[i].func != NULL; i++) { struct acutest_test_data_ *details = ´st_test_data_[i]; - fprintf(acutest_xml_output_, " \n", acutest_list_[i].name, details->duration); + fprintf(acutest_xml_output_, + " \n", + acutest_list_[i].name, details->duration); if (details->flags & ACUTEST_FLAG_FAILURE_) fprintf(acutest_xml_output_, " \n"); - if (!(details->flags & ACUTEST_FLAG_FAILURE_) && !(details->flags & ACUTEST_FLAG_SUCCESS_)) + if (!(details->flags & ACUTEST_FLAG_FAILURE_) && + !(details->flags & ACUTEST_FLAG_SUCCESS_)) fprintf(acutest_xml_output_, " \n"); fprintf(acutest_xml_output_, " \n"); } @@ -1823,15 +1899,14 @@ main(int argc, char** argv) return (acutest_stat_failed_units_ == 0) ? 0 : 1; } - -#endif /* #ifndef TEST_NO_MAIN */ +#endif /* #ifndef TEST_NO_MAIN */ #ifdef _MSC_VER - #pragma warning(pop) +#pragma warning(pop) #endif #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif -#endif /* #ifndef ACUTEST_H */ +#endif /* #ifndef ACUTEST_H */ diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 6a609243..4bfd3127 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -3,14 +3,17 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_arm_nop() { - uc_engine* uc; +static void test_arm_nop() +{ + uc_engine *uc; char code[] = "\x00\xf0\x20\xe3"; // nop int r_r0 = 0x1234; int r_r2 = 0x6789; @@ -29,8 +32,9 @@ static void test_arm_nop() { OK(uc_close(uc)); } -static void test_arm_thumb_sub() { - uc_engine* uc; +static void test_arm_thumb_sub() +{ + uc_engine *uc; char code[] = "\x83\xb0"; // sub sp, #0xc int r_sp = 0x1234; @@ -45,15 +49,18 @@ static void test_arm_thumb_sub() { OK(uc_close(uc)); } -static void test_armeb_sub() { - uc_engine* uc; - char code[] = "\xe3\xa0\x00\x37\xe0\x42\x10\x03"; // mov r0, #0x37; sub r1, r2, r3 +static void test_armeb_sub() +{ + uc_engine *uc; + char code[] = + "\xe3\xa0\x00\x37\xe0\x42\x10\x03"; // mov r0, #0x37; sub r1, r2, r3 int r_r0 = 0x1234; int r_r2 = 0x6789; int r_r3 = 0x3333; int r_r1; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_ARM_REG_R0, &r_r0)); OK(uc_reg_write(uc, UC_ARM_REG_R2, &r_r2)); OK(uc_reg_write(uc, UC_ARM_REG_R3, &r_r3)); @@ -73,12 +80,14 @@ static void test_armeb_sub() { OK(uc_close(uc)); } -static void test_arm_thumbeb_sub() { - uc_engine* uc; +static void test_arm_thumbeb_sub() +{ + uc_engine *uc; char code[] = "\xb0\x83"; // sub sp, #0xc int r_sp = 0x1234; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0)); @@ -89,16 +98,25 @@ static void test_arm_thumbeb_sub() { OK(uc_close(uc)); } -static void test_arm_thumb_ite_count_callback(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) { - uint64_t* count = (uint64_t*)user_data; +static void test_arm_thumb_ite_count_callback(uc_engine *uc, uint64_t address, + uint32_t size, void *user_data) +{ + uint64_t *count = (uint64_t *)user_data; (*count) += 1; } -static void test_arm_thumb_ite() { - uc_engine* uc; +static void test_arm_thumb_ite() +{ + uc_engine *uc; uc_hook hook; - char code[] = "\x9a\x42\x15\xbf\x00\x9a\x01\x9a\x78\x23\x15\x23"; // cmp r2, r3; itete ne; ldrne r2, [sp]; ldreq r2, [sp,#4]; movne r3, #0x78; moveq r3, #0x15 + char code[] = + "\x9a\x42\x15\xbf\x00\x9a\x01\x9a\x78\x23\x15\x23"; // cmp r2, r3; itete + // ne; ldrne r2, + // [sp]; ldreq r2, + // [sp,#4]; movne + // r3, #0x78; moveq + // r3, #0x15 int r_sp = 0x8000; int r_r2 = 0; int r_r3 = 1; @@ -116,7 +134,8 @@ static void test_arm_thumb_ite() { r_r2 = 0x4d; OK(uc_mem_write(uc, r_sp + 4, &r_r2, 4)); - OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_arm_thumb_ite_count_callback, &count, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_arm_thumb_ite_count_callback, + &count, 1, 0)); // Execute four instructions at a time. OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0)); @@ -146,19 +165,22 @@ static void test_arm_thumb_ite() { OK(uc_close(uc)); } -static void test_arm_m_thumb_mrs() { - uc_engine* uc; - char code[] = "\xef\xf3\x14\x80\xef\xf3\x00\x81"; // mrs r0, control; mrs r1, apsr +static void test_arm_m_thumb_mrs() +{ + uc_engine *uc; + char code[] = + "\xef\xf3\x14\x80\xef\xf3\x00\x81"; // mrs r0, control; mrs r1, apsr uint32_t r_control = 0b10; uint32_t r_apsr = (0b10101 << 27); uint32_t r_r0, r_r1; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control)); OK(uc_reg_write(uc, UC_ARM_REG_APSR_NZCVQ, &r_apsr)); OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0)); - + OK(uc_reg_read(uc, UC_ARM_REG_R0, &r_r0)); OK(uc_reg_read(uc, UC_ARM_REG_R1, &r_r1)); @@ -168,8 +190,9 @@ static void test_arm_m_thumb_mrs() { OK(uc_close(uc)); } -static void test_arm_m_control() { - uc_engine* uc; +static void test_arm_m_control() +{ + uc_engine *uc; int r_control, r_msp, r_psp; OK(uc_open(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, &uc)); @@ -195,16 +218,19 @@ static void test_arm_m_control() { OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_msp)); TEST_CHECK(r_psp != r_msp); TEST_CHECK(r_msp == 0x1000); - + OK(uc_close(uc)); } // // Some notes: -// Qemu raise a special exception EXCP_EXCEPTION_EXIT to handle the EXC_RETURN. We can't -// help user handle EXC_RETURN since unicorn is designed not to handle any CPU exception. +// Qemu raise a special exception EXCP_EXCEPTION_EXIT to handle the +// EXC_RETURN. We can't help user handle EXC_RETURN since unicorn is designed +// not to handle any CPU exception. // -static void test_arm_m_exc_return_hook_interrupt(uc_engine* uc, int intno, void* data) { +static void test_arm_m_exc_return_hook_interrupt(uc_engine *uc, int intno, + void *data) +{ int r_pc; OK(uc_reg_read(uc, UC_ARM_REG_PC, &r_pc)); @@ -213,16 +239,19 @@ static void test_arm_m_exc_return_hook_interrupt(uc_engine* uc, int intno, void* OK(uc_emu_stop(uc)); } -static void test_arm_m_exc_return() { - uc_engine* uc; +static void test_arm_m_exc_return() +{ + uc_engine *uc; char code[] = "\x6f\xf0\x02\x00\x00\x47"; // mov r0, #0xFFFFFFFD; bx r0; int r_ipsr; int r_sp = 0x8000; uc_hook hook; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, + sizeof(code) - 1); OK(uc_mem_map(uc, r_sp - 0x1000, 0x1000, UC_PROT_ALL)); - OK(uc_hook_add(uc, &hook, UC_HOOK_INTR, test_arm_m_exc_return_hook_interrupt, NULL, 0, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_INTR, + test_arm_m_exc_return_hook_interrupt, NULL, 0, 0)); r_sp -= 0x1c; OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); @@ -230,20 +259,19 @@ static void test_arm_m_exc_return() { r_ipsr = 16; // We are in whatever exception. OK(uc_reg_write(uc, UC_ARM_REG_IPSR, &r_ipsr)); - OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 2)); // Just execute 2 instructions. + OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, + 2)); // Just execute 2 instructions. OK(uc_hook_del(uc, hook)); OK(uc_close(uc)); } -TEST_LIST = { - { "test_arm_nop", test_arm_nop }, - { "test_arm_thumb_sub", test_arm_thumb_sub }, - { "test_armeb_sub", test_armeb_sub }, - { "test_arm_thumbeb_sub", test_arm_thumbeb_sub }, - { "test_arm_thumb_ite", test_arm_thumb_ite }, - { "test_arm_m_thumb_mrs", test_arm_m_thumb_mrs }, - { "test_arm_m_control", test_arm_m_control }, - { "test_arm_m_exc_return", test_arm_m_exc_return }, - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{"test_arm_nop", test_arm_nop}, + {"test_arm_thumb_sub", test_arm_thumb_sub}, + {"test_armeb_sub", test_armeb_sub}, + {"test_arm_thumbeb_sub", test_arm_thumbeb_sub}, + {"test_arm_thumb_ite", test_arm_thumb_ite}, + {"test_arm_m_thumb_mrs", test_arm_m_thumb_mrs}, + {"test_arm_m_control", test_arm_m_control}, + {"test_arm_m_exc_return", test_arm_m_exc_return}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 972d24c6..302945db 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -3,6 +3,51 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + +static void test_arm64_until() +{ + uc_engine *uc; + char code[] = "\x30\x00\x80\xd2\x11\x04\x80\xd2\x9c\x23\x00\x91"; + + /* + mov x16, #1 + mov x17, #0x20 + add x28, x28, 8 + */ + + uint64_t r_x16 = 0x12341234; + uint64_t r_x17 = 0x78907890; + uint64_t r_pc = 0x00000000; + uint64_t r_x28 = 0x12341234; + + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16)); + OK(uc_reg_write(uc, UC_ARM64_REG_X17, &r_x17)); + OK(uc_reg_write(uc, UC_ARM64_REG_X28, &r_x28)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3)); + + OK(uc_reg_read(uc, UC_ARM64_REG_X16, &r_x16)); + OK(uc_reg_read(uc, UC_ARM64_REG_X17, &r_x17)); + OK(uc_reg_read(uc, UC_ARM64_REG_X28, &r_x28)); + OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc)); + + TEST_CHECK(r_x16 == 0x1); + TEST_CHECK(r_x17 == 0x20); + TEST_CHECK(r_x28 == 0x1234123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +TEST_LIST = {{"test_arm64_until", test_arm64_until}, {NULL, NULL}}; diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c new file mode 100644 index 00000000..31594bfc --- /dev/null +++ b/tests/unit/test_ctl.c @@ -0,0 +1,165 @@ +#include "unicorn_test.h" +#include +#include + +// We have to copy this for Android. +#ifdef _WIN32 + +#include "windows.h" + +static inline int64_t get_clock_realtime(void) +{ + // code from + // https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows + // >>>>>>>>> + const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); + + long tv_sec, tv_usec; + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = ((uint64_t)file_time.dwLowDateTime); + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tv_sec = (long)((time - EPOCH) / 10000000L); + tv_usec = (long)(system_time.wMilliseconds * 1000); + // <<<<<<<<< + + return tv_sec * 1000000000LL + (tv_usec * 1000); +} +#else + +#include + +/* get host real time in nanosecond */ +static inline int64_t get_clock_realtime(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); +} + +#endif + +const uint64_t code_start = 0x1000; +const uint64_t code_len = 0x4000; + +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + +#define GEN_SIMPLE_READ_TEST(field, ctl_type, arg_type, expected) \ + static void test_uc_ctl_##field() \ + { \ + uc_engine *uc; \ + arg_type arg; \ + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); \ + OK(uc_ctl(uc, UC_CTL_READ(ctl_type, 1), &arg)); \ + TEST_CHECK(arg == expected); \ + OK(uc_close(uc)); \ + } + +GEN_SIMPLE_READ_TEST(mode, UC_CTL_UC_MODE, int, 4) +GEN_SIMPLE_READ_TEST(arch, UC_CTL_UC_ARCH, int, 4) +GEN_SIMPLE_READ_TEST(page_size, UC_CTL_UC_PAGE_SIZE, uint32_t, 4096) +GEN_SIMPLE_READ_TEST(time_out, UC_CTL_UC_TIMEOUT, uint64_t, 0) + +static void test_uc_ctl_exits() +{ + uc_engine *uc; + // cmp eax, 0; + // jg lb; + // inc eax; + // nop; <---- exit1 + // lb: + // inc ebx; + // nop; <---- exit2 + char code[] = "\x83\xf8\x00\x7f\x02\x40\x90\x43\x90"; + int r_eax; + int r_ebx; + uint64_t exits[] = {code_start + 6, code_start + 8}; + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); + OK(uc_ctl_exits_enabled(uc, true)); + OK(uc_ctl_set_exists(uc, exits, 2)); + r_eax = 0; + r_ebx = 0; + OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); + OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_ebx)); + + // Run two times. + OK(uc_emu_start(uc, code_start, 0, 0, 0)); + OK(uc_emu_start(uc, code_start, 0, 0, 0)); + + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_ebx)); + + TEST_CHECK(r_eax == 1); + TEST_CHECK(r_ebx == 1); + + OK(uc_close(uc)); +} + +double time_emulation(uc_engine *uc, uint64_t start, uint64_t end) +{ + int64_t t1, t2; + + t1 = get_clock_realtime(); + + OK(uc_emu_start(uc, start, end, 0, 0)); + + t2 = get_clock_realtime(); + + return t2 - t1; +} + +#define TB_COUNT (8) +#define TCG_MAX_INSNS (512) // from tcg.h +#define CODE_LEN TB_COUNT *TCG_MAX_INSNS + +static void test_uc_ctl_tb_cache() +{ + uc_engine *uc; + char code[CODE_LEN]; + double standard, cached, evicted; + + memset(code, 0x90, CODE_LEN); + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); + + standard = time_emulation(uc, code_start, code_start + sizeof(code) - 1); + + for (int i = 0; i < TB_COUNT; i++) { + OK(uc_ctl_request_cache(uc, code_start + i * TCG_MAX_INSNS, NULL)); + } + + cached = time_emulation(uc, code_start, code_start + sizeof(code) - 1); + + for (int i = 0; i < TB_COUNT; i++) { + OK(uc_ctl_remove_cache(uc, code_start + i * TCG_MAX_INSNS)); + } + evicted = time_emulation(uc, code_start, code_start + sizeof(code) - 1); + + // In fact, evicted is also slightly faster than standard but we don't do + // this guarantee. + TEST_CHECK(cached < standard); + TEST_CHECK(evicted > cached); + + OK(uc_close(uc)); +} + +TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, + {"test_uc_ctl_page_size", test_uc_ctl_page_size}, + {"test_uc_ctl_arch", test_uc_ctl_arch}, + {"test_uc_ctl_time_out", test_uc_ctl_time_out}, + {"test_uc_ctl_exits", test_uc_ctl_exits}, + {"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_m68k.c b/tests/unit/test_m68k.c index 972d24c6..4c2505f4 100644 --- a/tests/unit/test_m68k.c +++ b/tests/unit/test_m68k.c @@ -3,6 +3,4 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c new file mode 100644 index 00000000..987a3ae3 --- /dev/null +++ b/tests/unit/test_mem.c @@ -0,0 +1,40 @@ +#include "unicorn_test.h" + +static void test_map_correct() +{ + uc_engine *uc; + + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_mem_map(uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); // [0x40000, 0x50000] + OK(uc_mem_map(uc, 0x60000, 0x1000 * 16, UC_PROT_ALL)); // [0x60000, 0x70000] + OK(uc_mem_map(uc, 0x20000, 0x1000 * 16, UC_PROT_ALL)); // [0x20000, 0x30000] + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x10000, 0x2000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x25000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x35000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x45000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x55000, 0x2000 * 16, UC_PROT_ALL)); + OK(uc_mem_map(uc, 0x35000, 0x5000, UC_PROT_ALL)); + OK(uc_mem_map(uc, 0x50000, 0x5000, UC_PROT_ALL)); + + OK(uc_close(uc)); +} + +static void test_map_wrapping() +{ + uc_engine *uc; + + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + uc_assert_err(UC_ERR_ARG, uc_mem_map(uc, (~0ll - 0x4000) & ~0xfff, 0x8000, + UC_PROT_ALL)); + + OK(uc_close(uc)); +} + +TEST_LIST = {{"test_map_correct", test_map_correct}, + {"test_map_wrapping", test_map_wrapping}, + {NULL, NULL}}; diff --git a/tests/unit/test_mips.c b/tests/unit/test_mips.c index bfff4cad..61699e5d 100644 --- a/tests/unit/test_mips.c +++ b/tests/unit/test_mips.c @@ -3,18 +3,22 @@ const uint64_t code_start = 0x10000000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_mips_el_ori() { - uc_engine* uc; +static void test_mips_el_ori() +{ + uc_engine *uc; char code[] = "\x56\x34\x21\x34"; // ori $at, $at, 0x3456; int r_r1 = 0x6789; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -26,12 +30,14 @@ static void test_mips_el_ori() { OK(uc_close(uc)); } -static void test_mips_eb_ori() { - uc_engine* uc; +static void test_mips_eb_ori() +{ + uc_engine *uc; char code[] = "\x34\x21\x34\x56"; // ori $at, $at, 0x3456; int r_r1 = 0x6789; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -43,37 +49,43 @@ static void test_mips_eb_ori() { OK(uc_close(uc)); } -static void test_mips_stop_at_branch() { - uc_engine* uc; - char code[] = "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; +static void test_mips_stop_at_branch() +{ + uc_engine *uc; + char code[] = + "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; int r_pc = 0x0; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); - + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); + // Execute one instruction with branch delay slot. OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 1)); OK(uc_reg_read(uc, UC_MIPS_REG_PC, &r_pc)); - // Even if we just execute one instruction, the instruction in the + // Even if we just execute one instruction, the instruction in the // delay slot would also be executed. TEST_CHECK(r_pc == code_start + 0x8); OK(uc_close(uc)); } -static void test_mips_stop_at_delay_slot() { - uc_engine* uc; - char code[] = "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; +static void test_mips_stop_at_delay_slot() +{ + uc_engine *uc; + char code[] = + "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; int r_pc = 0x0; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); - + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); + // Stop at the delay slot by design. OK(uc_emu_start(uc, code_start, code_start + 4, 0, 0)); OK(uc_reg_read(uc, UC_MIPS_REG_PC, &r_pc)); - + // The branch instruction isn't committed and the PC is not updated. // Users is responsible to restart emulation at the branch instruction. TEST_CHECK(r_pc == code_start); @@ -81,12 +93,14 @@ static void test_mips_stop_at_delay_slot() { OK(uc_close(uc)); } -static void test_mips_lwx_exception_issue_1314() { - uc_engine* uc; +static void test_mips_lwx_exception_issue_1314() +{ + uc_engine *uc; char code[] = "\x0a\xc8\x79\x7e"; // lwx $t9, $t9($s3) int reg; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); OK(uc_mem_map(uc, 0x10000, 0x4000, UC_PROT_ALL)); // Enable DSP @@ -113,10 +127,9 @@ static void test_mips_lwx_exception_issue_1314() { } TEST_LIST = { - { "test_mips_stop_at_branch", test_mips_stop_at_branch }, - { "test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot}, - { "test_mips_el_ori", test_mips_el_ori}, - { "test_mips_eb_ori", test_mips_eb_ori}, - { "test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314}, - { NULL, NULL } -}; \ No newline at end of file + {"test_mips_stop_at_branch", test_mips_stop_at_branch}, + {"test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot}, + {"test_mips_el_ori", test_mips_el_ori}, + {"test_mips_eb_ori", test_mips_eb_ori}, + {"test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_ppc.c b/tests/unit/test_ppc.c index c457bd70..41fed7c4 100644 --- a/tests/unit/test_ppc.c +++ b/tests/unit/test_ppc.c @@ -3,18 +3,22 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_ppc32_add() { - uc_engine* uc; +static void test_ppc32_add() +{ + uc_engine *uc; char code[] = "\x7f\x46\x1a\x14"; // ADD 26, 6, 3 int reg; - uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); reg = 42; OK(uc_reg_write(uc, UC_PPC_REG_3, ®)); @@ -30,7 +34,4 @@ static void test_ppc32_add() { OK(uc_close(uc)); } -TEST_LIST = { - { "test_ppc32_add", test_ppc32_add }, - { NULL, NULL} -}; \ No newline at end of file +TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 972d24c6..24fb87e1 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -3,6 +3,224 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + +static void test_riscv32_nop() +{ + uc_engine *uc; + char code[] = "\x13\x00\x00\x00"; // nop + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x5678; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, + sizeof(code) - 1); + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + TEST_CHECK(r_t0 == 0x1234); + TEST_CHECK(r_t1 == 0x5678); + + OK(uc_close(uc)); +} + +static void test_riscv64_nop() +{ + uc_engine *uc; + char code[] = "\x13\x00\x00\x00"; // nop + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x5678; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, + sizeof(code) - 1); + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + TEST_CHECK(r_t0 == 0x1234); + TEST_CHECK(r_t1 == 0x5678); + + OK(uc_close(uc)); +} + +static void test_riscv32_until_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x7890; + uint32_t r_pc = 0x0000; + uint32_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, + sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +static void test_riscv64_until_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x7890; + uint64_t r_pc = 0x0000; + uint64_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, + sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +static void test_riscv32_3steps_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x7890; + uint32_t r_pc = 0x0000; + uint32_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, + sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, -1, 0, 3)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +static void test_riscv64_3steps_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x7890; + uint64_t r_pc = 0x0000; + uint64_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, + sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, -1, 0, 3)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +TEST_LIST = {{"test_riscv32_nop", test_riscv32_nop}, + {"test_riscv64_nop", test_riscv64_nop}, + {"test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update}, + {"test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update}, + {"test_riscv32_until_pc_update", test_riscv32_until_pc_update}, + {"test_riscv64_until_pc_update", test_riscv64_until_pc_update}, + {NULL, NULL}}; diff --git a/tests/unit/test_sparc.c b/tests/unit/test_sparc.c index 972d24c6..4c2505f4 100644 --- a/tests/unit/test_sparc.c +++ b/tests/unit/test_sparc.c @@ -3,6 +3,4 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 17d346ef..bbf35697 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -3,7 +3,9 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); @@ -14,22 +16,26 @@ typedef struct _INSN_IN_RESULT { int size; } INSN_IN_RESULT; -static void test_x86_in_callback(uc_engine* uc, uint32_t port, int size, void* user_data) { - INSN_IN_RESULT* result = (INSN_IN_RESULT*)user_data; +static void test_x86_in_callback(uc_engine *uc, uint32_t port, int size, + void *user_data) +{ + INSN_IN_RESULT *result = (INSN_IN_RESULT *)user_data; result->port = port; result->size = size; } -static void test_x86_in() { - uc_engine* uc; +static void test_x86_in() +{ + uc_engine *uc; uc_hook hook; char code[] = "\xe5\x10"; // IN eax, 0x10 INSN_IN_RESULT result; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_in_callback, &result, 1, 0, UC_X86_INS_IN)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_in_callback, &result, 1, 0, + UC_X86_INS_IN)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); TEST_CHECK(result.port == 0x10); TEST_CHECK(result.size == 4); @@ -44,23 +50,27 @@ typedef struct _INSN_OUT_RESULT { uint32_t value; } INSN_OUT_RESULT; -static void test_x86_out_callback(uc_engine* uc, uint32_t port, int size, uint32_t value, void* user_data) { - INSN_OUT_RESULT* result = (INSN_OUT_RESULT*)user_data; +static void test_x86_out_callback(uc_engine *uc, uint32_t port, int size, + uint32_t value, void *user_data) +{ + INSN_OUT_RESULT *result = (INSN_OUT_RESULT *)user_data; result->port = port; result->size = size; result->value = value; } -static void test_x86_out() { - uc_engine* uc; +static void test_x86_out() +{ + uc_engine *uc; uc_hook hook; char code[] = "\xb0\x32\xe6\x46"; // MOV al, 0x32; OUT 0x46, al; INSN_OUT_RESULT result; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_out_callback, &result, 1, 0, UC_X86_INS_OUT)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_out_callback, &result, 1, + 0, UC_X86_INS_OUT)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); TEST_CHECK(result.port == 0x46); TEST_CHECK(result.size == 1); @@ -82,8 +92,11 @@ typedef struct _MEM_HOOK_RESULTS { MEM_HOOK_RESULT results[16]; } MEM_HOOK_RESULTS; -static bool test_x86_mem_hook_all_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) { - MEM_HOOK_RESULTS* r = (MEM_HOOK_RESULTS*)user_data; +static bool test_x86_mem_hook_all_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, + uint64_t value, void *user_data) +{ + MEM_HOOK_RESULTS *r = (MEM_HOOK_RESULTS *)user_data; uint64_t count = r->count; if (count >= 16) { @@ -103,27 +116,28 @@ static bool test_x86_mem_hook_all_callback(uc_engine* uc, uc_mem_type type, uint return true; } -static void test_x86_mem_hook_all() { - uc_engine* uc; +static void test_x86_mem_hook_all() +{ + uc_engine *uc; uc_hook hook; // mov eax, 0xdeadbeef; // mov [0x8000], eax; // mov eax, [0x10000]; - char code[] = "\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00"; - MEM_HOOK_RESULTS r = { 0 }; - MEM_HOOK_RESULT expects[3] = { - {UC_MEM_WRITE, 0x8000, 4, 0xdeadbeef}, - {UC_MEM_READ_UNMAPPED, 0x10000, 4, 0}, - {UC_MEM_READ, 0x10000, 4, 0} - }; + char code[] = + "\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00"; + MEM_HOOK_RESULTS r = {0}; + MEM_HOOK_RESULT expects[3] = {{UC_MEM_WRITE, 0x8000, 4, 0xdeadbeef}, + {UC_MEM_READ_UNMAPPED, 0x10000, 4, 0}, + {UC_MEM_READ, 0x10000, 4, 0}}; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); OK(uc_mem_map(uc, 0x8000, 0x1000, UC_PROT_ALL)); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_VALID | UC_HOOK_MEM_INVALID, test_x86_mem_hook_all_callback, &r, 1, 0)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_VALID | UC_HOOK_MEM_INVALID, + test_x86_mem_hook_all_callback, &r, 1, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); TEST_CHECK(r.count == 3); - for (int i = 0; i < r.count; i ++) { + for (int i = 0; i < r.count; i++) { TEST_CHECK(expects[i].type == r.results[i].type); TEST_CHECK(expects[i].address == r.results[i].address); TEST_CHECK(expects[i].size == r.results[i].size); @@ -134,9 +148,11 @@ static void test_x86_mem_hook_all() { OK(uc_close(uc)); } -static void test_x86_inc_dec_pxor() { - uc_engine* uc; - char code[] = "\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1 +static void test_x86_inc_dec_pxor() +{ + uc_engine *uc; + char code[] = + "\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1 int r_ecx = 0x1234; int r_edx = 0x7890; uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607}; @@ -162,9 +178,11 @@ static void test_x86_inc_dec_pxor() { OK(uc_close(uc)); } -static void test_x86_relative_jump() { - uc_engine* uc; - char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop; nop; nop; nop +static void test_x86_relative_jump() +{ + uc_engine *uc; + char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop; + // nop; nop; nop int r_eip; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); @@ -178,8 +196,9 @@ static void test_x86_relative_jump() { OK(uc_close(uc)); } -static void test_x86_loop() { - uc_engine* uc; +static void test_x86_loop() +{ + uc_engine *uc; char code[] = "\x41\x4a\xeb\xfe"; // inc ecx; dec edx; jmp $; int r_ecx = 0x1234; int r_edx = 0x7890; @@ -188,7 +207,8 @@ static void test_x86_loop() { OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 1 * 1000000, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 1 * 1000000, + 0)); OK(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx)); @@ -199,40 +219,50 @@ static void test_x86_loop() { OK(uc_close(uc)); } -static void test_x86_invalid_mem_read() { - uc_engine* uc; +static void test_x86_invalid_mem_read() +{ + uc_engine *uc; char code[] = "\x8b\x0d\xaa\xaa\xaa\xaa"; // mov ecx, [0xAAAAAAAA] uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - uc_assert_err(UC_ERR_READ_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_READ_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_close(uc)); } -static void test_x86_invalid_mem_write() { - uc_engine* uc; +static void test_x86_invalid_mem_write() +{ + uc_engine *uc; char code[] = "\x89\x0d\xaa\xaa\xaa\xaa"; // mov ecx, [0xAAAAAAAA] uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - uc_assert_err(UC_ERR_WRITE_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_WRITE_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_close(uc)); } -static void test_x86_invalid_jump() { - uc_engine* uc; +static void test_x86_invalid_jump() +{ + uc_engine *uc; char code[] = "\xe9\xe9\xee\xee\xee"; // jmp 0xEEEEEEEE uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - uc_assert_err(UC_ERR_FETCH_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_FETCH_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_close(uc)); } -static void test_x86_64_syscall_callback(uc_engine* uc, void* user_data) { +static void test_x86_64_syscall_callback(uc_engine *uc, void *user_data) +{ uint64_t rax; OK(uc_reg_read(uc, UC_X86_REG_RAX, &rax)); @@ -240,15 +270,17 @@ static void test_x86_64_syscall_callback(uc_engine* uc, void* user_data) { TEST_CHECK(rax == 0x100); } -static void test_x86_64_syscall() { - uc_engine* uc; +static void test_x86_64_syscall() +{ + uc_engine *uc; uc_hook hook; char code[] = "\x0f\x05"; // syscall uint64_t r_rax = 0x100; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1); OK(uc_reg_write(uc, UC_X86_REG_RAX, &r_rax)); - OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_64_syscall_callback, NULL, 1, 0, UC_X86_INS_SYSCALL)); + OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_64_syscall_callback, NULL, + 1, 0, UC_X86_INS_SYSCALL)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -256,8 +288,9 @@ static void test_x86_64_syscall() { OK(uc_close(uc)); } -static void test_x86_16_add() { - uc_engine* uc; +static void test_x86_16_add() +{ + uc_engine *uc; char code[] = "\x00\x00"; // add byte ptr [bx + si], al uint16_t r_ax = 7; uint16_t r_bx = 5; @@ -277,9 +310,10 @@ static void test_x86_16_add() { OK(uc_close(uc)); } -static void test_x86_reg_save() { - uc_engine* uc; - uc_context* ctx; +static void test_x86_reg_save() +{ + uc_engine *uc; + uc_context *ctx; char code[] = "\x40"; // inc eax int r_eax = 1; @@ -289,7 +323,7 @@ static void test_x86_reg_save() { OK(uc_context_alloc(uc, &ctx)); OK(uc_context_save(uc, ctx)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); - + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); TEST_CHECK(r_eax == 2); @@ -302,27 +336,38 @@ static void test_x86_reg_save() { OK(uc_close(uc)); } -static bool test_x86_invalid_mem_read_stop_in_cb_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) { - // False indicates that we fail to handle this ERROR and let the emulation stop. +static bool +test_x86_invalid_mem_read_stop_in_cb_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, + uint64_t value, void *user_data) +{ + // False indicates that we fail to handle this ERROR and let the emulation + // stop. // - // Note that the memory must be mapped properly if we return true! Check test_x86_mem_hook_all for example. + // Note that the memory must be mapped properly if we return true! Check + // test_x86_mem_hook_all for example. return false; } -static void test_x86_invalid_mem_read_stop_in_cb() { - uc_engine* uc; +static void test_x86_invalid_mem_read_stop_in_cb() +{ + uc_engine *uc; uc_hook hook; - char code[] = "\x40\x8b\x1d\x00\x00\x10\x00\x42"; // inc eax; mov ebx, [0x100000]; inc edx + char code[] = "\x40\x8b\x1d\x00\x00\x10\x00\x42"; // inc eax; mov ebx, + // [0x100000]; inc edx int r_eax = 0x1234; int r_edx = 0x5678; int r_eip = 0; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, test_x86_invalid_mem_read_stop_in_cb_callback, NULL, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, + test_x86_invalid_mem_read_stop_in_cb_callback, NULL, 1, 0)); OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - uc_assert_err(UC_ERR_READ_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_READ_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); // The state of Unicorn should be correct at this time. OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip)); @@ -336,8 +381,9 @@ static void test_x86_invalid_mem_read_stop_in_cb() { OK(uc_close(uc)); } - -static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) { +static void test_x86_x87_fnstenv_callback(uc_engine *uc, uint64_t address, + uint32_t size, void *user_data) +{ uint32_t r_eip; uint32_t r_eax; uint32_t fnstenv[7]; @@ -345,8 +391,8 @@ static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint3 if (address == code_start + 4) { // The first fnstenv executed // Save the address of the fld. OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip)); - *((uint32_t*)user_data) = r_eip; - + *((uint32_t *)user_data) = r_eip; + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); OK(uc_mem_read(uc, r_eax, fnstenv, sizeof(fnstenv))); // Don't update FCS:FIP for fnop. @@ -354,10 +400,13 @@ static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint3 } } -static void test_x86_x87_fnstenv() { - uc_engine* uc; +static void test_x86_x87_fnstenv() +{ + uc_engine *uc; uc_hook hook; - char code[] = "\xd9\xd0\xd9\x30\xd9\x00\xd9\x30"; // fnop;fnstenv [eax];fld dword ptr [eax];fnstenv [eax] + char code[] = + "\xd9\xd0\xd9\x30\xd9\x00\xd9\x30"; // fnop;fnstenv [eax];fld dword ptr + // [eax];fnstenv [eax] uint32_t base = code_start + 3 * code_len; uint32_t last_eip; uint32_t fnstenv[7]; @@ -366,25 +415,31 @@ static void test_x86_x87_fnstenv() { OK(uc_mem_map(uc, base, code_len, UC_PROT_ALL)); OK(uc_reg_write(uc, UC_X86_REG_EAX, &base)); - OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_x86_x87_fnstenv_callback, &last_eip, 1, 0)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_x86_x87_fnstenv_callback, + &last_eip, 1, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_mem_read(uc, base, fnstenv, sizeof(fnstenv))); - //But update FCS:FIP for fld. + // But update FCS:FIP for fld. TEST_CHECK(fnstenv[3] == last_eip); OK(uc_close(uc)); } -static uint64_t test_x86_mmio_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) { +static uint64_t test_x86_mmio_read_callback(uc_engine *uc, uint64_t offset, + unsigned size, void *user_data) +{ TEST_CHECK(offset == 4); TEST_CHECK(size == 4); return 0x19260817; } -static void test_x86_mmio_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) { +static void test_x86_mmio_write_callback(uc_engine *uc, uint64_t offset, + unsigned size, uint64_t value, + void *user_data) +{ TEST_CHECK(offset == 4); TEST_CHECK(size == 4); TEST_CHECK(value == 0xdeadbeef); @@ -392,14 +447,19 @@ static void test_x86_mmio_write_callback(uc_engine* uc, uint64_t offset, unsigne return; } -static void test_x86_mmio() { - uc_engine* uc; +static void test_x86_mmio() +{ + uc_engine *uc; int r_ecx = 0xdeadbeef; - char code[] = "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00"; // mov [0x20004], ecx; mov ecx, [0x20004] + char code[] = + "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00"; // mov [0x20004], + // ecx; mov ecx, + // [0x20004] uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); - OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_read_callback, NULL, test_x86_mmio_write_callback, NULL)); + OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_read_callback, NULL, + test_x86_mmio_write_callback, NULL)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -410,7 +470,10 @@ static void test_x86_mmio() { OK(uc_close(uc)); } -static bool test_x86_missing_code_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) { +static bool test_x86_missing_code_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, + uint64_t value, void *user_data) +{ char code[] = "\x41\x4a"; // inc ecx; dec edx; uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL; int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000; @@ -422,8 +485,9 @@ static bool test_x86_missing_code_callback(uc_engine* uc, uc_mem_type type, uint return true; } -static void test_x86_missing_code() { - uc_engine* uc; +static void test_x86_missing_code() +{ + uc_engine *uc; uc_hook hook; int r_ecx = 0x1234; int r_edx = 0x7890; @@ -432,7 +496,8 @@ static void test_x86_missing_code() { OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED, test_x86_missing_code_callback, NULL, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED, + test_x86_missing_code_callback, NULL, 1, 0)); OK(uc_emu_start(uc, code_start, code_start + 2, 0, 0)); @@ -445,13 +510,14 @@ static void test_x86_missing_code() { OK(uc_close(uc)); } -static void test_x86_smc_xor() { - uc_engine* uc; +static void test_x86_smc_xor() +{ + uc_engine *uc; /* - * 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6 - * 0x1003 dw 0x3ea98b13 - */ - char code[] = "\x31\x47\x03\x13\x8b\xa9\x3e"; + * 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6 + * 0x1003 dw 0x3ea98b13 + */ + char code[] = "\x31\x47\x03\x13\x8b\xa9\x3e"; int r_edi = code_start; int r_eax = 0xbc4177e6; uint32_t result; @@ -469,14 +535,23 @@ static void test_x86_smc_xor() { OK(uc_close(uc)); } -static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) { +static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine *uc, + uint64_t offset, + unsigned size, + void *user_data) +{ TEST_CHECK(offset == 8); TEST_CHECK(size == 4); return 0x19260817; } -static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) { +static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine *uc, + uint64_t offset, + unsigned size, + uint64_t value, + void *user_data) +{ TEST_CHECK(offset == 4); TEST_CHECK(size == 4); TEST_CHECK(value == 0xdeadbeef); @@ -484,39 +559,40 @@ static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine* uc, uint64_t offse return; } - -static void test_x86_mmio_uc_mem_rw() { - uc_engine* uc; +static void test_x86_mmio_uc_mem_rw() +{ + uc_engine *uc; int data = 0xdeadbeef; OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); - OK(uc_mmio_map(uc, - 0x20000, 0x1000, - test_x86_mmio_uc_mem_rw_read_callback, NULL, - test_x86_mmio_uc_mem_rw_write_callback, NULL)); + OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_uc_mem_rw_read_callback, + NULL, test_x86_mmio_uc_mem_rw_write_callback, NULL)); - OK(uc_mem_write(uc, 0x20004, (void*)&data, 4)); - OK(uc_mem_read(uc, 0x20008, (void*)&data, 4)); + OK(uc_mem_write(uc, 0x20004, (void *)&data, 4)); + OK(uc_mem_read(uc, 0x20008, (void *)&data, 4)); TEST_CHECK(data == 0x19260817); OK(uc_close(uc)); } -static void test_x86_sysenter_hook(uc_engine* uc, void* user) { - *(int*)user = 1; +static void test_x86_sysenter_hook(uc_engine *uc, void *user) +{ + *(int *)user = 1; } -static void test_x86_sysenter() { - uc_engine* uc; +static void test_x86_sysenter() +{ + uc_engine *uc; char code[] = "\x0F\x34"; // sysenter uc_hook h; int called = 0; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_sysenter_hook, &called, 1, 0, UC_X86_INS_SYSENTER)); + OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_sysenter_hook, &called, 1, 0, + UC_X86_INS_SYSENTER)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -525,21 +601,24 @@ static void test_x86_sysenter() { OK(uc_close(uc)); } -static void test_x86_hook_cpuid_callback(uc_engine* uc, void* data) { +static void test_x86_hook_cpuid_callback(uc_engine *uc, void *data) +{ int reg = 7; OK(uc_reg_write(uc, UC_X86_REG_EAX, ®)); } -static void test_x86_hook_cpuid() { - uc_engine* uc; +static void test_x86_hook_cpuid() +{ + uc_engine *uc; char code[] = "\x40\x0F\xA2"; // INC EAX; CPUID uc_hook h; int reg; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_hook_cpuid_callback, NULL, 1, 0, UC_X86_INS_CPUID)); + OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_hook_cpuid_callback, NULL, 1, + 0, UC_X86_INS_CPUID)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -550,26 +629,60 @@ static void test_x86_hook_cpuid() { OK(uc_close(uc)); } -TEST_LIST = { - { "test_x86_in", test_x86_in }, - { "test_x86_out", test_x86_out }, - { "test_x86_mem_hook_all", test_x86_mem_hook_all }, - { "test_x86_inc_dec_pxor", test_x86_inc_dec_pxor }, - { "test_x86_relative_jump", test_x86_relative_jump }, - { "test_x86_loop", test_x86_loop }, - { "test_x86_invalid_mem_read", test_x86_invalid_mem_read }, - { "test_x86_invalid_mem_write", test_x86_invalid_mem_write }, - { "test_x86_invalid_jump", test_x86_invalid_jump}, - { "test_x86_64_syscall", test_x86_64_syscall }, - { "test_x86_16_add", test_x86_16_add }, - { "test_x86_reg_save", test_x86_reg_save }, - { "test_x86_invalid_mem_read_stop_in_cb", test_x86_invalid_mem_read_stop_in_cb }, - { "test_x86_x87_fnstenv", test_x86_x87_fnstenv}, - { "test_x86_mmio", test_x86_mmio}, - { "test_x86_missing_code", test_x86_missing_code}, - { "test_x86_smc_xor", test_x86_smc_xor}, - { "test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw}, - { "test_x86_sysenter", test_x86_sysenter}, - { "test_x86_hook_cpuid", test_x86_hook_cpuid}, - { NULL, NULL } -}; \ No newline at end of file +// This is a regression bug. +static void test_x86_clear_tb_cache() +{ + uc_engine *uc; + char code[] = "\x83\xc1\x01\x4a"; // ADD ecx, 1; DEC edx; + int r_ecx = 0x1234; + int r_edx = 0x7890; + uint64_t code_start = 0x1240; // Choose this address by design + uint64_t code_len = 0x1000; + + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); + OK(uc_mem_map(uc, code_start & (1 << 12), code_len, UC_PROT_ALL)); + OK(uc_mem_write(uc, code_start, code, sizeof(code))); + OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); + OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); + + // This emulation should take no effect at all. + OK(uc_emu_start(uc, code_start, code_start, 0, 0)); + + // Emulate ADD ecx, 1. + OK(uc_emu_start(uc, code_start, code_start + 3, 0, 0)); + + // If tb cache is not cleared, edx would be still 0x7890 + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx)); + OK(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx)); + + TEST_CHECK(r_ecx == 0x1236); + TEST_CHECK(r_edx == 0x788f); + + OK(uc_close(uc)); +} + +TEST_LIST = {{"test_x86_in", test_x86_in}, + {"test_x86_out", test_x86_out}, + {"test_x86_mem_hook_all", test_x86_mem_hook_all}, + {"test_x86_inc_dec_pxor", test_x86_inc_dec_pxor}, + {"test_x86_relative_jump", test_x86_relative_jump}, + {"test_x86_loop", test_x86_loop}, + {"test_x86_invalid_mem_read", test_x86_invalid_mem_read}, + {"test_x86_invalid_mem_write", test_x86_invalid_mem_write}, + {"test_x86_invalid_jump", test_x86_invalid_jump}, + {"test_x86_64_syscall", test_x86_64_syscall}, + {"test_x86_16_add", test_x86_16_add}, + {"test_x86_reg_save", test_x86_reg_save}, + {"test_x86_invalid_mem_read_stop_in_cb", + test_x86_invalid_mem_read_stop_in_cb}, + {"test_x86_x87_fnstenv", test_x86_x87_fnstenv}, + {"test_x86_mmio", test_x86_mmio}, + {"test_x86_missing_code", test_x86_missing_code}, + {"test_x86_smc_xor", test_x86_smc_xor}, + {"test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw}, + {"test_x86_sysenter", test_x86_sysenter}, + {"test_x86_hook_cpuid", test_x86_hook_cpuid}, + {"test_x86_clear_tb_cache", test_x86_clear_tb_cache}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index e3a45c02..a2e12042 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -2,23 +2,24 @@ #define UNICORN_TEST_H #include +#include #include #include "acutest.h" /** * Assert that err matches expect */ -#define uc_assert_err(expect, err) \ -do { \ - uc_err __err = err; \ - if (!TEST_CHECK(__err == expect)) { \ - TEST_MSG("%s", uc_strerror(__err)); \ - } \ -} while (0) +#define uc_assert_err(expect, err) \ + do { \ + uc_err __err = err; \ + if (!TEST_CHECK(__err == expect)) { \ + TEST_MSG("%s", uc_strerror(__err)); \ + } \ + } while (0) /** * Assert that err is UC_ERR_OK */ -#define OK(stat) uc_assert_err(UC_ERR_OK, stat) +#define OK(stat) uc_assert_err(UC_ERR_OK, stat) #endif /* UNICORN_TEST_H */ diff --git a/uc.c b/uc.c index bc50b9ba..48a925fb 100644 --- a/uc.c +++ b/uc.c @@ -10,7 +10,7 @@ #include #endif -#include // nanosleep +#include // nanosleep #include #include "uc_priv.h" @@ -37,99 +37,118 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor) return (UC_API_MAJOR << 8) + UC_API_MINOR; } - UNICORN_EXPORT uc_err uc_errno(uc_engine *uc) { return uc->errnum; } - UNICORN_EXPORT const char *uc_strerror(uc_err code) { - switch(code) { - default: - return "Unknown error code"; - case UC_ERR_OK: - return "OK (UC_ERR_OK)"; - case UC_ERR_NOMEM: - return "No memory available or memory not present (UC_ERR_NOMEM)"; - case UC_ERR_ARCH: - return "Invalid/unsupported architecture (UC_ERR_ARCH)"; - case UC_ERR_HANDLE: - return "Invalid handle (UC_ERR_HANDLE)"; - case UC_ERR_MODE: - return "Invalid mode (UC_ERR_MODE)"; - case UC_ERR_VERSION: - return "Different API version between core & binding (UC_ERR_VERSION)"; - case UC_ERR_READ_UNMAPPED: - return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; - case UC_ERR_WRITE_UNMAPPED: - return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; - case UC_ERR_FETCH_UNMAPPED: - return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; - case UC_ERR_HOOK: - return "Invalid hook type (UC_ERR_HOOK)"; - case UC_ERR_INSN_INVALID: - return "Invalid instruction (UC_ERR_INSN_INVALID)"; - case UC_ERR_MAP: - return "Invalid memory mapping (UC_ERR_MAP)"; - case UC_ERR_WRITE_PROT: - return "Write to write-protected memory (UC_ERR_WRITE_PROT)"; - case UC_ERR_READ_PROT: - return "Read from non-readable memory (UC_ERR_READ_PROT)"; - case UC_ERR_FETCH_PROT: - return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)"; - case UC_ERR_ARG: - return "Invalid argument (UC_ERR_ARG)"; - case UC_ERR_READ_UNALIGNED: - return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)"; - case UC_ERR_WRITE_UNALIGNED: - return "Write to unaligned memory (UC_ERR_WRITE_UNALIGNED)"; - case UC_ERR_FETCH_UNALIGNED: - return "Fetch from unaligned memory (UC_ERR_FETCH_UNALIGNED)"; - case UC_ERR_RESOURCE: - return "Insufficient resource (UC_ERR_RESOURCE)"; - case UC_ERR_EXCEPTION: - return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; + switch (code) { + default: + return "Unknown error code"; + case UC_ERR_OK: + return "OK (UC_ERR_OK)"; + case UC_ERR_NOMEM: + return "No memory available or memory not present (UC_ERR_NOMEM)"; + case UC_ERR_ARCH: + return "Invalid/unsupported architecture (UC_ERR_ARCH)"; + case UC_ERR_HANDLE: + return "Invalid handle (UC_ERR_HANDLE)"; + case UC_ERR_MODE: + return "Invalid mode (UC_ERR_MODE)"; + case UC_ERR_VERSION: + return "Different API version between core & binding (UC_ERR_VERSION)"; + case UC_ERR_READ_UNMAPPED: + return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; + case UC_ERR_WRITE_UNMAPPED: + return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; + case UC_ERR_FETCH_UNMAPPED: + return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; + case UC_ERR_HOOK: + return "Invalid hook type (UC_ERR_HOOK)"; + case UC_ERR_INSN_INVALID: + return "Invalid instruction (UC_ERR_INSN_INVALID)"; + case UC_ERR_MAP: + return "Invalid memory mapping (UC_ERR_MAP)"; + case UC_ERR_WRITE_PROT: + return "Write to write-protected memory (UC_ERR_WRITE_PROT)"; + case UC_ERR_READ_PROT: + return "Read from non-readable memory (UC_ERR_READ_PROT)"; + case UC_ERR_FETCH_PROT: + return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)"; + case UC_ERR_ARG: + return "Invalid argument (UC_ERR_ARG)"; + case UC_ERR_READ_UNALIGNED: + return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)"; + case UC_ERR_WRITE_UNALIGNED: + return "Write to unaligned memory (UC_ERR_WRITE_UNALIGNED)"; + case UC_ERR_FETCH_UNALIGNED: + return "Fetch from unaligned memory (UC_ERR_FETCH_UNALIGNED)"; + case UC_ERR_RESOURCE: + return "Insufficient resource (UC_ERR_RESOURCE)"; + case UC_ERR_EXCEPTION: + return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; } } - UNICORN_EXPORT bool uc_arch_supported(uc_arch arch) { switch (arch) { #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: return true; + case UC_ARCH_ARM: + return true; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: return true; + case UC_ARCH_ARM64: + return true; #endif #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: return true; + case UC_ARCH_M68K: + return true; #endif #ifdef UNICORN_HAS_MIPS - case UC_ARCH_MIPS: return true; + case UC_ARCH_MIPS: + return true; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: return true; + case UC_ARCH_PPC: + return true; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: return true; + case UC_ARCH_SPARC: + return true; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: return true; + case UC_ARCH_X86: + return true; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: return true; + case UC_ARCH_RISCV: + return true; #endif - /* Invalid or disabled arch */ - default: return false; + /* Invalid or disabled arch */ + default: + return false; } } +static gint uc_exits_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ + uint64_t lhs = *((uint64_t *)a); + uint64_t rhs = *((uint64_t *)b); + + if (lhs < rhs) { + return -1; + } else if (lhs == rhs) { + return 0; + } else { + return 1; + } +} UNICORN_EXPORT uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) @@ -156,142 +175,140 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) QTAILQ_INIT(&uc->address_spaces); - switch(arch) { - default: - break; + uc->exits = g_tree_new_full(uc_exits_cmp, NULL, g_free, NULL); + + switch (arch) { + default: + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - if ((mode & ~UC_MODE_M68K_MASK) || - !(mode & UC_MODE_BIG_ENDIAN)) { - free(uc); - return UC_ERR_MODE; - } - uc->init_arch = m68k_uc_init; - break; + case UC_ARCH_M68K: + if ((mode & ~UC_MODE_M68K_MASK) || !(mode & UC_MODE_BIG_ENDIAN)) { + free(uc); + return UC_ERR_MODE; + } + uc->init_arch = m68k_uc_init; + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - if ((mode & ~UC_MODE_X86_MASK) || - (mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64))) { - free(uc); - return UC_ERR_MODE; - } - uc->init_arch = x86_uc_init; - break; + case UC_ARCH_X86: + if ((mode & ~UC_MODE_X86_MASK) || (mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_16 | UC_MODE_32 | UC_MODE_64))) { + free(uc); + return UC_ERR_MODE; + } + uc->init_arch = x86_uc_init; + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - if ((mode & ~UC_MODE_ARM_MASK)) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { - uc->init_arch = armeb_uc_init; - } else { - uc->init_arch = arm_uc_init; - } + case UC_ARCH_ARM: + if ((mode & ~UC_MODE_ARM_MASK)) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { + uc->init_arch = armeb_uc_init; + } else { + uc->init_arch = arm_uc_init; + } - if (mode & UC_MODE_THUMB) { - uc->thumb = 1; - } - break; + if (mode & UC_MODE_THUMB) { + uc->thumb = 1; + } + break; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - if (mode & ~UC_MODE_ARM_MASK) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { - uc->init_arch = arm64eb_uc_init; - } else { - uc->init_arch = arm64_uc_init; - } - break; + case UC_ARCH_ARM64: + if (mode & ~UC_MODE_ARM_MASK) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { + uc->init_arch = arm64eb_uc_init; + } else { + uc->init_arch = arm64_uc_init; + } + break; #endif -#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) - case UC_ARCH_MIPS: - if ((mode & ~UC_MODE_MIPS_MASK) || - !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { +#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || \ + defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) + case UC_ARCH_MIPS: + if ((mode & ~UC_MODE_MIPS_MASK) || + !(mode & (UC_MODE_MIPS32 | UC_MODE_MIPS64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { #ifdef UNICORN_HAS_MIPS - if (mode & UC_MODE_MIPS32) { - uc->init_arch = mips_uc_init; - } + if (mode & UC_MODE_MIPS32) { + uc->init_arch = mips_uc_init; + } #endif #ifdef UNICORN_HAS_MIPS64 - if (mode & UC_MODE_MIPS64) { - uc->init_arch = mips64_uc_init; - } + if (mode & UC_MODE_MIPS64) { + uc->init_arch = mips64_uc_init; + } #endif - } else { // little endian + } else { // little endian #ifdef UNICORN_HAS_MIPSEL - if (mode & UC_MODE_MIPS32) { - uc->init_arch = mipsel_uc_init; - } + if (mode & UC_MODE_MIPS32) { + uc->init_arch = mipsel_uc_init; + } #endif #ifdef UNICORN_HAS_MIPS64EL - if (mode & UC_MODE_MIPS64) { - uc->init_arch = mips64el_uc_init; - } -#endif + if (mode & UC_MODE_MIPS64) { + uc->init_arch = mips64el_uc_init; } - break; +#endif + } + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - if ((mode & ~UC_MODE_SPARC_MASK) || - !(mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_SPARC32|UC_MODE_SPARC64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_SPARC64) { - uc->init_arch = sparc64_uc_init; - } else { - uc->init_arch = sparc_uc_init; - } - break; + case UC_ARCH_SPARC: + if ((mode & ~UC_MODE_SPARC_MASK) || !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_SPARC32 | UC_MODE_SPARC64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_SPARC64) { + uc->init_arch = sparc64_uc_init; + } else { + uc->init_arch = sparc_uc_init; + } + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - if ((mode & ~UC_MODE_PPC_MASK) || - !(mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_PPC32|UC_MODE_PPC64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_PPC64) { - uc->init_arch = ppc64_uc_init; - } else { - uc->init_arch = ppc_uc_init; - } - break; + case UC_ARCH_PPC: + if ((mode & ~UC_MODE_PPC_MASK) || !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_PPC32 | UC_MODE_PPC64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_PPC64) { + uc->init_arch = ppc64_uc_init; + } else { + uc->init_arch = ppc_uc_init; + } + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - if ((mode & ~UC_MODE_RISCV_MASK) || - !(mode & (UC_MODE_RISCV32|UC_MODE_RISCV64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_RISCV32) { - uc->init_arch = riscv32_uc_init; - } else if (mode & UC_MODE_RISCV64) { - uc->init_arch =riscv64_uc_init; - } else { - free(uc); - return UC_ERR_MODE; - } - break; + case UC_ARCH_RISCV: + if ((mode & ~UC_MODE_RISCV_MASK) || + !(mode & (UC_MODE_RISCV32 | UC_MODE_RISCV64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_RISCV32) { + uc->init_arch = riscv32_uc_init; + } else if (mode & UC_MODE_RISCV64) { + uc->init_arch = riscv64_uc_init; + } else { + free(uc); + return UC_ERR_MODE; + } + break; #endif - } if (uc->init_arch == NULL) { @@ -317,7 +334,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) } } - UNICORN_EXPORT uc_err uc_close(uc_engine *uc) { @@ -341,7 +357,7 @@ uc_err uc_close(uc_engine *uc) /* flatviews */ g_hash_table_destroy(uc->flat_views); - + // During flatviews destruction, we may still access memory regions. // So we free them afterwards. /* memory */ @@ -390,12 +406,14 @@ uc_err uc_close(uc_engine *uc) cur = uc->saved_contexts.head; while (cur != NULL) { struct list_item *next = cur->next; - struct uc_context *context = (struct uc_context*)cur->data; + struct uc_context *context = (struct uc_context *)cur->data; context->uc = NULL; cur = next; } list_clear(&uc->saved_contexts); + g_tree_destroy(uc->exits); + // finally, free uc itself. memset(uc, 0, sizeof(*uc)); free(uc); @@ -403,7 +421,6 @@ uc_err uc_close(uc_engine *uc) return UC_ERR_OK; } - UNICORN_EXPORT uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) { @@ -417,7 +434,6 @@ uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) return ret; } - UNICORN_EXPORT uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) { @@ -431,7 +447,6 @@ uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) return ret; } - UNICORN_EXPORT uc_err uc_reg_read(uc_engine *uc, int regid, void *value) { @@ -450,13 +465,13 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) { size_t count = 0, len; - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { len = (size_t)MIN(size - count, mr->end - address); count += len; address += len; - } else {// this address is not mapped in yet + } else { // this address is not mapped in yet break; } } @@ -464,7 +479,6 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) return (count == size); } - UNICORN_EXPORT uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) { @@ -484,11 +498,12 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) } // memory area can overlap adjacent memory blocks - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { len = (size_t)MIN(size - count, mr->end - address); - if (uc->read_mem(&uc->address_space_memory, address, bytes, len) == false) { + if (uc->read_mem(&uc->address_space_memory, address, bytes, len) == + false) { break; } count += len; @@ -507,7 +522,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) } UNICORN_EXPORT -uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t size) +uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, + size_t size) { size_t count = 0, len; const uint8_t *bytes = _bytes; @@ -525,21 +541,23 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t } // memory area can overlap adjacent memory blocks - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { uint32_t operms = mr->perms; - if (!(operms & UC_PROT_WRITE)) {// write protected - // but this is not the program accessing memory, so temporarily mark writable + if (!(operms & UC_PROT_WRITE)) { // write protected + // but this is not the program accessing memory, so temporarily + // mark writable uc->readonly_mem(mr, false); } len = (size_t)MIN(size - count, mr->end - address); - if (uc->write_mem(&uc->address_space_memory, address, bytes, len) == false) { + if (uc->write_mem(&uc->address_space_memory, address, bytes, len) == + false) { break; } - if (!(operms & UC_PROT_WRITE)) {// write protected + if (!(operms & UC_PROT_WRITE)) { // write protected // now write protect it again uc->readonly_mem(mr, true); } @@ -547,7 +565,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t count += len; address += len; bytes += len; - } else {// this address is not mapped in yet + } else { // this address is not mapped in yet break; } } @@ -559,7 +577,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t } } -#define TIMEOUT_STEP 2 // microseconds +#define TIMEOUT_STEP 2 // microseconds static void *_timeout_fn(void *arg) { struct uc_struct *uc = arg; @@ -571,7 +589,7 @@ static void *_timeout_fn(void *arg) if (uc->emulation_done) { break; } - } while((uint64_t)(get_clock() - current_time) < uc->timeout); + } while ((uint64_t)(get_clock() - current_time) < uc->timeout); // timeout before emulation is done? if (!uc->emulation_done) { @@ -586,11 +604,12 @@ static void *_timeout_fn(void *arg) static void enable_emu_timer(uc_engine *uc, uint64_t timeout) { uc->timeout = timeout; - qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, - uc, QEMU_THREAD_JOINABLE); + qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, uc, + QEMU_THREAD_JOINABLE); } -static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, + void *user_data) { // count this instruction. ah ah ah. uc->emu_counter++; @@ -604,11 +623,12 @@ static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, static void clear_deleted_hooks(uc_engine *uc) { - struct list_item * cur; - struct hook * hook; + struct list_item *cur; + struct hook *hook; int i; - - for (cur = uc->hooks_to_del.head; cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + + for (cur = uc->hooks_to_del.head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { assert(hook->to_delete); for (i = 0; i < UC_HOOK_MAX; i++) { if (list_remove(&uc->hook[i], (void *)hook)) { @@ -626,7 +646,8 @@ static void clear_deleted_hooks(uc_engine *uc) } UNICORN_EXPORT -uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count) +uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, + uint64_t timeout, size_t count) { // reset the counter uc->emu_counter = 0; @@ -636,69 +657,75 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time uc->timed_out = false; uc->first_tb = true; - switch(uc->arch) { - default: - break; + // In this case, we don't do any emulation because it will generate + // an empty translation block which we can't invalidate. + if (begin == until) { + return UC_ERR_OK; + } + + switch (uc->arch) { + default: + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - uc_reg_write(uc, UC_M68K_REG_PC, &begin); - break; + case UC_ARCH_M68K: + uc_reg_write(uc, UC_M68K_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - switch(uc->mode) { - default: - break; - case UC_MODE_16: { - uint64_t ip; - uint16_t cs; - - uc_reg_read(uc, UC_X86_REG_CS, &cs); - // compensate for later adding up IP & CS - ip = begin - cs*16; - uc_reg_write(uc, UC_X86_REG_IP, &ip); - break; - } - case UC_MODE_32: - uc_reg_write(uc, UC_X86_REG_EIP, &begin); - break; - case UC_MODE_64: - uc_reg_write(uc, UC_X86_REG_RIP, &begin); - break; - } + case UC_ARCH_X86: + switch (uc->mode) { + default: break; + case UC_MODE_16: { + uint64_t ip; + uint16_t cs; + + uc_reg_read(uc, UC_X86_REG_CS, &cs); + // compensate for later adding up IP & CS + ip = begin - cs * 16; + uc_reg_write(uc, UC_X86_REG_IP, &ip); + break; + } + case UC_MODE_32: + uc_reg_write(uc, UC_X86_REG_EIP, &begin); + break; + case UC_MODE_64: + uc_reg_write(uc, UC_X86_REG_RIP, &begin); + break; + } + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - uc_reg_write(uc, UC_ARM_REG_R15, &begin); - break; + case UC_ARCH_ARM: + uc_reg_write(uc, UC_ARM_REG_R15, &begin); + break; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - uc_reg_write(uc, UC_ARM64_REG_PC, &begin); - break; + case UC_ARCH_ARM64: + uc_reg_write(uc, UC_ARM64_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_MIPS - case UC_ARCH_MIPS: - // TODO: MIPS32/MIPS64/BIGENDIAN etc - uc_reg_write(uc, UC_MIPS_REG_PC, &begin); - break; + case UC_ARCH_MIPS: + // TODO: MIPS32/MIPS64/BIGENDIAN etc + uc_reg_write(uc, UC_MIPS_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - // TODO: Sparc/Sparc64 - uc_reg_write(uc, UC_SPARC_REG_PC, &begin); - break; + case UC_ARCH_SPARC: + // TODO: Sparc/Sparc64 + uc_reg_write(uc, UC_SPARC_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - uc_reg_write(uc, UC_PPC_REG_PC, &begin); - break; + case UC_ARCH_PPC: + uc_reg_write(uc, UC_PPC_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - uc_reg_write(uc, UC_RISCV_REG_PC, &begin); - break; + case UC_ARCH_RISCV: + uc_reg_write(uc, UC_RISCV_REG_PC, &begin); + break; #endif } @@ -717,7 +744,8 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time // so instead of appending, we must insert the hook at the begin // of the hook list uc->hook_insert = 1; - err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL, 1, 0); + err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, + NULL, 1, 0); // restore to append mode for uc_hook_add() uc->hook_insert = 0; if (err != UC_ERR_OK) { @@ -725,10 +753,15 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time } } - uc->addr_end = until; + // If UC_CTL_UC_USE_EXITS is set, then the @until param won't have any + // effect. This is designed for the backward compatibility. + if (!uc->use_exits) { + g_tree_remove_all(uc->exits); + uc_add_exit(uc, until); + } if (timeout) { - enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds + enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds } uc->vm_start(uc); @@ -747,7 +780,6 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time return uc->invalid_error; } - UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc) { @@ -765,56 +797,94 @@ uc_err uc_emu_stop(uc_engine *uc) return UC_ERR_OK; } +// return target index where a memory region at the address exists, or could be +// inserted +// +// address either is inside the mapping at the returned index, or is in free +// space before the next mapping. +// +// if there is overlap, between regions, ending address will be higher than the +// starting address of the mapping at returned index +static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) +{ + int left, right, mid; + MemoryRegion *mapping; + + left = 0; + right = uc->mapped_block_count; + + while (left < right) { + mid = left + (right - left) / 2; + + mapping = uc->mapped_blocks[mid]; + + if (mapping->end - 1 < address) { + left = mid + 1; + } else if (mapping->addr > address) { + right = mid; + } else { + return mid; + } + } + + return left; +} + // find if a memory range overlaps with existing mapped regions static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size) { unsigned int i; uint64_t end = begin + size - 1; - for(i = 0; i < uc->mapped_block_count; i++) { - // begin address falls inside this region? - if (begin >= uc->mapped_blocks[i]->addr && begin <= uc->mapped_blocks[i]->end - 1) { - return true; - } - // end address falls inside this region? - if (end >= uc->mapped_blocks[i]->addr && end <= uc->mapped_blocks[i]->end - 1) { - return true; - } - // this region falls totally inside this range? - if (begin < uc->mapped_blocks[i]->addr && end > uc->mapped_blocks[i]->end - 1) { - return true; - } - } + i = bsearch_mapped_blocks(uc, begin); + + // is this the highest region with no possible overlap? + if (i >= uc->mapped_block_count) + return false; + + // end address overlaps this region? + if (end >= uc->mapped_blocks[i]->addr) + return true; // not found return false; } // common setup/error checking shared between uc_mem_map and uc_mem_map_ptr -static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, MemoryRegion *block) +static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, MemoryRegion *block) { MemoryRegion **regions; + int pos; if (block == NULL) { return UC_ERR_NOMEM; } - if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow - regions = (MemoryRegion**)g_realloc(uc->mapped_blocks, - sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR)); + if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { // time to grow + regions = (MemoryRegion **)g_realloc( + uc->mapped_blocks, + sizeof(MemoryRegion *) * (uc->mapped_block_count + MEM_BLOCK_INCR)); if (regions == NULL) { return UC_ERR_NOMEM; } uc->mapped_blocks = regions; } - uc->mapped_blocks[uc->mapped_block_count] = block; + pos = bsearch_mapped_blocks(uc, block->addr); + + // shift the array right to give space for the new pointer + memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], + sizeof(MemoryRegion *) * (uc->mapped_block_count - pos)); + + uc->mapped_blocks[pos] = block; uc->mapped_block_count++; return UC_ERR_OK; } -static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) +static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms) { if (size == 0) { // invalid memory mapping @@ -863,11 +933,13 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) return res; } - return mem_map(uc, address, size, perms, uc->memory_map(uc, address, size, perms)); + return mem_map(uc, address, size, perms, + uc->memory_map(uc, address, size, perms)); } UNICORN_EXPORT -uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr) +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, void *ptr) { uc_err res; @@ -884,7 +956,8 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per return res; } - return mem_map(uc, address, size, UC_PROT_ALL, uc->memory_map_ptr(uc, address, size, perms, ptr)); + return mem_map(uc, address, size, UC_PROT_ALL, + uc->memory_map_ptr(uc, address, size, perms, ptr)); } UNICORN_EXPORT @@ -905,7 +978,8 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, // The callbacks do not need to be checked for NULL here, as their presence // (or lack thereof) will determine the permissions used. return mem_map(uc, address, size, UC_PROT_NONE, - uc->memory_map_io(uc, address, size, read_cb, write_cb, user_data_read, user_data_write)); + uc->memory_map_io(uc, address, size, read_cb, write_cb, + user_data_read, user_data_write)); } // Create a backup copy of the indicated MemoryRegion. @@ -914,7 +988,8 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) { uint8_t *block = (uint8_t *)g_malloc0((size_t)int128_get64(mr->size)); if (block != NULL) { - uc_err err = uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); + uc_err err = + uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); if (err != UC_ERR_OK) { free(block); block = NULL; @@ -939,8 +1014,8 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) */ // TODO: investigate whether qemu region manipulation functions already offered // this capability -static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t address, - size_t size, bool do_delete) +static bool split_region(struct uc_struct *uc, MemoryRegion *mr, + uint64_t address, size_t size, bool do_delete) { uint8_t *backup; uint32_t perms; @@ -967,8 +1042,10 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres return false; } - QLIST_FOREACH(block, &uc->ram_list.blocks, next) { - if (block->offset <= mr->addr && block->used_length >= (mr->end - mr->addr)) { + QLIST_FOREACH(block, &uc->ram_list.blocks, next) + { + if (block->offset <= mr->addr && + block->used_length >= (mr->end - mr->addr)) { break; } } @@ -990,13 +1067,15 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres } } - // save the essential information required for the split before mr gets deleted + // save the essential information required for the split before mr gets + // deleted perms = mr->perms; begin = mr->addr; end = mr->end; // unmap this region first, then do split it later - if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != UC_ERR_OK) { + if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != + UC_ERR_OK) { goto error; } @@ -1020,10 +1099,10 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres r_size = (size_t)(end - chunk_end); m_size = (size_t)(chunk_end - address); - // If there are error in any of the below operations, things are too far gone - // at that point to recover. Could try to remap orignal region, but these smaller - // allocation just failed so no guarantee that we can recover the original - // allocation at this point + // If there are error in any of the below operations, things are too far + // gone at that point to recover. Could try to remap orignal region, but + // these smaller allocation just failed so no guarantee that we can recover + // the original allocation at this point if (l_size > 0) { if (!prealloc) { if (uc_mem_map(uc, begin, l_size, perms) != UC_ERR_OK) { @@ -1044,11 +1123,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres if (uc_mem_map(uc, address, m_size, perms) != UC_ERR_OK) { goto error; } - if (uc_mem_write(uc, address, backup + l_size, m_size) != UC_ERR_OK) { + if (uc_mem_write(uc, address, backup + l_size, m_size) != + UC_ERR_OK) { goto error; } } else { - if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != UC_ERR_OK) { + if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != + UC_ERR_OK) { goto error; } } @@ -1059,11 +1140,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres if (uc_mem_map(uc, chunk_end, r_size, perms) != UC_ERR_OK) { goto error; } - if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) { + if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != + UC_ERR_OK) { goto error; } } else { - if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, backup + l_size + m_size) != UC_ERR_OK) { + if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, + backup + l_size + m_size) != UC_ERR_OK) { goto error; } } @@ -1082,7 +1165,8 @@ error: } UNICORN_EXPORT -uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms) +uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, + uint32_t perms) { MemoryRegion *mr; uint64_t addr = address; @@ -1122,7 +1206,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 // We may need to split regions if this area spans adjacent regions addr = address; count = 0; - while(count < size) { + while (count < size) { mr = memory_mapping(uc, addr); len = (size_t)MIN(size - count, mr->end - addr); if (!split_region(uc, mr, addr, len, false)) { @@ -1131,7 +1215,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 mr = memory_mapping(uc, addr); // will this remove EXEC permission? - if (((mr->perms & UC_PROT_EXEC) != 0) && ((perms & UC_PROT_EXEC) == 0)) { + if (((mr->perms & UC_PROT_EXEC) != 0) && + ((perms & UC_PROT_EXEC) == 0)) { remove_exec = true; } mr->perms = perms; @@ -1141,7 +1226,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 addr += len; } - // if EXEC permission is removed, then quit TB and continue at the same place + // if EXEC permission is removed, then quit TB and continue at the same + // place if (remove_exec) { uc->quit_request = true; uc_emu_stop(uc); @@ -1185,7 +1271,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) // We may need to split regions if this area spans adjacent regions addr = address; count = 0; - while(count < size) { + while (count < size) { mr = memory_mapping(uc, addr); len = (size_t)MIN(size - count, mr->end - addr); if (!split_region(uc, mr, addr, len, true)) { @@ -1196,7 +1282,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) // so unmap here mr = memory_mapping(uc, addr); if (mr != NULL) { - uc->memory_unmap(uc, mr); + uc->memory_unmap(uc, mr); } count += len; addr += len; @@ -1206,7 +1292,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) } // find the memory region of this address -MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) +MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address) { unsigned int i; @@ -1221,17 +1307,16 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) // try with the cache index first i = uc->mapped_block_cache_index; - if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end) { + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && + address < uc->mapped_blocks[i]->end) { return uc->mapped_blocks[i]; } - for(i = 0; i < uc->mapped_block_count; i++) { - if (address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1) { - // cache this index for the next query - uc->mapped_block_cache_index = i; - return uc->mapped_blocks[i]; - } - } + i = bsearch_mapped_blocks(uc, address); + + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && + address <= uc->mapped_blocks[i]->end - 1) + return uc->mapped_blocks[i]; // not found return NULL; @@ -1239,7 +1324,7 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) UNICORN_EXPORT uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, - void *user_data, uint64_t begin, uint64_t end, ...) + void *user_data, uint64_t begin, uint64_t end, ...) { int ret = UC_ERR_OK; int i = 0; @@ -1267,7 +1352,7 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, va_end(valist); if (uc->insn_hook_validate) { - if (! uc->insn_hook_validate(hook->insn)) { + if (!uc->insn_hook_validate(hook->insn)) { free(hook); return UC_ERR_HOOK; } @@ -1323,7 +1408,6 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, return ret; } - UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh) { @@ -1336,7 +1420,7 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) // an optimization would be to align the hook pointer // and store the type mask in the hook pointer. for (i = 0; i < UC_HOOK_MAX; i++) { - if (list_exists(&uc->hook[i], (void *) hook)) { + if (list_exists(&uc->hook[i], (void *)hook)) { hook->to_delete = true; list_append(&uc->hooks_to_del, hook); } @@ -1346,13 +1430,18 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) } // TCG helper -void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t address); -void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t address) +void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, + int64_t address); +void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, + int64_t address) { struct uc_struct *uc = handle; struct list_item *cur; struct hook *hook; - int hook_flags = index & UC_HOOK_FLAG_MASK; // The index here may contain additional flags. See the comments of uc_hook_idx for details. + int hook_flags = + index & + UC_HOOK_FLAG_MASK; // The index here may contain additional flags. See + // the comments of uc_hook_idx for details. index = index & UC_HOOK_IDX_MASK; @@ -1366,30 +1455,35 @@ void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t return; } - for (cur = uc->hook[index].head; cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + for (cur = uc->hook[index].head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { if (hook->to_delete) { continue; } - // on invalid block/instruction, call instruction counter (if enable), then quit + // on invalid block/instruction, call instruction counter (if enable), + // then quit if (size == 0) { if (index == UC_HOOK_CODE_IDX && uc->count_hook) { // this is the instruction counter (first hook in the list) - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, + hook->user_data); } return; } if (HOOK_BOUND_CHECK(hook, (uint64_t)address)) { - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, + hook->user_data); } // the last callback may already asked to stop emulation // Unicorn: - // In an ARM IT block, we behave like the emulation continues normally. No check_exit_request - // is generated and the hooks are triggered normally. In other words, the whole IT block is - // treated as a single instruction. + // In an ARM IT block, we behave like the emulation continues + // normally. No check_exit_request is generated and the hooks are + // triggered normally. In other words, the whole IT block is treated + // as a single instruction. if (uc->stop_request && !(hook_flags & UC_HOOK_FLAG_NO_STOP)) { break; } @@ -1426,30 +1520,30 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count) UNICORN_EXPORT uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) { - switch(type) { - default: - return UC_ERR_ARG; + switch (type) { + default: + return UC_ERR_ARG; - case UC_QUERY_PAGE_SIZE: - *result = uc->target_page_size; - break; + case UC_QUERY_PAGE_SIZE: + *result = uc->target_page_size; + break; - case UC_QUERY_ARCH: - *result = uc->arch; - break; + case UC_QUERY_ARCH: + *result = uc->arch; + break; - case UC_QUERY_MODE: + case UC_QUERY_MODE: #ifdef UNICORN_HAS_ARM - if (uc->arch == UC_ARCH_ARM) { - return uc->query(uc, type, result); - } + if (uc->arch == UC_ARCH_ARM) { + return uc->query(uc, type, result); + } #endif - *result = uc->mode; - break; + *result = uc->mode; + break; - case UC_QUERY_TIMEOUT: - *result = uc->timed_out; - break; + case UC_QUERY_TIMEOUT: + *result = uc->timed_out; + break; } return UC_ERR_OK; @@ -1489,20 +1583,20 @@ UNICORN_EXPORT size_t uc_context_size(uc_engine *uc) { // return the total size of struct uc_context - return sizeof(uc_context) + uc->cpu_context_size + sizeof(*uc->cpu->jmp_env); + return sizeof(uc_context) + uc->cpu_context_size + + sizeof(*uc->cpu->jmp_env); } UNICORN_EXPORT uc_err uc_context_save(uc_engine *uc, uc_context *context) { memcpy(context->data, uc->cpu->env_ptr, context->context_size); - memcpy(context->data + context->context_size, uc->cpu->jmp_env, context->jmp_env_size); + memcpy(context->data + context->context_size, uc->cpu->jmp_env, + context->jmp_env_size); return UC_ERR_OK; } - - UNICORN_EXPORT uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value) { @@ -1516,120 +1610,123 @@ uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value) } // Keep in mind that we don't a uc_engine when r/w the registers of a context. -static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, context_reg_rw_t *rw) +static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, + context_reg_rw_t *rw) { // We believe that the arch/mode pair is correct. - switch(arch) { - default: - rw->context_reg_read = NULL; - rw->context_reg_write = NULL; - break; + switch (arch) { + default: + rw->context_reg_read = NULL; + rw->context_reg_write = NULL; + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - rw->context_reg_read = m68k_context_reg_read; - rw->context_reg_write = m68k_context_reg_write; - break; + case UC_ARCH_M68K: + rw->context_reg_read = m68k_context_reg_read; + rw->context_reg_write = m68k_context_reg_write; + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - rw->context_reg_read = x86_context_reg_read; - rw->context_reg_write = x86_context_reg_write; - break; + case UC_ARCH_X86: + rw->context_reg_read = x86_context_reg_read; + rw->context_reg_write = x86_context_reg_write; + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - if (mode & UC_MODE_BIG_ENDIAN) { - rw->context_reg_read = armeb_context_reg_read; - rw->context_reg_write = armeb_context_reg_write; - } else { - rw->context_reg_read = arm_context_reg_read; - rw->context_reg_write = arm_context_reg_write; - } + case UC_ARCH_ARM: + if (mode & UC_MODE_BIG_ENDIAN) { + rw->context_reg_read = armeb_context_reg_read; + rw->context_reg_write = armeb_context_reg_write; + } else { + rw->context_reg_read = arm_context_reg_read; + rw->context_reg_write = arm_context_reg_write; + } #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - if (mode & UC_MODE_BIG_ENDIAN) { - rw->context_reg_read = arm64eb_context_reg_read; - rw->context_reg_write = arm64eb_context_reg_write; - } else { - rw->context_reg_read = arm64_context_reg_read; - rw->context_reg_write = arm64_context_reg_write; - } - break; + case UC_ARCH_ARM64: + if (mode & UC_MODE_BIG_ENDIAN) { + rw->context_reg_read = arm64eb_context_reg_read; + rw->context_reg_write = arm64eb_context_reg_write; + } else { + rw->context_reg_read = arm64_context_reg_read; + rw->context_reg_write = arm64_context_reg_write; + } + break; #endif -#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) - case UC_ARCH_MIPS: - if (mode & UC_MODE_BIG_ENDIAN) { +#if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || \ + defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) + case UC_ARCH_MIPS: + if (mode & UC_MODE_BIG_ENDIAN) { #ifdef UNICORN_HAS_MIPS - if (mode & UC_MODE_MIPS32) { - rw->context_reg_read = mips_context_reg_read; - rw->context_reg_write = mips_context_reg_write; - } + if (mode & UC_MODE_MIPS32) { + rw->context_reg_read = mips_context_reg_read; + rw->context_reg_write = mips_context_reg_write; + } #endif #ifdef UNICORN_HAS_MIPS64 - if (mode & UC_MODE_MIPS64) { - rw->context_reg_read = mips64_context_reg_read; - rw->context_reg_write = mips64_context_reg_write; - } + if (mode & UC_MODE_MIPS64) { + rw->context_reg_read = mips64_context_reg_read; + rw->context_reg_write = mips64_context_reg_write; + } #endif - } else { // little endian + } else { // little endian #ifdef UNICORN_HAS_MIPSEL - if (mode & UC_MODE_MIPS32) { - rw->context_reg_read = mipsel_context_reg_read; - rw->context_reg_write = mipsel_context_reg_write; - } + if (mode & UC_MODE_MIPS32) { + rw->context_reg_read = mipsel_context_reg_read; + rw->context_reg_write = mipsel_context_reg_write; + } #endif #ifdef UNICORN_HAS_MIPS64EL - if (mode & UC_MODE_MIPS64) { - rw->context_reg_read = mips64el_context_reg_read; - rw->context_reg_write = mips64el_context_reg_write; - } -#endif + if (mode & UC_MODE_MIPS64) { + rw->context_reg_read = mips64el_context_reg_read; + rw->context_reg_write = mips64el_context_reg_write; } - break; +#endif + } + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - if (mode & UC_MODE_SPARC64) { - rw->context_reg_read = sparc64_context_reg_read; - rw->context_reg_write = sparc64_context_reg_write; - } else { - rw->context_reg_read = sparc_context_reg_read; - rw->context_reg_write = sparc_context_reg_write; - } - break; + case UC_ARCH_SPARC: + if (mode & UC_MODE_SPARC64) { + rw->context_reg_read = sparc64_context_reg_read; + rw->context_reg_write = sparc64_context_reg_write; + } else { + rw->context_reg_read = sparc_context_reg_read; + rw->context_reg_write = sparc_context_reg_write; + } + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - if (mode & UC_MODE_PPC64) { - rw->context_reg_read = ppc64_context_reg_read; - rw->context_reg_write = ppc64_context_reg_write; - } else { - rw->context_reg_read = ppc_context_reg_read; - rw->context_reg_write = ppc_context_reg_write; - } - break; + case UC_ARCH_PPC: + if (mode & UC_MODE_PPC64) { + rw->context_reg_read = ppc64_context_reg_read; + rw->context_reg_write = ppc64_context_reg_write; + } else { + rw->context_reg_read = ppc_context_reg_read; + rw->context_reg_write = ppc_context_reg_write; + } + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - if (mode & UC_MODE_RISCV32) { - rw->context_reg_read = riscv32_context_reg_read; - rw->context_reg_write = riscv32_context_reg_write; - } else if (mode & UC_MODE_RISCV64) { - rw->context_reg_read = riscv64_context_reg_read; - rw->context_reg_write = riscv64_context_reg_write; - } - break; + case UC_ARCH_RISCV: + if (mode & UC_MODE_RISCV32) { + rw->context_reg_read = riscv32_context_reg_read; + rw->context_reg_write = riscv32_context_reg_write; + } else if (mode & UC_MODE_RISCV64) { + rw->context_reg_read = riscv64_context_reg_read; + rw->context_reg_write = riscv64_context_reg_write; + } + break; #endif } - + return; } UNICORN_EXPORT -uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, int count) +uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, + int count) { int ret = UC_ERR_OK; context_reg_rw_t rw; @@ -1645,7 +1742,8 @@ uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, } UNICORN_EXPORT -uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, int count) +uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, + int count) { int ret = UC_ERR_OK; context_reg_rw_t rw; @@ -1665,7 +1763,8 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) { memcpy(uc->cpu->env_ptr, context->data, context->context_size); if (list_exists(&uc->saved_contexts, context)) { - memcpy(uc->cpu->jmp_env, context->data + context->context_size, context->jmp_env_size); + memcpy(uc->cpu->jmp_env, context->data + context->context_size, + context->jmp_env_size); } return UC_ERR_OK; @@ -1674,10 +1773,166 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) UNICORN_EXPORT uc_err uc_context_free(uc_context *context) { - uc_engine* uc = context->uc; + uc_engine *uc = context->uc; // if uc is NULL, it means that uc_engine has been free-ed. if (uc) { list_remove(&uc->saved_contexts, context); } return uc_free(context); } + +typedef struct _uc_ctl_exit_request { + uint64_t *array; + size_t len; +} uc_ctl_exit_request; + +static inline gboolean uc_read_exit_iter(gpointer key, gpointer val, + gpointer data) +{ + uc_ctl_exit_request *req = (uc_ctl_exit_request *)data; + + req->array[req->len++] = *(uint64_t *)key; + + return false; +} + +UNICORN_EXPORT +uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) +{ + int rw, type; + uc_err err = UC_ERR_OK; + va_list args; + + // MSVC Would do signed shift on signed integers. + rw = (uint32_t)control >> 30; + type = (control & ((1 << 16) - 1)); + va_start(args, control); + + switch (type) { + case UC_CTL_UC_MODE: { + if (rw == UC_CTL_IO_READ) { + int *pmode = va_arg(args, int *); + *pmode = uc->mode; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_ARCH: { + if (rw == UC_CTL_IO_READ) { + int *arch = va_arg(args, int *); + *arch = uc->arch; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_TIMEOUT: { + if (rw == UC_CTL_IO_READ) { + uint64_t *arch = va_arg(args, uint64_t *); + *arch = uc->timeout; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_PAGE_SIZE: { + if (rw == UC_CTL_IO_READ) { + uint32_t *page_size = va_arg(args, uint32_t *); + *page_size = uc->target_page_size; + } else { + // Not implemented. + err = UC_ERR_ARG; + } + break; + } + case UC_CTL_UC_USE_EXITS: { + if (rw == UC_CTL_IO_WRITE) { + int use_exits = va_arg(args, int); + uc->use_exits = use_exits; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_EXITS_CNT: { + if (!uc->use_exits) { + err = UC_ERR_ARG; + } else if (rw == UC_CTL_IO_READ) { + size_t *exits_cnt = va_arg(args, size_t *); + *exits_cnt = g_tree_nnodes(uc->exits); + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_EXITS: { + if (!uc->use_exits) { + err = UC_ERR_ARG; + } else if (rw == UC_CTL_IO_READ) { + uint64_t *exits = va_arg(args, uint64_t *); + size_t cnt = va_arg(args, size_t); + if (cnt < g_tree_nnodes(uc->exits)) { + err = UC_ERR_ARG; + } else { + uc_ctl_exit_request req; + req.array = exits; + req.len = 0; + + g_tree_foreach(uc->exits, uc_read_exit_iter, (void *)&req); + } + } else if (rw == UC_CTL_IO_WRITE) { + uint64_t *exits = va_arg(args, uint64_t *); + size_t cnt = va_arg(args, size_t); + + g_tree_remove_all(uc->exits); + + for (size_t i = 0; i < cnt; i++) { + uc_add_exit(uc, exits[i]); + } + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_CPU_MODEL: + // Not implemented. + err = UC_ERR_ARG; + break; + + case UC_CTL_TB_REQUEST_CACHE: { + if (rw == UC_CTL_IO_READ_WRITE) { + uint64_t addr = va_arg(args, uint64_t); + uc_tb *tb = va_arg(args, uc_tb *); + err = uc->uc_gen_tb(uc, addr, tb); + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_TB_REMOVE_CACHE: { + if (rw == UC_CTL_IO_READ) { + uint64_t addr = va_arg(args, uint64_t); + uc->uc_invalidate_tb(uc, addr, 1); + } else { + err = UC_ERR_ARG; + } + break; + } + + default: + err = UC_ERR_ARG; + break; + } + + va_end(args); + + return err; +}