| Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame^] | 1 | /* Capstone Disassembler Engine */ | 
 | 2 | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */ | 
 | 3 |  | 
 | 4 | #include <stdio.h> | 
 | 5 | #include <stdlib.h> | 
 | 6 | #include <inttypes.h> | 
 | 7 |  | 
 | 8 | #include <capstone.h> | 
 | 9 |  | 
 | 10 | struct platform { | 
 | 11 | 	cs_arch arch; | 
 | 12 | 	cs_mode mode; | 
 | 13 | 	char *code; | 
 | 14 | 	int size; | 
 | 15 | 	char *comment; | 
 | 16 | }; | 
 | 17 |  | 
 | 18 | static csh handle; | 
 | 19 |  | 
 | 20 | static void print_string_hex(char *comment, char *str, int len) | 
 | 21 | { | 
 | 22 | 	char *c; | 
 | 23 |  | 
 | 24 | 	printf("%s", comment); | 
 | 25 | 	for (c = str; c < str + len; c++) { | 
 | 26 | 		printf("0x%02x ", *c & 0xff); | 
 | 27 | 	} | 
 | 28 |  | 
 | 29 | 	printf("\n"); | 
 | 30 | } | 
 | 31 |  | 
 | 32 | static void print_insn_detail(cs_arch mode, cs_insn *ins) | 
 | 33 | { | 
 | 34 | 	cs_mips *mips = &(ins->mips); | 
 | 35 |  | 
 | 36 | 	if (mips->op_count) | 
 | 37 | 		printf("\top_count: %u\n", mips->op_count); | 
 | 38 |  | 
 | 39 | 	int i; | 
 | 40 | 	for (i = 0; i < mips->op_count; i++) { | 
 | 41 | 		cs_mips_op *op = &(mips->operands[i]); | 
 | 42 | 		switch((int)op->type) { | 
 | 43 | 			default: | 
 | 44 | 				break; | 
 | 45 | 			case MIPS_OP_REG: | 
 | 46 | 				printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg)); | 
 | 47 | 				break; | 
 | 48 | 			case MIPS_OP_IMM: | 
 | 49 | 				printf("\t\toperands[%u].type: IMM = 0x%"PRIx64 "\n", i, op->imm); | 
 | 50 | 				break; | 
 | 51 | 			case MIPS_OP_MEM: | 
 | 52 | 				printf("\t\toperands[%u].type: MEM\n", i); | 
 | 53 | 				if (op->mem.base != X86_REG_INVALID) | 
 | 54 | 					printf("\t\t\toperands[%u].mem.base: REG = %s\n", | 
 | 55 | 							i, cs_reg_name(handle, op->mem.base)); | 
 | 56 | 				if (op->mem.disp != 0) | 
 | 57 | 					printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp); | 
 | 58 |  | 
 | 59 | 				break; | 
 | 60 | 		} | 
 | 61 |  | 
 | 62 | 	} | 
 | 63 |  | 
 | 64 | 	printf("\n"); | 
 | 65 | } | 
 | 66 |  | 
 | 67 | static void test() | 
 | 68 | { | 
 | 69 | //#define MIPS_CODE "\x8f\xa2\x00\x00" | 
 | 70 | //#define MIPS_CODE "\x00\x00\xa7\xac\x10\x00\xa2\x8f" | 
 | 71 | //#define MIPS_CODE "\x21\x30\xe6\x70"	// clo $6, $7 | 
 | 72 | //#define MIPS_CODE "\x00\x00\x00\x00" // nop | 
 | 73 | //#define MIPS_CODE "\xc6\x23\xe9\xe4"	// swc1	$f9, 0x23c6($7) | 
 | 74 | //#define MIPS_CODE "\x21\x38\x00\x01"	// move $7, $8 | 
 | 75 | #define MIPS_CODE "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56" | 
 | 76 | #define MIPS_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00" | 
 | 77 |  | 
 | 78 | 	struct platform platforms[] = { | 
 | 79 | 		{ | 
 | 80 | 			.arch = CS_ARCH_MIPS, | 
 | 81 | 			.mode = CS_MODE_32 + CS_MODE_BIG_ENDIAN, | 
 | 82 | 			.code = MIPS_CODE, | 
 | 83 | 			.size = sizeof(MIPS_CODE) - 1, | 
 | 84 | 			.comment = "MIPS-32 (Big-endian)" | 
 | 85 | 		}, | 
 | 86 | 		{ | 
 | 87 | 			.arch = CS_ARCH_MIPS, | 
 | 88 | 			.mode = CS_MODE_64+ CS_MODE_LITTLE_ENDIAN, | 
 | 89 | 			.code = MIPS_CODE2, | 
 | 90 | 			.size = sizeof(MIPS_CODE2) - 1, | 
 | 91 | 			.comment = "MIPS-64-EL (Little-endian)" | 
 | 92 | 		}, | 
 | 93 | 	}; | 
 | 94 |  | 
 | 95 | 	uint64_t address = 0x1000; | 
 | 96 | 	cs_insn *insn; | 
 | 97 | 	int i; | 
 | 98 |  | 
 | 99 | 	for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { | 
 | 100 | 		if (cs_open(platforms[i].arch, platforms[i].mode, &handle)) | 
 | 101 | 			return; | 
 | 102 |  | 
 | 103 | 		uint64_t count = cs_disasm_dyn(handle, platforms[i].code, platforms[i].size, address, 0, &insn); | 
 | 104 | 		if (count) { | 
 | 105 | 			printf("****************\n"); | 
 | 106 | 			printf("Platform: %s\n", platforms[i].comment); | 
 | 107 | 			print_string_hex("Code:", platforms[i].code, platforms[i].size); | 
 | 108 | 			printf("Disasm:\n"); | 
 | 109 |  | 
 | 110 | 			uint64_t j; | 
 | 111 | 			for (j = 0; j < count; j++) { | 
 | 112 | 				printf("0x%"PRIx64":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); | 
 | 113 | 				print_insn_detail(platforms[i].mode, &insn[j]); | 
 | 114 | 			} | 
 | 115 | 			printf("0x%"PRIx64":\n", insn[j-1].address + insn[j-1].size); | 
 | 116 |  | 
 | 117 | 			// free memory allocated by cs_disasm_dyn() | 
 | 118 | 			cs_free(insn); | 
 | 119 | 		} else { | 
 | 120 | 			printf("****************\n"); | 
 | 121 | 			printf("Platform: %s\n", platforms[i].comment); | 
 | 122 | 			print_string_hex("Code:", platforms[i].code, platforms[i].size); | 
 | 123 | 			printf("ERROR: Failed to disasm given code!\n"); | 
 | 124 | 		} | 
 | 125 |  | 
 | 126 | 		printf("\n"); | 
 | 127 |  | 
 | 128 | 		cs_close(handle); | 
 | 129 | 	} | 
 | 130 | } | 
 | 131 |  | 
 | 132 | int main() | 
 | 133 | { | 
 | 134 | 	test(); | 
 | 135 |  | 
 | 136 | 	return 0; | 
 | 137 | } |