Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +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> |
Yegor Derevenets | ced9d24 | 2014-09-21 17:27:11 +0200 | [diff] [blame] | 6 | #include "../inttypes.h" |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 7 | |
| 8 | #include <capstone.h> |
| 9 | |
| 10 | struct platform { |
| 11 | cs_arch arch; |
| 12 | cs_mode mode; |
| 13 | unsigned char *code; |
| 14 | size_t size; |
| 15 | char *comment; |
| 16 | cs_opt_type opt_type; |
| 17 | cs_opt_value opt_value; |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 18 | cs_opt_type opt_skipdata; |
| 19 | size_t skipdata; |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 20 | }; |
| 21 | |
Mr. eXoDia | 9be1f93 | 2014-08-26 12:46:15 +0200 | [diff] [blame] | 22 | static void print_string_hex(unsigned char *str, size_t len) |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 23 | { |
| 24 | unsigned char *c; |
| 25 | |
| 26 | printf("Code: "); |
| 27 | for (c = str; c < str + len; c++) { |
| 28 | printf("0x%02x ", *c & 0xff); |
| 29 | } |
| 30 | printf("\n"); |
| 31 | } |
| 32 | |
Nguyen Anh Quynh | 0df7e93 | 2014-07-10 15:42:16 +0800 | [diff] [blame] | 33 | static size_t mycallback(const uint8_t *buffer, size_t buffer_size, size_t offset, void *p) |
Nguyen Anh Quynh | 943cb2d | 2014-04-11 17:12:58 +0800 | [diff] [blame] | 34 | { |
| 35 | // always skip 2 bytes when encountering data |
| 36 | return 2; |
| 37 | } |
| 38 | |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 39 | static void test() |
| 40 | { |
| 41 | #define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92" |
| 42 | #define RANDOM_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" |
| 43 | |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 44 | cs_opt_skipdata skipdata = { |
| 45 | // rename default "data" instruction from ".byte" to "db" |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 46 | "db", |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 47 | }; |
| 48 | |
| 49 | cs_opt_skipdata skipdata_callback = { |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 50 | "db", |
Nguyen Anh Quynh | 2c61656 | 2014-05-20 10:30:33 +0800 | [diff] [blame] | 51 | &mycallback, |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 52 | }; |
| 53 | |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 54 | struct platform platforms[] = { |
| 55 | { |
Axel 0vercl0k Souchet | de2dff4 | 2014-05-09 21:32:41 +0100 | [diff] [blame] | 56 | CS_ARCH_X86, |
| 57 | CS_MODE_32, |
| 58 | (unsigned char*)X86_CODE32, |
| 59 | sizeof(X86_CODE32) - 1, |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 60 | "X86 32 (Intel syntax) - Skip data", |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 61 | }, |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 62 | { |
Axel 0vercl0k Souchet | de2dff4 | 2014-05-09 21:32:41 +0100 | [diff] [blame] | 63 | CS_ARCH_ARM, |
| 64 | CS_MODE_ARM, |
| 65 | (unsigned char*)RANDOM_CODE, |
| 66 | sizeof(RANDOM_CODE) - 1, |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 67 | "Arm - Skip data", |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 68 | }, |
| 69 | { |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 70 | CS_ARCH_X86, |
| 71 | CS_MODE_32, |
| 72 | (unsigned char*)X86_CODE32, |
| 73 | sizeof(X86_CODE32) - 1, |
Nguyen Anh Quynh | 2c61656 | 2014-05-20 10:30:33 +0800 | [diff] [blame] | 74 | "X86 32 (Intel syntax) - Skip data with custom mnemonic", |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 75 | 0, 0, |
| 76 | CS_OPT_SKIPDATA_SETUP, |
| 77 | (size_t) &skipdata, |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 78 | }, |
| 79 | { |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 80 | CS_ARCH_ARM, |
| 81 | CS_MODE_ARM, |
| 82 | (unsigned char*)RANDOM_CODE, |
| 83 | sizeof(RANDOM_CODE) - 1, |
Nguyen Anh Quynh | 2c61656 | 2014-05-20 10:30:33 +0800 | [diff] [blame] | 84 | "Arm - Skip data with callback", |
danghvu | 50fdc6c | 2014-05-19 21:21:03 -0500 | [diff] [blame] | 85 | 0, 0, |
| 86 | CS_OPT_SKIPDATA_SETUP, |
| 87 | (size_t) &skipdata_callback, |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 88 | }, |
| 89 | }; |
| 90 | |
| 91 | csh handle; |
| 92 | uint64_t address = 0x1000; |
| 93 | cs_insn *insn; |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 94 | cs_err err; |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 95 | int i; |
Nguyen Anh Quynh | 5b556e5 | 2014-04-11 10:15:26 +0800 | [diff] [blame] | 96 | size_t count; |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 97 | |
| 98 | for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { |
| 99 | printf("****************\n"); |
| 100 | printf("Platform: %s\n", platforms[i].comment); |
Nguyen Anh Quynh | 655c702 | 2014-04-11 12:15:33 +0800 | [diff] [blame] | 101 | err = cs_open(platforms[i].arch, platforms[i].mode, &handle); |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 102 | if (err) { |
| 103 | printf("Failed on cs_open() with error returned: %u\n", err); |
| 104 | continue; |
| 105 | } |
| 106 | |
| 107 | if (platforms[i].opt_type) |
| 108 | cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); |
| 109 | |
Nguyen Anh Quynh | 943cb2d | 2014-04-11 17:12:58 +0800 | [diff] [blame] | 110 | // turn on SKIPDATA mode |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 111 | cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); |
danghvu | 69a7c2d | 2014-05-19 20:52:25 -0500 | [diff] [blame] | 112 | cs_option(handle, platforms[i].opt_skipdata, platforms[i].skipdata); |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 113 | |
Nguyen Anh Quynh | 0beb0d4 | 2014-08-27 22:55:29 +0800 | [diff] [blame] | 114 | count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn); |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 115 | if (count) { |
Nguyen Anh Quynh | 5b556e5 | 2014-04-11 10:15:26 +0800 | [diff] [blame] | 116 | size_t j; |
| 117 | |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 118 | print_string_hex(platforms[i].code, platforms[i].size); |
| 119 | printf("Disasm:\n"); |
| 120 | |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 121 | for (j = 0; j < count; j++) { |
| 122 | printf("0x%"PRIx64":\t%s\t\t%s\n", |
| 123 | insn[j].address, insn[j].mnemonic, insn[j].op_str); |
| 124 | } |
| 125 | |
| 126 | // print out the next offset, after the last insn |
| 127 | printf("0x%"PRIx64":\n", insn[j-1].address + insn[j-1].size); |
| 128 | |
Nguyen Anh Quynh | 0beb0d4 | 2014-08-27 22:55:29 +0800 | [diff] [blame] | 129 | // free memory allocated by cs_disasm() |
Nguyen Anh Quynh | c825819 | 2014-04-10 17:49:50 +0800 | [diff] [blame] | 130 | cs_free(insn, count); |
| 131 | } else { |
| 132 | printf("****************\n"); |
| 133 | printf("Platform: %s\n", platforms[i].comment); |
| 134 | print_string_hex(platforms[i].code, platforms[i].size); |
| 135 | printf("ERROR: Failed to disasm given code!\n"); |
| 136 | } |
| 137 | |
| 138 | printf("\n"); |
| 139 | |
| 140 | cs_close(&handle); |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | int main() |
| 145 | { |
| 146 | test(); |
| 147 | |
| 148 | #if 0 |
| 149 | #define offsetof(st, m) __builtin_offsetof(st, m) |
| 150 | |
| 151 | cs_insn insn; |
| 152 | printf("size: %lu\n", sizeof(insn)); |
| 153 | printf("@id: %lu\n", offsetof(cs_insn, id)); |
| 154 | printf("@address: %lu\n", offsetof(cs_insn, address)); |
| 155 | printf("@size: %lu\n", offsetof(cs_insn, size)); |
| 156 | printf("@bytes: %lu\n", offsetof(cs_insn, bytes)); |
| 157 | printf("@mnemonic: %lu\n", offsetof(cs_insn, mnemonic)); |
| 158 | printf("@op_str: %lu\n", offsetof(cs_insn, op_str)); |
| 159 | printf("@regs_read: %lu\n", offsetof(cs_insn, regs_read)); |
| 160 | printf("@regs_read_count: %lu\n", offsetof(cs_insn, regs_read_count)); |
| 161 | printf("@regs_write: %lu\n", offsetof(cs_insn, regs_write)); |
| 162 | printf("@regs_write_count: %lu\n", offsetof(cs_insn, regs_write_count)); |
| 163 | printf("@groups: %lu\n", offsetof(cs_insn, groups)); |
| 164 | printf("@groups_count: %lu\n", offsetof(cs_insn, groups_count)); |
| 165 | printf("@arch: %lu\n", offsetof(cs_insn, x86)); |
| 166 | #endif |
| 167 | |
| 168 | return 0; |
| 169 | } |