/* Capstone testing regression */ /* By Do Minh Tuan , 02-2019 */ #include "capstone_test.h" 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} }; 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} }; 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_OPT_UNSIGNED", CS_OPT_UNSIGNED, CS_OPT_ON} }; 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; 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); }