1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <inttypes.h>
4 #include <capstone.h>
5
6 struct platform {
7 cs_arch arch;
8 cs_mode mode;
9 char *comment;
10 };
11
main(int argc,char ** argv)12 int main(int argc, char **argv)
13 {
14 if (argc != 2) {
15 printf("Usage: %s <testcase>\n", argv[0]);
16 return 1;
17 }
18
19 struct platform platforms[] = {
20 {
21 CS_ARCH_X86,
22 CS_MODE_32,
23 "X86 32 (Intel syntax)"
24 },
25 {
26 CS_ARCH_X86,
27 CS_MODE_64,
28 "X86 64 (Intel syntax)"
29 },
30 {
31 CS_ARCH_ARM,
32 CS_MODE_ARM,
33 "ARM"
34 },
35 {
36 CS_ARCH_ARM,
37 CS_MODE_THUMB,
38 "THUMB-2"
39 },
40 {
41 CS_ARCH_ARM,
42 CS_MODE_ARM,
43 "ARM: Cortex-A15 + NEON"
44 },
45 {
46 CS_ARCH_ARM,
47 CS_MODE_THUMB,
48 "THUMB"
49 },
50 {
51 CS_ARCH_ARM,
52 (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
53 "Thumb-MClass"
54 },
55 {
56 CS_ARCH_ARM,
57 (cs_mode)(CS_MODE_ARM + CS_MODE_V8),
58 "Arm-V8"
59 },
60 {
61 CS_ARCH_MIPS,
62 (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
63 "MIPS-32 (Big-endian)"
64 },
65 {
66 CS_ARCH_MIPS,
67 (cs_mode)(CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN),
68 "MIPS-64-EL (Little-endian)"
69 },
70 {
71 CS_ARCH_MIPS,
72 (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
73 "MIPS-32R6 | Micro (Big-endian)"
74 },
75 {
76 CS_ARCH_MIPS,
77 (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
78 "MIPS-32R6 (Big-endian)"
79 },
80 {
81 CS_ARCH_ARM64,
82 CS_MODE_ARM,
83 "ARM-64"
84 },
85 {
86 CS_ARCH_PPC,
87 CS_MODE_BIG_ENDIAN,
88 "PPC-64"
89 },
90 {
91 CS_ARCH_SPARC,
92 CS_MODE_BIG_ENDIAN,
93 "Sparc"
94 },
95 {
96 CS_ARCH_SPARC,
97 (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9),
98 "SparcV9"
99 },
100 {
101 CS_ARCH_SYSZ,
102 (cs_mode)0,
103 "SystemZ"
104 },
105 {
106 CS_ARCH_XCORE,
107 (cs_mode)0,
108 "XCore"
109 },
110 };
111
112 // Read input
113 long bufsize = 0;
114 unsigned char *buf = NULL;
115 FILE *fp = fopen(argv[1], "r");
116
117 if (fp == NULL) return 1;
118
119 if (fseek(fp, 0L, SEEK_END) == 0) {
120 bufsize = ftell(fp);
121
122 if (bufsize == -1) return 1;
123
124 buf = malloc(bufsize + 1);
125
126 if (buf == NULL) return 1;
127 if (fseek(fp, 0L, SEEK_SET) != 0) return 1;
128
129 size_t len = fread(buf, sizeof(char), bufsize, fp);
130
131 if (len == 0) return 2;
132 }
133 fclose(fp);
134
135 // Disassemble
136 csh handle;
137 cs_insn *all_insn;
138 cs_detail *detail;
139 cs_err err;
140
141 if (bufsize < 3) return 0;
142
143 int platforms_len = sizeof(platforms)/sizeof(platforms[0]);
144 int i = (int)buf[0] % platforms_len;
145
146 unsigned char *buf_ptr = buf + 1;
147 long buf_ptr_size = bufsize - 1;
148
149 printf("Platform: %s (0x%.2x of 0x%.2x)\n", platforms[i].comment, i, platforms_len);
150
151 err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
152 if (err) {
153 printf("Failed on cs_open() with error returned: %u\n", err);
154 return 1;
155 }
156
157 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
158
159 uint64_t address = 0x1000;
160 size_t count = cs_disasm(handle, buf_ptr, buf_ptr_size, address, 0, &all_insn);
161
162 if (count) {
163 size_t j;
164 int n;
165
166 printf("Disasm:\n");
167
168 for (j = 0; j < count; j++) {
169 cs_insn *i = &(all_insn[j]);
170 printf("0x%"PRIx64":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
171 i->address, i->mnemonic, i->op_str,
172 i->id, cs_insn_name(handle, i->id));
173
174 detail = i->detail;
175
176 if (detail->regs_read_count > 0) {
177 printf("\tImplicit registers read: ");
178 for (n = 0; n < detail->regs_read_count; n++) {
179 printf("%s ", cs_reg_name(handle, detail->regs_read[n]));
180 }
181 printf("\n");
182 }
183
184 if (detail->regs_write_count > 0) {
185 printf("\tImplicit registers modified: ");
186 for (n = 0; n < detail->regs_write_count; n++) {
187 printf("%s ", cs_reg_name(handle, detail->regs_write[n]));
188 }
189 printf("\n");
190 }
191
192 if (detail->groups_count > 0) {
193 printf("\tThis instruction belongs to groups: ");
194 for (n = 0; n < detail->groups_count; n++) {
195 printf("%s ", cs_group_name(handle, detail->groups[n]));
196 }
197 printf("\n");
198 }
199 }
200 printf("0x%"PRIx64":\n", all_insn[j-1].address + all_insn[j-1].size);
201 cs_free(all_insn, count);
202 } else {
203 printf("ERROR: Failed to disasm given code!\n");
204 }
205
206 printf("\n");
207
208 free(buf);
209 cs_close(&handle);
210
211 return 0;
212 }
213