1 /* Capstone testing regression */
2 /* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
3
4
5 #include "factory.h"
6
print_string_hex(char ** result,const char * comment,unsigned char * str,size_t len)7 static void print_string_hex(char **result, const char *comment, unsigned char *str, size_t len)
8 {
9 unsigned char *c;
10
11 add_str(result, "%s", comment);
12 for (c = str; c < str + len; c++) {
13 add_str(result, "0x%02x", *c & 0xff);
14 if (c < str + len - 1)
15 add_str(result, " ");
16 }
17
18 }
19
get_eflag_name(uint64_t flag)20 static const char *get_eflag_name(uint64_t flag)
21 {
22 switch(flag) {
23 default:
24 return NULL;
25 case X86_EFLAGS_UNDEFINED_OF:
26 return "UNDEF_OF";
27 case X86_EFLAGS_UNDEFINED_SF:
28 return "UNDEF_SF";
29 case X86_EFLAGS_UNDEFINED_ZF:
30 return "UNDEF_ZF";
31 case X86_EFLAGS_MODIFY_AF:
32 return "MOD_AF";
33 case X86_EFLAGS_UNDEFINED_PF:
34 return "UNDEF_PF";
35 case X86_EFLAGS_MODIFY_CF:
36 return "MOD_CF";
37 case X86_EFLAGS_MODIFY_SF:
38 return "MOD_SF";
39 case X86_EFLAGS_MODIFY_ZF:
40 return "MOD_ZF";
41 case X86_EFLAGS_UNDEFINED_AF:
42 return "UNDEF_AF";
43 case X86_EFLAGS_MODIFY_PF:
44 return "MOD_PF";
45 case X86_EFLAGS_UNDEFINED_CF:
46 return "UNDEF_CF";
47 case X86_EFLAGS_MODIFY_OF:
48 return "MOD_OF";
49 case X86_EFLAGS_RESET_OF:
50 return "RESET_OF";
51 case X86_EFLAGS_RESET_CF:
52 return "RESET_CF";
53 case X86_EFLAGS_RESET_DF:
54 return "RESET_DF";
55 case X86_EFLAGS_RESET_IF:
56 return "RESET_IF";
57 case X86_EFLAGS_RESET_ZF:
58 return "RESET_ZF";
59 case X86_EFLAGS_TEST_OF:
60 return "TEST_OF";
61 case X86_EFLAGS_TEST_SF:
62 return "TEST_SF";
63 case X86_EFLAGS_TEST_ZF:
64 return "TEST_ZF";
65 case X86_EFLAGS_TEST_PF:
66 return "TEST_PF";
67 case X86_EFLAGS_TEST_CF:
68 return "TEST_CF";
69 case X86_EFLAGS_RESET_SF:
70 return "RESET_SF";
71 case X86_EFLAGS_RESET_AF:
72 return "RESET_AF";
73 case X86_EFLAGS_RESET_TF:
74 return "RESET_TF";
75 case X86_EFLAGS_RESET_NT:
76 return "RESET_NT";
77 case X86_EFLAGS_PRIOR_OF:
78 return "PRIOR_OF";
79 case X86_EFLAGS_PRIOR_SF:
80 return "PRIOR_SF";
81 case X86_EFLAGS_PRIOR_ZF:
82 return "PRIOR_ZF";
83 case X86_EFLAGS_PRIOR_AF:
84 return "PRIOR_AF";
85 case X86_EFLAGS_PRIOR_PF:
86 return "PRIOR_PF";
87 case X86_EFLAGS_PRIOR_CF:
88 return "PRIOR_CF";
89 case X86_EFLAGS_PRIOR_TF:
90 return "PRIOR_TF";
91 case X86_EFLAGS_PRIOR_IF:
92 return "PRIOR_IF";
93 case X86_EFLAGS_PRIOR_DF:
94 return "PRIOR_DF";
95 case X86_EFLAGS_TEST_NT:
96 return "TEST_NT";
97 case X86_EFLAGS_TEST_DF:
98 return "TEST_DF";
99 case X86_EFLAGS_RESET_PF:
100 return "RESET_PF";
101 case X86_EFLAGS_PRIOR_NT:
102 return "PRIOR_NT";
103 case X86_EFLAGS_MODIFY_TF:
104 return "MOD_TF";
105 case X86_EFLAGS_MODIFY_IF:
106 return "MOD_IF";
107 case X86_EFLAGS_MODIFY_DF:
108 return "MOD_DF";
109 case X86_EFLAGS_MODIFY_NT:
110 return "MOD_NT";
111 case X86_EFLAGS_MODIFY_RF:
112 return "MOD_RF";
113 case X86_EFLAGS_SET_CF:
114 return "SET_CF";
115 case X86_EFLAGS_SET_DF:
116 return "SET_DF";
117 case X86_EFLAGS_SET_IF:
118 return "SET_IF";
119 case X86_EFLAGS_SET_OF:
120 return "SET_OF";
121 case X86_EFLAGS_SET_SF:
122 return "SET_SF";
123 case X86_EFLAGS_SET_ZF:
124 return "SET_ZF";
125 case X86_EFLAGS_SET_AF:
126 return "SET_AF";
127 case X86_EFLAGS_SET_PF:
128 return "SET_PF";
129 case X86_EFLAGS_TEST_AF:
130 return "TEST_AF";
131 case X86_EFLAGS_TEST_TF:
132 return "TEST_TF";
133 case X86_EFLAGS_TEST_RF:
134 return "TEST_RF";
135 case X86_EFLAGS_RESET_0F:
136 return "RESET_0F";
137 case X86_EFLAGS_RESET_AC:
138 return "RESET_AC";
139 }
140 }
141
get_fpu_flag_name(uint64_t flag)142 static const char *get_fpu_flag_name(uint64_t flag)
143 {
144 switch (flag) {
145 default:
146 return NULL;
147 case X86_FPU_FLAGS_MODIFY_C0:
148 return "MOD_C0";
149 case X86_FPU_FLAGS_MODIFY_C1:
150 return "MOD_C1";
151 case X86_FPU_FLAGS_MODIFY_C2:
152 return "MOD_C2";
153 case X86_FPU_FLAGS_MODIFY_C3:
154 return "MOD_C3";
155 case X86_FPU_FLAGS_RESET_C0:
156 return "RESET_C0";
157 case X86_FPU_FLAGS_RESET_C1:
158 return "RESET_C1";
159 case X86_FPU_FLAGS_RESET_C2:
160 return "RESET_C2";
161 case X86_FPU_FLAGS_RESET_C3:
162 return "RESET_C3";
163 case X86_FPU_FLAGS_SET_C0:
164 return "SET_C0";
165 case X86_FPU_FLAGS_SET_C1:
166 return "SET_C1";
167 case X86_FPU_FLAGS_SET_C2:
168 return "SET_C2";
169 case X86_FPU_FLAGS_SET_C3:
170 return "SET_C3";
171 case X86_FPU_FLAGS_UNDEFINED_C0:
172 return "UNDEF_C0";
173 case X86_FPU_FLAGS_UNDEFINED_C1:
174 return "UNDEF_C1";
175 case X86_FPU_FLAGS_UNDEFINED_C2:
176 return "UNDEF_C2";
177 case X86_FPU_FLAGS_UNDEFINED_C3:
178 return "UNDEF_C3";
179 case X86_FPU_FLAGS_TEST_C0:
180 return "TEST_C0";
181 case X86_FPU_FLAGS_TEST_C1:
182 return "TEST_C1";
183 case X86_FPU_FLAGS_TEST_C2:
184 return "TEST_C2";
185 case X86_FPU_FLAGS_TEST_C3:
186 return "TEST_C3";
187 }
188 }
189
get_detail_x86(csh * ud,cs_mode mode,cs_insn * ins)190 char *get_detail_x86(csh *ud, cs_mode mode, cs_insn *ins)
191 {
192 int count, i;
193 cs_x86 *x86;
194 cs_regs regs_read, regs_write;
195 uint8_t regs_read_count, regs_write_count;
196 char *result;
197
198 result = (char *)malloc(sizeof(char));
199 result[0] = '\0';
200
201 if (ins->detail == NULL)
202 return result;
203
204 x86 = &(ins->detail->x86);
205
206 print_string_hex(&result, " ; Prefix:", x86->prefix, 4);
207 print_string_hex(&result, " ; Opcode:", x86->opcode, 4);
208 add_str(&result, " ; rex: 0x%x", x86->rex);
209 add_str(&result, " ; addr_size: %u", x86->addr_size);
210 add_str(&result, " ; modrm: 0x%x", x86->modrm);
211 add_str(&result, " ; disp: 0x%" PRIx64 "", x86->disp);
212
213 if ((mode & CS_MODE_16) == 0) {
214 add_str(&result, " ; sib: 0x%x", x86->sib);
215 if (x86->sib_base != X86_REG_INVALID)
216 add_str(&result, " ; sib_base: %s", cs_reg_name(*ud, x86->sib_base));
217 if (x86->sib_index != X86_REG_INVALID)
218 add_str(&result, " ; sib_index: %s", cs_reg_name(*ud, x86->sib_index));
219 if (x86->sib_scale != 0)
220 add_str(&result, " ; sib_scale: %d", x86->sib_scale);
221 }
222
223 if (x86->xop_cc != X86_XOP_CC_INVALID) {
224 add_str(&result, " ; xop_cc: %u", x86->xop_cc);
225 }
226
227 if (x86->sse_cc != X86_SSE_CC_INVALID) {
228 add_str(&result, " ; sse_cc: %u", x86->sse_cc);
229 }
230
231 if (x86->avx_cc != X86_AVX_CC_INVALID) {
232 add_str(&result, " ; avx_cc: %u", x86->avx_cc);
233 }
234
235 if (x86->avx_sae) {
236 add_str(&result, " ; avx_sae: %u", x86->avx_sae);
237 }
238
239 if (x86->avx_rm != X86_AVX_RM_INVALID) {
240 add_str(&result, " ; avx_rm: %u", x86->avx_rm);
241 }
242
243 count = cs_op_count(*ud, ins, X86_OP_IMM);
244 if (count > 0) {
245 add_str(&result, " ; imm_count: %u", count);
246 for (i = 1; i < count + 1; i++) {
247 int index = cs_op_index(*ud, ins, X86_OP_IMM, i);
248 add_str(&result, " ; imms[%u]: 0x%" PRIx64 "", i, x86->operands[index].imm);
249 }
250 }
251
252 if (x86->op_count)
253 add_str(&result, " ; op_count: %u", x86->op_count);
254
255 for (i = 0; i < x86->op_count; i++) {
256 cs_x86_op *op = &(x86->operands[i]);
257
258 switch((int)op->type) {
259 case X86_OP_REG:
260 add_str(&result, " ; operands[%u].type: REG = %s", i, cs_reg_name(*ud, op->reg));
261 break;
262 case X86_OP_IMM:
263 add_str(&result, " ; operands[%u].type: IMM = 0x%" PRIx64 "", i, op->imm);
264 break;
265 case X86_OP_MEM:
266 add_str(&result, " ; operands[%u].type: MEM", i);
267 if (op->mem.segment != X86_REG_INVALID)
268 add_str(&result, " ; operands[%u].mem.segment: REG = %s", i, cs_reg_name(*ud, op->mem.segment));
269 if (op->mem.base != X86_REG_INVALID)
270 add_str(&result, " ; operands[%u].mem.base: REG = %s", i, cs_reg_name(*ud, op->mem.base));
271 if (op->mem.index != X86_REG_INVALID)
272 add_str(&result, " ; operands[%u].mem.index: REG = %s", i, cs_reg_name(*ud, op->mem.index));
273 if (op->mem.scale != 1)
274 add_str(&result, " ; operands[%u].mem.scale: %u", i, op->mem.scale);
275 if (op->mem.disp != 0)
276 add_str(&result, " ; operands[%u].mem.disp: 0x%" PRIx64 "", i, op->mem.disp);
277 break;
278 default:
279 break;
280 }
281
282 if (op->avx_bcast != X86_AVX_BCAST_INVALID)
283 add_str(&result, " ; operands[%u].avx_bcast: %u", i, op->avx_bcast);
284
285 if (op->avx_zero_opmask != false)
286 add_str(&result, " ; operands[%u].avx_zero_opmask: TRUE", i);
287
288 add_str(&result, " ; operands[%u].size: %u", i, op->size);
289
290 switch(op->access) {
291 default:
292 break;
293 case CS_AC_READ:
294 add_str(&result, " ; operands[%u].access: READ", i);
295 break;
296 case CS_AC_WRITE:
297 add_str(&result, " ; operands[%u].access: WRITE", i);
298 break;
299 case CS_AC_READ | CS_AC_WRITE:
300 add_str(&result, " ; operands[%u].access: READ | WRITE", i);
301 break;
302 }
303 }
304
305 if (!cs_regs_access(*ud, ins, regs_read, ®s_read_count, regs_write, ®s_write_count)) {
306 if (regs_read_count) {
307 add_str(&result, " ; Registers read:");
308 for(i = 0; i < regs_read_count; i++) {
309 add_str(&result, " %s", cs_reg_name(*ud, regs_read[i]));
310 }
311 }
312
313 if (regs_write_count) {
314 add_str(&result, " ; Registers modified:");
315 for(i = 0; i < regs_write_count; i++) {
316 add_str(&result, " %s", cs_reg_name(*ud, regs_write[i]));
317 }
318 }
319 }
320
321 if (x86->eflags || x86->fpu_flags) {
322 for(i = 0; i < ins->detail->groups_count; i++) {
323 if (ins->detail->groups[i] == X86_GRP_FPU) {
324 add_str(&result, " ; FPU_FLAGS:");
325 for(i = 0; i <= 63; i++)
326 if (x86->fpu_flags & ((uint64_t)1 << i)) {
327 add_str(&result, " %s", get_fpu_flag_name((uint64_t)1 << i));
328 }
329 break;
330 }
331 }
332
333 if (i == ins->detail->groups_count) {
334 add_str(&result, " ; EFLAGS:");
335 for(i = 0; i <= 63; i++)
336 if (x86->eflags & ((uint64_t)1 << i)) {
337 add_str(&result, " %s", get_eflag_name((uint64_t)1 << i));
338 }
339 }
340 }
341
342 return result;
343 }
344
345