diff options
Diffstat (limited to 'capstone/suite/cstest')
26 files changed, 3647 insertions, 0 deletions
diff --git a/capstone/suite/cstest/Makefile b/capstone/suite/cstest/Makefile new file mode 100644 index 000000000..fb4b7c294 --- /dev/null +++ b/capstone/suite/cstest/Makefile @@ -0,0 +1,13 @@ +SOURCE = src +INCLUDE = include +BUILD = build +LIBRARY = -lcmocka -lcapstone -L../.. + +all: + rm -rf $(BUILD) + mkdir $(BUILD) + $(CC) $(SOURCE)/*.c -I$(INCLUDE) -o $(BUILD)/cstest $(LIBRARY) +cstest: + $(BUILD)/cstest -d ../MC +clean: + rm -rf $(BUILD) diff --git a/capstone/suite/cstest/README.md b/capstone/suite/cstest/README.md new file mode 100644 index 000000000..a9880dadf --- /dev/null +++ b/capstone/suite/cstest/README.md @@ -0,0 +1,78 @@ +# Regression testing +This directory contains a tool for regression testing core of Capstone + +## Dependency + +- MacOS users can install cmocka with: + +``` +brew install cmocka +``` + +- Or download & build from source code [Cmocka](https://git.cryptomilk.org/projects/cmocka.git) + +- Build Cmocka + +``` +cd cmocka_dir +mkdir build +cd build +cmake .. +make +sudo make isntall +``` + +## Build + +- Build `cstest` + +``` +cd suite/cstest +make +``` + +## Usage + +- Usage: `cstest [-e] [-f <file_name.cs>] [-d <directory>]` + - `-e` : test all commented test + +- Test for all closed issues + +``` +cd suite/cstest +./build/cstest -f ./issues.cs +``` + +- Test for some input from LLVM + +``` +cd suite/cstest +./build/cstest -f ../MC/AArch64/basic-a64-instructions.s.cs +``` + +- Test for all cs file in a folder + +``` +cd suite/cstest +./build/cstest -d ../MC +``` + +- Test all + +``` +cd suite/cstest +make cstest +``` + +## Report tool + +- Usage `cstest_report.py [-Dc] -t <cstest_path> [-f <file_name.cs>] [-d <directory>]` + - `-D` : print details + - `-c` : auto comment out failed test + +- Example: + +``` +./cstest_report.py -t build/cstest -d ../MC/PowerPC/ +./cstest_report.py -t build/cstest -f issues.cs +``` diff --git a/capstone/suite/cstest/build_cstest.sh b/capstone/suite/cstest/build_cstest.sh new file mode 100644 index 000000000..5b4ba4c2b --- /dev/null +++ b/capstone/suite/cstest/build_cstest.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +cd cmocka && mkdir build && cd build +if [ "$(uname)" = Darwin ]; then +cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make -j2 && sudo make install +else # Linux +cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make -j2 && sudo make install +fi +cd ../.. && make diff --git a/capstone/suite/cstest/cstest_report.py b/capstone/suite/cstest/cstest_report.py new file mode 100755 index 000000000..17da3957f --- /dev/null +++ b/capstone/suite/cstest/cstest_report.py @@ -0,0 +1,102 @@ +#!/usr/bin/python + +import re +import sys +import getopt +from subprocess import Popen, PIPE +from pprint import pprint as ppr +import os + + +def Usage(s): + print 'Usage: {} -t <cstest_path> [-f <file_name.cs>] [-d <directory>]'.format(s) + sys.exit(-1) + +def get_report_file(toolpath, filepath, getDetails, cmt_out): + cmd = [toolpath, '-f', filepath] + process = Popen(cmd, stdout=PIPE, stderr=PIPE) + stdout, stderr = process.communicate() + +# stdout + failed_tests = [] +# print '---> stdout\n', stdout +# print '---> stderr\n', stderr + matches = re.finditer(r'\[\s+RUN\s+\]\s+(.*)\n\[\s+FAILED\s+\]', stdout) + for match in matches: + failed_tests.append(match.group(1)) +# stderr + counter = 0 + details = [] + for line in stderr.split('\n'): + if '[ PASSED ] 0 test(s).' in line: + break + elif 'LINE' in line: + continue + elif 'ERROR' in line and ' --- ' in line: + parts = line.split(' --- ') + try: + details.append((parts[1], failed_tests[counter], parts[2])) + except IndexError: + details.append(('', 'Unknown test', line.split(' --- ')[1])) + counter += 1 + else: + continue + print '\n[-] There are/is {} failed test(s)'.format(len(details)) + if len(details) > 0 and getDetails: + print '[-] Detailed report for {}:\n'.format(filepath) + for c, f, d in details: + print '\t[+] {}: {}\n\t\t{}\n'.format(f, c, d) + print '\n' + return 0 + elif len(details) > 0: + for c, f, d in details: + if len(f) > 0 and cmt_out is True: + tmp_cmd = ['sed', '-E', '-i.bak', 's/({})(.*)/\/\/ \\1\\2/g'.format(c), filepath] + sed_proc = Popen(tmp_cmd, stdout=PIPE, stderr=PIPE) + sed_proc.communicate() + tmp_cmd2 = ['rm', '-f', filepath + '.bak'] + rm_proc = Popen(tmp_cmd2, stdout=PIPE, stderr=PIPE) + rm_proc.communicate() + + return 0; + return 1 + +def get_report_folder(toolpath, folderpath, details, cmt_out): + result = 1 + for root, dirs, files in os.walk(folderpath): + path = root.split(os.sep) + for f in files: + if f.split('.')[-1] == 'cs': + print '[-] Target:', f, + result *= get_report_file(toolpath, os.sep.join(x for x in path) + os.sep + f, details, cmt_out) + + sys.exit(result ^ 1) + +if __name__ == '__main__': + Done = False + details = False + toolpath = '' + cmt_out = False + try: + opts, args = getopt.getopt(sys.argv[1:], "ct:f:d:D") + for opt, arg in opts: + if opt == '-f': + result = get_report_file(toolpath, arg, details, cmt_out) + if result == 0: + sys.exit(1) + Done = True + elif opt == '-d': + get_report_folder(toolpath, arg, details, cmt_out) + Done = True + elif opt == '-t': + toolpath = arg + elif opt == '-D': + details = True + elif opt == '-c': + cmt_out = True + + except getopt.GetoptError: + Usage(sys.argv[0]) + + if Done is False: + Usage(sys.argv[0]) diff --git a/capstone/suite/cstest/include/capstone_test.h b/capstone/suite/cstest/include/capstone_test.h new file mode 100644 index 000000000..5936678f0 --- /dev/null +++ b/capstone/suite/cstest/include/capstone_test.h @@ -0,0 +1,62 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#ifndef CAPSTONE_TEST_H +#define CAPSTONE_TEST_H + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <stdlib.h> +#include <string.h> +#include <capstone/capstone.h> +#include "helper.h" +#include "factory.h" + +#define cs_assert_err(expect, err) \ + do { \ + cs_err __err = err; \ + if (__err != expect) { \ + fail_msg("%s",cs_strerror(__err)); \ + } \ + } while (0) + + +#define cs_assert_success(err) cs_assert_err(CS_ERR_OK, err) + + +#define cs_assert_fail(err) \ + do { \ + cs_err __err = err; \ + if (__err == CS_ERR_OK) { \ + fail_msg("%s",cs_strerror(__err)); \ + } \ + } while (0) + +#define NUMARCH 10 +#define NUMMODE 35 +#define NUMOPTION 41 +#define MAXMEM 1024 + +typedef struct { + const char *str; + unsigned int value; +} single_dict; + +typedef struct { + const char *str; + unsigned int first_value; + unsigned int second_value; +} double_dict; + +extern char *(*function)(csh *, cs_mode, cs_insn*); + +int get_index(double_dict d[], unsigned size, const char *str); +int get_value(single_dict d[], unsigned size, const char *str); +void test_single_MC(csh *handle, int mc_mode, char *line); +void test_single_issue(csh *handle, cs_mode mode, char *line, int detail); +int set_function(int arch); + +#endif /* CAPSTONE_TEST_H */ diff --git a/capstone/suite/cstest/include/factory.h b/capstone/suite/cstest/include/factory.h new file mode 100644 index 000000000..7df6c7838 --- /dev/null +++ b/capstone/suite/cstest/include/factory.h @@ -0,0 +1,27 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#ifndef FACTORY_H +#define FACTORY_H + +#include <capstone/capstone.h> +#include "helper.h" + +char *get_detail_evm(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_arm(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_arm64(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_m680x(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_mips(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_ppc(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_sparc(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_sysz(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_x86(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_xcore(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_riscv(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_m68k(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_mos65xx(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_tms320c64x(csh *handle, cs_mode mode, cs_insn *ins); +char *get_detail_bpf(csh *handle, cs_mode mode, cs_insn *ins); + +#endif /* FACTORY_H */ diff --git a/capstone/suite/cstest/include/helper.h b/capstone/suite/cstest/include/helper.h new file mode 100644 index 000000000..102230385 --- /dev/null +++ b/capstone/suite/cstest/include/helper.h @@ -0,0 +1,32 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#ifndef HELPER_H +#define HELPER_H + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <ctype.h> +#include <dirent.h> +#include "capstone_test.h" + +#define X86_16 0 +#define X86_32 1 +#define X86_64 2 + +char **split(char *str, char *delim, int *size); +void print_strs(char **list_str, int size); +void free_strs(char **list_str, int size); +void add_str(char **src, const char *format, ...); +void trim_str(char *src); +void replace_hex(char *src); +void replace_negative(char *src, int mode); +const char *get_filename_ext(const char *filename); + +char *readfile(const char *filename); +void listdir(const char *name, char ***files, int *num_files); + +#endif /* HELPER_H */ diff --git a/capstone/suite/cstest/issues.cs b/capstone/suite/cstest/issues.cs new file mode 100644 index 000000000..d8b0b7ebc --- /dev/null +++ b/capstone/suite/cstest/issues.cs @@ -0,0 +1,770 @@ +!# issue 1504 movhps qword ptr +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0f,0x16,0x08 == movhps xmm1, qword ptr [rax] ; Opcode:0x0f 0x16 0x00 0x00 + +!# issue 1505 opcode 0f +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0f,0xa5,0xc2 == shld edx, eax, cl ; Opcode:0x0f 0xa5 0x00 0x00 + +!# issue 1478 tbegin. +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x7c,0x20,0x05,0x1d == tbegin. 1 ; Update-CR0: True + +!# issue 970 PPC bdnzt lt +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x41,0x00,0xff,0xac == bdnzt lt, 0xffffffffffffffac ; operands[0].type: REG = cr0lt + +!# issue 970 PPC bdnzt eq +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x41,0x02,0xff,0xac == bdnzt eq, 0xffffffffffffffac ; operands[0].type: REG = cr0eq + +!# issue 969 PPC bdnzflr operand 2 +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x4c,0x10,0x00,0x20 == bdnzflr 4*cr4+lt ; operands[0].type: REG = cr4lt + +0x41,0x82,0x00,0x10 == beq 0x10 ; Groups: jump + +!# issue 1481 ARM64 LDR operand2 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0xe9,0x03,0x40,0xf9 == ldr x9, [sp] ; operands[1].mem.base: REG = sp + +!# issue 968 PPC absolute branch: bdnzla +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None +0x1000: 0x42,0x00,0x12,0x37 == bdnzla 0x1234 + +!# issue 968 PPC absolute branch: bdzla +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None +0x1000: 0x42,0x40,0x12,0x37 == bdzla 0x1234 + +!# issue X86 xrelease xchg +!# CS_ARCH_X86, CS_MODE_32, None +0xf3,0x87,0x03 == xrelease xchg dword ptr [ebx], eax + +!# issue X86 xacquire xchg +!# CS_ARCH_X86, CS_MODE_32, None +0xf2,0x87,0x03 == xacquire xchg dword ptr [ebx], eax + +!# issue X86 xrelease +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0xf0,0x31,0x1f == xrelease lock xor dword ptr [rdi], ebx + +!# issue 1477 X86 xacquire +!# CS_ARCH_X86, CS_MODE_64, None +0xf2,0xf0,0x31,0x1f == xacquire lock xor dword ptr [rdi], ebx + +!# issue PPC JUMP group +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x41,0x82,0x00,0x10 == beq 0x10 ; Groups: jump + +!# issue 1468 PPC bdnz +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None +0x101086c: 0x42,0x00,0xff,0xf8 == bdnz 0x1010864 + +!# issue PPC bdnzt +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None +0x1000: 0x41,0x00,0xff,0xac == bdnzt lt, 0xfac + +!# issue 1469 PPC CRx +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x4c,0x02,0x39,0x82 == crxor cr0lt, cr0eq, cr1un ; operands[0].type: REG = cr0lt + +!# issue 1468 B target +!# CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, None +0x1000: 0x4b,0xff,0xf8,0x00 == b 0x800 + +!# issue 1456 test alt 1 +!# CS_ARCH_X86, CS_MODE_32, None +0xf6,0x08,0x00 == test byte ptr [eax], 0 + +!# issue 1456 test alt 2 +!# CS_ARCH_X86, CS_MODE_32, None +0xf7,0x08,0x00,0x00,0x00,0x00 == test dword ptr [eax], 0 + +!# issue 1472 lock sub +!# CS_ARCH_X86, CS_MODE_32, None +0xF0,0x2B,0x45,0x08 == lock sub eax, dword ptr [ebp + 8] + +!# issue 1472 lock or +!# CS_ARCH_X86, CS_MODE_32, None +0xF0,0x0B,0x45,0x08 == lock or eax, dword ptr [ebp + 8] + +!# issue 1472 lock and +!# CS_ARCH_X86, CS_MODE_32, None +0xF0,0x23,0x45,0x08 == lock and eax, dword ptr [ebp + 8] + +!# issue 1472 lock add +!# CS_ARCH_X86, CS_MODE_32, None +0xF0,0x03,0x45,0x08 == lock add eax, dword ptr [ebp + 8] + +!# issue 1456 MOV dr +!# CS_ARCH_X86, CS_MODE_32, None +0x0f,0x23,0x00 == mov dr0, eax + +!# issue 1456 MOV dr +!# CS_ARCH_X86, CS_MODE_32, None +0x0f,0x21,0x00 == mov eax, dr0 + +!# issue 1456 MOV cr +!# CS_ARCH_X86, CS_MODE_32, None +0x0f,0x22,0x00 == mov cr0, eax + +!# issue 1472 lock adc +!# CS_ARCH_X86, CS_MODE_32, None +0xf0,0x12,0x45,0x08 == lock adc al, byte ptr [ebp + 8] + +!# issue 1456 xmmword +!# CS_ARCH_X86, CS_MODE_32, None +0x66,0x0f,0x2f,0x00 == comisd xmm0, xmmword ptr [eax] + +!# issue 1456 ARM printPKHASRShiftImm +!# CS_ARCH_ARM, CS_MODE_THUMB, None +0xca,0xea,0x21,0x06 == pkhtb r6, sl, r1, asr #0x20 + +!# issue 1456 EIZ +!# CS_ARCH_X86, CS_MODE_32, None +0x8d,0xb4,0x26,0x00,0x00,0x00,0x00 == lea esi, [esi] + +!# issue 1456 ARM POP +!# CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN, None +0x04,0x10,0x9d,0xe4 == pop {r1} + +!# issue 1456 +!# CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0x31,0x02,0xa0,0xe1 == lsr r0, r1, r2 ; operands[2].type: REG = r2 + +!# issue 1456 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0x0c,0x00,0x80,0x12 == mov w12, #-1 ; operands[1].type: IMM = 0xffffffffffffffff + +0xb8,0x00,0x00,0x00,0x00 == movl $0, %eax + +!# issue 1456 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT +0xb8,0x00,0x00,0x00,0x00 == movl $0, %eax + +0xd1,0x5e,0x48 == rcrl $1, 0x48(%esi) + +!# issue 1456 +!# CS_ARCH_X86, CS_MODE_32, None +0xd1,0x5e,0x48 == rcr dword ptr [esi + 0x48], 1 + +!# issue 1456 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT +0xd1,0x5e,0x48 == rcrl $1, 0x48(%esi) + +!# issue 1456 +!# CS_ARCH_X86, CS_MODE_32, None +0x62,0x00 == bound eax, qword ptr [eax] + +!# issue 1454 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0xf0,0x0f,0xb1,0x1e == lock cmpxchg dword ptr [esi], ebx ; Registers read: eax esi ebx + +!# issue 1452 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0x20,0x3c,0x0c,0x0e == mov w0, v1.s[1] ; Vector Arrangement Specifier: 0xb + +!# issue 1452 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0x20,0x3c,0x18,0x4e == mov x0, v1.d[1] ; Vector Arrangement Specifier: 0xd + +!# issue 1452 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0x20,0x3c,0x03,0x0e == umov w0, v1.b[1] ; Vector Arrangement Specifier: 0x4 + +!# issue 1452 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, CS_OPT_DETAIL +0x20,0x3c,0x06,0x0e == umov w0, v1.h[1] ; Vector Arrangement Specifier: 0x8 + +!# issue 1211 +!# CS_ARCH_X86, CS_MODE_64, None +0xc4,0xe1,0xf8,0x90,0xc0 == kmovq k0, k0 + +!# issue 1211 +!# CS_ARCH_X86, CS_MODE_64, None +0xc4,0xe1,0xfb,0x92,0xc3 == kmovq k0, rbx + +!# issue 1211 +!# CS_ARCH_X86, CS_MODE_64, None +0x62,0xf1,0x7d,0x48,0x74,0x83,0x12,0x00,0x00,0x00 == vpcmpeqb k0, zmm0, zmmword ptr [rbx + 0x12] + +!# issue 1211 +!# CS_ARCH_X86, CS_MODE_64, None +0x62,0xf2,0x7d,0x48,0x30,0x43,0x08 == vpmovzxbw zmm0, ymmword ptr [rbx + 0x100] + +!# issue x86 BND register (OSS-fuzz #13467) +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0f,0x1a,0x1a == bndldx bnd3, [edx] ; operands[0].type: REG = bnd3 + +!# issue 1335 +!# CS_ARCH_X86, CS_MODE_32, None +0x0f,0x1f,0xc0 == nop eax + +!# issue 1335 +!# CS_ARCH_X86, CS_MODE_64, None +0x48,0x0f,0x1f,0x00 == nop qword ptr [rax] + +!# issue 1259 +!# CS_ARCH_X86, CS_MODE_64, None +0x0f,0x0d,0x44,0x11,0x40 == prefetch byte ptr [rcx + rdx + 0x40] + +!# issue 1259 +!# CS_ARCH_X86, CS_MODE_64, None +0x41,0x0f,0x0d,0x44,0x12,0x40 == prefetch byte ptr [r10 + rdx + 0x40] + +!# issue 1304 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x66,0x0f,0x7f,0x4c,0x24,0x40 == movdqa xmmword ptr [rsp + 0x40], xmm1 ; operands[0].access: WRITE + +!# issue 1304 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x66,0x0f,0x7e,0x04,0x24 == movd dword ptr [rsp], xmm0 ; operands[0].access: WRITE + +!# issue 1304 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0xf3,0x41,0x0f,0x7f,0x4d,0x00 == movdqu xmmword ptr [r13], xmm1 ; operands[0].access: WRITE + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x48,0x0f,0x1e,0xc8 == rdsspq rax + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0x1e,0xc8 == rdsspd eax + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x48,0x0f,0xae,0xe8 == incsspq rax + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0xae,0xe8 == incsspd eax + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0x01,0xea == saveprevssp + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0x01,0x28 == rstorssp dword ptr [rax] + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0x67,0xf3,0x0f,0x01,0x28 == rstorssp dword ptr [eax] + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0x48,0x0f,0x38,0xf6,0x00 == wrssq qword ptr [rax], rax + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0x67,0x0f,0x38,0xf6,0x00 == wrssd dword ptr [eax], eax + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0x01,0xe8 == setssbsy + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0xae,0x30 == clrssbsy dword ptr [rax] + +!# issue 1346 +!# CS_ARCH_X86, CS_MODE_64, None +0x67,0xf3,0x0f,0xae,0x30 == clrssbsy dword ptr [eax] + +!# issue 1206 +!# CS_ARCH_X86, CS_MODE_64, None +0xc4,0xe2,0x7d,0x5a,0x0c,0x0e == vbroadcasti128 ymm1, xmmword ptr [rsi + rcx] + +!# issue xchg 16bit +!# CS_ARCH_X86, CS_MODE_16, None +0x91 == xchg cx, ax + +!# issue ROL 1, ATT syntax +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x66,0x48,0xf3,0xd1,0xc0 == rolw $1, %ax + +!# issue 1129 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0x1e,0xfa == endbr64 + +!# issue 1129 +!# CS_ARCH_X86, CS_MODE_32, None +0xf3,0x0f,0x1e,0xfa == endbr64 + +!# issue 1129 +!# CS_ARCH_X86, CS_MODE_64, None +0xf3,0x0f,0x1e,0xfb == endbr32 + +!# issue 1129 +!# CS_ARCH_X86, CS_MODE_32, None +0xf3,0x0f,0x1e,0xfb == endbr32 + +!# issue x64 jmp +!# CS_ARCH_X86, CS_MODE_64, None +0x1000: 0xeb,0xfe == jmp 0x1000 + +!# issue x64att jmp +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x1000: 0xeb,0xfe == jmp 0x1000 + +!# issue x32 jmp +!# CS_ARCH_X86, CS_MODE_32, None +0x1000: 0xeb,0xfe == jmp 0x1000 + +!# issue x32att jmp +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_SYNTAX_ATT +0x1000: 0xeb,0xfe == jmp 0x1000 + +!# issue 1389 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x66,0x0f,0x73,0xf9,0x01 == pslldq xmm1, 1 ; operands[1].size: 1 + +!# issue 1389 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT | CS_OPT_DETAIL +0x66,0x0f,0x73,0xf9,0x01 == pslldq $1, %xmm1 ; operands[0].size: 1 + +!# issue x64 unsigned +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_UNSIGNED +0x66,0x83,0xc0,0x80 == add ax, 0xff80 + +!# issue x64att unsigned +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT | CS_OPT_UNSIGNED +0x66,0x83,0xc0,0x80 == addw $0xff80, %ax + +!# issue 1323 +!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL +0x0: 0x70,0x47,0x00 == bx lr ; op_count: 1 ; operands[0].type: REG = lr ; operands[0].access: READ ; Registers read: lr ; Registers modified: pc ; Groups: thumb jump + +!# issue 1317 +!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL +0x0: 0xd0,0xe8,0x11,0xf0 == tbh [r0, r1, lsl #1] ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = r0 ; operands[0].mem.index: REG = r1 ; operands[0].mem.lshift: 0x1 ; operands[0].access: READ ; Shift: 2 = 1 ; Registers read: r0 r1 ; Groups: thumb2 jump + +!# issue 1308 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0x83,0x3d,0xa1,0x75,0x21,0x00,0x04 == cmp dword ptr [rip + 0x2175a1], 4 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x83 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x3d ; disp: 0x2175a1 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x4 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.base: REG = rip ; operands[0].mem.disp: 0x2175a1 ; operands[0].size: 4 ; operands[0].access: READ ; operands[1].type: IMM = 0x4 ; operands[1].size: 4 ; Registers read: rip ; Registers modified: rflags ; EFLAGS: MOD_AF MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF + +!# issue 1262 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0x0f,0x95,0x44,0x24,0x5e == setne byte ptr [rsp + 0x5e] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x95 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x44 ; disp: 0x5e ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x5e ; operands[0].size: 1 ; operands[0].access: WRITE ; Registers read: rflags rsp ; EFLAGS: TEST_ZF + +!# issue 1262 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0x0f,0x94,0x44,0x24,0x1f == sete byte ptr [rsp + 0x1f] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x94 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x44 ; disp: 0x1f ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x1f ; operands[0].size: 1 ; operands[0].access: WRITE ; Registers read: rflags rsp ; EFLAGS: TEST_ZF + +!# issue 1263 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x67,0x48,0x89,0x18 == mov qword ptr [eax], rbx + +!# issue 1263 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x67,0x48,0x8b,0x03 == mov rax, qword ptr [ebx] + +!# issue 1255 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0xdb,0x7c,0x24,0x40 == fstp xword ptr [rsp + 0x40] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xdb 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x7c ; disp: 0x40 ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x40 ; operands[0].size: 10 ; operands[0].access: WRITE ; Registers read: rsp ; Registers modified: fpsw ; FPU_FLAGS: MOD_C1 UNDEF_C0 UNDEF_C2 UNDEF_C3 ; Groups: fpu + +!# issue 1255 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0xdd,0xd9 == fstp st(1) ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xdd 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0xd9 ; disp: 0x0 ; sib: 0x0 ; op_count: 1 ; operands[0].type: REG = st(1) ; operands[0].size: 10 ; operands[0].access: WRITE ; Registers modified: fpsw st(1) ; EFLAGS: MOD_CF PRIOR_SF PRIOR_AF PRIOR_PF + +!# issue 1255 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0xdf,0x7c,0x24,0x68 == fistp qword ptr [rsp + 0x68] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xdf 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x7c ; disp: 0x68 ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x68 ; operands[0].size: 8 ; operands[0].access: WRITE ; Registers read: rsp ; Registers modified: fpsw ; FPU_FLAGS: RESET_C1 UNDEF_C0 UNDEF_C2 UNDEF_C3 ; Groups: fpu + +!# issue 1221 +!# CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, None +0x0: 0x55,0x48,0x89,0xe5 == call 0x55222794 + +!# issue 1144 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None +0x0: 0x00,0x00,0x02,0xb6 == tbz x0, #0x20, #0x4000 + +!# issue 1144 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None +0x0: 0x00,0x00,0x04,0xb6 == tbz x0, #0x20, #0xffffffffffff8000 + +!# issue 1144 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None +0x0: 0x00,0x00,0x02,0xb7 == tbnz x0, #0x20, #0x4000 + +!# issue 1144 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None +0x0: 0x00,0x00,0x04,0xb7 == tbnz x0, #0x20, #0xffffffffffff8000 + +!# issue 826 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x0b,0x00,0x00,0x0a == beq #0x34 ; op_count: 1 ; operands[0].type: IMM = 0x34 ; Code condition: 1 ; Registers read: pc ; Registers modified: pc ; Groups: branch_relative arm jump + +!# issue 1047 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x0: 0x48,0x83,0xe4,0xf0 == andq $0xfffffffffffffff0, %rsp + +!# issue 959 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xa0,0x28,0x57,0x88,0x7c == mov al, byte ptr [0x7c885728] + +!# issue 950 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0x66,0xa3,0x94,0x90,0x04,0x08 == mov word ptr [0x8049094], ax ; Prefix:0x00 0x00 0x66 0x00 ; Opcode:0xa3 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x8049094 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.disp: 0x8049094 ; operands[0].size: 2 ; operands[0].access: WRITE ; operands[1].type: REG = ax ; operands[1].size: 2 ; operands[1].access: READ ; Registers read: ax + +!# issue 938 +!# CS_ARCH_MIPS, CS_MODE_MIPS64+CS_MODE_LITTLE_ENDIAN, None +0x0: 0x70,0x00,0xb2,0xff == sd $s2, 0x70($sp) + +!# issue 915 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0xf0,0x0f,0x1f,0x00 == lock nop dword ptr [rax] + +// !# issue 913 +// !# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x04,0x10,0x9d,0xe4 == pop {r1} ; op_count: 1 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; Write-back: True ; Registers read: sp ; Registers modified: sp r1 ; Groups: arm + +!# issue 884 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x0: 0x64,0x48,0x03,0x04,0x25,0x00,0x00,0x00,0x00 == addq %fs:0, %rax + +!# issue 872 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0xeb,0x3e == bnd jmp 0x41 + +!# issue 861 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x01,0x81,0xa0,0xfc == stc2 p1, c8, [r0], #4 ; op_count: 4 ; operands[0].type: P-IMM = 1 ; operands[1].type: C-IMM = 8 ; operands[2].type: MEM ; operands[2].mem.base: REG = r0 ; operands[2].access: READ ; operands[3].type: IMM = 0x4 ; Write-back: True ; Registers read: r0 ; Registers modified: r0 ; Groups: prev8 + +!# issue 852 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0x64,0xa3,0x00,0x00,0x00,0x00 == mov dword ptr fs:[0], eax ; Prefix:0x00 0x64 0x00 0x00 ; Opcode:0xa3 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.segment: REG = fs ; operands[0].size: 4 ; operands[0].access: WRITE ; operands[1].type: REG = eax ; operands[1].size: 4 ; operands[1].access: READ ; Registers read: fs eax + +!# issue 825 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x0e,0xf0,0xa0,0xe1 == mov pc, lr ; op_count: 2 ; operands[0].type: REG = pc ; operands[0].access: WRITE ; operands[1].type: REG = lr ; operands[1].access: READ ; Registers read: lr ; Registers modified: pc ; Groups: arm + +!# issue 813 +!# CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_BIG_ENDIAN, None +0x0: 0xF6,0xC0,0x04,0x01 == movt r4, #0x801 + +!# issue 809 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL +0x0: 0x0f,0x29,0x8d,0xf0,0xfd,0xff,0xff == movaps xmmword ptr [rbp - 0x210], xmm1 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x29 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x8d ; disp: 0xfffffffffffffdf0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.base: REG = rbp ; operands[0].mem.disp: 0xfffffffffffffdf0 ; operands[0].size: 16 ; operands[0].access: WRITE ; operands[1].type: REG = xmm1 ; operands[1].size: 16 ; operands[1].access: READ ; Registers read: rbp xmm1 ; Groups: sse1 + +!# issue 807 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x4c,0x0f,0x00,0x80,0x16,0x76,0x8a,0xfe == sldt word ptr [rax - 0x17589ea] + +!# issue 806 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x0f,0x35 == sysexit + +!# issue 805 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x0: 0x48,0x4c,0x0f,0xb5,0x80,0x16,0x76,0x8a,0xfe == lgs -0x17589ea(%rax), %r8 + +!# issue 804 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x0: 0x66,0x48,0xf3,0xd1,0xc0 == rolw $1, %ax + +!# issue 789 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x0: 0x8e,0x1e == movw (%rsi), %ds + +!# issue 767 +!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL +0x0: 0xb1,0xe8,0xfc,0x07 == ldm.w r1!, {r2, r3, r4, r5, r6, r7, r8, sb, sl} ; op_count: 10 ; operands[0].type: REG = r1 ; operands[0].access: READ | WRITE ; operands[1].type: REG = r2 ; operands[1].access: WRITE ; operands[2].type: REG = r3 ; operands[2].access: WRITE ; operands[3].type: REG = r4 ; operands[3].access: WRITE ; operands[4].type: REG = r5 ; operands[4].access: WRITE ; operands[5].type: REG = r6 ; operands[5].access: WRITE ; operands[6].type: REG = r7 ; operands[6].access: WRITE ; operands[7].type: REG = r8 ; operands[7].access: WRITE ; operands[8].type: REG = sb ; operands[8].access: WRITE ; operands[9].type: REG = sl ; operands[9].access: WRITE ; Write-back: True ; Registers read: r1 ; Registers modified: r1 r2 r3 r4 r5 r6 r7 r8 sb sl ; Groups: thumb2 + +!# issue 760 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x02,0x80,0xbd,0xe8 == pop {r1, pc} ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: REG = pc ; operands[1].access: WRITE ; Registers read: sp ; Registers modified: sp r1 pc ; Groups: arm + +!# issue 750 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x0e,0x00,0x20,0xe9 == stmdb r0!, {r1, r2, r3} ; op_count: 4 ; operands[0].type: REG = r0 ; operands[0].access: READ ; operands[1].type: REG = r1 ; operands[2].type: REG = r2 ; operands[3].type: REG = r3 ; Write-back: True ; Registers read: r0 ; Groups: arm + +!# issue 747 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x0e,0x00,0xb0,0xe8 == ldm r0!, {r1, r2, r3} ; op_count: 4 ; operands[0].type: REG = r0 ; operands[0].access: READ | WRITE ; operands[1].type: REG = r1 ; operands[1].access: WRITE ; operands[2].type: REG = r2 ; operands[2].access: WRITE ; operands[3].type: REG = r3 ; operands[3].access: WRITE ; Write-back: True ; Registers read: r0 ; Registers modified: r0 r1 r2 r3 ; Groups: arm + +!# issue 747 +!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL +0x0: 0x0e,0xc8 == ldm r0!, {r1, r2, r3} ; op_count: 4 ; operands[0].type: REG = r0 ; operands[0].access: READ | WRITE ; operands[1].type: REG = r1 ; operands[1].access: WRITE ; operands[2].type: REG = r2 ; operands[2].access: WRITE ; operands[3].type: REG = r3 ; operands[3].access: WRITE ; Write-back: True ; Registers read: r0 ; Registers modified: r0 r1 r2 r3 ; Groups: thumb thumb1only + +!# issue 746 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x89,0x00,0x2d,0xe9 == push {r0, r3, r7} ; op_count: 3 ; operands[0].type: REG = r0 ; operands[0].access: READ ; operands[1].type: REG = r3 ; operands[1].access: READ ; operands[2].type: REG = r7 ; operands[2].access: READ ; Registers read: sp r0 r3 r7 ; Registers modified: sp ; Groups: arm + +!# issue 744 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0x02,0x80,0xbd,0xe8 == pop {r1, pc} ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: REG = pc ; operands[1].access: WRITE ; Registers read: sp ; Registers modified: sp r1 pc ; Groups: arm + +!# issue 741 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x83,0xff,0xf7 == cmp edi, -9 + +!# issue 717 +!# CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT +0x0: 0x48,0x8b,0x04,0x25,0x00,0x00,0x00,0x00 == movq 0, %rax + +!# issue 711 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xa3,0x44,0xb0,0x00,0x10 == mov dword ptr [0x1000b044], eax ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xa3 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x1000b044 ; sib: 0x0 ; op_count: 2 ; operands[0].type: MEM ; operands[0].mem.disp: 0x1000b044 ; operands[0].size: 4 ; operands[0].access: WRITE ; operands[1].type: REG = eax ; operands[1].size: 4 ; operands[1].access: READ ; Registers read: eax + +!# issue 613 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0xd9,0x74,0x24,0xd8 == fnstenv [rsp - 0x28] + +!# issue 554 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xe7,0x84 == out 0x84, eax + +!# issue 554 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xe5,0x8c == in eax, 0x8c + +!# issue 545 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0x95 == xchg ebp, eax ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x95 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = ebp ; operands[0].size: 4 ; operands[0].access: READ | WRITE ; operands[1].type: REG = eax ; operands[1].size: 4 ; operands[1].access: READ | WRITE ; Registers read: ebp eax ; Registers modified: ebp eax ; Groups: not64bitmode + +!# issue 544 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xdf,0x30 == fbstp tbyte ptr [eax] + +!# issue 544 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xdf,0x20 == fbld tbyte ptr [eax] + +!# issue 541 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x48,0xb8,0x00,0x00,0x00,0x00,0x80,0xf8,0xff,0xff == movabs rax, 0xfffff88000000000 + +!# issue 499 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x48,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80 == movabs rax, 0x8000000000000000 + +!# issue 492 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xff,0x18 == call ptr [eax] + +!# issue 492 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xff,0x28 == jmp ptr [eax] + +!# issue 492 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x0f,0xae,0x04,0x24 == fxsave [esp] + +!# issue 492 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x0f,0xae,0x0c,0x24 == fxrstor [esp] + +!# issue 470 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x0f,0x01,0x05,0xa0,0x90,0x04,0x08 == sgdt [0x80490a0] + +!# issue 470 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x0f,0x01,0x0d,0xa7,0x90,0x04,0x08 == sidt [0x80490a7] + +!# issue 470 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x0f,0x01,0x15,0xa0,0x90,0x04,0x08 == lgdt [0x80490a0] + +!# issue 470 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x0f,0x01,0x1d,0xa7,0x90,0x04,0x08 == lidt [0x80490a7] + +!# issue 459 +!# CS_ARCH_ARM, CS_MODE_ARM, CS_OPT_DETAIL +0x0: 0xd3,0x20,0x11,0xe1 == ldrsb r2, [r1, -r3] ; op_count: 2 ; operands[0].type: REG = r2 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r1 ; operands[1].mem.index: REG = r3 ; operands[1].mem.scale: -1 ; Subtracted: True ; Registers read: r1 r3 ; Registers modified: r2 ; Groups: arm + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_16, None +0x0: 0xe8,0x35,0x64 == call 0x6438 + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_16, None +0x0: 0xe9,0x35,0x64 == jmp 0x6438 + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_16, None +0x0: 0x66,0xe9,0x35,0x64,0x93,0x53 == jmp 0x5393643b + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_16, None +0x0: 0x66,0xe8,0x35,0x64,0x93,0x53 == call 0x5393643b + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_16, None +0x0: 0x66,0xe9,0x35,0x64,0x93,0x53 == jmp 0x5393643b + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x66,0xe8,0x35,0x64 == call 0x6439 + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xe9,0x35,0x64,0x93,0x53 == jmp 0x5393643a + +!# issue 456 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x66,0xe9,0x35,0x64 == jmp 0x6439 + +!# issue 458 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xA1,0x12,0x34,0x90,0x90 == mov eax, dword ptr [0x90903412] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xa1 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x90903412 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = eax ; operands[0].size: 4 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.disp: 0x90903412 ; operands[1].size: 4 ; operands[1].access: READ ; Registers modified: eax + +!# issue 454 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0x6c == repne insb byte ptr es:[edi], dx + +!# issue 454 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0x6d == repne insd dword ptr es:[edi], dx + +!# issue 454 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0x6e == repne outsb dx, byte ptr [esi] + +!# issue 454 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0x6f == repne outsd dx, dword ptr [esi] + +!# issue 454 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0xac == repne lodsb al, byte ptr [esi] + +!# issue 454 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf2,0xad == repne lodsd eax, dword ptr [esi] + +!# issue 450 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xff,0x2d,0x34,0x35,0x23,0x01 == jmp ptr [0x1233534] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xff 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x2d ; disp: 0x1233534 ; sib: 0x0 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.disp: 0x1233534 ; operands[0].size: 6 ; Groups: jump + +!# issue 448 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xea,0x12,0x34,0x56,0x78,0x9a,0xbc == ljmp 0xbc9a:0x78563412 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xea 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 2 ; imms[1]: 0xbc9a ; imms[2]: 0x78563412 ; op_count: 2 ; operands[0].type: IMM = 0xbc9a ; operands[0].size: 2 ; operands[1].type: IMM = 0x78563412 ; operands[1].size: 4 ; Groups: not64bitmode jump + +!# issue 426 +!# CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, None +0x0: 0xbb,0x70,0x00,0x00 == popc %g0, %i5 + +!# issue 358 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xe8,0xe3,0xf6,0xff,0xff == call 0xfffff6e8 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xe8 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0xfffff6e8 ; op_count: 1 ; operands[0].type: IMM = 0xfffff6e8 ; operands[0].size: 4 ; Registers read: esp eip ; Registers modified: esp ; Groups: call branch_relative not64bitmode + +!# issue 353 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xe6,0xa2 == out 0xa2, al ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xe6 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0xa2 ; op_count: 2 ; operands[0].type: IMM = 0xa2 ; operands[0].size: 1 ; operands[1].type: REG = al ; operands[1].size: 1 ; operands[1].access: READ ; Registers read: al + +!# issue 305 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x34,0x8b == xor al, 0x8b + +!# issue 298 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xf3,0x90 == pause + +!# issue 298 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0x66,0xf3,0xf2,0x0f,0x59,0xff == mulsd xmm7, xmm7 + +// !# issue 298 +// !# CS_ARCH_X86, CS_MODE_32, None +// 0x0: 0xf2,0x66,0x0f,0x59,0xff == mulpd xmm7, xmm7 + +!# issue 294 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xc1,0xe6,0x08 == shl esi, 8 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xc1 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0xe6 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x8 ; op_count: 2 ; operands[0].type: REG = esi ; operands[0].size: 4 ; operands[0].access: READ | WRITE ; operands[1].type: IMM = 0x8 ; operands[1].size: 1 ; Registers read: esi ; Registers modified: eflags esi ; EFLAGS: MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF UNDEF_AF + +!# issue 285 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0x3c,0x12,0x80 == cmp al, 0x12 ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x3c 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x12 ; op_count: 2 ; operands[0].type: REG = al ; operands[0].size: 1 ; operands[0].access: READ ; operands[1].type: IMM = 0x12 ; operands[1].size: 1 ; Registers read: al ; Registers modified: eflags ; EFLAGS: MOD_AF MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF + +!# issue 265 +!# CS_ARCH_ARM, CS_MODE_THUMB, CS_OPT_DETAIL +0x0: 0x52,0xf8,0x23,0x30 == ldr.w r3, [r2, r3, lsl #2] ; op_count: 2 ; operands[0].type: REG = r3 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r2 ; operands[1].mem.index: REG = r3 ; operands[1].access: READ ; Shift: 2 = 2 ; Registers read: r2 r3 ; Registers modified: r3 ; Groups: thumb2 + +!# issue 264 +!# CS_ARCH_ARM, CS_MODE_THUMB, None +0x0: 0x0c,0xbf == ite eq + +!# issue 264 +!# CS_ARCH_ARM, CS_MODE_THUMB, None +0x0: 0x17,0x20 == movs r0, #0x17 + +!# issue 264 +!# CS_ARCH_ARM, CS_MODE_THUMB, None +0x0: 0x4f,0xf0,0xff,0x30 == mov.w r0, #-1 + +!# issue 246 +!# CS_ARCH_ARM, CS_MODE_THUMB, None +0x0: 0x52,0xf8,0x23,0xf0 == ldr.w pc, [r2, r3, lsl #2] + +!# issue 232 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0x8e,0x10 == mov ss, word ptr [eax] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x8e 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x10 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = ss ; operands[0].size: 2 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = eax ; operands[1].size: 2 ; operands[1].access: READ ; Registers read: eax ; Registers modified: ss ; Groups: privilege + +!# issue 231 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0x66,0x6b,0xc0,0x02 == imul ax, ax, 2 ; Prefix:0x00 0x00 0x66 0x00 ; Opcode:0x6b 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0xc0 ; disp: 0x0 ; sib: 0x0 ; imm_count: 1 ; imms[1]: 0x2 ; op_count: 3 ; operands[0].type: REG = ax ; operands[0].size: 2 ; operands[0].access: WRITE ; operands[1].type: REG = ax ; operands[1].size: 2 ; operands[1].access: READ ; operands[2].type: IMM = 0x2 ; operands[2].size: 2 ; Registers read: ax ; Registers modified: eflags ax ; EFLAGS: MOD_CF MOD_SF MOD_OF UNDEF_ZF UNDEF_PF UNDEF_AF + +!# issue 230 +!# CS_ARCH_X86, CS_MODE_32, CS_OPT_DETAIL +0x0: 0xec == in al, dx ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0xec 0x00 0x00 0x00 ; rex: 0x0 ; addr_size: 4 ; modrm: 0x0 ; disp: 0x0 ; sib: 0x0 ; op_count: 2 ; operands[0].type: REG = al ; operands[0].size: 1 ; operands[0].access: WRITE ; operands[1].type: REG = dx ; operands[1].size: 2 ; operands[1].access: READ ; Registers read: dx ; Registers modified: al + +!# issue 213 +!# CS_ARCH_X86, CS_MODE_16, None +0x0: 0xea,0xaa,0xff,0x00,0xf0 == ljmp 0xf000:0xffaa + +!# issue 191 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0xc5,0xe8,0xc2,0x33,0x9b == vcmpps xmm6, xmm2, xmmword ptr [rbx], 0x9b + +!# issue 176 +!# CS_ARCH_ARM, CS_MODE_ARM, None +0x0: 0xfd,0xff,0xff,0x1a == bne #0xfffffffc + +!# issue 151 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x4d,0x8d,0x3d,0x02,0x00,0x00,0x00 == lea r15, [rip + 2] + +!# issue 151 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0xeb,0xb0 == jmp 0xffffffffffffffb2 + +!# issue 134 +!# CS_ARCH_ARM, CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x0: 0xe7,0x92,0x11,0x80 == ldr r1, [r2, r0, lsl #3] ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = r2 ; operands[1].mem.index: REG = r0 ; operands[1].access: READ ; Shift: 2 = 3 ; Registers read: r2 r0 ; Registers modified: r1 ; Groups: arm + +!# issue 133 +!# CS_ARCH_ARM, CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x0: 0xed,0xdf,0x2b,0x1b == vldr d18, [pc, #0x6c] ; op_count: 2 ; operands[0].type: REG = d18 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = pc ; operands[1].mem.disp: 0x6c ; operands[1].access: READ ; Registers read: pc ; Registers modified: d18 ; Groups: vfp2 + +!# issue 132 +!# CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x0: 0x49,0x19 == ldr r1, [pc, #0x64] ; op_count: 2 ; operands[0].type: REG = r1 ; operands[0].access: WRITE ; operands[1].type: MEM ; operands[1].mem.base: REG = pc ; operands[1].mem.disp: 0x64 ; operands[1].access: READ ; Registers read: pc ; Registers modified: r1 ; Groups: thumb thumb1only + +!# issue 130 +!# CS_ARCH_ARM, CS_MODE_BIG_ENDIAN, CS_OPT_DETAIL +0x0: 0xe1,0xa0,0xf0,0x0e == mov pc, lr ; op_count: 2 ; operands[0].type: REG = pc ; operands[0].access: WRITE ; operands[1].type: REG = lr ; operands[1].access: READ ; Registers read: lr ; Registers modified: pc ; Groups: arm + +!# issue 85 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None +0x0: 0xee,0x3f,0xbf,0x29 == stp w14, w15, [sp, #-8]! + +!# issue 82 +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0xf2,0x66,0xaf == repne scasw ax, word ptr [rdi] + +!# issue 35 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xe8,0xc6,0x02,0x00,0x00 == call 0x2cb + +!# issue 8 +!# CS_ARCH_X86, CS_MODE_32, None +0x0: 0xff,0x8c,0xf9,0xff,0xff,0x9b,0xf9 == dec dword ptr [ecx + edi*8 - 0x6640001] + +!# issue 29 +!# CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, None +0x0: 0x00,0x00,0x00,0x4c == st4 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0] + diff --git a/capstone/suite/cstest/src/arm64_detail.c b/capstone/suite/cstest/src/arm64_detail.c new file mode 100644 index 000000000..e45ba4f6b --- /dev/null +++ b/capstone/suite/cstest/src/arm64_detail.c @@ -0,0 +1,138 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_arm64(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_arm64 *arm64; + int i; + cs_regs regs_read, regs_write; + uint8_t regs_read_count, regs_write_count; + uint8_t access; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + // detail can be NULL if SKIPDATA option is turned ON + if (ins->detail == NULL) + return result; + + arm64 = &(ins->detail->arm64); + if (arm64->op_count) + add_str(&result, " ; op_count: %u", arm64->op_count); + + for (i = 0; i < arm64->op_count; i++) { + cs_arm64_op *op = &(arm64->operands[i]); + switch(op->type) { + default: + break; + case ARM64_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case ARM64_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64, i, op->imm); + break; + case ARM64_OP_FP: +#if defined(_KERNEL_MODE) + // Issue #681: Windows kernel does not support formatting float point + add_str(&result, " ; operands[%u].type: FP = <float_point_unsupported>", i); +#else + add_str(&result, " ; operands[%u].type: FP = %f", i, op->fp); +#endif + break; + case ARM64_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != ARM64_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.index != ARM64_REG_INVALID) + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index)); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + + break; + case ARM64_OP_CIMM: + add_str(&result, " ; operands[%u].type: C-IMM = %u", i, (int)op->imm); + break; + case ARM64_OP_REG_MRS: + add_str(&result, " ; operands[%u].type: REG_MRS = 0x%x", i, op->reg); + break; + case ARM64_OP_REG_MSR: + add_str(&result, " ; operands[%u].type: REG_MSR = 0x%x", i, op->reg); + break; + case ARM64_OP_PSTATE: + add_str(&result, " ; operands[%u].type: PSTATE = 0x%x", i, op->pstate); + break; + case ARM64_OP_SYS: + add_str(&result, " ; operands[%u].type: SYS = 0x%x", i, op->sys); + break; + case ARM64_OP_PREFETCH: + add_str(&result, " ; operands[%u].type: PREFETCH = 0x%x", i, op->prefetch); + break; + case ARM64_OP_BARRIER: + add_str(&result, " ; operands[%u].type: BARRIER = 0x%x", i, op->barrier); + break; + } + + access = op->access; + switch(access) { + default: + break; + case CS_AC_READ: + add_str(&result, " ; operands[%u].access: READ", i); + break; + case CS_AC_WRITE: + add_str(&result, " ; operands[%u].access: WRITE", i); + break; + case CS_AC_READ | CS_AC_WRITE: + add_str(&result, " ; operands[%u].access: READ | WRITE", i); + break; + } + + if (op->shift.type != ARM64_SFT_INVALID && + op->shift.value) + add_str(&result, " ; Shift: type = %u, value = %u", + op->shift.type, op->shift.value); + + if (op->ext != ARM64_EXT_INVALID) + add_str(&result, " ; Ext: %u", op->ext); + + if (op->vas != ARM64_VAS_INVALID) + add_str(&result, " ; Vector Arrangement Specifier: 0x%x", op->vas); + + if (op->vector_index != -1) + add_str(&result, " ; Vector Index: %u", op->vector_index); + } + + if (arm64->update_flags) + add_str(&result, " ; Update-flags: True"); + + if (arm64->writeback) + add_str(&result, " ; Write-back: True"); + + if (arm64->cc) + add_str(&result, " ; Code-condition: %u", arm64->cc); + + // Print out all registers accessed by this instruction (either implicit or explicit) + if (!cs_regs_access(*handle, ins, + regs_read, ®s_read_count, + regs_write, ®s_write_count)) { + if (regs_read_count) { + add_str(&result, " ; Registers read:"); + for(i = 0; i < regs_read_count; i++) { + add_str(&result, " %s", cs_reg_name(*handle, regs_read[i])); + } + } + + if (regs_write_count) { + add_str(&result, " ; Registers modified:"); + for(i = 0; i < regs_write_count; i++) { + add_str(&result, " %s", cs_reg_name(*handle, regs_write[i])); + } + } + } + + return result; +} diff --git a/capstone/suite/cstest/src/arm_detail.c b/capstone/suite/cstest/src/arm_detail.c new file mode 100644 index 000000000..f1d6402a9 --- /dev/null +++ b/capstone/suite/cstest/src/arm_detail.c @@ -0,0 +1,150 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_arm(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_arm *arm; + int i; + cs_regs regs_read, regs_write; + uint8_t regs_read_count, regs_write_count; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + arm = &(ins->detail->arm); + + if (arm->op_count) + add_str(&result, " ; op_count: %u", arm->op_count); + + for (i = 0; i < arm->op_count; i++) { + cs_arm_op *op = &(arm->operands[i]); + switch((int)op->type) { + default: + break; + case ARM_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case ARM_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm); + break; + case ARM_OP_FP: +#if defined(_KERNEL_MODE) + // Issue #681: Windows kernel does not support formatting float point + add_str(&result, " ; operands[%u].type: FP = <float_point_unsupported>", i); +#else + add_str(&result, " ; operands[%u].type: FP = %f", i, op->fp); +#endif + break; + case ARM_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != ARM_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.index != ARM_REG_INVALID) + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index)); + if (op->mem.scale != 1) + add_str(&result, " ; operands[%u].mem.scale: %d", i, op->mem.scale); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + if (op->mem.lshift != 0) + add_str(&result, " ; operands[%u].mem.lshift: 0x%x", i, op->mem.lshift); + + break; + case ARM_OP_PIMM: + add_str(&result, " ; operands[%u].type: P-IMM = %u", i, op->imm); + break; + case ARM_OP_CIMM: + add_str(&result, " ; operands[%u].type: C-IMM = %u", i, op->imm); + break; + case ARM_OP_SETEND: + add_str(&result, " ; operands[%u].type: SETEND = %s", i, op->setend == ARM_SETEND_BE? "be" : "le"); + break; + case ARM_OP_SYSREG: + add_str(&result, " ; operands[%u].type: SYSREG = %u", i, op->reg); + break; + } + + if (op->neon_lane != -1) { + add_str(&result, " ; operands[%u].neon_lane = %u", i, op->neon_lane); + } + + switch(op->access) { + default: + break; + case CS_AC_READ: + add_str(&result, " ; operands[%u].access: READ", i); + break; + case CS_AC_WRITE: + add_str(&result, " ; operands[%u].access: WRITE", i); + break; + case CS_AC_READ | CS_AC_WRITE: + add_str(&result, " ; operands[%u].access: READ | WRITE", i); + break; + } + + if (op->shift.type != ARM_SFT_INVALID && op->shift.value) { + if (op->shift.type < ARM_SFT_ASR_REG) + add_str(&result, " ; Shift: %u = %u", op->shift.type, op->shift.value); + else + add_str(&result, " ; Shift: %u = %s", op->shift.type, cs_reg_name(*handle, op->shift.value)); + } + + if (op->vector_index != -1) { + add_str(&result, " ; operands[%u].vector_index = %u", i, op->vector_index); + } + + if (op->subtracted) + add_str(&result, " ; Subtracted: True"); + } + + if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID) + add_str(&result, " ; Code condition: %u", arm->cc); + + if (arm->update_flags) + add_str(&result, " ; Update-flags: True"); + + if (arm->writeback) + add_str(&result, " ; Write-back: True"); + + if (arm->cps_mode) + add_str(&result, " ; CPSI-mode: %u", arm->cps_mode); + + if (arm->cps_flag) + add_str(&result, " ; CPSI-flag: %u", arm->cps_flag); + + if (arm->vector_data) + add_str(&result, " ; Vector-data: %u", arm->vector_data); + + if (arm->vector_size) + add_str(&result, " ; Vector-size: %u", arm->vector_size); + + if (arm->usermode) + add_str(&result, " ; User-mode: True"); + + if (arm->mem_barrier) + add_str(&result, " ; Memory-barrier: %u", arm->mem_barrier); + + if (!cs_regs_access(*handle, ins, regs_read, ®s_read_count, regs_write, ®s_write_count)) { + if (regs_read_count) { + add_str(&result, " ; Registers read:"); + for(i = 0; i < regs_read_count; i++) { + add_str(&result, " %s", cs_reg_name(*handle, regs_read[i])); + } + } + + if (regs_write_count) { + add_str(&result, " ; Registers modified:"); + for(i = 0; i < regs_write_count; i++) { + add_str(&result, " %s", cs_reg_name(*handle, regs_write[i])); + } + } + } + + return result; +} diff --git a/capstone/suite/cstest/src/bpf_detail.c b/capstone/suite/cstest/src/bpf_detail.c new file mode 100644 index 000000000..d72332f79 --- /dev/null +++ b/capstone/suite/cstest/src/bpf_detail.c @@ -0,0 +1,77 @@ +/* Capstone testing regression */ +/* By david942j <david942j@gmail.com>, 2019 */ + +#include <capstone/platform.h> + +#include "factory.h" + +static char * ext_name[] = { + [BPF_EXT_LEN] = "#len", +}; + +char *get_detail_bpf(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_bpf *bpf; + unsigned int i; + cs_regs regs_read, regs_write; + uint8_t regs_read_count, regs_write_count; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + if (ins->detail == NULL) + return result; + + bpf = &(ins->detail->bpf); + + if (bpf->op_count) + add_str(&result, " ; op_count: %u", bpf->op_count); + for (i = 0; i < bpf->op_count; i++) { + cs_bpf_op *op = &(bpf->operands[i]); + add_str(&result, " ; operands[%u].type: ", i); + switch (op->type) { + case BPF_OP_INVALID: + add_str(&result, "INVALID"); + break; + case BPF_OP_REG: + add_str(&result, "REG = %s", cs_reg_name(*handle, op->reg)); + break; + case BPF_OP_IMM: + add_str(&result, "IMM = 0x%" PRIx64, op->imm); + break; + case BPF_OP_OFF: + add_str(&result, "OFF = +0x%x", op->off); + break; + case BPF_OP_MEM: + add_str(&result, "MEM [base=%s, disp=0x%x]", + cs_reg_name(*handle, op->mem.base), op->mem.disp); + break; + case BPF_OP_MMEM: + add_str(&result, "MMEM = M[0x%x]", op->mmem); + break; + case BPF_OP_MSH: + add_str(&result, "MSH = 4*([0x%x]&0xf)", op->msh); + break; + case BPF_OP_EXT: + add_str(&result, "EXT = %s", ext_name[op->ext]); + break; + } + } + + if (!cs_regs_access(*handle, ins, + regs_read, ®s_read_count, + regs_write, ®s_write_count)) { + if (regs_read_count) { + add_str(&result, " ; Registers read:"); + for(i = 0; i < regs_read_count; i++) + add_str(&result, " %s", cs_reg_name(*handle, regs_read[i])); + } + + if (regs_write_count) { + add_str(&result, " ; Registers modified:"); + for(i = 0; i < regs_write_count; i++) + add_str(&result, " %s", cs_reg_name(*handle, regs_write[i])); + } + } + return result; +} diff --git a/capstone/suite/cstest/src/capstone_test.c b/capstone/suite/cstest/src/capstone_test.c new file mode 100644 index 000000000..a534e49b3 --- /dev/null +++ b/capstone/suite/cstest/src/capstone_test.c @@ -0,0 +1,281 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "capstone_test.h" + +char *(*function)(csh *, cs_mode, cs_insn*) = NULL; + +void test_single_MC(csh *handle, int mc_mode, char *line) +{ + char **list_part, **list_byte; + int size_part, size_byte, size_data, size_insn; + int i, count, count_noreg; + unsigned char *code; + cs_insn *insn; + char tmp[MAXMEM], tmp_mc[MAXMEM], origin[MAXMEM], tmp_noreg[MAXMEM]; + char **offset_opcode; + int size_offset_opcode; + unsigned long offset; + char *p; + + list_part = split(line, " = ", &size_part); + offset_opcode = split(list_part[0], ": ", &size_offset_opcode); + if (size_offset_opcode > 1) { + offset = (unsigned int)strtol(offset_opcode[0], NULL, 16); + list_byte = split(offset_opcode[1], ",", &size_byte); + } else { + offset = 0; + list_byte = split(offset_opcode[0], ",", &size_byte); + } + + code = (unsigned char *)malloc(size_byte * sizeof(char)); + for (i = 0; i < size_byte; ++i) { + code[i] = (unsigned char)strtol(list_byte[i], NULL, 16); + } + + count = cs_disasm(*handle, code, size_byte, offset, 0, &insn); + if (count == 0) { + fprintf(stderr, "[ ERROR ] --- %s --- Failed to disassemble given code!\n", list_part[0]); + free_strs(list_part, size_part); + free_strs(offset_opcode, size_offset_opcode); + free_strs(list_byte, size_byte); + free(code); + _fail(__FILE__, __LINE__); + } + if (count > 1) { + fprintf(stderr, "[ ERROR ] --- %s --- Multiple instructions(%d) disassembling doesn't support!\n", list_part[0], count); + free_strs(list_part, size_part); + free_strs(offset_opcode, size_offset_opcode); + free_strs(list_byte, size_byte); + free(code); + _fail(__FILE__, __LINE__); + } + + for (p = list_part[1]; *p; ++p) *p = tolower(*p); + for (p = list_part[1]; *p; ++p) + if (*p == '\t') *p = ' '; + trim_str(list_part[1]); + strcpy(tmp_mc, list_part[1]); + replace_hex(tmp_mc); + replace_negative(tmp_mc, mc_mode); + + strcpy(tmp, insn[0].mnemonic); + if (strlen(insn[0].op_str) > 0) { + tmp[strlen(insn[0].mnemonic)] = ' '; + strcpy(tmp + strlen(insn[0].mnemonic) + 1, insn[0].op_str); + } + + trim_str(tmp); + strcpy(origin, tmp); + replace_hex(tmp); + replace_negative(tmp, mc_mode); + + if (cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME) == CS_ERR_OK) { + count_noreg = cs_disasm(*handle, code, size_byte, offset, 0, &insn); + strcpy(tmp_noreg, insn[0].mnemonic); + if (strlen(insn[0].op_str) > 0) { + tmp_noreg[strlen(insn[0].mnemonic)] = ' '; + strcpy(tmp_noreg + strlen(insn[0].mnemonic) + 1, insn[0].op_str); + } + + trim_str(tmp_noreg); + replace_hex(tmp_noreg); + replace_negative(tmp_noreg, mc_mode); + + if (strcmp(tmp, tmp_mc) && strcmp(tmp_noreg, tmp_mc)) { + fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" and \"%s\" != \"%s\" )\n", list_part[0], origin, list_part[1], tmp, tmp_mc, tmp_noreg, tmp_mc); + free_strs(list_part, size_part); + free_strs(offset_opcode, size_offset_opcode); + free_strs(list_byte, size_byte); + free(code); + cs_free(insn, count); + _fail(__FILE__, __LINE__); + } + + cs_option(*handle, CS_OPT_SYNTAX, 0); + + } else if (strcmp(tmp, tmp_mc)) { + fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" )\n", list_part[0], origin, list_part[1], tmp, tmp_mc); + free_strs(list_part, size_part); + free_strs(offset_opcode, size_offset_opcode); + free_strs(list_byte, size_byte); + free(code); + cs_free(insn, count); + _fail(__FILE__, __LINE__); + } + + free_strs(list_part, size_part); + free_strs(offset_opcode, size_offset_opcode); + free_strs(list_byte, size_byte); + free(code); + cs_free(insn, count); +} + +int get_value(single_dict d[], unsigned int size, const char *str) +{ + int i; + + for (i = 0; i < size; ++i) + if (!strcmp(d[i].str, str)) + return d[i].value; + return -1; +} + +int get_index(double_dict d[], unsigned int size, const char *s) +{ + int i; + + for (i = 0; i < size; ++i) { + if (!strcmp(s, d[i].str)) + return i; + } + return -1; +} + +int set_function(int arch) +{ + switch(arch) { + case CS_ARCH_ARM: + function = get_detail_arm; + break; + case CS_ARCH_ARM64: + function = get_detail_arm64; + break; + case CS_ARCH_MIPS: + function = get_detail_mips; + break; + case CS_ARCH_PPC: + function = get_detail_ppc; + break; + case CS_ARCH_SPARC: + function = get_detail_sparc; + break; + case CS_ARCH_SYSZ: + function = get_detail_sysz; + break; + case CS_ARCH_X86: + function = get_detail_x86; + break; + case CS_ARCH_XCORE: + function = get_detail_xcore; + break; + case CS_ARCH_M68K: + function = get_detail_m68k; + break; + case CS_ARCH_M680X: + function = get_detail_m680x; + break; + case CS_ARCH_EVM: + function = get_detail_evm; + break; + case CS_ARCH_MOS65XX: + function = get_detail_mos65xx; + break; + case CS_ARCH_TMS320C64X: + function = get_detail_tms320c64x; + break; + case CS_ARCH_BPF: + function = get_detail_bpf; + break; + case CS_ARCH_RISCV: + function = get_detail_riscv; + break; + default: + return -1; + } + return 0; +} + +void test_single_issue(csh *handle, cs_mode mode, char *line, int detail) +{ + char **list_part, **list_byte, **list_part_cs_result, **list_part_issue_result; + int size_part, size_byte, size_part_cs_result, size_part_issue_result; + char *tmptmp; + int i, count, j; + unsigned char *code; + cs_insn *insn; + char *cs_result, *tmp, *p; + char **offset_opcode; + int size_offset_opcode; + unsigned long offset; + + cs_result = (char *)malloc(sizeof(char)); + cs_result[0] = '\0'; + + list_part = split(line, " == ", &size_part); + + offset_opcode = split(list_part[0], ": ", &size_offset_opcode); + if (size_offset_opcode > 1) { + offset = (unsigned int)strtol(offset_opcode[0], NULL, 16); + list_byte = split(offset_opcode[1], ",", &size_byte); + } else { + offset = 0; + list_byte = split(offset_opcode[0], ",", &size_byte); + } + + code = (unsigned char *)malloc(sizeof(char) * size_byte); + for (i = 0; i < size_byte; ++i) { + code[i] = (unsigned char)strtol(list_byte[i], NULL, 16); + } + + count = cs_disasm(*handle, code, size_byte, offset, 0, &insn); + for (i = 0; i < count; ++i) { + tmp = (char *)malloc(strlen(insn[i].mnemonic) + strlen(insn[i].op_str) + 100); + strcpy(tmp, insn[i].mnemonic); + if (strlen(insn[i].op_str) > 0) { + tmp[strlen(insn[i].mnemonic)] = ' '; + strcpy(tmp + strlen(insn[i].mnemonic) + 1, insn[i].op_str); + } + add_str(&cs_result, "%s", tmp); + free(tmp); + } + + if (detail == 1) { + tmp = (*function)(handle, mode, insn); + add_str(&cs_result, "%s", tmp); + free(tmp); + + if (insn->detail->groups_count) { + add_str(&cs_result, " ; Groups: "); + for (j = 0; j < insn->detail->groups_count; j++) { + add_str(&cs_result, "%s ", cs_group_name(*handle, insn->detail->groups[j])); + } + } + } + + trim_str(cs_result); + add_str(&cs_result, " ;"); + // list_part_cs_result = split(cs_result, " ; ", &size_part_cs_result); + for (p = list_part[1]; *p; ++p) if (*p == '\t') *p = ' '; + list_part_issue_result = split(list_part[1], " ; ", &size_part_issue_result); + + for (i = 0; i < size_part_issue_result; ++i) { + trim_str(list_part_issue_result[i]); + memset(tmptmp, MAXMEM, 0); + + tmptmp = (char *)malloc(sizeof(char)); + tmptmp[0] = '\0'; + add_str(&tmptmp, "%s", list_part_issue_result[i]); + add_str(&tmptmp, " ;"); + + if ((strstr(cs_result, tmptmp)) == NULL) { + fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" not in \"%s\"\n", list_part[0], list_part_issue_result[i], cs_result); + cs_free(insn, count); + free_strs(list_part, size_part); + free_strs(list_byte, size_byte); + free(cs_result); + // free_strs(list_part_cs_result, size_part_cs_result); + free_strs(list_part_issue_result, size_part_issue_result); + free(tmptmp); + _fail(__FILE__, __LINE__); + } + } + + cs_free(insn, count); + free_strs(list_part, size_part); + free_strs(list_byte, size_byte); + free(cs_result); + // free_strs(list_part_cs_result, size_part_cs_result); + free_strs(list_part_issue_result, size_part_issue_result); +} diff --git a/capstone/suite/cstest/src/evm_detail.c b/capstone/suite/cstest/src/evm_detail.c new file mode 100644 index 000000000..635d309e3 --- /dev/null +++ b/capstone/suite/cstest/src/evm_detail.c @@ -0,0 +1,30 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_evm(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_evm *evm; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + evm = &(ins->detail->evm); + + if (evm->pop) + add_str(&result, " ; Pop: %u", evm->pop); + + if (evm->push) + add_str(&result, " ; Push: %u", evm->push); + + if (evm->fee) + add_str(&result, " ; Gas fee: %u", evm->fee); + + return result; +} diff --git a/capstone/suite/cstest/src/helper.c b/capstone/suite/cstest/src/helper.c new file mode 100644 index 000000000..02365510c --- /dev/null +++ b/capstone/suite/cstest/src/helper.c @@ -0,0 +1,267 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "helper.h" + +char **split(char *str, char *delim, int *size) +{ + char **result; + char *token, *src; + int cnt; + + cnt = 0; + src = str; + result = NULL; + + while ((token = strstr(src, delim)) != NULL) { + result = (char **)realloc(result, sizeof(char *) * (cnt + 1)); + result[cnt] = (char *)calloc(1, sizeof(char) * (int)(token - src + 10)); + memcpy(result[cnt], src, token - src); + result[cnt][token - src] = '\0'; + src = token + strlen(delim); + cnt ++; + } + + if (strlen(src) > 0) { + result = (char **)realloc(result, sizeof(char *) * (cnt + 1)); + result[cnt] = strdup(src); + cnt ++; + } + + *size = cnt; + return result; +} + +void print_strs(char **list_str, int size) +{ + int i; + + printf("[+] Debug %d strings:\n", size); + for (i = 0; i < size; ++i) + printf("String %d'th: %s\n", i+1, list_str[i]); +} + +void free_strs(char **list_str, int size) +{ + int i; + for (i = 0; i < size; ++i) + free(list_str[i]); + + free(list_str); +} + +const char *get_filename_ext(const char *filename) +{ + const char *dot; + + dot = strrchr(filename, '.'); + if (!dot || dot == filename) + return ""; + + return dot + 1; +} + +char *readfile(const char *filename) +{ + char *result; + FILE *fp; + int size; + + fp = fopen(filename, "r"); + if (fp == NULL) { + puts("No such file"); + exit(-1); + } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + rewind(fp); + + result = (char *)calloc(1, sizeof(char) * size + 1); + fread(result, size, 1, fp); + result[size] = '\0'; + + fclose(fp); + return result; +} + +void add_str(char **src, const char *format, ...) +{ + char *tmp; + size_t len1, len2; + va_list args; + + tmp = (char *)malloc(sizeof(char) * 1000); + va_start(args, format); + vsprintf(tmp, format, args); + va_end(args); + + len1 = strlen(*src); + len2 = strlen(tmp); + + *src = (char *)realloc(*src, sizeof(char) * (len1 + len2 + 10)); + memcpy(*src + len1, tmp, len2 + 1); + free(tmp); +} + +void replace_hex(char *src) +{ + char *tmp, *result, *found, *origin, *orig_found; + int i, valid; + unsigned long long int value; + char *tmp_tmp; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + tmp = strdup(src); + origin = tmp; + + while ((found = strstr(tmp, "0x")) != NULL) { + orig_found = found; + found += 2; + value = 0; + valid = 0; + + tmp_tmp = strndup(tmp, orig_found - tmp); + while (*found != '\0' && isxdigit(*found)) { + valid = 1; + if (*found >= 'a' && *found <='f') + value = value*0x10 + (*found - 'a' + 10); + else + value = value*0x10 + (*found - '0'); + found++; + } + + if (valid == 1) add_str(&result, "%s%llu", tmp_tmp, value); + else add_str(&result, "%s0x", tmp_tmp); + tmp = found; + free(tmp_tmp); + } + + add_str(&result, "%s", tmp); + if (strlen(result) >= MAXMEM) { + fprintf(stderr, "[ Error ] --- Buffer Overflow in replace_hex()\n"); + free(result); + free(origin); + _fail(__FILE__, __LINE__); + } + + strcpy(src, result); + free(result); + free(origin); +} + +void replace_negative(char *src, int mode) +{ + char *tmp, *result, *found, *origin, *orig_found; + int i, cnt, valid; + char *value, *tmp_tmp; + unsigned short int tmp_short; + unsigned int tmp_int; + unsigned long int tmp_long; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + tmp = strdup(src); + origin = tmp; + + while ((found = strstr(tmp, "-")) != NULL) { + orig_found = found; + found ++; + valid = 0; + + value = strdup("-"); + cnt = 2; + + while (*found != '\0' && isdigit(*found)) { + valid = 1; + value = (char *)realloc(value, cnt + 1); + value[cnt - 1] = *found; + value[cnt] = '\0'; + cnt ++; + found++; + } + + tmp_tmp = strndup(tmp, orig_found - tmp); + if (valid == 1) { + *orig_found = '\0'; + if (mode == X86_16) { + sscanf(value, "%hu", &tmp_short); + add_str(&result, "%s%hu", tmp_tmp, tmp_short); + } else if (mode == X86_32) { + sscanf(value, "%u", &tmp_int); + add_str(&result, "%s%u", tmp_tmp, tmp_int); + } else if (mode == X86_64) { + sscanf(value, "%lu", &tmp_long); + add_str(&result, "%s%lu", tmp_tmp, tmp_long); + } + } + else add_str(&result, "%s-", tmp_tmp); + + tmp = found; + free(value); + free(tmp_tmp); + } + + add_str(&result, "%s", tmp); + if (strlen(result) >= MAXMEM) { + fprintf(stderr, "[ Error ] --- Buffer Overflow in replace_negative()\n"); + free(result); + free(origin); + _fail(__FILE__, __LINE__); + } + + strcpy(src, result); + free(result); + free(origin); +} + +void listdir(const char *name, char ***files, int *num_files) +{ + DIR *dir; + struct dirent *entry; + int cnt; + + if (!(dir = opendir(name))) + return; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_DIR) { + char path[1024]; + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + snprintf(path, sizeof(path), "%s/%s", name, entry->d_name); + listdir(path, files, num_files); + } else { + cnt = *num_files; + *files = (char **)realloc(*files, sizeof(char *) * (cnt + 1)); + (*files)[cnt] = (char *)malloc(sizeof(char) * ( strlen(name) + 1 + strlen(entry->d_name) + 10)); + sprintf((*files)[cnt], "%s/%s", name, entry->d_name); + cnt ++; + *num_files = cnt; + } + } + + closedir(dir); +} + +void trim_str(char *str) +{ + char tmp[MAXMEM]; + int start, end, j, i; + + start = 0; + end = strlen(str) - 1; + j = 0; + while (start < strlen(str) && isspace(str[start])) start++; + while (end >= 0 && isspace(str[end])) end--; + + for (i = start; i <= end; ++i) + tmp[j++] = str[i]; + + tmp[j] = '\0'; + strcpy(str, tmp); + + return; +} diff --git a/capstone/suite/cstest/src/m680x_detail.c b/capstone/suite/cstest/src/m680x_detail.c new file mode 100644 index 000000000..62c429812 --- /dev/null +++ b/capstone/suite/cstest/src/m680x_detail.c @@ -0,0 +1,137 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +static const char *s_access[] = { + "UNCHANGED", "READ", "WRITE", "READ ; WRITE", +}; + +static void print_read_write_regs(char *result, csh *handle, cs_detail *detail) +{ + int i; + + if (detail->regs_read_count > 0) { + add_str(&result, "\treading from regs: "); + + for (i = 0; i < detail->regs_read_count; ++i) { + if (i > 0) + add_str(&result, ", "); + + add_str(&result, "%s", cs_reg_name(*handle, detail->regs_read[i])); + } + } + + if (detail->regs_write_count > 0) { + add_str(&result, "\twriting to regs: "); + + for (i = 0; i < detail->regs_write_count; ++i) { + if (i > 0) + add_str(&result, ", "); + + add_str(&result, "%s", cs_reg_name(*handle, detail->regs_write[i])); + } + } +} + +char *get_detail_m680x(csh *handle, cs_mode mode, cs_insn *insn) +{ + cs_detail *detail = insn->detail; + cs_m680x *m680x = NULL; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (detail == NULL) + return result; + + m680x = &detail->m680x; + + if (m680x->op_count) + add_str(&result, " ; op_count: %u", m680x->op_count); + + for (i = 0; i < m680x->op_count; i++) { + cs_m680x_op *op = &(m680x->operands[i]); + const char *comment; + + switch ((int)op->type) { + default: + break; + + case M680X_OP_REGISTER: + comment = ""; + + if ((i == 0 && m680x->flags & M680X_FIRST_OP_IN_MNEM) || + (i == 1 && m680x->flags & + M680X_SECOND_OP_IN_MNEM)) + comment = " (in mnemonic)"; + + add_str(&result, " ; operands[%u].type: REGISTER = %s%s", i, cs_reg_name(*handle, op->reg), comment); + break; + + case M680X_OP_CONSTANT: + add_str(&result, " ; operands[%u].type: CONSTANT = %u", i, op->const_val); + break; + + case M680X_OP_IMMEDIATE: + add_str(&result, " ; operands[%u].type: IMMEDIATE = #%d", i, op->imm); + break; + + case M680X_OP_DIRECT: + add_str(&result, " ; operands[%u].type: DIRECT = 0x%02x", i, op->direct_addr); + break; + + case M680X_OP_EXTENDED: + add_str(&result, " ; operands[%u].type: EXTENDED %s = 0x%04x", i, op->ext.indirect ? "INDIRECT" : "", op->ext.address); + break; + + case M680X_OP_RELATIVE: + add_str(&result, " ; operands[%u].type: RELATIVE = 0x%04x", i, op->rel.address); + break; + + case M680X_OP_INDEXED: + add_str(&result, " ; operands[%u].type: INDEXED%s", i, (op->idx.flags & M680X_IDX_INDIRECT) ? " INDIRECT" : ""); + + if (op->idx.base_reg != M680X_REG_INVALID) + add_str(&result, " ; base register: %s", cs_reg_name(*handle, op->idx.base_reg)); + + if (op->idx.offset_reg != M680X_REG_INVALID) + add_str(&result, " ; offset register: %s", cs_reg_name(*handle, op->idx.offset_reg)); + + if ((op->idx.offset_bits != 0) && + (op->idx.offset_reg == M680X_REG_INVALID) && + !op->idx.inc_dec) { + add_str(&result, " ; offset: %d", op->idx.offset); + + if (op->idx.base_reg == M680X_REG_PC) + add_str(&result, " ; offset address: 0x%x", op->idx.offset_addr); + + add_str(&result, " ; offset bits: %u", op->idx.offset_bits); + } + + if (op->idx.inc_dec) { + const char *post_pre = op->idx.flags & + M680X_IDX_POST_INC_DEC ? "post" : "pre"; + const char *inc_dec = (op->idx.inc_dec > 0) ? + "increment" : "decrement"; + + add_str(&result, " ; %s %s: %d", post_pre, inc_dec, abs(op->idx.inc_dec)); + } + + break; + } + + if (op->size != 0) + add_str(&result, " ; size: %u", op->size); + + if (op->access != CS_AC_INVALID) + add_str(&result, " ; access: %s", s_access[op->access]); + } + + print_read_write_regs(result, handle, detail); + + return result; +} diff --git a/capstone/suite/cstest/src/m68k_detail.c b/capstone/suite/cstest/src/m68k_detail.c new file mode 100644 index 000000000..a3dfc7491 --- /dev/null +++ b/capstone/suite/cstest/src/m68k_detail.c @@ -0,0 +1,116 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +static const char* s_addressing_modes[] = { + "<invalid mode>", + + "Register Direct - Data", + "Register Direct - Address", + + "Register Indirect - Address", + "Register Indirect - Address with Postincrement", + "Register Indirect - Address with Predecrement", + "Register Indirect - Address with Displacement", + + "Address Register Indirect With Index - 8-bit displacement", + "Address Register Indirect With Index - Base displacement", + + "Memory indirect - Postindex", + "Memory indirect - Preindex", + + "Program Counter Indirect - with Displacement", + + "Program Counter Indirect with Index - with 8-Bit Displacement", + "Program Counter Indirect with Index - with Base Displacement", + + "Program Counter Memory Indirect - Postindexed", + "Program Counter Memory Indirect - Preindexed", + + "Absolute Data Addressing - Short", + "Absolute Data Addressing - Long", + "Immediate value", +}; + +static void print_read_write_regs(char *result, cs_detail* detail, csh *handle) +{ + int i; + + for (i = 0; i < detail->regs_read_count; ++i) { + uint16_t reg_id = detail->regs_read[i]; + const char* reg_name = cs_reg_name(*handle, reg_id); + add_str(&result, " ; reading from reg: %s", reg_name); + } + + for (i = 0; i < detail->regs_write_count; ++i) { + uint16_t reg_id = detail->regs_write[i]; + const char* reg_name = cs_reg_name(*handle, reg_id); + add_str(&result, " ; writing to reg: %s", reg_name); + } +} + +char *get_detail_m68k(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_m68k* m68k; + cs_detail* detail; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + + detail = ins->detail; + m68k = &detail->m68k; + if (m68k->op_count) + add_str(&result, " ; op_count: %u", m68k->op_count); + + print_read_write_regs(result, detail, handle); + + add_str(&result, " ; groups_count: %u", detail->groups_count); + + for (i = 0; i < m68k->op_count; i++) { + cs_m68k_op* op = &(m68k->operands[i]); + + switch((int)op->type) { + default: + break; + case M68K_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case M68K_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, (int)op->imm); + break; + case M68K_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base_reg != M68K_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base_reg)); + if (op->mem.index_reg != M68K_REG_INVALID) { + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index_reg)); + add_str(&result, " ; operands[%u].mem.index: size = %c", i, op->mem.index_size ? 'l' : 'w'); + } + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + if (op->mem.scale != 0) + add_str(&result, " ; operands[%u].mem.scale: %d", i, op->mem.scale); + + add_str(&result, " ; address mode: %s", s_addressing_modes[op->address_mode]); + break; + case M68K_OP_FP_SINGLE: + add_str(&result, " ; operands[%u].type: FP_SINGLE", i); + add_str(&result, " ; operands[%u].simm: %f", i, op->simm); + break; + case M68K_OP_FP_DOUBLE: + add_str(&result, " ; operands[%u].type: FP_DOUBLE", i); + add_str(&result, " ; operands[%u].dimm: %lf", i, op->dimm); + break; + } + } + + return result; +} diff --git a/capstone/suite/cstest/src/main.c b/capstone/suite/cstest/src/main.c new file mode 100644 index 000000000..55619e987 --- /dev/null +++ b/capstone/suite/cstest/src/main.c @@ -0,0 +1,454 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "helper.h" +#include "capstone_test.h" +#include <unistd.h> + +#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) + +static single_dict arches[] = { + {"CS_ARCH_ARM", CS_ARCH_ARM}, + {"CS_ARCH_ARM64", CS_ARCH_ARM64}, + {"CS_ARCH_MIPS", CS_ARCH_MIPS}, + {"CS_ARCH_PPC", CS_ARCH_PPC}, + {"CS_ARCH_SPARC", CS_ARCH_SPARC}, + {"CS_ARCH_SYSZ", CS_ARCH_SYSZ}, + {"CS_ARCH_X86", CS_ARCH_X86}, + {"CS_ARCH_XCORE", CS_ARCH_XCORE}, + {"CS_ARCH_M68K", CS_ARCH_M68K}, + {"CS_ARCH_BPF", CS_ARCH_BPF}, + {"CS_ARCH_RISCV", CS_ARCH_RISCV}, +}; + + static single_dict modes[] = { + {"CS_MODE_LITTLE_ENDIAN", CS_MODE_LITTLE_ENDIAN}, + {"CS_MODE_ARM", CS_MODE_ARM}, + {"CS_MODE_16", CS_MODE_16}, + {"CS_MODE_32", CS_MODE_32}, + {"CS_MODE_64", CS_MODE_64}, + {"CS_MODE_THUMB", CS_MODE_THUMB}, + {"CS_MODE_MCLASS", CS_MODE_MCLASS}, + {"CS_MODE_V8", CS_MODE_V8}, + {"CS_MODE_MICRO", CS_MODE_MICRO}, + {"CS_MODE_MIPS3", CS_MODE_MIPS3}, + {"CS_MODE_MIPS32R6", CS_MODE_MIPS32R6}, + {"CS_MODE_MIPS2", CS_MODE_MIPS2}, + {"CS_MODE_V9", CS_MODE_V9}, + {"CS_MODE_QPX", CS_MODE_QPX}, + {"CS_MODE_M68K_000", CS_MODE_M68K_000}, + {"CS_MODE_M68K_010", CS_MODE_M68K_010}, + {"CS_MODE_M68K_020", CS_MODE_M68K_020}, + {"CS_MODE_M68K_030", CS_MODE_M68K_030}, + {"CS_MODE_M68K_040", CS_MODE_M68K_040}, + {"CS_MODE_M68K_060", CS_MODE_M68K_060}, + {"CS_MODE_BIG_ENDIAN", CS_MODE_BIG_ENDIAN}, + {"CS_MODE_MIPS32", CS_MODE_MIPS32}, + {"CS_MODE_MIPS64", CS_MODE_MIPS64}, + {"CS_MODE_M680X_6301", CS_MODE_M680X_6301}, + {"CS_MODE_M680X_6309", CS_MODE_M680X_6309}, + {"CS_MODE_M680X_6800", CS_MODE_M680X_6800}, + {"CS_MODE_M680X_6801", CS_MODE_M680X_6801}, + {"CS_MODE_M680X_6805", CS_MODE_M680X_6805}, + {"CS_MODE_M680X_6808", CS_MODE_M680X_6808}, + {"CS_MODE_M680X_6809", CS_MODE_M680X_6809}, + {"CS_MODE_M680X_6811", CS_MODE_M680X_6811}, + {"CS_MODE_M680X_CPU12", CS_MODE_M680X_CPU12}, + {"CS_MODE_M680X_HCS08", CS_MODE_M680X_HCS08}, + {"CS_MODE_BPF_CLASSIC", CS_MODE_BPF_CLASSIC}, + {"CS_MODE_BPF_EXTENDED", CS_MODE_BPF_EXTENDED}, + {"CS_MODE_RISCV32", CS_MODE_RISCV32}, + {"CS_MODE_RISCV64", CS_MODE_RISCV64}, +}; + + static double_dict options[] = { + {"CS_OPT_DETAIL", CS_OPT_DETAIL, CS_OPT_ON}, + {"CS_OPT_SKIPDATA", CS_OPT_SKIPDATA, CS_OPT_ON}, + {"CS_OPT_SYNTAX_DEFAULT", CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT}, + {"CS_OPT_SYNTAX_INTEL", CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL}, + {"CS_OPT_SYNTAX_ATT", CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT}, + {"CS_OPT_SYNTAX_NOREGNAME", CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME}, + {"CS_OPT_SYNTAX_MASM", CS_OPT_SYNTAX, CS_OPT_SYNTAX_MASM}, + {"CS_MODE_LITTLE_ENDIAN", CS_OPT_MODE, CS_MODE_LITTLE_ENDIAN}, + {"CS_MODE_ARM", CS_OPT_MODE, CS_MODE_ARM}, + {"CS_MODE_16", CS_OPT_MODE, CS_MODE_16}, + {"CS_MODE_32", CS_OPT_MODE, CS_MODE_32}, + {"CS_MODE_64", CS_OPT_MODE, CS_MODE_64}, + {"CS_MODE_THUMB", CS_OPT_MODE, CS_MODE_THUMB}, + {"CS_MODE_MCLASS", CS_OPT_MODE, CS_MODE_MCLASS}, + {"CS_MODE_V8", CS_OPT_MODE, CS_MODE_V8}, + {"CS_MODE_MICRO", CS_OPT_MODE, CS_MODE_MICRO}, + {"CS_MODE_MIPS3", CS_OPT_MODE, CS_MODE_MIPS3}, + {"CS_MODE_MIPS32R6", CS_OPT_MODE, CS_MODE_MIPS32R6}, + {"CS_MODE_MIPS2", CS_OPT_MODE, CS_MODE_MIPS2}, + {"CS_MODE_V9", CS_OPT_MODE, CS_MODE_V9}, + {"CS_MODE_QPX", CS_OPT_MODE, CS_MODE_QPX}, + {"CS_MODE_M68K_000", CS_OPT_MODE, CS_MODE_M68K_000}, + {"CS_MODE_M68K_010", CS_OPT_MODE, CS_MODE_M68K_010}, + {"CS_MODE_M68K_020", CS_OPT_MODE, CS_MODE_M68K_020}, + {"CS_MODE_M68K_030", CS_OPT_MODE, CS_MODE_M68K_030}, + {"CS_MODE_M68K_040", CS_OPT_MODE, CS_MODE_M68K_040}, + {"CS_MODE_M68K_060", CS_OPT_MODE, CS_MODE_M68K_060}, + {"CS_MODE_BIG_ENDIAN", CS_OPT_MODE, CS_MODE_BIG_ENDIAN}, + {"CS_MODE_MIPS32", CS_OPT_MODE, CS_MODE_MIPS32}, + {"CS_MODE_MIPS64", CS_OPT_MODE, CS_MODE_MIPS64}, + {"CS_MODE_M680X_6301", CS_OPT_MODE, CS_MODE_M680X_6301}, + {"CS_MODE_M680X_6309", CS_OPT_MODE, CS_MODE_M680X_6309}, + {"CS_MODE_M680X_6800", CS_OPT_MODE, CS_MODE_M680X_6800}, + {"CS_MODE_M680X_6801", CS_OPT_MODE, CS_MODE_M680X_6801}, + {"CS_MODE_M680X_6805", CS_OPT_MODE, CS_MODE_M680X_6805}, + {"CS_MODE_M680X_6808", CS_OPT_MODE, CS_MODE_M680X_6808}, + {"CS_MODE_M680X_6809", CS_OPT_MODE, CS_MODE_M680X_6809}, + {"CS_MODE_M680X_6811", CS_OPT_MODE, CS_MODE_M680X_6811}, + {"CS_MODE_M680X_CPU12", CS_OPT_MODE, CS_MODE_M680X_CPU12}, + {"CS_MODE_M680X_HCS08", CS_OPT_MODE, CS_MODE_M680X_HCS08}, + {"CS_MODE_RISCV32", CS_OPT_MODE, CS_MODE_RISCV32}, + {"CS_MODE_RISCV64", CS_OPT_MODE, CS_MODE_RISCV64}, + {"CS_OPT_UNSIGNED", CS_OPT_UNSIGNED, CS_OPT_ON}, +}; + +static int counter; +static char **list_lines; +static int failed_setup; +static int size_lines; +static cs_mode issue_mode; +static int getDetail; +static int mc_mode; +static int e_flag; + +static int setup_MC(void **state) +{ + csh *handle; + char **list_params; + int size_params; + int arch, mode; + int i, index, tmp_counter; + + if (failed_setup) { + fprintf(stderr, "[ ERROR ] --- Invalid file to setup\n"); + return -1; + } + + tmp_counter = 0; + while (tmp_counter < size_lines && list_lines[tmp_counter][0] != '#') + tmp_counter++; + + list_params = split(list_lines[tmp_counter] + 2, ", ", &size_params); + if (size_params != 3) { + fprintf(stderr, "[ ERROR ] --- Invalid options ( arch, mode, option )\n"); + failed_setup = 1; + return -1; + } + + arch = get_value(arches, ARR_SIZE(arches), list_params[0]); + if (!strcmp(list_params[0], "CS_ARCH_ARM64")) + mc_mode = 2; + else + mc_mode = 1; + + mode = 0; + for (i = 0; i < ARR_SIZE(modes); ++i) { + if (strstr(list_params[1], modes[i].str)) { + mode += modes[i].value; + switch (modes[i].value) { + case CS_MODE_16: + mc_mode = 0; + break; + case CS_MODE_64: + mc_mode = 2; + break; + case CS_MODE_THUMB: + mc_mode = 1; + break; + default: + break; + } + } + } + + if (arch == -1) { + fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n"); + failed_setup = 1; + return -1; + } + + handle = (csh *)malloc(sizeof(csh)); + if(cs_open(arch, mode, handle) != CS_ERR_OK) { + fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n"); + failed_setup = 1; + return -1; + } + + for (i = 0; i < ARR_SIZE(options); ++i) { + if (strstr(list_params[2], options[i].str)) { + if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) { + fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n"); + failed_setup = 1; + return -1; + } + } + } + + *state = (void *)handle; + counter++; + if (e_flag == 0) + while (counter < size_lines && strncmp(list_lines[counter], "0x", 2)) + counter++; + else + while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5)) + counter++; + + free_strs(list_params, size_params); + return 0; +} + +static void test_MC(void **state) +{ + if (e_flag == 1) + test_single_MC((csh *)*state, mc_mode, list_lines[counter] + 3); + else + test_single_MC((csh *)*state, mc_mode, list_lines[counter]); +} + +static int teardown_MC(void **state) +{ + cs_close(*state); + free(*state); + return 0; +} + +static int setup_issue(void **state) +{ + csh *handle; + char **list_params; + int size_params; + int arch, mode; + int i, index, result; + char *(*function)(csh *, cs_mode, cs_insn*); + + getDetail = 0; + failed_setup = 0; + + if (e_flag == 0) + while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3)) + counter++; // get issue line + else + while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6)) + counter++; + + counter++; + if (e_flag == 0) + while (counter < size_lines && strncmp(list_lines[counter], "!#", 2)) + counter++; // get arch line + else + while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6)) + counter++; + + if (e_flag == 0) + list_params = split(list_lines[counter] + 3, ", ", &size_params); + else + list_params = split(list_lines[counter] + 6, ", ", &size_params); + + arch = get_value(arches, ARR_SIZE(arches), list_params[0]); + + if (!strcmp(list_params[0], "CS_ARCH_ARM64")) + mc_mode = 2; + else + mc_mode = 1; + + mode = 0; + for (i = 0; i < ARR_SIZE(modes); ++i) { + if (strstr(list_params[1], modes[i].str)) { + mode += modes[i].value; + switch (modes[i].value) { + case CS_MODE_16: + mc_mode = 0; + break; + case CS_MODE_64: + mc_mode = 2; + break; + case CS_MODE_THUMB: + mc_mode = 1; + break; + default: + break; + } + } + } + + if (arch == -1) { + fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n"); + failed_setup = 1; + return -1; + } + + handle = (csh *)calloc(1, sizeof(csh)); + if(cs_open(arch, mode, handle) != CS_ERR_OK) { + fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n"); + failed_setup = 1; + return -1; + } + + for (i = 0; i < ARR_SIZE(options); ++i) { + if (strstr(list_params[2], options[i].str)) { + if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) { + fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n"); + failed_setup = 1; + return -1; + } + + if (i == 0) { + result = set_function(arch); + if (result == -1) { + fprintf(stderr, "[ ERROR ] --- Cannot get details\n"); + failed_setup = 1; + return -1; + } + + getDetail = 1; + } + } + } + + *state = (void *)handle; + issue_mode = mode; + + if (e_flag == 0) + while (counter < size_lines && strncmp(list_lines[counter], "0x", 2)) + counter++; + else + while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5)) + counter++; + + free_strs(list_params, size_params); + return 0; +} + +static void test_issue(void **state) +{ + if (e_flag == 0) + test_single_issue((csh *)*state, issue_mode, list_lines[counter], getDetail); + else + test_single_issue((csh *)*state, issue_mode, list_lines[counter] + 3, getDetail); + + return; +} + +static int teardown_issue(void **state) +{ + if (e_flag == 0) + while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3)) + counter++; + else + while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6)) + counter++; + + cs_close(*state); + free(*state); + function = NULL; + return 0; +} + +static void test_file(const char *filename) +{ + int size, i; + char **list_str; + char *content, *tmp; + struct CMUnitTest *tests; + int issue_num, number_of_tests; + + printf("[+] TARGET: %s\n", filename); + content = readfile(filename); + counter = 0; + failed_setup = 0; + function = NULL; + + if (strstr(filename, "issue")) { + number_of_tests = 0; + list_lines = split(content, "\n", &size_lines); + tests = NULL; + for (i = 0; i < size_lines; ++i) { + if ((!strncmp(list_lines[i], "// !# issue", 11) && e_flag == 1) || + (!strncmp(list_lines[i], "!# issue", 8) && e_flag == 0)) { + tests = (struct CMUnitTest *)realloc(tests, sizeof(struct CMUnitTest) * (number_of_tests + 1)); + tests[number_of_tests] = (struct CMUnitTest)cmocka_unit_test_setup_teardown(test_issue, setup_issue, teardown_issue); + tests[number_of_tests].name = strdup(list_lines[i]); + number_of_tests ++; + } + } + + _cmocka_run_group_tests("Testing issues", tests, number_of_tests, NULL, NULL); + } else { + list_lines = split(content, "\n", &size_lines); + number_of_tests = 0; + + tests = NULL; + for (i = 1; i < size_lines; ++i) { + if ((!strncmp(list_lines[i], "// 0x", 5) && e_flag == 1) || (!strncmp(list_lines[i], "0x", 2) && e_flag == 0)) { + tmp = (char *)malloc(sizeof(char) * 100); + sprintf(tmp, "Line %d", i+1); + tests = (struct CMUnitTest *)realloc(tests, sizeof(struct CMUnitTest) * (number_of_tests + 1)); + tests[number_of_tests] = (struct CMUnitTest)cmocka_unit_test_setup_teardown(test_MC, setup_MC, teardown_MC); + tests[number_of_tests].name = tmp; + number_of_tests ++; + } + } + + _cmocka_run_group_tests("Testing MC", tests, number_of_tests, NULL, NULL); + } + + printf("[+] DONE: %s\n", filename); + printf("[!] Noted:\n[ ERROR ] --- \"<capstone result>\" != \"<user result>\"\n"); + printf("\n\n"); + free_strs(list_lines, size_lines); +} + +static void test_folder(const char *folder) +{ + char **files; + int num_files, i; + + files = NULL; + num_files = 0; + listdir(folder, &files, &num_files); + for (i = 0; i < num_files; ++i) { + if (strcmp("cs", get_filename_ext(files[i]))) + continue; + test_file(files[i]); + } +} + +int main(int argc, char *argv[]) +{ + int opt, flag; + + flag = 0; + e_flag = 0; + + while ((opt = getopt(argc, argv, "ef:d:")) > 0) { + switch (opt) { + case 'f': + test_file(optarg); + flag = 1; + break; + case 'd': + test_folder(optarg); + flag = 1; + break; + case 'e': + e_flag = 1; + break; + default: + printf("Usage: %s [-e] [-f <file_name.cs>] [-d <directory>]\n", argv[0]); + exit(-1); + } + } + + if (flag == 0) { + printf("Usage: %s [-e] [-f <file_name.cs>] [-d <directory>]\n", argv[0]); + exit(-1); + } + + return 0; +} diff --git a/capstone/suite/cstest/src/mips_detail.c b/capstone/suite/cstest/src/mips_detail.c new file mode 100644 index 000000000..c859ab6d7 --- /dev/null +++ b/capstone/suite/cstest/src/mips_detail.c @@ -0,0 +1,48 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_mips(csh *handle, cs_mode mode, cs_insn *ins) +{ + int i; + cs_mips *mips; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + mips = &(ins->detail->mips); + if (mips->op_count) + add_str(&result, " ; op_count: %u", mips->op_count); + + for (i = 0; i < mips->op_count; i++) { + cs_mips_op *op = &(mips->operands[i]); + switch((int)op->type) { + default: + break; + case MIPS_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case MIPS_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm); + break; + case MIPS_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != MIPS_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp); + + break; + } + + } + + return result; +} + diff --git a/capstone/suite/cstest/src/mos65xx_detail.c b/capstone/suite/cstest/src/mos65xx_detail.c new file mode 100644 index 000000000..b039f2e76 --- /dev/null +++ b/capstone/suite/cstest/src/mos65xx_detail.c @@ -0,0 +1,103 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +static const char *get_am_name(mos65xx_address_mode mode) +{ + switch(mode) { + default: + case MOS65XX_AM_NONE: + return "No address mode"; + case MOS65XX_AM_IMP: + return "implied"; + case MOS65XX_AM_ACC: + return "accumulator"; + case MOS65XX_AM_IMM: + return "immediate value"; + case MOS65XX_AM_REL: + return "relative"; + case MOS65XX_AM_INT: + return "interrupt signature"; + case MOS65XX_AM_BLOCK: + return "block move"; + case MOS65XX_AM_ZP: + return "zero page"; + case MOS65XX_AM_ZP_X: + return "zero page indexed with x"; + case MOS65XX_AM_ZP_Y: + return "zero page indexed with y"; + case MOS65XX_AM_ZP_REL: + return "relative bit branch"; + case MOS65XX_AM_ZP_IND: + return "zero page indirect"; + case MOS65XX_AM_ZP_X_IND: + return "zero page indexed with x indirect"; + case MOS65XX_AM_ZP_IND_Y: + return "zero page indirect indexed with y"; + case MOS65XX_AM_ZP_IND_LONG: + return "zero page indirect long"; + case MOS65XX_AM_ZP_IND_LONG_Y: + return "zero page indirect long indexed with y"; + case MOS65XX_AM_ABS: + return "absolute"; + case MOS65XX_AM_ABS_X: + return "absolute indexed with x"; + case MOS65XX_AM_ABS_Y: + return "absolute indexed with y"; + case MOS65XX_AM_ABS_IND: + return "absolute indirect"; + case MOS65XX_AM_ABS_X_IND: + return "absolute indexed with x indirect"; + case MOS65XX_AM_ABS_IND_LONG: + return "absolute indirect long"; + case MOS65XX_AM_ABS_LONG: + return "absolute long"; + case MOS65XX_AM_ABS_LONG_X: + return "absolute long indexed with x"; + case MOS65XX_AM_SR: + return "stack relative"; + case MOS65XX_AM_SR_IND_Y: + return "stack relative indirect indexed with y"; + } +} + + +char *get_detail_mos65xx(csh *handle, cs_mode mode, cs_insn *ins) +{ + int i; + cs_mos65xx *mos65xx; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + mos65xx = &(ins->detail->mos65xx); + add_str(&result, " ; address mode: %s", get_am_name(mos65xx->am)); + add_str(&result, " ; modifies flags: %s", mos65xx->modifies_flags ? "true": "false"); + + if (mos65xx->op_count) + add_str(&result, " ; op_count: %u", mos65xx->op_count); + + for (i = 0; i < mos65xx->op_count; i++) { + cs_mos65xx_op *op = &(mos65xx->operands[i]); + switch((int)op->type) { + default: + break; + case MOS65XX_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case MOS65XX_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm); + break; + case MOS65XX_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM = 0x%x", i, op->mem); + break; + } + } + return result; +} diff --git a/capstone/suite/cstest/src/ppc_detail.c b/capstone/suite/cstest/src/ppc_detail.c new file mode 100644 index 000000000..7a2ab8856 --- /dev/null +++ b/capstone/suite/cstest/src/ppc_detail.c @@ -0,0 +1,91 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +static const char* get_bc_name(int bc) +{ + switch(bc) { + default: + case PPC_BC_INVALID: + return ("invalid"); + case PPC_BC_LT: + return ("lt"); + case PPC_BC_LE: + return ("le"); + case PPC_BC_EQ: + return ("eq"); + case PPC_BC_GE: + return ("ge"); + case PPC_BC_GT: + return ("gt"); + case PPC_BC_NE: + return ("ne"); + case PPC_BC_UN: + return ("un"); + case PPC_BC_NU: + return ("nu"); + case PPC_BC_SO: + return ("so"); + case PPC_BC_NS: + return ("ns"); + } +} + +char *get_detail_ppc(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_ppc *ppc; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + ppc = &(ins->detail->ppc); + if (ppc->op_count) + add_str(&result, " ; op_count: %u", ppc->op_count); + + for (i = 0; i < ppc->op_count; i++) { + cs_ppc_op *op = &(ppc->operands[i]); + switch((int)op->type) { + default: + break; + case PPC_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case PPC_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%"PRIx64"", i, op->imm); + break; + case PPC_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != PPC_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + + break; + case PPC_OP_CRX: + add_str(&result, " ; operands[%u].type: CRX", i); + add_str(&result, " ; operands[%u].crx.scale: %d", i, op->crx.scale); + add_str(&result, " ; operands[%u].crx.reg: %s", i, cs_reg_name(*handle, op->crx.reg)); + add_str(&result, " ; operands[%u].crx.cond: %s", i, get_bc_name(op->crx.cond)); + break; + } + } + + if (ppc->bc != 0) + add_str(&result, " ; Branch code: %u", ppc->bc); + + if (ppc->bh != 0) + add_str(&result, " ; Branch hint: %u", ppc->bh); + + if (ppc->update_cr0) + add_str(&result, " ; Update-CR0: True"); + + return result; +} + diff --git a/capstone/suite/cstest/src/riscv_detail.c b/capstone/suite/cstest/src/riscv_detail.c new file mode 100644 index 000000000..70cc770e2 --- /dev/null +++ b/capstone/suite/cstest/src/riscv_detail.c @@ -0,0 +1,47 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_riscv(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_riscv *riscv; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + riscv = &(ins->detail->riscv); + if (riscv->op_count) + add_str(&result, " ; op_count: %u", riscv->op_count); + + for (i = 0; i < riscv->op_count; i++) { + cs_riscv_op *op = &(riscv->operands[i]); + switch((int)op->type) { + default: + break; + case RISCV_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case RISCV_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm); + break; + case RISCV_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != RISCV_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", + i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + break; + } + } + + return result; +} + diff --git a/capstone/suite/cstest/src/sparc_detail.c b/capstone/suite/cstest/src/sparc_detail.c new file mode 100644 index 000000000..54c6bb483 --- /dev/null +++ b/capstone/suite/cstest/src/sparc_detail.c @@ -0,0 +1,55 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_sparc(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_sparc *sparc; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + sparc = &(ins->detail->sparc); + if (sparc->op_count) + add_str(&result, " ; op_count: %u", sparc->op_count); + + for (i = 0; i < sparc->op_count; i++) { + cs_sparc_op *op = &(sparc->operands[i]); + switch((int)op->type) { + default: + break; + case SPARC_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case SPARC_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm); + break; + case SPARC_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != X86_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.index != X86_REG_INVALID) + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index)); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + + break; + } + } + + if (sparc->cc != 0) + add_str(&result, " ; Code condition: %u", sparc->cc); + + if (sparc->hint != 0) + add_str(&result, " ; Hint code: %u", sparc->hint); + + return result; +} + diff --git a/capstone/suite/cstest/src/systemz_detail.c b/capstone/suite/cstest/src/systemz_detail.c new file mode 100644 index 000000000..b9d24a055 --- /dev/null +++ b/capstone/suite/cstest/src/systemz_detail.c @@ -0,0 +1,57 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_sysz(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_sysz *sysz; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + sysz = &(ins->detail->sysz); + if (sysz->op_count) + add_str(&result, " ; op_count: %u", sysz->op_count); + + for (i = 0; i < sysz->op_count; i++) { + cs_sysz_op *op = &(sysz->operands[i]); + switch((int)op->type) { + default: + break; + case SYSZ_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case SYSZ_OP_ACREG: + add_str(&result, " ; operands[%u].type: ACREG = %u", i, op->reg); + break; + case SYSZ_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm); + break; + case SYSZ_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != SYSZ_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.index != SYSZ_REG_INVALID) + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index)); + if (op->mem.length != 0) + add_str(&result, " ; operands[%u].mem.length: 0x%" PRIx64 "", i, op->mem.length); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp); + + break; + } + } + + if (sysz->cc != 0) + add_str(&result, " ; Code condition: %u", sysz->cc); + + return result; +} + diff --git a/capstone/suite/cstest/src/tms320c64x_detail.c b/capstone/suite/cstest/src/tms320c64x_detail.c new file mode 100644 index 000000000..f6b0b9185 --- /dev/null +++ b/capstone/suite/cstest/src/tms320c64x_detail.c @@ -0,0 +1,107 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_tms320c64x(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_tms320c64x *tms320c64x; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + tms320c64x = &(ins->detail->tms320c64x); + if (tms320c64x->op_count) + add_str(&result, " ; op_count: %u", tms320c64x->op_count); + + for (i = 0; i < tms320c64x->op_count; i++) { + cs_tms320c64x_op *op = &(tms320c64x->operands[i]); + switch((int)op->type) { + default: + break; + case TMS320C64X_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case TMS320C64X_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm); + break; + case TMS320C64X_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != TMS320C64X_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + add_str(&result, " ; operands[%u].mem.disptype: ", i); + if (op->mem.disptype == TMS320C64X_MEM_DISP_INVALID) { + add_str(&result, "Invalid"); + add_str(&result, " ; operands[%u].mem.disp: %u", i, op->mem.disp); + } + if (op->mem.disptype == TMS320C64X_MEM_DISP_CONSTANT) { + add_str(&result, "Constant"); + add_str(&result, " ; operands[%u].mem.disp: %u", i, op->mem.disp); + } + if (op->mem.disptype == TMS320C64X_MEM_DISP_REGISTER) { + add_str(&result, "Register"); + add_str(&result, " ; operands[%u].mem.disp: %s", i, cs_reg_name(*handle, op->mem.disp)); + } + add_str(&result, " ; operands[%u].mem.unit: %u", i, op->mem.unit); + add_str(&result, " ; operands[%u].mem.direction: ", i); + if (op->mem.direction == TMS320C64X_MEM_DIR_INVALID) + add_str(&result, "Invalid"); + if (op->mem.direction == TMS320C64X_MEM_DIR_FW) + add_str(&result, "Forward"); + if (op->mem.direction == TMS320C64X_MEM_DIR_BW) + add_str(&result, "Backward"); + add_str(&result, " ; operands[%u].mem.modify: ", i); + if (op->mem.modify == TMS320C64X_MEM_MOD_INVALID) + add_str(&result, "Invalid"); + if (op->mem.modify == TMS320C64X_MEM_MOD_NO) + add_str(&result, "No"); + if (op->mem.modify == TMS320C64X_MEM_MOD_PRE) + add_str(&result, "Pre"); + if (op->mem.modify == TMS320C64X_MEM_MOD_POST) + add_str(&result, "Post"); + add_str(&result, " ; operands[%u].mem.scaled: %u", i, op->mem.scaled); + + break; + case TMS320C64X_OP_REGPAIR: + add_str(&result, " ; operands[%u].type: REGPAIR = %s:%s", i, cs_reg_name(*handle, op->reg + 1), cs_reg_name(*handle, op->reg)); + break; + } + } + + add_str(&result, " ; Functional unit: "); + switch(tms320c64x->funit.unit) { + case TMS320C64X_FUNIT_D: + add_str(&result, "D%u", tms320c64x->funit.side); + break; + case TMS320C64X_FUNIT_L: + add_str(&result, "L%u", tms320c64x->funit.side); + break; + case TMS320C64X_FUNIT_M: + add_str(&result, "M%u", tms320c64x->funit.side); + break; + case TMS320C64X_FUNIT_S: + add_str(&result, "S%u", tms320c64x->funit.side); + break; + case TMS320C64X_FUNIT_NO: + add_str(&result, "No Functional Unit"); + break; + default: + add_str(&result, "Unknown (Unit %u, Side %u)", tms320c64x->funit.unit, tms320c64x->funit.side); + break; + } + if (tms320c64x->funit.crosspath == 1) + add_str(&result, " ; Crosspath: 1"); + + if (tms320c64x->condition.reg != TMS320C64X_REG_INVALID) + add_str(&result, " ; Condition: [%c%s]", (tms320c64x->condition.zero == 1) ? '!' : ' ', cs_reg_name(*handle, tms320c64x->condition.reg)); + add_str(&result, " ; Parallel: %s", (tms320c64x->parallel == 1) ? "true" : "false"); + + return result; +} + diff --git a/capstone/suite/cstest/src/x86_detail.c b/capstone/suite/cstest/src/x86_detail.c new file mode 100644 index 000000000..f5456877c --- /dev/null +++ b/capstone/suite/cstest/src/x86_detail.c @@ -0,0 +1,344 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +static void print_string_hex(char **result, const char *comment, unsigned char *str, size_t len) +{ + unsigned char *c; + + add_str(result, "%s", comment); + for (c = str; c < str + len; c++) { + add_str(result, "0x%02x", *c & 0xff); + if (c < str + len - 1) + add_str(result, " "); + } + +} + +static const char *get_eflag_name(uint64_t flag) +{ + switch(flag) { + default: + return NULL; + case X86_EFLAGS_UNDEFINED_OF: + return "UNDEF_OF"; + case X86_EFLAGS_UNDEFINED_SF: + return "UNDEF_SF"; + case X86_EFLAGS_UNDEFINED_ZF: + return "UNDEF_ZF"; + case X86_EFLAGS_MODIFY_AF: + return "MOD_AF"; + case X86_EFLAGS_UNDEFINED_PF: + return "UNDEF_PF"; + case X86_EFLAGS_MODIFY_CF: + return "MOD_CF"; + case X86_EFLAGS_MODIFY_SF: + return "MOD_SF"; + case X86_EFLAGS_MODIFY_ZF: + return "MOD_ZF"; + case X86_EFLAGS_UNDEFINED_AF: + return "UNDEF_AF"; + case X86_EFLAGS_MODIFY_PF: + return "MOD_PF"; + case X86_EFLAGS_UNDEFINED_CF: + return "UNDEF_CF"; + case X86_EFLAGS_MODIFY_OF: + return "MOD_OF"; + case X86_EFLAGS_RESET_OF: + return "RESET_OF"; + case X86_EFLAGS_RESET_CF: + return "RESET_CF"; + case X86_EFLAGS_RESET_DF: + return "RESET_DF"; + case X86_EFLAGS_RESET_IF: + return "RESET_IF"; + case X86_EFLAGS_RESET_ZF: + return "RESET_ZF"; + case X86_EFLAGS_TEST_OF: + return "TEST_OF"; + case X86_EFLAGS_TEST_SF: + return "TEST_SF"; + case X86_EFLAGS_TEST_ZF: + return "TEST_ZF"; + case X86_EFLAGS_TEST_PF: + return "TEST_PF"; + case X86_EFLAGS_TEST_CF: + return "TEST_CF"; + case X86_EFLAGS_RESET_SF: + return "RESET_SF"; + case X86_EFLAGS_RESET_AF: + return "RESET_AF"; + case X86_EFLAGS_RESET_TF: + return "RESET_TF"; + case X86_EFLAGS_RESET_NT: + return "RESET_NT"; + case X86_EFLAGS_PRIOR_OF: + return "PRIOR_OF"; + case X86_EFLAGS_PRIOR_SF: + return "PRIOR_SF"; + case X86_EFLAGS_PRIOR_ZF: + return "PRIOR_ZF"; + case X86_EFLAGS_PRIOR_AF: + return "PRIOR_AF"; + case X86_EFLAGS_PRIOR_PF: + return "PRIOR_PF"; + case X86_EFLAGS_PRIOR_CF: + return "PRIOR_CF"; + case X86_EFLAGS_PRIOR_TF: + return "PRIOR_TF"; + case X86_EFLAGS_PRIOR_IF: + return "PRIOR_IF"; + case X86_EFLAGS_PRIOR_DF: + return "PRIOR_DF"; + case X86_EFLAGS_TEST_NT: + return "TEST_NT"; + case X86_EFLAGS_TEST_DF: + return "TEST_DF"; + case X86_EFLAGS_RESET_PF: + return "RESET_PF"; + case X86_EFLAGS_PRIOR_NT: + return "PRIOR_NT"; + case X86_EFLAGS_MODIFY_TF: + return "MOD_TF"; + case X86_EFLAGS_MODIFY_IF: + return "MOD_IF"; + case X86_EFLAGS_MODIFY_DF: + return "MOD_DF"; + case X86_EFLAGS_MODIFY_NT: + return "MOD_NT"; + case X86_EFLAGS_MODIFY_RF: + return "MOD_RF"; + case X86_EFLAGS_SET_CF: + return "SET_CF"; + case X86_EFLAGS_SET_DF: + return "SET_DF"; + case X86_EFLAGS_SET_IF: + return "SET_IF"; + case X86_EFLAGS_SET_OF: + return "SET_OF"; + case X86_EFLAGS_SET_SF: + return "SET_SF"; + case X86_EFLAGS_SET_ZF: + return "SET_ZF"; + case X86_EFLAGS_SET_AF: + return "SET_AF"; + case X86_EFLAGS_SET_PF: + return "SET_PF"; + case X86_EFLAGS_TEST_AF: + return "TEST_AF"; + case X86_EFLAGS_TEST_TF: + return "TEST_TF"; + case X86_EFLAGS_TEST_RF: + return "TEST_RF"; + case X86_EFLAGS_RESET_0F: + return "RESET_0F"; + case X86_EFLAGS_RESET_AC: + return "RESET_AC"; + } +} + +static const char *get_fpu_flag_name(uint64_t flag) +{ + switch (flag) { + default: + return NULL; + case X86_FPU_FLAGS_MODIFY_C0: + return "MOD_C0"; + case X86_FPU_FLAGS_MODIFY_C1: + return "MOD_C1"; + case X86_FPU_FLAGS_MODIFY_C2: + return "MOD_C2"; + case X86_FPU_FLAGS_MODIFY_C3: + return "MOD_C3"; + case X86_FPU_FLAGS_RESET_C0: + return "RESET_C0"; + case X86_FPU_FLAGS_RESET_C1: + return "RESET_C1"; + case X86_FPU_FLAGS_RESET_C2: + return "RESET_C2"; + case X86_FPU_FLAGS_RESET_C3: + return "RESET_C3"; + case X86_FPU_FLAGS_SET_C0: + return "SET_C0"; + case X86_FPU_FLAGS_SET_C1: + return "SET_C1"; + case X86_FPU_FLAGS_SET_C2: + return "SET_C2"; + case X86_FPU_FLAGS_SET_C3: + return "SET_C3"; + case X86_FPU_FLAGS_UNDEFINED_C0: + return "UNDEF_C0"; + case X86_FPU_FLAGS_UNDEFINED_C1: + return "UNDEF_C1"; + case X86_FPU_FLAGS_UNDEFINED_C2: + return "UNDEF_C2"; + case X86_FPU_FLAGS_UNDEFINED_C3: + return "UNDEF_C3"; + case X86_FPU_FLAGS_TEST_C0: + return "TEST_C0"; + case X86_FPU_FLAGS_TEST_C1: + return "TEST_C1"; + case X86_FPU_FLAGS_TEST_C2: + return "TEST_C2"; + case X86_FPU_FLAGS_TEST_C3: + return "TEST_C3"; + } +} + +char *get_detail_x86(csh *ud, cs_mode mode, cs_insn *ins) +{ + int count, i; + cs_x86 *x86; + cs_regs regs_read, regs_write; + uint8_t regs_read_count, regs_write_count; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + x86 = &(ins->detail->x86); + + print_string_hex(&result, " ; Prefix:", x86->prefix, 4); + print_string_hex(&result, " ; Opcode:", x86->opcode, 4); + add_str(&result, " ; rex: 0x%x", x86->rex); + add_str(&result, " ; addr_size: %u", x86->addr_size); + add_str(&result, " ; modrm: 0x%x", x86->modrm); + add_str(&result, " ; disp: 0x%" PRIx64 "", x86->disp); + + if ((mode & CS_MODE_16) == 0) { + add_str(&result, " ; sib: 0x%x", x86->sib); + if (x86->sib_base != X86_REG_INVALID) + add_str(&result, " ; sib_base: %s", cs_reg_name(*ud, x86->sib_base)); + if (x86->sib_index != X86_REG_INVALID) + add_str(&result, " ; sib_index: %s", cs_reg_name(*ud, x86->sib_index)); + if (x86->sib_scale != 0) + add_str(&result, " ; sib_scale: %d", x86->sib_scale); + } + + if (x86->xop_cc != X86_XOP_CC_INVALID) { + add_str(&result, " ; xop_cc: %u", x86->xop_cc); + } + + if (x86->sse_cc != X86_SSE_CC_INVALID) { + add_str(&result, " ; sse_cc: %u", x86->sse_cc); + } + + if (x86->avx_cc != X86_AVX_CC_INVALID) { + add_str(&result, " ; avx_cc: %u", x86->avx_cc); + } + + if (x86->avx_sae) { + add_str(&result, " ; avx_sae: %u", x86->avx_sae); + } + + if (x86->avx_rm != X86_AVX_RM_INVALID) { + add_str(&result, " ; avx_rm: %u", x86->avx_rm); + } + + count = cs_op_count(*ud, ins, X86_OP_IMM); + if (count > 0) { + add_str(&result, " ; imm_count: %u", count); + for (i = 1; i < count + 1; i++) { + int index = cs_op_index(*ud, ins, X86_OP_IMM, i); + add_str(&result, " ; imms[%u]: 0x%" PRIx64 "", i, x86->operands[index].imm); + } + } + + if (x86->op_count) + add_str(&result, " ; op_count: %u", x86->op_count); + + for (i = 0; i < x86->op_count; i++) { + cs_x86_op *op = &(x86->operands[i]); + + switch((int)op->type) { + case X86_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*ud, op->reg)); + break; + case X86_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm); + break; + case X86_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.segment != X86_REG_INVALID) + add_str(&result, " ; operands[%u].mem.segment: REG = %s", i, cs_reg_name(*ud, op->mem.segment)); + if (op->mem.base != X86_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*ud, op->mem.base)); + if (op->mem.index != X86_REG_INVALID) + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*ud, op->mem.index)); + if (op->mem.scale != 1) + add_str(&result, " ; operands[%u].mem.scale: %u", i, op->mem.scale); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp); + break; + default: + break; + } + + if (op->avx_bcast != X86_AVX_BCAST_INVALID) + add_str(&result, " ; operands[%u].avx_bcast: %u", i, op->avx_bcast); + + if (op->avx_zero_opmask != false) + add_str(&result, " ; operands[%u].avx_zero_opmask: TRUE", i); + + add_str(&result, " ; operands[%u].size: %u", i, op->size); + + switch(op->access) { + default: + break; + case CS_AC_READ: + add_str(&result, " ; operands[%u].access: READ", i); + break; + case CS_AC_WRITE: + add_str(&result, " ; operands[%u].access: WRITE", i); + break; + case CS_AC_READ | CS_AC_WRITE: + add_str(&result, " ; operands[%u].access: READ | WRITE", i); + break; + } + } + + if (!cs_regs_access(*ud, ins, regs_read, ®s_read_count, regs_write, ®s_write_count)) { + if (regs_read_count) { + add_str(&result, " ; Registers read:"); + for(i = 0; i < regs_read_count; i++) { + add_str(&result, " %s", cs_reg_name(*ud, regs_read[i])); + } + } + + if (regs_write_count) { + add_str(&result, " ; Registers modified:"); + for(i = 0; i < regs_write_count; i++) { + add_str(&result, " %s", cs_reg_name(*ud, regs_write[i])); + } + } + } + + if (x86->eflags || x86->fpu_flags) { + for(i = 0; i < ins->detail->groups_count; i++) { + if (ins->detail->groups[i] == X86_GRP_FPU) { + add_str(&result, " ; FPU_FLAGS:"); + for(i = 0; i <= 63; i++) + if (x86->fpu_flags & ((uint64_t)1 << i)) { + add_str(&result, " %s", get_fpu_flag_name((uint64_t)1 << i)); + } + break; + } + } + + if (i == ins->detail->groups_count) { + add_str(&result, " ; EFLAGS:"); + for(i = 0; i <= 63; i++) + if (x86->eflags & ((uint64_t)1 << i)) { + add_str(&result, " %s", get_eflag_name((uint64_t)1 << i)); + } + } + } + + return result; +} + diff --git a/capstone/suite/cstest/src/xcore_detail.c b/capstone/suite/cstest/src/xcore_detail.c new file mode 100644 index 000000000..d4f51f818 --- /dev/null +++ b/capstone/suite/cstest/src/xcore_detail.c @@ -0,0 +1,52 @@ +/* Capstone testing regression */ +/* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */ + + +#include "factory.h" + +char *get_detail_xcore(csh *handle, cs_mode mode, cs_insn *ins) +{ + cs_xcore *xcore; + int i; + char *result; + + result = (char *)malloc(sizeof(char)); + result[0] = '\0'; + + if (ins->detail == NULL) + return result; + + xcore = &(ins->detail->xcore); + if (xcore->op_count) + add_str(&result, " ; op_count: %u", xcore->op_count); + + for (i = 0; i < xcore->op_count; i++) { + cs_xcore_op *op = &(xcore->operands[i]); + switch((int)op->type) { + default: + break; + case XCORE_OP_REG: + add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*handle, op->reg)); + break; + case XCORE_OP_IMM: + add_str(&result, " ; operands[%u].type: IMM = 0x%x", i, op->imm); + break; + case XCORE_OP_MEM: + add_str(&result, " ; operands[%u].type: MEM", i); + if (op->mem.base != XCORE_REG_INVALID) + add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*handle, op->mem.base)); + if (op->mem.index != XCORE_REG_INVALID) + add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*handle, op->mem.index)); + if (op->mem.disp != 0) + add_str(&result, " ; operands[%u].mem.disp: 0x%x", i, op->mem.disp); + if (op->mem.direct != 1) + add_str(&result, " ; operands[%u].mem.direct: -1", i); + + + break; + } + } + + return result; +} + |