1 /* radare2 - LGPL - Copyright 2013-2019 - pancake */
2
3 #include <r_anal.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6 #include <x86.h>
7
8 #if 0
9 CYCLES:
10 ======
11 register access = 1
12 memory access = 2
13 jump = 3
14 call = 4
15 #endif
16
17 #define CYCLE_REG 0
18 #define CYCLE_MEM 1
19 #define CYCLE_JMP 2
20
21 // TODO: when capstone-4 is released, add proper check here
22
23 #if CS_NEXT_VERSION>0
24 #define HAVE_CSGRP_PRIVILEGE 1
25 #else
26 #define HAVE_CSGRP_PRIVILEGE 0
27 #endif
28
29 #define USE_ITER_API 0
30
31 #if CS_API_MAJOR < 2
32 #error Old Capstone not supported
33 #endif
34
35 #define esilprintf(op, fmt, ...) r_strbuf_setf (&op->esil, fmt, ##__VA_ARGS__)
36 #define opexprintf(op, fmt, ...) r_strbuf_setf (&op->opex, fmt, ##__VA_ARGS__)
37 #define INSOP(n) insn->detail->x86.operands[n]
38 #define INSOPS insn->detail->x86.op_count
39 #define ISIMM(x) insn->detail->x86.operands[x].type == X86_OP_IMM
40 #define ISMEM(x) insn->detail->x86.operands[x].type == X86_OP_MEM
41
42 #define BUF_SZ 64
43
44 #define AR_DIM 4
45
46 #define SRC_AR 0
47 #define DST_AR 1
48 #define DST_R_AR 1
49 #define DST_W_AR 2
50 #define SRC2_AR 2
51 #define DST2_AR 2
52 #define DSTADD_AR 3
53 #define ARG0_AR 0
54 #define ARG1_AR 1
55 #define ARG2_AR 2
56
57 struct Getarg {
58 csh handle;
59 cs_insn *insn;
60 int bits;
61 };
62
63 static csh handle = 0;
64
hidden_op(cs_insn * insn,cs_x86 * x,int mode)65 static void hidden_op(cs_insn *insn, cs_x86 *x, int mode) {
66 unsigned int id = insn->id;
67 int regsz = 4;
68 switch (mode) {
69 case CS_MODE_64:
70 regsz = 8;
71 break;
72 case CS_MODE_16:
73 regsz = 2;
74 break;
75 default:
76 regsz = 4; //32 bit
77 break;
78 }
79
80 switch (id) {
81 case X86_INS_PUSHF:
82 case X86_INS_POPF:
83 case X86_INS_PUSHFD:
84 case X86_INS_POPFD:
85 case X86_INS_PUSHFQ:
86 case X86_INS_POPFQ:
87 x->op_count = 1;
88 cs_x86_op *op = &x->operands[0];
89 op->type = X86_OP_REG;
90 op->reg = X86_REG_EFLAGS;
91 op->size = regsz;
92 #if CS_API_MAJOR >=4
93 if (id == X86_INS_PUSHF || id == X86_INS_PUSHFD || id == X86_INS_PUSHFQ) {
94 op->access = 1;
95 } else {
96 op->access = 2;
97 }
98 #endif
99 break;
100 case X86_INS_PUSHAW:
101 case X86_INS_PUSHAL:
102 case X86_INS_POPAW:
103 case X86_INS_POPAL:
104 default:
105 break;
106 }
107 }
108
opex(RStrBuf * buf,cs_insn * insn,int mode)109 static void opex(RStrBuf *buf, cs_insn *insn, int mode) {
110 int i;
111 PJ *pj = pj_new ();
112 if (!pj) {
113 return;
114 }
115 pj_o (pj);
116 cs_x86 *x = &insn->detail->x86;
117 if (x->op_count == 0) {
118 hidden_op (insn, x, mode);
119 }
120 pj_ka (pj, "operands");
121 for (i = 0; i < x->op_count; i++) {
122 cs_x86_op *op = x->operands + i;
123 pj_o (pj);
124 pj_ki (pj, "size", op->size);
125 #if CS_API_MAJOR >= 4
126 pj_ki (pj, "rw", op->access); // read, write, read|write
127 #endif
128 switch (op->type) {
129 case X86_OP_REG:
130 pj_ks (pj, "type", "reg");
131 pj_ks (pj, "value", cs_reg_name (handle, op->reg));
132 break;
133 case X86_OP_IMM:
134 pj_ks (pj, "type", "imm");
135 pj_kN (pj, "value", op->imm);
136 break;
137 case X86_OP_MEM:
138 pj_ks (pj, "type", "mem");
139 if (op->mem.segment != X86_REG_INVALID) {
140 pj_ks (pj, "segment", cs_reg_name (handle, op->mem.segment));
141 }
142 if (op->mem.base != X86_REG_INVALID) {
143 pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
144 }
145 if (op->mem.index != X86_REG_INVALID) {
146 pj_ks (pj, "index", cs_reg_name (handle, op->mem.index));
147 }
148 pj_ki (pj, "scale", op->mem.scale);
149 pj_kN (pj, "disp", op->mem.disp);
150 break;
151 default:
152 pj_ks (pj, "type", "invalid");
153 break;
154 }
155 pj_end (pj); /* o operand */
156 }
157 pj_end (pj); /* a operands */
158 if (x->rex) {
159 pj_kb (pj, "rex", true);
160 }
161 if (x->modrm) {
162 pj_kb (pj, "modrm", true);
163 }
164 if (x->sib) {
165 pj_ki (pj, "sib", x->sib);
166 }
167 if (x->disp) {
168 pj_kN (pj, "disp", x->disp);
169 }
170 if (x->sib_index != X86_REG_INVALID) {
171 pj_ki (pj, "sib_scale", x->sib_scale);
172 pj_ks (pj, "sib_index", cs_reg_name (handle, x->sib_index));
173 }
174 if (x->sib_base != X86_REG_INVALID) {
175 pj_ks (pj, "sib_base", cs_reg_name (handle, x->sib_base));
176 }
177 pj_end (pj);
178
179 r_strbuf_init (buf);
180 r_strbuf_append (buf, pj_string (pj));
181 pj_free (pj);
182 }
183
is_xmm_reg(cs_x86_op op)184 static bool is_xmm_reg(cs_x86_op op) {
185 switch (op.reg) {
186 case X86_REG_XMM0:
187 case X86_REG_XMM1:
188 case X86_REG_XMM2:
189 case X86_REG_XMM3:
190 case X86_REG_XMM4:
191 case X86_REG_XMM5:
192 case X86_REG_XMM6:
193 case X86_REG_XMM7:
194 case X86_REG_XMM8:
195 case X86_REG_XMM9:
196 case X86_REG_XMM10:
197 case X86_REG_XMM11:
198 case X86_REG_XMM12:
199 case X86_REG_XMM13:
200 case X86_REG_XMM14:
201 case X86_REG_XMM15:
202 case X86_REG_XMM16:
203 case X86_REG_XMM17:
204 case X86_REG_XMM18:
205 case X86_REG_XMM19:
206 case X86_REG_XMM20:
207 case X86_REG_XMM21:
208 case X86_REG_XMM22:
209 case X86_REG_XMM23:
210 case X86_REG_XMM24:
211 case X86_REG_XMM25:
212 case X86_REG_XMM26:
213 case X86_REG_XMM27:
214 case X86_REG_XMM28:
215 case X86_REG_XMM29:
216 case X86_REG_XMM30:
217 case X86_REG_XMM31: return true;
218 default: return false;
219 }
220 }
221
222 /**
223 * Translates operand N to esil
224 *
225 * @param handle csh
226 * @param insn cs_insn
227 * @param n Operand index
228 * @param set if 1 it adds set (=) to the operand
229 * @param setoper Extra operation for the set (^, -, +, etc...)
230 * @param sel Selector for output buffer in staic array
231 * @return Pointer to esil operand in static array
232 */
getarg(struct Getarg * gop,int n,int set,char * setop,int sel,ut32 * bitsize)233 static char *getarg(struct Getarg* gop, int n, int set, char *setop, int sel, ut32 *bitsize) {
234 static char buf[AR_DIM][BUF_SZ];
235 char *out = buf[sel];
236 const char *setarg = r_str_get (setop);
237 cs_insn *insn = gop->insn;
238 csh handle = gop->handle;
239 cs_x86_op op;
240
241 if (!insn->detail) {
242 return NULL;
243 }
244 if (n < 0 || n >= INSOPS) {
245 return NULL;
246 }
247 out[0] = 0;
248 op = INSOP (n);
249 if (bitsize) {
250 *bitsize = op.size * 8;
251 }
252 switch (op.type) {
253 #if CS_API_MAJOR == 3
254 case X86_OP_FP:
255 return "invalid";
256 #endif
257 case X86_OP_INVALID:
258 return "invalid";
259 case X86_OP_REG:
260 if (set == 1) {
261 snprintf (out, BUF_SZ, "%s,%s=",
262 cs_reg_name (handle, op.reg), setarg);
263 return out;
264 }
265 return (char *)cs_reg_name (handle, op.reg);
266 case X86_OP_IMM:
267 if (set == 1) {
268 snprintf (out, BUF_SZ, "%"PFMT64u",%s=[%d]",
269 (ut64)op.imm, setarg, op.size);
270 return out;
271 }
272 snprintf (out, BUF_SZ, "%"PFMT64u, (ut64)op.imm);
273 return out;
274 case X86_OP_MEM:
275 {
276 // address = (base + (index * scale) + offset)
277 char buf_[BUF_SZ] = {0};
278 int component_count = 0;
279 const char *base = cs_reg_name (handle, op.mem.base);
280 const char *index = cs_reg_name (handle, op.mem.index);
281 int scale = op.mem.scale;
282 st64 disp = op.mem.disp;
283
284 if (disp != 0) {
285 snprintf (out, BUF_SZ, "0x%"PFMT64x",", (disp < 0) ? -disp : disp);
286 component_count++;
287 }
288
289 if (index) {
290 if (scale > 1) {
291 snprintf (buf_, BUF_SZ, "%s%s,%d,*,", out, index, scale);
292 } else {
293 snprintf (buf_, BUF_SZ, "%s%s,", out, index);
294 }
295 strncpy (out, buf_, BUF_SZ);
296 component_count++;
297 }
298
299 if (base) {
300 snprintf (buf_, BUF_SZ, "%s%s,", out, base);
301 strncpy (out, buf_, BUF_SZ);
302 component_count++;
303 }
304
305 if (component_count > 1) {
306 if (component_count > 2) {
307 snprintf (buf_, BUF_SZ, "%s+,", out);
308 strncpy (out, buf_, BUF_SZ);
309 }
310 if (disp < 0) {
311 snprintf (buf_, BUF_SZ, "%s-", out);
312 } else {
313 snprintf (buf_, BUF_SZ, "%s+", out);
314 }
315 strncpy (out, buf_, BUF_SZ);
316 } else {
317 // Remove the trailing ',' from esil statement.
318 if (*out) {
319 int out_len = strlen (out);
320 out[out_len> 0? out_len - 1: 0] = 0;
321 }
322 }
323
324 // set = 2 is reserved for lea, where the operand is a memory address,
325 // but the corresponding memory is not loaded.
326 if (set == 1) {
327 size_t len = strlen (setarg);
328 if (len > 0 && setarg[len - 1] == ',') {
329 snprintf (buf_, BUF_SZ, "%s,%s%s=[%d]", out, setarg,
330 gop->bits == 32 ? "0xffffffff,&," : "", op.size==10?8:op.size);
331 } else {
332 snprintf (buf_, BUF_SZ, "%s,%s=[%d]", out, setarg, op.size==10?8:op.size);
333 }
334 strncpy (out, buf_, BUF_SZ);
335 } else if (set == 0) {
336 if (!*out) {
337 strcpy (out, "0");
338 }
339 snprintf (buf_, BUF_SZ, "%s,[%d]", out, op.size==10? 8: op.size);
340 strncpy (out, buf_, BUF_SZ);
341 }
342 out[BUF_SZ - 1] = 0;
343 }
344 return out;
345 }
346 return NULL;
347 }
348
cond_x862r2(int id)349 static int cond_x862r2(int id) {
350 switch (id) {
351 case X86_INS_JE:
352 return R_ANAL_COND_EQ;
353 case X86_INS_JNE:
354 return R_ANAL_COND_NE;
355 case X86_INS_JB:
356 case X86_INS_JL:
357 return R_ANAL_COND_LT;
358 case X86_INS_JBE:
359 case X86_INS_JLE:
360 return R_ANAL_COND_LE;
361 case X86_INS_JG:
362 case X86_INS_JA:
363 return R_ANAL_COND_GT;
364 case X86_INS_JAE:
365 return R_ANAL_COND_GE;
366 case X86_INS_JS:
367 case X86_INS_JNS:
368 case X86_INS_JO:
369 case X86_INS_JNO:
370 case X86_INS_JGE:
371 case X86_INS_JP:
372 case X86_INS_JNP:
373 case X86_INS_JCXZ:
374 case X86_INS_JECXZ:
375 break;
376 }
377 return 0;
378 }
379
380 /* reg indices are based on Intel doc for 32-bit ModR/M byte */
reg32_to_name(ut8 reg)381 static const char *reg32_to_name(ut8 reg) {
382 const char * const names[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
383 return reg < R_ARRAY_SIZE (names) ? names[reg] : "unk";
384 }
385
anop_esil(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,csh * handle,cs_insn * insn)386 static void anop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
387 int rs = a->bits/8;
388 const char *pc = (a->bits==16)?"ip":
389 (a->bits==32)?"eip":"rip";
390 const char *sp = (a->bits==16)?"sp":
391 (a->bits==32)?"esp":"rsp";
392 const char *bp = (a->bits==16)?"bp":
393 (a->bits==32)?"ebp":"rbp";
394 const char *si = (a->bits==16)?"si":
395 (a->bits==32)?"esi":"rsi";
396 struct Getarg gop = {
397 .handle = *handle,
398 .insn = insn,
399 .bits = a->bits
400 };
401 char *src;
402 char *src2;
403 char *dst;
404 char *dst2;
405 char *dst_r;
406 char *dst_w;
407 char *dstAdd;
408 char *arg0;
409 char *arg1;
410 char *arg2;
411
412 // counter for rep prefix
413 const char *counter = (a->bits==16)?"cx":
414 (a->bits==32)?"ecx":"rcx";
415
416 bool repe = false;
417
418 switch (insn->id) {
419 case X86_INS_FNOP:
420 case X86_INS_NOP:
421 case X86_INS_PAUSE:
422 esilprintf (op, ",");
423 break;
424 case X86_INS_HLT:
425 break;
426 case X86_INS_FBLD:
427 case X86_INS_FBSTP:
428 case X86_INS_FCOMPP:
429 case X86_INS_FDECSTP:
430 case X86_INS_FEMMS:
431 case X86_INS_FFREE:
432 case X86_INS_FICOM:
433 case X86_INS_FICOMP:
434 case X86_INS_FINCSTP:
435 case X86_INS_FNCLEX:
436 case X86_INS_FNINIT:
437 case X86_INS_FNSTCW:
438 case X86_INS_FNSTSW:
439 case X86_INS_FPATAN:
440 case X86_INS_FPREM:
441 case X86_INS_FPREM1:
442 case X86_INS_FPTAN:
443 #if CS_API_MAJOR >=4
444 case X86_INS_FFREEP:
445 #endif
446 case X86_INS_FRNDINT:
447 case X86_INS_FRSTOR:
448 case X86_INS_FNSAVE:
449 case X86_INS_FSCALE:
450 case X86_INS_FSETPM:
451 case X86_INS_FSINCOS:
452 case X86_INS_FNSTENV:
453 case X86_INS_FXAM:
454 case X86_INS_FXSAVE:
455 case X86_INS_FXSAVE64:
456 case X86_INS_FXTRACT:
457 case X86_INS_FYL2X:
458 case X86_INS_FYL2XP1:
459 case X86_INS_FISTTP:
460 case X86_INS_FSQRT:
461 case X86_INS_FXCH:
462 break;
463 case X86_INS_FTST:
464 case X86_INS_FUCOMI:
465 case X86_INS_FUCOMPP:
466 case X86_INS_FUCOMP:
467 case X86_INS_FUCOM:
468 break;
469 case X86_INS_FABS:
470 break;
471 case X86_INS_FLDCW:
472 case X86_INS_FLDENV:
473 case X86_INS_FLDL2E:
474 case X86_INS_FLDL2T:
475 case X86_INS_FLDLG2:
476 case X86_INS_FLDLN2:
477 case X86_INS_FLDPI:
478 case X86_INS_FLDZ:
479 case X86_INS_FLD1:
480 case X86_INS_FLD:
481 break;
482 case X86_INS_FIST:
483 case X86_INS_FISTP:
484 case X86_INS_FST:
485 case X86_INS_FSTP:
486 case X86_INS_FSTPNCE:
487 case X86_INS_FXRSTOR:
488 case X86_INS_FXRSTOR64:
489 break;
490 case X86_INS_FIDIV:
491 case X86_INS_FIDIVR:
492 case X86_INS_FDIV:
493 case X86_INS_FDIVP:
494 case X86_INS_FDIVR:
495 case X86_INS_FDIVRP:
496 break;
497 case X86_INS_FSUBR:
498 case X86_INS_FISUBR:
499 case X86_INS_FSUBRP:
500 case X86_INS_FSUB:
501 case X86_INS_FISUB:
502 case X86_INS_FSUBP:
503 break;
504 case X86_INS_FMUL:
505 case X86_INS_FIMUL:
506 case X86_INS_FMULP:
507 break;
508 case X86_INS_CLI:
509 esilprintf (op, "0,if,:=");
510 break;
511 case X86_INS_STI:
512 esilprintf (op, "1,if,:=");
513 break;
514 case X86_INS_CLC:
515 esilprintf (op, "0,cf,:=");
516 break;
517 case X86_INS_CMC:
518 esilprintf (op, "cf,!,cf,=");
519 break;
520 case X86_INS_STC:
521 esilprintf (op, "1,cf,:=");
522 break;
523 case X86_INS_CLAC:
524 case X86_INS_CLGI:
525 case X86_INS_CLTS:
526 #if CS_API_MAJOR >= 4
527 case X86_INS_CLWB:
528 #endif
529 case X86_INS_STAC:
530 case X86_INS_STGI:
531 break;
532 // cmov
533 case X86_INS_SETNE:
534 case X86_INS_SETNO:
535 case X86_INS_SETNP:
536 case X86_INS_SETNS:
537 case X86_INS_SETO:
538 case X86_INS_SETP:
539 case X86_INS_SETS:
540 case X86_INS_SETL:
541 case X86_INS_SETLE:
542 case X86_INS_SETB:
543 case X86_INS_SETG:
544 case X86_INS_SETAE:
545 case X86_INS_SETA:
546 case X86_INS_SETBE:
547 case X86_INS_SETE:
548 case X86_INS_SETGE:
549 {
550 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
551 switch (insn->id) {
552 case X86_INS_SETE: esilprintf (op, "zf,%s", dst); break;
553 case X86_INS_SETNE: esilprintf (op, "zf,!,%s", dst); break;
554 case X86_INS_SETO: esilprintf (op, "of,%s", dst); break;
555 case X86_INS_SETNO: esilprintf (op, "of,!,%s", dst); break;
556 case X86_INS_SETP: esilprintf (op, "pf,%s", dst); break;
557 case X86_INS_SETNP: esilprintf (op, "pf,!,%s", dst); break;
558 case X86_INS_SETS: esilprintf (op, "sf,%s", dst); break;
559 case X86_INS_SETNS: esilprintf (op, "sf,!,%s", dst); break;
560 case X86_INS_SETB: esilprintf (op, "cf,%s", dst); break;
561 case X86_INS_SETAE: esilprintf (op, "cf,!,%s", dst); break;
562 case X86_INS_SETL: esilprintf (op, "sf,of,^,%s", dst); break;
563 case X86_INS_SETLE: esilprintf (op, "zf,sf,of,^,|,%s", dst); break;
564 case X86_INS_SETG: esilprintf (op, "zf,!,sf,of,^,!,&,%s", dst); break;
565 case X86_INS_SETGE: esilprintf (op, "sf,of,^,!,%s", dst); break;
566 case X86_INS_SETA: esilprintf (op, "cf,zf,|,!,%s", dst); break;
567 case X86_INS_SETBE: esilprintf (op, "cf,zf,|,%s", dst); break;
568 }
569 }
570 break;
571 // cmov
572 case X86_INS_FCMOVBE:
573 case X86_INS_FCMOVB:
574 case X86_INS_FCMOVNBE:
575 case X86_INS_FCMOVNB:
576 case X86_INS_FCMOVE:
577 case X86_INS_FCMOVNE:
578 case X86_INS_FCMOVNU:
579 case X86_INS_FCMOVU:
580 break;
581 case X86_INS_CMOVA:
582 case X86_INS_CMOVAE:
583 case X86_INS_CMOVB:
584 case X86_INS_CMOVBE:
585 case X86_INS_CMOVE:
586 case X86_INS_CMOVG:
587 case X86_INS_CMOVGE:
588 case X86_INS_CMOVL:
589 case X86_INS_CMOVLE:
590 case X86_INS_CMOVNE:
591 case X86_INS_CMOVNO:
592 case X86_INS_CMOVNP:
593 case X86_INS_CMOVNS:
594 case X86_INS_CMOVO:
595 case X86_INS_CMOVP:
596 case X86_INS_CMOVS: {
597 const char *conditional = NULL;
598 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
599 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
600 switch (insn->id) {
601 case X86_INS_CMOVA:
602 // mov if CF = 0 *AND* ZF = 0
603 conditional = "cf,zf,|,!";
604 break;
605 case X86_INS_CMOVAE:
606 // mov if CF = 0
607 conditional = "cf,!";
608 break;
609 case X86_INS_CMOVB:
610 // mov if CF = 1
611 conditional = "cf";
612 break;
613 case X86_INS_CMOVBE:
614 // mov if CF = 1 *OR* ZF = 1
615 conditional = "cf,zf,|";
616 break;
617 case X86_INS_CMOVE:
618 // mov if ZF = 1
619 conditional = "zf";
620 break;
621 case X86_INS_CMOVG:
622 // mov if ZF = 0 *AND* SF = OF
623 conditional = "zf,!,sf,of,^,!,&";
624 break;
625 case X86_INS_CMOVGE:
626 // mov if SF = OF
627 conditional = "sf,of,^,!";
628 break;
629 case X86_INS_CMOVL:
630 // mov if SF != OF
631 conditional = "sf,of,^";
632 break;
633 case X86_INS_CMOVLE:
634 // mov if ZF = 1 *OR* SF != OF
635 conditional = "zf,sf,of,^,|";
636 break;
637 case X86_INS_CMOVNE:
638 // mov if ZF = 0
639 conditional = "zf,!";
640 break;
641 case X86_INS_CMOVNO:
642 // mov if OF = 0
643 conditional = "of,!";
644 break;
645 case X86_INS_CMOVNP:
646 // mov if PF = 0
647 conditional = "pf,!";
648 break;
649 case X86_INS_CMOVNS:
650 // mov if SF = 0
651 conditional = "sf,!";
652 break;
653 case X86_INS_CMOVO:
654 // mov if OF = 1
655 conditional = "of";
656 break;
657 case X86_INS_CMOVP:
658 // mov if PF = 1
659 conditional = "pf";
660 break;
661 case X86_INS_CMOVS:
662 // mov if SF = 1
663 conditional = "sf";
664 break;
665 }
666 if (src && dst && conditional) {
667 esilprintf (op, "%s,?{,%s,%s,}", conditional, src, dst);
668 }
669 }
670 break;
671 case X86_INS_STOSB:
672 if (a->bits<32) {
673 r_strbuf_appendf (&op->esil, "al,di,=[1],df,?{,1,di,-=,},df,!,?{,1,di,+=,}");
674 } else {
675 r_strbuf_appendf (&op->esil, "al,edi,=[1],df,?{,1,edi,-=,},df,!,?{,1,edi,+=,}");
676 }
677 break;
678 case X86_INS_STOSW:
679 if (a->bits<32) {
680 r_strbuf_appendf (&op->esil, "ax,di,=[2],df,?{,2,di,-=,},df,!,?{,2,di,+=,}");
681 } else {
682 r_strbuf_appendf (&op->esil, "ax,edi,=[2],df,?{,2,edi,-=,},df,!,?{,2,edi,+=,}");
683 }
684 break;
685 case X86_INS_STOSD:
686 r_strbuf_appendf (&op->esil, "eax,edi,=[4],df,?{,4,edi,-=,},df,!,?{,4,edi,+=,}");
687 break;
688 case X86_INS_STOSQ:
689 r_strbuf_appendf (&op->esil, "rax,rdi,=[8],df,?{,8,edi,-=,},df,!,?{,8,edi,+=,}");
690 break;
691 case X86_INS_LODSB:
692 r_strbuf_appendf (&op->esil, "%s,[1],al,=,df,?{,1,%s,-=,},df,!,?{,1,%s,+=,}", si, si, si);
693 break;
694 case X86_INS_LODSW:
695 r_strbuf_appendf (&op->esil, "%s,[2],ax,=,df,?{,2,%s,-=,},df,!,?{,2,%s,+=,}", si, si, si);
696 break;
697 case X86_INS_LODSD:
698 r_strbuf_appendf (&op->esil, "esi,[4],eax,=,df,?{,4,esi,-=,},df,!,?{,4,esi,+=,}");
699 break;
700 case X86_INS_LODSQ:
701 r_strbuf_appendf (&op->esil, "rsi,[8],rax,=,df,?{,8,rsi,-=,},df,!,?{,8,rsi,+=,}");
702 break;
703 case X86_INS_PEXTRB:
704 r_strbuf_appendf (&op->esil, "TODO");
705 break;
706 // string mov
707 // PS: MOVSD can correspond to one of the two instruction (yes, intel x86
708 // has the same pneumonic for two different opcodes!). We can decide which
709 // of the two it is based on the operands.
710 // For more information, see:
711 // http://x86.renejeschke.de/html/file_module_x86_id_203.html
712 // (vs)
713 // http://x86.renejeschke.de/html/file_module_x86_id_204.html
714 case X86_INS_MOVSD:
715 // Handle "Move Scalar Double-Precision Floating-Point Value"
716 if (is_xmm_reg (INSOP(0)) || is_xmm_reg (INSOP(1))) {
717 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
718 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
719 if (src && dst) {
720 esilprintf (op, "%s,%s", src, dst);
721 }
722 break;
723 }
724 case X86_INS_MOVSB:
725 case X86_INS_MOVSQ:
726 case X86_INS_MOVSW:
727 if (op->prefix & R_ANAL_OP_PREFIX_REP) {
728 int width = INSOP(0).size;
729 src = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
730 dst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
731 r_strbuf_appendf (&op->esil,
732 "%s,[%d],%s,=[%d],"\
733 "df,?{,%d,%s,-=,%d,%s,-=,},"\
734 "df,!,?{,%d,%s,+=,%d,%s,+=,}",
735 src, width, dst, width,
736 width, src, width, dst,
737 width, src, width, dst);
738 } else {
739 int width = INSOP(0).size;
740 src = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
741 dst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
742 esilprintf (op, "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\
743 "df,!,?{,%d,%s,+=,%d,%s,+=,}",
744 src, width, dst, width, width, src, width,
745 dst, width, src, width, dst);
746 }
747 break;
748 // mov
749 case X86_INS_MOVSS:
750 case X86_INS_MOV:
751 case X86_INS_MOVAPS:
752 case X86_INS_MOVAPD:
753 case X86_INS_MOVZX:
754 case X86_INS_MOVUPS:
755 case X86_INS_MOVABS:
756 case X86_INS_MOVHPD:
757 case X86_INS_MOVHPS:
758 case X86_INS_MOVLPD:
759 case X86_INS_MOVLPS:
760 case X86_INS_MOVBE:
761 case X86_INS_MOVSX:
762 case X86_INS_MOVSXD:
763 case X86_INS_MOVD:
764 case X86_INS_MOVQ:
765 case X86_INS_MOVDQU:
766 case X86_INS_MOVDQA:
767 case X86_INS_MOVDQ2Q:
768 {
769 switch (INSOP(0).type) {
770 case X86_OP_MEM:
771 if (op->prefix & R_ANAL_OP_PREFIX_REP) {
772 int width = INSOP(0).size;
773 src = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
774 dst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
775 const char *counter = (a->bits==16)?"cx":
776 (a->bits==32)?"ecx":"rcx";
777 esilprintf (op, "%s,!,?{,BREAK,},%s,NUM,%s,NUM,"\
778 "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\
779 "df,!,?{,%d,%s,+=,%d,%s,+=,},%s,--=,%s," \
780 "?{,8,GOTO,}",
781 counter, src, dst, src, width, dst,
782 width, width, src, width, dst, width, src,
783 width, dst, counter, counter);
784 } else {
785 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
786 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
787 esilprintf (op, "%s,%s", src, dst);
788 }
789 break;
790 case X86_OP_REG:
791 default:
792 if (INSOP(0).type == X86_OP_MEM) {
793 op->direction = 1; // read
794 }
795 if (INSOP(1).type == X86_OP_MEM) {
796 // MOV REG, [PTR + IREG*SCALE]
797 op->ireg = cs_reg_name (*handle, INSOP (1).mem.index);
798 op->disp = INSOP(1).mem.disp;
799 op->scale = INSOP(1).mem.scale;
800 }
801 {
802 int width = INSOP(1).size;
803
804 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
805 // dst is name of register from instruction.
806 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
807 const char *dst64 = r_reg_32_to_64 (a->reg, dst);
808 if (a->bits == 64 && dst64) {
809 // Here it is still correct, because 'e** = X'
810 // turns into 'r** = X' (first one will keep higher bytes,
811 // second one will overwrite them with zeros).
812 if (insn->id == X86_INS_MOVSX || insn->id == X86_INS_MOVSXD) {
813 esilprintf (op, "%d,%s,~,%s,=", width*8, src, dst64);
814 } else {
815 esilprintf (op, "%s,%s,=", src, dst64);
816 }
817
818 } else {
819 if (insn->id == X86_INS_MOVSX || insn->id == X86_INS_MOVSXD) {
820 esilprintf (op, "%d,%s,~,%s,=", width*8, src, dst);
821 } else {
822 esilprintf (op, "%s,%s,=", src, dst);
823 }
824 }
825 }
826 break;
827 }
828 }
829 break;
830 case X86_INS_ROL:
831 case X86_INS_RCL:
832 // TODO: RCL Still does not work as intended
833 // - Set flags
834 {
835 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
836 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
837 esilprintf (op, "%s,%s,<<<,%s,=", src, dst, dst);
838 }
839 break;
840 case X86_INS_ROR:
841 case X86_INS_RCR:
842 // TODO: RCR Still does not work as intended
843 // - Set flags
844 {
845 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
846 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
847 esilprintf (op, "%s,%s,>>>,%s,=", src, dst, dst);
848 }
849 break;
850 case X86_INS_CPUID:
851 // https://c9x.me/x86/html/file_module_x86_id_45.html
852 // GenuineIntel
853 esilprintf (op, "0xa,eax,=,0x756E6547,ebx,=,0x6C65746E,ecx,=,0x49656E69,edx,=");
854 break;
855 case X86_INS_SHLD:
856 case X86_INS_SHLX:
857 // TODO: SHLD is not implemented yet.
858 {
859 ut32 bitsize;
860 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
861 dst = getarg (&gop, 0, 1, "<<", DST_AR, &bitsize);
862 esilprintf (op, "%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=", src, dst, bitsize - 1);
863 }
864 break;
865 case X86_INS_SAR:
866 // TODO: Set CF. See case X86_INS_SHL for more details.
867 {
868 #if 0
869 ut64 val = 0;
870 switch (gop.insn->detail->x86.operands[0].size) {
871 case 1:
872 val = 0x80;
873 break;
874 case 2:
875 val = 0x8000;
876 break;
877 case 4:
878 val = 0x80000000;
879 break;
880 case 8:
881 val = 0x8000000000000000;
882 break;
883 default:
884 val = 0x80;
885 }
886 src = getarg (&gop, 1, 0, NULL, SRC_AR);
887 dst = getarg (&gop, 0, 0, NULL, DST_AR);
888 esilprintf (op, "%s,1,%s,>>,0x%"PFMT64x",%s,&,|,%s,=,1,%s,&,cf,=,1,REPEAT", src, dst, val, dst, dst, dst);
889 #endif
890 ut32 bitsize;
891 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
892 dst_r = getarg (&gop, 0, 0, NULL, DST_R_AR, NULL);
893 dst_w = getarg (&gop, 0, 1, NULL, DST_W_AR, &bitsize);
894 esilprintf (op, "0,cf,:=,1,%s,-,1,<<,%s,&,?{,1,cf,:=,},%s,%s,>>>>,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=",
895 src, dst_r, src, dst_r, dst_w, bitsize - 1);
896 }
897 break;
898 case X86_INS_SARX:
899 {
900 dst = getarg (&gop, 0, 1, NULL, 0, NULL);
901 src = getarg (&gop, 1, 0, NULL, 1, NULL);
902 src2 = getarg (&gop, 1, 0, NULL, 2, NULL);
903 esilprintf (op, "%s,%s,>>>>,%s,=", src2, src, dst);
904 }
905 break;
906 case X86_INS_SHL:
907 case X86_INS_SAL:
908 {
909 ut64 val = 0;
910 switch (gop.insn->detail->x86.operands[0].size) {
911 case 1:
912 val = 0x80;
913 break;
914 case 2:
915 val = 0x8000;
916 break;
917 case 4:
918 val = 0x80000000;
919 break;
920 case 8:
921 val = 0x8000000000000000;
922 break;
923 default:
924 eprintf ("Error: unknown operand size: %d\n", gop.insn->detail->x86.operands[0].size);
925 val = 256;
926 }
927 ut32 bitsize;
928 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
929 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
930 dst2 = getarg (&gop, 0, 1, "<<", DST2_AR, &bitsize);
931 esilprintf (op, "0,%s,!,!,?{,1,%s,-,%s,<<,0x%llx,&,!,!,^,},%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,cf,=",
932 src, src, dst, val, src, dst2, bitsize - 1);
933 }
934 break;
935 case X86_INS_SALC:
936 esilprintf (op, "$z,DUP,zf,=,al,=");
937 break;
938 case X86_INS_SHR:
939 case X86_INS_SHRD:
940 case X86_INS_SHRX:
941 // TODO: Set CF: See case X86_INS_SAL for more details.
942 {
943 ut32 bitsize;
944 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
945 dst_r = getarg (&gop, 0, 0, NULL, DST_R_AR, NULL);
946 dst_w = getarg (&gop, 0, 1, NULL, DST_W_AR, &bitsize);
947 esilprintf (op, "0,cf,:=,1,%s,-,1,<<,%s,&,?{,1,cf,:=,},%s,%s,>>,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=",
948 src, dst_r, src, dst_r, dst_w, bitsize - 1);
949 }
950 break;
951 case X86_INS_CBW:
952 esilprintf (op, "al,ax,=,7,ax,>>,?{,0xff00,ax,|=,}");
953 break;
954 case X86_INS_CWDE:
955 esilprintf (op, "ax,eax,=,15,eax,>>,?{,0xffff0000,eax,|=,}");
956 break;
957 case X86_INS_CDQ:
958 esilprintf (op, "0,edx,=,31,eax,>>,?{,0xffffffff,edx,=,}");
959 break;
960 case X86_INS_CDQE:
961 esilprintf (op, "eax,rax,=,31,rax,>>,?{,0xffffffff00000000,rax,|=,}");
962 break;
963 case X86_INS_AAA:
964 esilprintf (op, "0,cf,:=,0,af,:=,9,al,>,?{,10,al,-=,1,ah,+=,1,cf,:=,1,af,:=,}"); //don't
965 break;
966 case X86_INS_AAD:
967 arg0 = "0,zf,:=,0,sf,:=,0,pf,:=,10,ah,*,al,+,ax,=";
968 arg1 = "0,al,==,?{,1,zf,:=,},2,al,%,0,==,?{,1,pf,:=,},7,al,>>,?{,1,sf,:=,}";
969 esilprintf (op, "%s,%s", arg0, arg1);
970 break;
971 case X86_INS_AAM:
972 arg0 = "0,zf,:=,0,sf,:=,0,pf,:=,10,al,/,ah,=,10,al,%,al,=";
973 arg1 = "0,al,==,?{,1,zf,:=,},2,al,%,0,==,?{,1,pf,:=,},7,al,>>,?{,1,sf,:=,}";
974 esilprintf (op, "%s,%s", arg0, arg1);
975 break;
976 // XXX: case X86_INS_AAS: too tough to implement. BCD is deprecated anyways
977 case X86_INS_CMPPD:
978 case X86_INS_CMPPS:
979 case X86_INS_CMPSW:
980 case X86_INS_CMPSD:
981 case X86_INS_CMPSQ:
982 case X86_INS_CMPSB:
983 case X86_INS_CMPSS:
984 repe = true;
985 case X86_INS_CMP:
986 case X86_INS_TEST:
987 {
988 ut32 bitsize;
989 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
990 dst = getarg (&gop, 0, 0, NULL, DST_AR, &bitsize);
991
992 if (!bitsize || bitsize > 64) {
993 break;
994 }
995
996 if (insn->id == X86_INS_TEST) {
997 esilprintf (op, "0,%s,%s,&,==,$z,zf,:=,$p,pf,:=,%u,$s,sf,:=,0,cf,:=,0,of,:=",
998 src, dst, bitsize - 1);
999 } else if (insn->id == X86_INS_CMP) {
1000 esilprintf (op,
1001 "%s,%s,==,$z,zf,:=,%u,$b,cf,:=,$p,pf,:=,%u,$s,sf,:=,"\
1002 "%s,0x%"PFMT64x",-,!,%u,$o,^,of,:=,3,$b,af,:=",
1003 src, dst, bitsize, bitsize - 1, src, 1ULL << (bitsize - 1), bitsize - 1);
1004 } else {
1005 char *rsrc = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
1006 char *rdst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
1007 const int width = INSOP(0).size;
1008 esilprintf (op,
1009 "%s,%s,==,$z,zf,:=,%u,$b,cf,:=,$p,pf,:=,%u,$s,sf,:=,%s,0x%"PFMT64x","\
1010 "-,!,%u,$o,^,of,:=,3,$b,af,:=,df,?{,%d,%s,-=,%d,%s,-=,}{,%d,%s,+=,%d,%s,+=,}",
1011 src, dst, bitsize, bitsize - 1, src, 1ULL << (bitsize - 1), bitsize - 1,
1012 width, rsrc, width, rdst, width, rsrc, width, rdst);
1013 }
1014 }
1015 break;
1016 case X86_INS_LEA:
1017 {
1018 src = getarg (&gop, 1, 2, NULL, SRC_AR, NULL);
1019 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
1020 esilprintf (op, "%s,%s", src, dst);
1021 }
1022 break;
1023 case X86_INS_PUSHAW:
1024 // pushal, popal - push/pop EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI
1025 case X86_INS_PUSHAL:
1026 {
1027 esilprintf (op,
1028 "0,%s,+,"
1029 "%d,%s,-=,%s,%s,=[%d],"
1030 "%d,%s,-=,%s,%s,=[%d],"
1031 "%d,%s,-=,%s,%s,=[%d],"
1032 "%d,%s,-=,%s,%s,=[%d],"
1033 "%d,%s,-=,%s,=[%d],"
1034 "%d,%s,-=,%s,%s,=[%d],"
1035 "%d,%s,-=,%s,%s,=[%d],"
1036 "%d,%s,-=,%s,%s,=[%d]",
1037 sp,
1038 rs, sp, "eax", sp, rs,
1039 rs, sp, "ecx", sp, rs,
1040 rs, sp, "edx", sp, rs,
1041 rs, sp, "ebx", sp, rs,
1042 rs, sp, "esp", rs,
1043 rs, sp, "ebp", sp, rs,
1044 rs, sp, "esi", sp, rs,
1045 rs, sp, "edi", sp, rs
1046 );
1047 }
1048 break;
1049 case X86_INS_ENTER:
1050 case X86_INS_PUSH:
1051 {
1052 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1053 esilprintf (op, "%s,%d,%s,-,=[%d],%d,%s,-=",
1054 r_str_get_fail (dst, "eax"), rs, sp, rs, rs, sp);
1055 }
1056 break;
1057 case X86_INS_PUSHF:
1058 case X86_INS_PUSHFD:
1059 case X86_INS_PUSHFQ:
1060 esilprintf (op, "%d,%s,-=,eflags,%s,=[%d]", rs, sp, sp, rs);
1061 break;
1062 case X86_INS_LEAVE:
1063 esilprintf (op, "%s,%s,=,%s,[%d],%s,=,%d,%s,+=",
1064 bp, sp, sp, rs, bp, rs, sp);
1065 break;
1066 case X86_INS_POPAW:
1067 case X86_INS_POPAL:
1068 {
1069 esilprintf (op,
1070 "%s,[%d],%d,%s,+=,%s,=,"
1071 "%s,[%d],%d,%s,+=,%s,=,"
1072 "%s,[%d],%d,%s,+=,%s,=,"
1073 "%s,[%d],%d,%s,+=,"
1074 "%s,[%d],%d,%s,+=,%s,=,"
1075 "%s,[%d],%d,%s,+=,%s,=,"
1076 "%s,[%d],%d,%s,+=,%s,=,"
1077 "%s,[%d],%d,%s,+=,%s,=,"
1078 "%s,=",
1079 sp, rs, rs, sp, "edi",
1080 sp, rs, rs, sp, "esi",
1081 sp, rs, rs, sp, "ebp",
1082 sp, rs, rs, sp,
1083 sp, rs, rs, sp, "ebx",
1084 sp, rs, rs, sp, "edx",
1085 sp, rs, rs, sp, "ecx",
1086 sp, rs, rs, sp, "eax",
1087 sp
1088 );
1089 }
1090 break;
1091 case X86_INS_POP:
1092 {
1093 switch (INSOP(0).type) {
1094 case X86_OP_MEM:
1095 {
1096 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
1097 esilprintf (op,
1098 "%s,[%d],%s,%d,%s,+=",
1099 sp, rs, dst, rs, sp);
1100 break;
1101 }
1102 case X86_OP_REG:
1103 default:
1104 {
1105 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1106 esilprintf (op,
1107 "%s,[%d],%s,=,%d,%s,+=",
1108 sp, rs, dst, rs, sp);
1109 break;
1110 }
1111 }
1112 }
1113 break;
1114 case X86_INS_POPF:
1115 case X86_INS_POPFD:
1116 case X86_INS_POPFQ:
1117 esilprintf (op, "%s,[%d],eflags,=", sp, rs);
1118 break;
1119 case X86_INS_RET:
1120 case X86_INS_RETF:
1121 case X86_INS_RETFQ:
1122 case X86_INS_IRET:
1123 case X86_INS_IRETD:
1124 case X86_INS_IRETQ:
1125 case X86_INS_SYSRET:
1126 {
1127 int cleanup = 0;
1128 if (INSOPS > 0) {
1129 cleanup = (int)INSOP(0).imm;
1130 }
1131 esilprintf (op, "%s,[%d],%s,=,%d,%s,+=",
1132 sp, rs, pc, rs + cleanup, sp);
1133 }
1134 break;
1135 case X86_INS_INT3:
1136 esilprintf (op, "3,$");
1137 break;
1138 case X86_INS_INT1:
1139 esilprintf (op, "1,$");
1140 break;
1141 case X86_INS_INT:
1142 esilprintf (op, "%d,$",
1143 R_ABS((int)INSOP(0).imm));
1144 break;
1145 case X86_INS_SYSCALL:
1146 esilprintf (op, "rax,()");
1147 break;
1148 case X86_INS_SYSENTER:
1149 case X86_INS_SYSEXIT:
1150 break;
1151 case X86_INS_INTO:
1152 case X86_INS_VMCALL:
1153 case X86_INS_VMMCALL:
1154 esilprintf (op, "%d,$", (int)INSOP(0).imm);
1155 break;
1156 case X86_INS_JL:
1157 case X86_INS_JLE:
1158 case X86_INS_JA:
1159 case X86_INS_JAE:
1160 case X86_INS_JB:
1161 case X86_INS_JBE:
1162 case X86_INS_JCXZ:
1163 case X86_INS_JECXZ:
1164 case X86_INS_JRCXZ:
1165 case X86_INS_JO:
1166 case X86_INS_JNO:
1167 case X86_INS_JS:
1168 case X86_INS_JNS:
1169 case X86_INS_JP:
1170 case X86_INS_JNP:
1171 case X86_INS_JE:
1172 case X86_INS_JNE:
1173 case X86_INS_JG:
1174 case X86_INS_JGE:
1175 case X86_INS_LOOP:
1176 case X86_INS_LOOPE:
1177 case X86_INS_LOOPNE:
1178 {
1179 const char *cnt = (a->bits==16)?"cx":(a->bits==32)?"ecx":"rcx";
1180 dst = getarg (&gop, 0, 2, NULL, DST_AR, NULL);
1181 switch (insn->id) {
1182 case X86_INS_JL:
1183 esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc);
1184 break;
1185 case X86_INS_JLE:
1186 esilprintf (op, "of,sf,^,zf,|,?{,%s,%s,=,}", dst, pc);
1187 break;
1188 case X86_INS_JA:
1189 esilprintf (op, "cf,zf,|,!,?{,%s,%s,=,}",dst, pc);
1190 break;
1191 case X86_INS_JAE:
1192 esilprintf (op, "cf,!,?{,%s,%s,=,}", dst, pc);
1193 break;
1194 case X86_INS_JB:
1195 esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc);
1196 break;
1197 case X86_INS_JO:
1198 esilprintf (op, "of,?{,%s,%s,=,}", dst, pc);
1199 break;
1200 case X86_INS_JNO:
1201 esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc);
1202 break;
1203 case X86_INS_JE:
1204 esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc);
1205 break;
1206 case X86_INS_JGE:
1207 esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc);
1208 break;
1209 case X86_INS_JNE:
1210 esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc);
1211 break;
1212 case X86_INS_JG:
1213 esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc);
1214 break;
1215 case X86_INS_JS:
1216 esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc);
1217 break;
1218 case X86_INS_JNS:
1219 esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc);
1220 break;
1221 case X86_INS_JP:
1222 esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc);
1223 break;
1224 case X86_INS_JNP:
1225 esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc);
1226 break;
1227 case X86_INS_JBE:
1228 esilprintf (op, "zf,cf,|,?{,%s,%s,=,}", dst, pc);
1229 break;
1230 case X86_INS_JCXZ:
1231 esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc);
1232 break;
1233 case X86_INS_JECXZ:
1234 esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc);
1235 break;
1236 case X86_INS_JRCXZ:
1237 esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc);
1238 break;
1239 case X86_INS_LOOP:
1240 esilprintf (op, "1,%s,-=,%s,?{,%s,%s,=,}", cnt, cnt, dst, pc);
1241 break;
1242 case X86_INS_LOOPE:
1243 esilprintf (op, "1,%s,-=,%s,?{,zf,?{,%s,%s,=,},}",
1244 cnt, cnt, dst, pc);
1245 break;
1246 case X86_INS_LOOPNE:
1247 esilprintf (op, "1,%s,-=,%s,?{,zf,!,?{,%s,%s,=,},}",
1248 cnt, cnt, dst, pc);
1249 break;
1250 }
1251 }
1252 break;
1253 case X86_INS_CALL:
1254 {
1255 if (a->read_at && a->bits != 16) {
1256 ut8 thunk[4] = {0};
1257 if (a->read_at (a, (ut64)INSOP (0).imm, thunk, sizeof (thunk))) {
1258 /* 8b xx x4 mov <reg>, dword [esp]
1259 c3 ret
1260 */
1261 if (thunk[0] == 0x8b && thunk[3] == 0xc3
1262 && (thunk[1] & 0xc7) == 4 /* 00rrr100 */
1263 && (thunk[2] & 0x3f) == 0x24) { /* --100100: ignore scale in SIB byte */
1264 ut8 reg = (thunk[1] & 0x38) >> 3;
1265 esilprintf (op, "0x%"PFMT64x",%s,=", addr + op->size,
1266 reg32_to_name (reg));
1267 break;
1268 }
1269 }
1270 }
1271 arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1272 esilprintf (op,
1273 "%s,%s,"
1274 "%d,%s,-=,%s,"
1275 "=[],"
1276 "%s,=",
1277 arg0, pc, rs, sp, sp, pc);
1278 }
1279 break;
1280 case X86_INS_LCALL:
1281 {
1282 arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1283 arg1 = getarg (&gop, 1, 0, NULL, ARG1_AR, NULL);
1284 if (arg1) {
1285 esilprintf (op,
1286 "2,%s,-=,cs,%s,=[2]," // push CS
1287 "%d,%s,-=,%s,%s,=[]," // push IP/EIP
1288 "%s,cs,=," // set CS
1289 "%s,%s,=", // set IP/EIP
1290 sp, sp, rs, sp, pc, sp, arg0, arg1, pc);
1291 } else {
1292 esilprintf (op,
1293 "%s,%s,-=,%d,%s,=[]," // push IP/EIP
1294 "%s,%s,=", // set IP/EIP
1295 sp, sp, rs, sp, arg0, pc);
1296 }
1297 }
1298 break;
1299 case X86_INS_JMP:
1300 case X86_INS_LJMP:
1301 {
1302 src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1303 esilprintf (op, "%s,%s,=", src, pc);
1304 }
1305 // TODO: what if UJMP?
1306 switch (INSOP(0).type) {
1307 case X86_OP_IMM:
1308 if (INSOP(1).type == X86_OP_IMM) {
1309 ut64 seg = INSOP(0).imm;
1310 ut64 off = INSOP(1).imm;
1311 esilprintf (
1312 op,
1313 "0x%"PFMT64x",cs,=,"
1314 "0x%"PFMT64x",%s,=",
1315 seg, off, pc);
1316 } else {
1317 ut64 dst = INSOP(0).imm;
1318 esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc);
1319 }
1320 break;
1321 case X86_OP_MEM:
1322 if (INSOP(0).mem.base == X86_REG_RIP) {
1323 /* nothing here */
1324 } else {
1325 cs_x86_op in = INSOP (0);
1326 if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) {
1327 if (in.mem.segment != X86_REG_INVALID) {
1328 esilprintf (
1329 op,
1330 "4,%s,<<,0x%"PFMT64x",+,[],%s,=",
1331 INSOP(0).mem.segment == X86_REG_ES ? "es"
1332 : INSOP(0).mem.segment == X86_REG_CS ? "cs"
1333 : INSOP(0).mem.segment == X86_REG_DS ? "ds"
1334 : INSOP(0).mem.segment == X86_REG_FS ? "fs"
1335 : INSOP(0).mem.segment == X86_REG_GS ? "gs"
1336 : INSOP(0).mem.segment == X86_REG_SS ? "ss"
1337 : "unknown_segment_register",
1338 (ut64)INSOP(0).mem.disp,
1339 pc);
1340 } else {
1341 esilprintf (
1342 op,
1343 "0x%"PFMT64x",[],%s,=",
1344 (ut64)INSOP(0).mem.disp, pc);
1345 }
1346 }
1347 }
1348 break;
1349 case X86_OP_REG:
1350 {
1351 src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1352 op->src[0] = r_anal_value_new ();
1353 op->src[0]->reg = r_reg_get (a->reg, src, R_REG_TYPE_GPR);
1354 //XXX fallthrough
1355 }
1356 //case X86_OP_FP:
1357 default: // other?
1358 break;
1359 }
1360 break;
1361 case X86_INS_IN:
1362 case X86_INS_INSW:
1363 case X86_INS_INSD:
1364 case X86_INS_INSB:
1365 if (ISIMM (1)) {
1366 op->val = INSOP (1).imm;
1367 }
1368 break;
1369 case X86_INS_OUT:
1370 case X86_INS_OUTSB:
1371 case X86_INS_OUTSD:
1372 case X86_INS_OUTSW:
1373 if (ISIMM (0)) {
1374 op->val = INSOP (0).imm;
1375 }
1376 break;
1377 case X86_INS_VXORPD:
1378 case X86_INS_VXORPS:
1379 case X86_INS_VPXORD:
1380 case X86_INS_VPXORQ:
1381 case X86_INS_VPXOR:
1382 case X86_INS_XORPS:
1383 case X86_INS_KXORW:
1384 case X86_INS_PXOR:
1385 case X86_INS_XOR:
1386 {
1387 ut32 bitsize;
1388 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1389 dst = getarg (&gop, 0, 1, "^", DST_AR, &bitsize);
1390 dst2 = getarg (&gop, 0, 0, NULL, DST2_AR, NULL);
1391 const char *dst_reg64 = r_reg_32_to_64 (a->reg, dst2); // 64-bit destination if exists
1392 if (a->bits == 64 && dst_reg64) {
1393 // (64-bit ^ 32-bit) & 0xFFFF FFFF -> 64-bit, it's alright, higher bytes will be eliminated
1394 // (consider this is operation with 32-bit regs in 64-bit environment).
1395 esilprintf (op, "%s,%s,^,0xffffffff,&,%s,=,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=",
1396 src, dst_reg64, dst_reg64, bitsize - 1);
1397 } else {
1398 esilprintf (op, "%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=",
1399 src, dst, bitsize - 1);
1400 }
1401 }
1402 break;
1403 case X86_INS_BSF:
1404 {
1405 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1406 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1407 int bits = INSOP (0).size * 8;
1408
1409 /*
1410 * Here we first set ZF depending on the source operand
1411 * (and bail out if it's 0), then test each bit in a loop
1412 * by creating a mask on the stack and applying it, returning
1413 * result if bit is set.
1414 */
1415 esilprintf (op, "%s,!,?{,1,zf,=,BREAK,},0,zf,=,"
1416 "%d,DUP,%d,-,1,<<,%s,&,?{,%d,-,%s,=,BREAK,},12,REPEAT",
1417 src, bits, bits, src, bits, dst);
1418 }
1419 break;
1420 case X86_INS_BSR:
1421 {
1422 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1423 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1424 int bits = INSOP (0).size * 8;
1425
1426 /*
1427 * Similar to BSF, except we naturally don't
1428 * need to subtract anything to create
1429 * a mask and return the result.
1430 */
1431 esilprintf (op, "%s,!,?{,1,zf,=,BREAK,},0,zf,=,"
1432 "%d,DUP,1,<<,%s,&,?{,%s,=,BREAK,},12,REPEAT",
1433 src, bits, src, dst);
1434 }
1435 break;
1436 case X86_INS_BSWAP:
1437 {
1438 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1439 if (INSOP(0).size == 4) {
1440 esilprintf (op, "0xff000000,24,%s,NUM,<<,&,24,%s,NUM,>>,|,"
1441 "8,0x00ff0000,%s,NUM,&,>>,|,"
1442 "8,0x0000ff00,%s,NUM,&,<<,|,"
1443 "%s,=", dst, dst, dst, dst, dst);
1444 } else {
1445 esilprintf (op, "0xff00000000000000,56,%s,NUM,<<,&,"
1446 "56,%s,NUM,>>,|,40,0xff000000000000,%s,NUM,&,>>,|,"
1447 "40,0xff00,%s,NUM,&,<<,|,24,0xff0000000000,%s,NUM,&,>>,|,"
1448 "24,0xff0000,%s,NUM,&,<<,|,8,0xff00000000,%s,NUM,&,>>,|,"
1449 "8,0xff000000,%s,NUM,&,<<,|,"
1450 "%s,=", dst, dst, dst, dst, dst, dst, dst, dst, dst);
1451 }
1452 }
1453 break;
1454 case X86_INS_OR:
1455 // The OF and CF flags are cleared; the SF, ZF, and PF flags are
1456 // set according to the result. The state of the AF flag is
1457 // undefined.
1458 {
1459 ut32 bitsize;
1460 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1461 dst = getarg (&gop, 0, 1, "|", DST_AR, &bitsize);
1462 esilprintf (op, "%s,%s,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,0,of,:=,0,cf,:=",
1463 src, dst, bitsize - 1);
1464 }
1465 break;
1466 case X86_INS_INC:
1467 // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
1468 // are set according to the result.
1469 {
1470 ut32 bitsize;
1471 src = getarg (&gop, 0, 1, "++", SRC_AR, &bitsize);
1472 esilprintf (op, "%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,3,$c,af,:=", src, bitsize - 1, bitsize - 1);
1473 }
1474 break;
1475 case X86_INS_DEC:
1476 // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
1477 // are set according to the result.
1478 {
1479 ut32 bitsize;
1480 src = getarg (&gop, 0, 1, "--", SRC_AR, &bitsize);
1481 esilprintf (op, "%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,3,$b,af,:=", src, bitsize - 1, bitsize - 1);
1482 }
1483 break;
1484 case X86_INS_PSUBB:
1485 case X86_INS_PSUBW:
1486 case X86_INS_PSUBD:
1487 case X86_INS_PSUBQ:
1488 case X86_INS_PSUBSB:
1489 case X86_INS_PSUBSW:
1490 case X86_INS_PSUBUSB:
1491 case X86_INS_PSUBUSW:
1492 {
1493 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1494 dst = getarg (&gop, 0, 1, "-", DST_AR, NULL);
1495 esilprintf (op, "%s,%s", src, dst);
1496 }
1497 break;
1498 case X86_INS_SUB:
1499 {
1500 ut32 bitsize;
1501 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1502 dst = getarg (&gop, 0, 1, "-", DST_AR, &bitsize);
1503
1504 if (!bitsize || bitsize > 64) {
1505 break;
1506 }
1507
1508 // Set OF, SF, ZF, AF, PF, and CF flags.
1509 // We use $b rather than $c here as the carry flag really
1510 // represents a "borrow"
1511 esilprintf (op, "%s,%s,%s,0x%"PFMT64x",-,!,%u,$o,^,of,:=,%u,$s,sf,:=,$z,zf,:=,$p,pf,:=,%u,$b,cf,:=,3,$b,af,:=",
1512 src, dst, src, 1ULL << (bitsize - 1), bitsize - 1, bitsize - 1, bitsize);
1513 }
1514 break;
1515 case X86_INS_SBB:
1516 // dst = dst - (src + cf)
1517 {
1518 ut32 bitsize;
1519 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1520 dst = getarg (&gop, 0, 0, NULL, DST_AR, &bitsize);
1521 esilprintf (op, "cf,%s,+,%s,-=,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,%d,$b,cf,:=",
1522 src, dst, bitsize - 1, bitsize - 1, bitsize);
1523 }
1524 break;
1525 case X86_INS_LIDT:
1526 break;
1527 case X86_INS_SIDT:
1528 break;
1529 case X86_INS_RDRAND:
1530 case X86_INS_RDSEED:
1531 case X86_INS_RDMSR:
1532 case X86_INS_RDPMC:
1533 case X86_INS_RDTSC:
1534 case X86_INS_RDTSCP:
1535 case X86_INS_CRC32:
1536 case X86_INS_SHA1MSG1:
1537 case X86_INS_SHA1MSG2:
1538 case X86_INS_SHA1NEXTE:
1539 case X86_INS_SHA1RNDS4:
1540 case X86_INS_SHA256MSG1:
1541 case X86_INS_SHA256MSG2:
1542 case X86_INS_SHA256RNDS2:
1543 case X86_INS_AESDECLAST:
1544 case X86_INS_AESDEC:
1545 case X86_INS_AESENCLAST:
1546 case X86_INS_AESENC:
1547 case X86_INS_AESIMC:
1548 case X86_INS_AESKEYGENASSIST:
1549 // AES instructions
1550 break;
1551 case X86_INS_AND:
1552 case X86_INS_ANDN:
1553 case X86_INS_ANDPD:
1554 case X86_INS_ANDPS:
1555 case X86_INS_ANDNPD:
1556 case X86_INS_ANDNPS:
1557 {
1558 ut32 bitsize;
1559 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1560 dst = getarg (&gop, 0, 1, "&", DST_AR, &bitsize);
1561 dst2 = getarg (&gop, 0, 0, NULL, DST2_AR, NULL);
1562 const char *dst_reg64 = r_reg_32_to_64 (a->reg, dst2); // 64-bit destination if exists
1563 if (a->bits == 64 && dst_reg64) {
1564 // (64-bit & 32-bit) & 0xFFFF FFFF -> 64-bit, it's alright, higher bytes will be eliminated
1565 // (consider this is operation with 32-bit regs in 64-bit environment).
1566 esilprintf (op, "%s,%s,&,0xffffffff,&,%s,=,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=",
1567 src, dst_reg64, dst_reg64, bitsize - 1);
1568 } else {
1569 esilprintf (op, "%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=", src, dst, bitsize - 1);
1570 }
1571 }
1572 break;
1573 case X86_INS_IDIV:
1574 {
1575 arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1576 arg1 = getarg (&gop, 1, 0, NULL, ARG1_AR, NULL);
1577 arg2 = getarg (&gop, 2, 0, NULL, ARG2_AR, NULL);
1578 // DONE handle signedness
1579 // IDIV does not change flags
1580 op->sign = true;
1581 if (!arg2 && !arg1) {
1582 // TODO: IDIV rbx not implemented. this is just a workaround
1583 //
1584 // http://www.tptp.cc/mirrors/siyobik.info/instruction/IDIV.html
1585 // Divides (signed) the value in the AX, DX:AX, or EDX:EAX registers (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers. The source operand can be a general-purpose register or a memory location. The action of this instruction depends on the operand size (dividend/divisor), as shown in the following table:
1586 // IDIV RBX == RDX:RAX /= RBX
1587
1588 //
1589 if (arg0) {
1590 int width = INSOP(0).size;
1591 const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1592 const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1593 const char *r_nume = (width==1)?"ax": r_quot;
1594
1595
1596 esilprintf (op, "%d,%s,~,%d,%s,<<,%s,+,~%%,%d,%s,~,%d,%s,<<,%s,+,~/,%s,=,%s,=",
1597 width*8, arg0, width*8, r_rema, r_nume, width*8, arg0, width*8, r_rema, r_nume, r_quot, r_rema);
1598 }
1599 else {
1600 /* should never happen */
1601 }
1602 } else {
1603 // does this instruction even exist?
1604 int width = INSOP(0).size;
1605 esilprintf (op, "%d,%s,~,%d,%s,~,~/,%s,=", width*8, arg2, width*8, arg1, arg0);
1606 }
1607 }
1608 break;
1609 case X86_INS_DIV:
1610 {
1611 int width = INSOP(0).size;
1612 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1613 const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1614 const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1615 const char *r_nume = (width==1)?"ax": r_quot;
1616 // DIV does not change flags and is unsigned
1617
1618 esilprintf (op, "%s,%d,%s,<<,%s,+,%%,%s,%d,%s,<<,%s,+,/,%s,=,%s,=",
1619 dst, width*8, r_rema, r_nume, dst, width*8, r_rema, r_nume, r_quot, r_rema);
1620 }
1621 break;
1622 case X86_INS_IMUL:
1623 {
1624 arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1625 arg1 = getarg (&gop, 1, 0, NULL, ARG1_AR, NULL);
1626 arg2 = getarg (&gop, 2, 0, NULL, ARG2_AR, NULL);
1627 op->sign = true;
1628 int width = INSOP(0).size;
1629 if (arg2) {
1630 // flags and sign have been handled
1631 esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,%s,=,%s,-,?{,1,1,}{,0,0,},cf,:=,of,:=", width*8, arg2, width*8, arg1, arg0, arg0);
1632 } else {
1633 if (arg1) {
1634 esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,%s,=,%s,-,?{,1,1,}{,0,0,},cf,:=,of,:=", width*8, arg0, width*8, arg1, arg0, arg0);
1635 } else {
1636 if (arg0) {
1637 const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1638 const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1639 const char *r_nume = (width==1)?"ax": r_quot;
1640
1641 if ( width == 1 ) {
1642 esilprintf(op, "0xffffff00,eflags,&=,%s,%s,%%,eflags,|=,%s,%s,*,%s,=,0xff,eflags,&,%s,=,0xffffff00,eflags,&=,2,eflags,|=",
1643 arg0, r_nume, arg0, r_nume, r_quot, r_rema);
1644 } else {
1645 // this got a little bit crazy,
1646 esilprintf (op, "%d,%d,%s,~,%d,%s,~,*,>>,%s,=,%s,%s,*=,%d,%d,%s,~,>>,%s,-,?{,1,1,}{,0,0,},cf,:=,of,:=",
1647 width*8, width*8, arg0, width*8, r_nume, r_rema, arg0, r_nume, width*8, width*8, r_nume, r_rema);
1648 }
1649 }
1650 else {
1651 /* should never happen */
1652 }
1653 }
1654 }
1655 }
1656 break;
1657 case X86_INS_MUL:
1658 {
1659 src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1660 if (src) {
1661 int width = INSOP(0).size;
1662 const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1663 const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1664 const char *r_nume = (width==1)?"ax": r_quot;
1665
1666 if ( width == 1 ) {
1667 esilprintf(op, "0xffffff00,eflags,&=,%s,%s,%%,eflags,|=,%s,%s,*,%s,=,0xff,eflags,&,%s,=,0xffffff00,eflags,&=,2,eflags,|=",
1668 src, r_nume, src, r_nume, r_quot, r_rema);
1669 } else {
1670 esilprintf (op, "%d,%s,%s,*,>>,%s,=,%s,%s,*=,%s,?{,1,1,}{,0,0,},cf,:=,of,:=",
1671 width*8, src, r_nume, r_rema, src, r_nume, r_rema);
1672 }
1673 } else {
1674 /* should never happen */
1675 }
1676 }
1677 break;
1678 case X86_INS_MULX:
1679 case X86_INS_MULPD:
1680 case X86_INS_MULPS:
1681 case X86_INS_MULSD:
1682 case X86_INS_MULSS:
1683 {
1684 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1685 dst = getarg (&gop, 0, 1, "*", DST_AR, NULL);
1686 if (!src && dst) {
1687 switch (dst[0]) {
1688 case 'r':
1689 src = "rax";
1690 break;
1691 case 'e':
1692 src = "eax";
1693 break;
1694 default:
1695 src = "al";
1696 break;
1697 }
1698 }
1699 esilprintf (op, "%s,%s", src, dst);
1700 }
1701 break;
1702 case X86_INS_NEG:
1703 {
1704 ut32 bitsize;
1705 src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1706 dst = getarg (&gop, 0, 1, NULL, DST_AR, &bitsize);
1707 ut64 xor = 0;
1708 switch (bitsize) {
1709 case 8:
1710 xor = 0xff;
1711 break;
1712 case 16:
1713 xor = 0xffff;
1714 break;
1715 case 32:
1716 xor = 0xffffffff;
1717 break;
1718 case 64:
1719 xor = 0xffffffffffffffff;
1720 break;
1721 default:
1722 eprintf ("Neg: Unhandled bitsize %d\n", bitsize);
1723 }
1724 esilprintf (op, "%s,!,!,cf,:=,%s,0x%"PFMT64x",^,1,+,%s,$z,zf,:=,0,of,:=,%d,$s,sf,:=,%d,$o,pf,:=",
1725 src, src, xor, dst, bitsize - 1, bitsize - 1);
1726 }
1727 break;
1728 case X86_INS_NOT:
1729 {
1730 dst = getarg (&gop, 0, 1, "^", DST_AR, NULL);
1731 esilprintf (op, "-1,%s", dst);
1732 }
1733 break;
1734 case X86_INS_PACKSSDW:
1735 case X86_INS_PACKSSWB:
1736 case X86_INS_PACKUSWB:
1737 break;
1738 case X86_INS_PADDB:
1739 case X86_INS_PADDD:
1740 case X86_INS_PADDW:
1741 case X86_INS_PADDSB:
1742 case X86_INS_PADDSW:
1743 case X86_INS_PADDUSB:
1744 case X86_INS_PADDUSW:
1745 break;
1746 case X86_INS_XCHG:
1747 {
1748 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1749 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1750 if (INSOP(0).type == X86_OP_MEM) {
1751 dst2 = getarg (&gop, 0, 1, NULL, DST2_AR, NULL);
1752 esilprintf (op,
1753 "%s,%s,^,%s,=,"
1754 "%s,%s,^,%s,"
1755 "%s,%s,^,%s,=",
1756 dst, src, src, // x = x ^ y
1757 src, dst, dst2, // y = y ^ x
1758 dst, src, src); // x = x ^ y
1759 } else {
1760 esilprintf (op,
1761 "%s,%s,^,%s,=,"
1762 "%s,%s,^,%s,=,"
1763 "%s,%s,^,%s,=",
1764 dst, src, src, // x = x ^ y
1765 src, dst, dst, // y = y ^ x
1766 dst, src, src); // x = x ^ y
1767 //esilprintf (op, "%s,%s,%s,=,%s", src, dst, src, dst);
1768 }
1769 }
1770 break;
1771 case X86_INS_XADD: /* xchg + add */
1772 {
1773 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1774 dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1775 dstAdd = getarg (&gop, 0, 1, "+", DSTADD_AR, NULL);
1776 if (INSOP(0).type == X86_OP_MEM) {
1777 dst2 = getarg (&gop, 0, 1, NULL, DST2_AR, NULL);
1778 esilprintf (op,
1779 "%s,%s,^,%s,=,"
1780 "%s,%s,^,%s,"
1781 "%s,%s,^,%s,=,"
1782 "%s,%s",
1783 dst, src, src, // x = x ^ y
1784 src, dst, dst2, // y = y ^ x
1785 dst, src, src, // x = x ^ y
1786 src, dstAdd);
1787 } else {
1788 esilprintf (op,
1789 "%s,%s,^,%s,=,"
1790 "%s,%s,^,%s,=,"
1791 "%s,%s,^,%s,=,"
1792 "%s,%s",
1793 dst, src, src, // x = x ^ y
1794 src, dst, dst, // y = y ^ x
1795 dst, src, src, // x = x ^ y
1796 src, dstAdd);
1797 //esilprintf (op, "%s,%s,%s,=,%s", src, dst, src, dst);
1798 }
1799 }
1800 break;
1801 case X86_INS_FADD:
1802 #if CS_API_MAJOR > 4
1803 case X86_INS_PFADD:
1804 #else
1805 case X86_INS_FADDP:
1806 #endif
1807 break;
1808 case X86_INS_ADDPS:
1809 case X86_INS_ADDSD:
1810 case X86_INS_ADDSS:
1811 case X86_INS_ADDSUBPD:
1812 case X86_INS_ADDSUBPS:
1813 case X86_INS_ADDPD:
1814 // The OF, SF, ZF, AF, CF, and PF flags are set according to the
1815 // result.
1816 if (INSOP(0).type == X86_OP_MEM) {
1817 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1818 src2 = getarg (&gop, 0, 0, NULL, SRC2_AR, NULL);
1819 dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
1820 esilprintf (op, "%s,%s,+,%s", src, src2, dst);
1821 } else {
1822 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1823 dst = getarg (&gop, 0, 1, "+", DST_AR, NULL);
1824 esilprintf (op, "%s,%s", src, dst);
1825 }
1826 break;
1827 case X86_INS_ADD:
1828 // The OF, SF, ZF, AF, CF, and PF flags are set according to the
1829 // result.
1830 {
1831 ut32 bitsize;
1832 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1833 dst = getarg (&gop, 0, 1, "+", DST_AR, &bitsize);
1834 esilprintf (op, "%s,%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,%d,$c,cf,:=,$p,pf,:=,3,$c,af,:=",
1835 src, dst, bitsize - 1, bitsize - 1, bitsize - 1);
1836 }
1837 break;
1838 case X86_INS_ADC:
1839 {
1840 ut32 bitsize;
1841 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1842 dst = getarg (&gop, 0, 1, "+", DST_AR, &bitsize);
1843 // dst = dst + src + cf
1844 // NOTE: We would like to add the carry first before adding the
1845 // source to ensure that the flag computation from $c belongs
1846 // to the operation of adding dst += src rather than the one
1847 // that adds carry (as esil only keeps track of the last
1848 // addition to set the flags).
1849 esilprintf (op, "cf,%s,+,%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,%d,$c,cf,:=,$p,pf,:=,3,$c,af,:=",
1850 src, dst, bitsize - 1, bitsize - 1, bitsize - 1);
1851 }
1852 break;
1853 /* Direction flag */
1854 case X86_INS_CLD:
1855 esilprintf (op, "0,df,:=");
1856 break;
1857 case X86_INS_STD:
1858 esilprintf (op, "1,df,:=");
1859 break;
1860 case X86_INS_SUBSD: //cvtss2sd
1861 case X86_INS_CVTSS2SD: //cvtss2sd
1862 break;
1863 case X86_INS_BT:
1864 case X86_INS_BTC:
1865 case X86_INS_BTR:
1866 case X86_INS_BTS:
1867 if (INSOP(0).type == X86_OP_MEM && INSOP(1).type == X86_OP_REG) {
1868 int width = INSOP(0).size;
1869 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1870 dst_r = getarg (&gop, 0, 2 /* use the address without loading */, NULL, DST_R_AR, NULL);
1871 esilprintf (op, "0,cf,:=,%d,%s,%%,1,<<,%d,%s,/,%s,+,[%d],&,?{,1,cf,:=,}",
1872 width * 8, src, width * 8, src, dst_r, width);
1873 switch (insn->id) {
1874 case X86_INS_BTS:
1875 case X86_INS_BTC:
1876 r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,%d,%s,/,%s,+,%c=[%d]",
1877 width * 8, src, width * 8, src, dst_r,
1878 (insn->id == X86_INS_BTS)?'|':'^', width);
1879 break;
1880 case X86_INS_BTR:
1881 dst_w = getarg (&gop, 0, 1, "&", DST_R_AR, NULL);
1882 r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,-1,^,%d,%s,/,%s,+,&=[%d]",
1883 width * 8, src, width * 8, src, dst_r, width);
1884 break;
1885 }
1886 } else {
1887 int width = INSOP(0).size;
1888 src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1889 dst_r = getarg (&gop, 0, 0, NULL, DST_R_AR, NULL);
1890 esilprintf (op, "0,cf,:=,%d,%s,%%,1,<<,%s,&,?{,1,cf,:=,}",
1891 width * 8, src, dst_r);
1892 switch (insn->id) {
1893 case X86_INS_BTS:
1894 case X86_INS_BTC:
1895 dst_w = getarg (&gop, 0, 1, (insn->id == X86_INS_BTS)?"|":"^", DST_R_AR, NULL);
1896 r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,%s", width * 8, src, dst_w);
1897 break;
1898 case X86_INS_BTR:
1899 dst_w = getarg (&gop, 0, 1, "&", DST_R_AR, NULL);
1900 r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,-1,^,%s", width * 8, src, dst_w);
1901 break;
1902 }
1903 }
1904 break;
1905 }
1906
1907 if (op->prefix & R_ANAL_OP_PREFIX_REP) {
1908 r_strbuf_prepend (&op->esil, ",!,?{,BREAK,},");
1909 r_strbuf_prepend (&op->esil, counter);
1910 if (repe) {
1911 r_strbuf_appendf (&op->esil, ",%s,--=,zf,!,?{,BREAK,},0,GOTO", counter);
1912 } else {
1913 r_strbuf_appendf (&op->esil, ",%s,--=,0,GOTO", counter);
1914 }
1915 }
1916 if (op->prefix & R_ANAL_OP_PREFIX_REPNE) {
1917 r_strbuf_prepend (&op->esil, ",!,?{,BREAK,},");
1918 r_strbuf_prepend (&op->esil, counter);
1919 r_strbuf_appendf (&op->esil, ",%s,--=,zf,?{,BREAK,},0,GOTO", counter);
1920 }
1921 }
1922
cs_reg2reg(RReg * reg,csh * h,int id)1923 static RRegItem *cs_reg2reg(RReg *reg, csh *h, int id) {
1924 if (id == X86_REG_INVALID) {
1925 return NULL;
1926 }
1927 return r_reg_get (reg, (char *)cs_reg_name (*h, id), -1);
1928 }
1929
set_access_info(RReg * reg,RAnalOp * op,csh * handle,cs_insn * insn,int mode)1930 static void set_access_info(RReg *reg, RAnalOp *op, csh *handle, cs_insn *insn, int mode) {
1931 int i;
1932 RAnalValue *val;
1933 int regsz;
1934 x86_reg sp;
1935 switch (mode) {
1936 case CS_MODE_64:
1937 regsz = 8;
1938 sp = X86_REG_RSP;
1939 break;
1940 case CS_MODE_32:
1941 regsz = 4;
1942 sp = X86_REG_ESP;
1943 break;
1944 case CS_MODE_16:
1945 regsz = 4;
1946 sp = X86_REG_ESP;
1947 break;
1948 default:
1949 regsz = 4;
1950 sp = X86_REG_ESP;
1951 break;
1952 }
1953 RList *ret = r_list_newf ((RListFree)r_anal_value_free);
1954 if (!ret) {
1955 return;
1956 }
1957
1958 // PC register
1959 val = r_anal_value_new ();
1960 val->type = R_ANAL_VAL_REG;
1961 val->access = R_ANAL_ACC_W;
1962 val->reg = cs_reg2reg (reg, handle, X86_REG_RIP);
1963 r_list_append (ret, val);
1964
1965 #if CS_API_MAJOR >= 4
1966 // Register access info
1967 cs_regs regs_read, regs_write;
1968 ut8 read_count, write_count;
1969 if (cs_regs_access (*handle, insn, regs_read, &read_count, regs_write, &write_count) == 0) {
1970 if (read_count > 0) {
1971 for (i = 0; i < read_count; i++) {
1972 val = r_anal_value_new ();
1973 val->type = R_ANAL_VAL_REG;
1974 val->access = R_ANAL_ACC_R;
1975 val->reg = cs_reg2reg (reg, handle, regs_read[i]);
1976 r_list_append (ret, val);
1977 }
1978 }
1979 if (write_count > 0) {
1980 for (i = 0; i < write_count; i++) {
1981 val = r_anal_value_new ();
1982 val->type = R_ANAL_VAL_REG;
1983 val->access = R_ANAL_ACC_W;
1984 val->reg = cs_reg2reg (reg, handle, regs_write[i]);
1985 r_list_append (ret, val);
1986 }
1987 }
1988 }
1989 #endif
1990
1991 switch (insn->id) {
1992 case X86_INS_PUSH:
1993 val = r_anal_value_new ();
1994 val->type = R_ANAL_VAL_MEM;
1995 val->access = R_ANAL_ACC_W;
1996 val->reg = cs_reg2reg (reg, handle, sp);
1997 val->delta = -INSOP(0).size;
1998 val->memref = INSOP(0).size;
1999 r_list_append (ret, val);
2000 break;
2001 case X86_INS_PUSHAW:
2002 // AX, CX, DX, BX, SP, BP, SI, DI
2003 val = r_anal_value_new ();
2004 val->type = R_ANAL_VAL_MEM;
2005 val->access = R_ANAL_ACC_W;
2006 val->reg = cs_reg2reg (reg, handle, sp);
2007 val->delta = -16;
2008 val->memref = 16;
2009 r_list_append (ret, val);
2010 break;
2011 case X86_INS_PUSHAL:
2012 // EAX, ECX, EDX, EBX, EBP, ESP, EBP, ESI, EDI
2013 val = r_anal_value_new ();
2014 val->type = R_ANAL_VAL_MEM;
2015 val->access = R_ANAL_ACC_W;
2016 val->reg = cs_reg2reg (reg, handle, sp);
2017 val->delta = -32;
2018 val->memref = 32;
2019 r_list_append (ret, val);
2020 break;
2021 case X86_INS_PUSHF:
2022 val = r_anal_value_new ();
2023 val->type = R_ANAL_VAL_MEM;
2024 val->access = R_ANAL_ACC_W;
2025 val->reg = cs_reg2reg (reg, handle, sp);
2026 val->delta = -2;
2027 val->memref = 2;
2028 r_list_append (ret, val);
2029 break;
2030 case X86_INS_PUSHFD:
2031 val = r_anal_value_new ();
2032 val->type = R_ANAL_VAL_MEM;
2033 val->access = R_ANAL_ACC_W;
2034 val->reg = cs_reg2reg (reg, handle, sp);
2035 val->delta = -4;
2036 val->memref = 4;
2037 r_list_append (ret, val);
2038 break;
2039 case X86_INS_PUSHFQ:
2040 val = r_anal_value_new ();
2041 val->type = R_ANAL_VAL_MEM;
2042 val->access = R_ANAL_ACC_W;
2043 val->reg = cs_reg2reg (reg, handle, sp);
2044 val->delta = -8;
2045 val->memref = 8;
2046 r_list_append (ret, val);
2047 break;
2048 case X86_INS_CALL:
2049 case X86_INS_LCALL:
2050 val = r_anal_value_new ();
2051 val->type = R_ANAL_VAL_MEM;
2052 val->access = R_ANAL_ACC_W;
2053 val->reg = cs_reg2reg (reg, handle, sp);
2054 val->delta = -regsz;
2055 val->memref = regsz;
2056 r_list_append (ret, val);
2057 break;
2058 default:
2059 break;
2060 }
2061
2062 // Memory access info based on operands
2063 for (i = 0; i < INSOPS; i++) {
2064 if (INSOP (i).type == X86_OP_MEM) {
2065 val = r_anal_value_new ();
2066 val->type = R_ANAL_VAL_MEM;
2067 #if CS_API_MAJOR >= 4
2068 switch (INSOP (i).access) {
2069 case CS_AC_READ:
2070 val->access = R_ANAL_ACC_R;
2071 break;
2072 case CS_AC_WRITE:
2073 val->access = R_ANAL_ACC_W;
2074 break;
2075 case CS_AC_INVALID:
2076 val->access = R_ANAL_ACC_UNKNOWN;
2077 break;
2078 }
2079 #else
2080 val->access = R_ANAL_ACC_UNKNOWN;
2081 #endif
2082 val->mul = INSOP (i).mem.scale;
2083 val->delta = INSOP (i).mem.disp;
2084 if (INSOP(0).mem.base == X86_REG_RIP ||
2085 INSOP(0).mem.base == X86_REG_EIP) {
2086 val->delta += insn->size;
2087 }
2088 val->memref = INSOP (i).size;
2089 val->seg = cs_reg2reg (reg, handle, INSOP (i).mem.segment);
2090 val->reg = cs_reg2reg (reg, handle, INSOP (i).mem.base);
2091 val->regdelta = cs_reg2reg (reg, handle, INSOP (i).mem.index);
2092 r_list_append (ret, val);
2093 }
2094 }
2095
2096 op->access = ret;
2097 }
2098
2099 #define CREATE_SRC_DST(op) \
2100 (op)->src[0] = r_anal_value_new (); \
2101 (op)->src[1] = r_anal_value_new (); \
2102 (op)->src[2] = r_anal_value_new (); \
2103 (op)->dst = r_anal_value_new ();
2104
set_src_dst(RReg * reg,RAnalValue * val,csh * handle,cs_insn * insn,int x)2105 static void set_src_dst(RReg *reg, RAnalValue *val, csh *handle, cs_insn *insn, int x) {
2106 switch (INSOP (x).type) {
2107 case X86_OP_MEM:
2108 val->mul = INSOP (x).mem.scale;
2109 val->delta = INSOP (x).mem.disp;
2110 val->memref = INSOP (x).size;
2111 val->seg = cs_reg2reg (reg, handle, INSOP (x).mem.segment);
2112 val->reg = cs_reg2reg (reg, handle, INSOP (x).mem.base);
2113 val->regdelta = cs_reg2reg (reg, handle, INSOP (x).mem.index);
2114 break;
2115 case X86_OP_REG:
2116 val->reg = cs_reg2reg (reg, handle, INSOP (x).reg);
2117 break;
2118 case X86_OP_IMM:
2119 val->imm = INSOP (x).imm;
2120 break;
2121 default:
2122 break;
2123 }
2124 }
2125
op_fillval(RAnal * a,RAnalOp * op,csh * handle,cs_insn * insn,int mode)2126 static void op_fillval(RAnal *a, RAnalOp *op, csh *handle, cs_insn *insn, int mode) {
2127 set_access_info (a->reg, op, handle, insn, mode);
2128 switch (op->type & R_ANAL_OP_TYPE_MASK) {
2129 case R_ANAL_OP_TYPE_MOV:
2130 case R_ANAL_OP_TYPE_CMP:
2131 case R_ANAL_OP_TYPE_LEA:
2132 case R_ANAL_OP_TYPE_CMOV:
2133 case R_ANAL_OP_TYPE_SHL:
2134 case R_ANAL_OP_TYPE_SHR:
2135 case R_ANAL_OP_TYPE_SAL:
2136 case R_ANAL_OP_TYPE_SAR:
2137 case R_ANAL_OP_TYPE_ROL:
2138 case R_ANAL_OP_TYPE_ROR:
2139 case R_ANAL_OP_TYPE_ADD:
2140 case R_ANAL_OP_TYPE_AND:
2141 case R_ANAL_OP_TYPE_OR:
2142 case R_ANAL_OP_TYPE_XOR:
2143 case R_ANAL_OP_TYPE_SUB:
2144 case R_ANAL_OP_TYPE_XCHG:
2145 case R_ANAL_OP_TYPE_POP:
2146 case R_ANAL_OP_TYPE_NOT:
2147 case R_ANAL_OP_TYPE_ACMP:
2148 CREATE_SRC_DST (op);
2149 set_src_dst (a->reg, op->dst, handle, insn, 0);
2150 set_src_dst (a->reg, op->src[0], handle, insn, 1);
2151 set_src_dst (a->reg, op->src[1], handle, insn, 2);
2152 set_src_dst (a->reg, op->src[2], handle, insn, 3);
2153 break;
2154 case R_ANAL_OP_TYPE_UPUSH:
2155 if ((op->type & R_ANAL_OP_TYPE_REG)) {
2156 CREATE_SRC_DST (op);
2157 set_src_dst (a->reg, op->src[0], handle, insn, 0);
2158 }
2159 break;
2160 default:
2161 break;
2162 }
2163 }
2164
op0_memimmhandle(RAnalOp * op,cs_insn * insn,ut64 addr,int regsz)2165 static void op0_memimmhandle(RAnalOp *op, cs_insn *insn, ut64 addr, int regsz) {
2166 op->ptr = UT64_MAX;
2167 switch (INSOP(0).type) {
2168 case X86_OP_MEM:
2169 op->cycles = CYCLE_MEM;
2170 op->disp = INSOP(0).mem.disp;
2171 if (!op->disp) {
2172 op->disp = UT64_MAX;
2173 }
2174 op->refptr = INSOP(0).size;
2175 if (INSOP(0).mem.base == X86_REG_RIP) {
2176 op->ptr = addr + insn->size + op->disp;
2177 } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) {
2178 op->type |= R_ANAL_OP_TYPE_REG;
2179 op->stackop = R_ANAL_STACK_SET;
2180 op->stackptr = regsz;
2181 } else if (INSOP(0).mem.segment == X86_REG_INVALID && INSOP(0).mem.base == X86_REG_INVALID
2182 && INSOP(0).mem.index == X86_REG_INVALID && INSOP(0).mem.scale == 1) { // [<addr>]
2183 op->ptr = op->disp;
2184 if (op->ptr < 0x1000) {
2185 op->ptr = UT64_MAX;
2186 }
2187 }
2188 if (INSOP(1).type == X86_OP_IMM) {
2189 op->val = INSOP(1).imm;
2190 }
2191 break;
2192 case X86_OP_REG:
2193 if (INSOP(1).type == X86_OP_IMM) {
2194 // (INSOP(0).reg != X86_REG_RSP) && (INSOP(0).reg != X86_REG_ESP)) {
2195 op->val = INSOP(1).imm;
2196 }
2197 break;
2198 default:
2199 break;
2200 }
2201 }
2202
op1_memimmhandle(RAnalOp * op,cs_insn * insn,ut64 addr,int regsz)2203 static void op1_memimmhandle(RAnalOp *op, cs_insn *insn, ut64 addr, int regsz) {
2204 if (op->refptr < 1 || op->ptr == UT64_MAX) {
2205 switch (INSOP(1).type) {
2206 case X86_OP_MEM:
2207 op->disp = INSOP(1).mem.disp;
2208 op->refptr = INSOP(1).size;
2209 if (INSOP(1).mem.base == X86_REG_RIP) {
2210 op->ptr = addr + insn->size + op->disp;
2211 } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) {
2212 op->stackop = R_ANAL_STACK_GET;
2213 op->stackptr = regsz;
2214 } else if (INSOP(1).mem.segment == X86_REG_INVALID && INSOP(1).mem.base == X86_REG_INVALID
2215 && INSOP(1).mem.index == X86_REG_INVALID && INSOP(1).mem.scale == 1) { // [<addr>]
2216 op->ptr = op->disp;
2217 }
2218 break;
2219 case X86_OP_IMM:
2220 if ((INSOP (1).imm > 10) &&
2221 (INSOP(0).reg != X86_REG_RSP) && (INSOP(0).reg != X86_REG_ESP)) {
2222 op->ptr = INSOP (1).imm;
2223 }
2224 break;
2225 default:
2226 break;
2227 }
2228 }
2229 }
2230
op_stackidx(RAnalOp * op,cs_insn * insn,bool minus)2231 static void op_stackidx(RAnalOp *op, cs_insn *insn, bool minus) {
2232 if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) {
2233 if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) {
2234 op->stackop = R_ANAL_STACK_INC;
2235 if (minus) {
2236 op->stackptr = -INSOP(1).imm;
2237 } else {
2238 op->stackptr = INSOP(1).imm;
2239 }
2240 }
2241 }
2242 }
2243
set_opdir(RAnalOp * op,cs_insn * insn)2244 static void set_opdir(RAnalOp *op, cs_insn *insn) {
2245 switch (op->type & R_ANAL_OP_TYPE_MASK) {
2246 case R_ANAL_OP_TYPE_MOV:
2247 switch (INSOP(0).type) {
2248 case X86_OP_MEM:
2249 op->direction = R_ANAL_OP_DIR_WRITE;
2250 break;
2251 case X86_OP_REG:
2252 if (INSOP(1).type == X86_OP_MEM) {
2253 op->direction = R_ANAL_OP_DIR_READ;
2254 }
2255 break;
2256 default:
2257 break;
2258 }
2259 break;
2260 case R_ANAL_OP_TYPE_LEA:
2261 op->direction = R_ANAL_OP_DIR_REF;
2262 break;
2263 case R_ANAL_OP_TYPE_CALL:
2264 case R_ANAL_OP_TYPE_JMP:
2265 case R_ANAL_OP_TYPE_UJMP:
2266 case R_ANAL_OP_TYPE_UCALL:
2267 op->direction = R_ANAL_OP_DIR_EXEC;
2268 break;
2269 default:
2270 break;
2271 }
2272 }
2273
anop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,csh * handle,cs_insn * insn)2274 static void anop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
2275 struct Getarg gop = {
2276 .handle = *handle,
2277 .insn = insn,
2278 .bits = a->bits
2279 };
2280 int regsz = 4;
2281 switch (a->bits) {
2282 case 64: regsz = 8; break;
2283 case 16: regsz = 2; break;
2284 default: regsz = 4; break; // 32
2285 }
2286 switch (insn->id) {
2287 case X86_INS_FNOP:
2288 op->family = R_ANAL_OP_FAMILY_FPU;
2289 /* fallthru */
2290 case X86_INS_NOP:
2291 case X86_INS_PAUSE:
2292 op->type = R_ANAL_OP_TYPE_NOP;
2293 break;
2294 case X86_INS_HLT:
2295 op->type = R_ANAL_OP_TYPE_TRAP;
2296 break;
2297 case X86_INS_FBLD:
2298 case X86_INS_FBSTP:
2299 case X86_INS_FCOMPP:
2300 case X86_INS_FDECSTP:
2301 case X86_INS_FEMMS:
2302 case X86_INS_FFREE:
2303 case X86_INS_FICOM:
2304 case X86_INS_FICOMP:
2305 case X86_INS_FINCSTP:
2306 case X86_INS_FNCLEX:
2307 case X86_INS_FNINIT:
2308 case X86_INS_FNSTCW:
2309 case X86_INS_FNSTSW:
2310 case X86_INS_FPATAN:
2311 case X86_INS_FPREM:
2312 case X86_INS_FPREM1:
2313 case X86_INS_FPTAN:
2314 #if CS_API_MAJOR >= 4
2315 case X86_INS_FFREEP:
2316 #endif
2317 case X86_INS_FRNDINT:
2318 case X86_INS_FRSTOR:
2319 case X86_INS_FNSAVE:
2320 case X86_INS_FSCALE:
2321 case X86_INS_FSETPM:
2322 case X86_INS_FSINCOS:
2323 case X86_INS_FNSTENV:
2324 case X86_INS_FXAM:
2325 case X86_INS_FXSAVE:
2326 case X86_INS_FXSAVE64:
2327 case X86_INS_FXTRACT:
2328 case X86_INS_FYL2X:
2329 case X86_INS_FYL2XP1:
2330 case X86_INS_FISTTP:
2331 case X86_INS_FSQRT:
2332 case X86_INS_FXCH:
2333 op->family = R_ANAL_OP_FAMILY_FPU;
2334 op->type = R_ANAL_OP_TYPE_STORE;
2335 break;
2336 case X86_INS_FTST:
2337 case X86_INS_FUCOMI:
2338 case X86_INS_FUCOMPP:
2339 case X86_INS_FUCOMP:
2340 case X86_INS_FUCOM:
2341 op->family = R_ANAL_OP_FAMILY_FPU;
2342 op->type = R_ANAL_OP_TYPE_CMP;
2343 break;
2344 case X86_INS_BT:
2345 case X86_INS_BTC:
2346 case X86_INS_BTR:
2347 case X86_INS_BTS:
2348 op->type = R_ANAL_OP_TYPE_CMP;
2349 break;
2350 case X86_INS_FABS:
2351 op->type = R_ANAL_OP_TYPE_ABS;
2352 op->family = R_ANAL_OP_FAMILY_FPU;
2353 break;
2354 case X86_INS_FLDCW:
2355 case X86_INS_FLDENV:
2356 case X86_INS_FLDL2E:
2357 case X86_INS_FLDL2T:
2358 case X86_INS_FLDLG2:
2359 case X86_INS_FLDLN2:
2360 case X86_INS_FLDPI:
2361 case X86_INS_FLDZ:
2362 case X86_INS_FLD1:
2363 case X86_INS_FLD:
2364 op->type = R_ANAL_OP_TYPE_LOAD;
2365 op->family = R_ANAL_OP_FAMILY_FPU;
2366 break;
2367 case X86_INS_FIST:
2368 case X86_INS_FISTP:
2369 case X86_INS_FST:
2370 case X86_INS_FSTP:
2371 case X86_INS_FSTPNCE:
2372 case X86_INS_FXRSTOR:
2373 case X86_INS_FXRSTOR64:
2374 op->type = R_ANAL_OP_TYPE_STORE;
2375 op->family = R_ANAL_OP_FAMILY_FPU;
2376 break;
2377 case X86_INS_FDIV:
2378 case X86_INS_FIDIV:
2379 case X86_INS_FDIVP:
2380 case X86_INS_FDIVR:
2381 case X86_INS_FIDIVR:
2382 case X86_INS_FDIVRP:
2383 op->type = R_ANAL_OP_TYPE_DIV;
2384 op->family = R_ANAL_OP_FAMILY_FPU;
2385 break;
2386 case X86_INS_FSUBR:
2387 case X86_INS_FISUBR:
2388 case X86_INS_FSUBRP:
2389 case X86_INS_FSUB:
2390 case X86_INS_FISUB:
2391 case X86_INS_FSUBP:
2392 op->type = R_ANAL_OP_TYPE_SUB;
2393 op->family = R_ANAL_OP_FAMILY_FPU;
2394 break;
2395 case X86_INS_FMUL:
2396 case X86_INS_FIMUL:
2397 case X86_INS_FMULP:
2398 op->type = R_ANAL_OP_TYPE_MUL;
2399 op->family = R_ANAL_OP_FAMILY_FPU;
2400 break;
2401 case X86_INS_CLI:
2402 case X86_INS_STI:
2403 op->type = R_ANAL_OP_TYPE_MOV;
2404 op->family = R_ANAL_OP_FAMILY_PRIV;
2405 break;
2406 case X86_INS_CLC:
2407 case X86_INS_STC:
2408 case X86_INS_CLAC:
2409 case X86_INS_CLGI:
2410 case X86_INS_CLTS:
2411 #if CS_API_MAJOR >= 4
2412 case X86_INS_CLWB:
2413 #endif
2414 case X86_INS_STAC:
2415 case X86_INS_STGI:
2416 op->type = R_ANAL_OP_TYPE_MOV;
2417 break;
2418 // cmov
2419 case X86_INS_SETNE:
2420 case X86_INS_SETNO:
2421 case X86_INS_SETNP:
2422 case X86_INS_SETNS:
2423 case X86_INS_SETO:
2424 case X86_INS_SETP:
2425 case X86_INS_SETS:
2426 case X86_INS_SETL:
2427 case X86_INS_SETLE:
2428 case X86_INS_SETB:
2429 case X86_INS_SETG:
2430 case X86_INS_SETAE:
2431 case X86_INS_SETA:
2432 case X86_INS_SETBE:
2433 case X86_INS_SETE:
2434 case X86_INS_SETGE:
2435 op->type = R_ANAL_OP_TYPE_CMOV;
2436 op->family = 0;
2437 break;
2438 // cmov
2439 case X86_INS_FCMOVBE:
2440 case X86_INS_FCMOVB:
2441 case X86_INS_FCMOVNBE:
2442 case X86_INS_FCMOVNB:
2443 case X86_INS_FCMOVE:
2444 case X86_INS_FCMOVNE:
2445 case X86_INS_FCMOVNU:
2446 case X86_INS_FCMOVU:
2447 op->family = R_ANAL_OP_FAMILY_FPU;
2448 op->type = R_ANAL_OP_TYPE_CMOV;
2449 break;
2450 case X86_INS_CMOVA:
2451 case X86_INS_CMOVAE:
2452 case X86_INS_CMOVB:
2453 case X86_INS_CMOVBE:
2454 case X86_INS_CMOVE:
2455 case X86_INS_CMOVG:
2456 case X86_INS_CMOVGE:
2457 case X86_INS_CMOVL:
2458 case X86_INS_CMOVLE:
2459 case X86_INS_CMOVNE:
2460 case X86_INS_CMOVNO:
2461 case X86_INS_CMOVNP:
2462 case X86_INS_CMOVNS:
2463 case X86_INS_CMOVO:
2464 case X86_INS_CMOVP:
2465 case X86_INS_CMOVS:
2466 op->type = R_ANAL_OP_TYPE_CMOV;
2467 break;
2468 case X86_INS_STOSB:
2469 case X86_INS_STOSD:
2470 case X86_INS_STOSQ:
2471 case X86_INS_STOSW:
2472 op->type = R_ANAL_OP_TYPE_STORE;
2473 break;
2474 case X86_INS_LODSB:
2475 case X86_INS_LODSD:
2476 case X86_INS_LODSQ:
2477 case X86_INS_LODSW:
2478 op->type = R_ANAL_OP_TYPE_LOAD;
2479 break;
2480 case X86_INS_PALIGNR:
2481 case X86_INS_VALIGND:
2482 case X86_INS_VALIGNQ:
2483 case X86_INS_VPALIGNR:
2484 op->type = R_ANAL_OP_TYPE_AND;
2485 op->family = R_ANAL_OP_FAMILY_CPU;
2486 break;
2487 case X86_INS_CPUID:
2488 op->type = R_ANAL_OP_TYPE_MOV;
2489 op->family = R_ANAL_OP_FAMILY_CPU;
2490 break;
2491 case X86_INS_SFENCE:
2492 case X86_INS_LFENCE:
2493 case X86_INS_MFENCE:
2494 op->type = R_ANAL_OP_TYPE_NOP;
2495 op->family = R_ANAL_OP_FAMILY_THREAD;
2496 break;
2497 // mov
2498 case X86_INS_MOVNTQ:
2499 case X86_INS_MOVNTDQA:
2500 case X86_INS_MOVNTDQ:
2501 case X86_INS_MOVNTI:
2502 case X86_INS_MOVNTPD:
2503 case X86_INS_MOVNTPS:
2504 case X86_INS_MOVNTSD:
2505 case X86_INS_MOVNTSS:
2506 case X86_INS_VMOVNTDQA:
2507 case X86_INS_VMOVNTDQ:
2508 case X86_INS_VMOVNTPD:
2509 case X86_INS_VMOVNTPS:
2510 op->type = R_ANAL_OP_TYPE_MOV;
2511 op->family = R_ANAL_OP_FAMILY_SSE;
2512 break;
2513 case X86_INS_PCMPEQB:
2514 case X86_INS_PCMPEQD:
2515 case X86_INS_PCMPEQW:
2516 case X86_INS_PCMPGTB:
2517 case X86_INS_PCMPGTD:
2518 case X86_INS_PCMPGTW:
2519 case X86_INS_PCMPEQQ:
2520 case X86_INS_PCMPESTRI:
2521 case X86_INS_PCMPESTRM:
2522 case X86_INS_PCMPGTQ:
2523 case X86_INS_PCMPISTRI:
2524 case X86_INS_PCMPISTRM:
2525 #if CS_API_MAJOR >= 4
2526 case X86_INS_VPCMPB:
2527 #endif
2528 case X86_INS_VPCMPD:
2529 case X86_INS_VPCMPEQB:
2530 case X86_INS_VPCMPEQD:
2531 case X86_INS_VPCMPEQQ:
2532 case X86_INS_VPCMPEQW:
2533 case X86_INS_VPCMPESTRI:
2534 case X86_INS_VPCMPESTRM:
2535 case X86_INS_VPCMPGTB:
2536 case X86_INS_VPCMPGTD:
2537 case X86_INS_VPCMPGTQ:
2538 case X86_INS_VPCMPGTW:
2539 case X86_INS_VPCMPISTRI:
2540 case X86_INS_VPCMPISTRM:
2541 case X86_INS_VPCMPQ:
2542 #if CS_API_MAJOR >= 4
2543 case X86_INS_VPCMPUB:
2544 #endif
2545 case X86_INS_VPCMPUD:
2546 case X86_INS_VPCMPUQ:
2547 #if CS_API_MAJOR >= 4
2548 case X86_INS_VPCMPUW:
2549 case X86_INS_VPCMPW:
2550 #endif
2551 op->type = R_ANAL_OP_TYPE_CMP;
2552 op->family = R_ANAL_OP_FAMILY_SSE;
2553 break;
2554 case X86_INS_MOVSS:
2555 case X86_INS_MOV:
2556 case X86_INS_MOVAPS:
2557 case X86_INS_MOVAPD:
2558 case X86_INS_MOVZX:
2559 case X86_INS_MOVUPS:
2560 case X86_INS_MOVABS:
2561 case X86_INS_MOVHPD:
2562 case X86_INS_MOVHPS:
2563 case X86_INS_MOVLPD:
2564 case X86_INS_MOVLPS:
2565 case X86_INS_MOVBE:
2566 case X86_INS_MOVSB:
2567 case X86_INS_MOVSD:
2568 case X86_INS_MOVSQ:
2569 case X86_INS_MOVSX:
2570 case X86_INS_MOVSXD:
2571 case X86_INS_MOVSW:
2572 case X86_INS_MOVD:
2573 case X86_INS_MOVQ:
2574 case X86_INS_MOVDQ2Q:
2575 {
2576 op->type = R_ANAL_OP_TYPE_MOV;
2577 op0_memimmhandle (op, insn, addr, regsz);
2578 op1_memimmhandle (op, insn, addr, regsz);
2579 }
2580 break;
2581 case X86_INS_ROL:
2582 case X86_INS_RCL:
2583 // TODO: RCL Still does not work as intended
2584 // - Set flags
2585 op->type = R_ANAL_OP_TYPE_ROL;
2586 break;
2587 case X86_INS_ROR:
2588 case X86_INS_RCR:
2589 // TODO: RCR Still does not work as intended
2590 // - Set flags
2591 op->type = R_ANAL_OP_TYPE_ROR;
2592 break;
2593 case X86_INS_SHL:
2594 case X86_INS_SHLD:
2595 case X86_INS_SHLX:
2596 // TODO: Set CF: Carry flag is the last bit shifted out due to
2597 // this operation. It is undefined for SHL and SHR where the
2598 // number of bits shifted is greater than the size of the
2599 // destination.
2600 op->type = R_ANAL_OP_TYPE_SHL;
2601 break;
2602 case X86_INS_SAR:
2603 case X86_INS_SARX:
2604 // TODO: Set CF. See case X86_INS_SHL for more details.
2605 op->type = R_ANAL_OP_TYPE_SAR;
2606 break;
2607 case X86_INS_SAL:
2608 // TODO: Set CF: See case X86_INS_SAL for more details.
2609 op->type = R_ANAL_OP_TYPE_SAL;
2610 break;
2611 case X86_INS_SALC:
2612 op->type = R_ANAL_OP_TYPE_SAL;
2613 break;
2614 case X86_INS_SHR:
2615 case X86_INS_SHRD:
2616 case X86_INS_SHRX:
2617 // TODO: Set CF: See case X86_INS_SAL for more details.
2618 op->type = R_ANAL_OP_TYPE_SHR;
2619 op->val = INSOP(1).imm;
2620 // XXX this should be op->imm
2621 //op->src[0] = r_anal_value_new ();
2622 //op->src[0]->imm = INSOP(1).imm;
2623 break;
2624 case X86_INS_CMP:
2625 case X86_INS_CMPPD:
2626 case X86_INS_CMPPS:
2627 case X86_INS_CMPSW:
2628 case X86_INS_CMPSD:
2629 case X86_INS_CMPSQ:
2630 case X86_INS_CMPSB:
2631 case X86_INS_CMPSS:
2632 case X86_INS_TEST:
2633 if (insn->id == X86_INS_TEST) {
2634 op->type = R_ANAL_OP_TYPE_ACMP; //compare via and
2635 } else {
2636 op->type = R_ANAL_OP_TYPE_CMP;
2637 }
2638 switch (INSOP(0).type) {
2639 case X86_OP_MEM:
2640 op->disp = INSOP(0).mem.disp;
2641 op->refptr = INSOP(0).size;
2642 if (INSOP(0).mem.base == X86_REG_RIP) {
2643 op->ptr = addr + insn->size + op->disp;
2644 } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) {
2645 op->stackop = R_ANAL_STACK_SET;
2646 op->stackptr = regsz;
2647 op->type |= R_ANAL_OP_TYPE_REG;
2648 } else if (INSOP(0).mem.segment == X86_REG_INVALID && INSOP(0).mem.base == X86_REG_INVALID
2649 && INSOP(0).mem.index == X86_REG_INVALID && INSOP(0).mem.scale == 1) { // [<addr>]
2650 op->ptr = op->disp;
2651 }
2652 if (INSOP(1).type == X86_OP_IMM) {
2653 op->val = INSOP(1).imm;
2654 }
2655 break;
2656 default:
2657 switch (INSOP(1).type) {
2658 case X86_OP_MEM:
2659 op->disp = INSOP(1).mem.disp;
2660 op->refptr = INSOP(1).size;
2661 if (INSOP(1).mem.base == X86_REG_RIP) {
2662 op->ptr = addr + insn->size + op->disp;;
2663 } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) {
2664 op->type |= R_ANAL_OP_TYPE_REG;
2665 op->stackop = R_ANAL_STACK_SET;
2666 op->stackptr = regsz;
2667 } else if (INSOP(1).mem.segment == X86_REG_INVALID
2668 && INSOP(1).mem.base == X86_REG_INVALID
2669 && INSOP(1).mem.index == X86_REG_INVALID
2670 && INSOP(1).mem.scale == 1) { // [<addr>]
2671 op->ptr = op->disp;
2672 }
2673 if (INSOP(0).type == X86_OP_IMM) {
2674 op->val = INSOP(0).imm;
2675 }
2676 break;
2677 case X86_OP_IMM:
2678 op->val = op->ptr = INSOP(1).imm;
2679 break;
2680 default:
2681 break;
2682 }
2683 break;
2684 }
2685 break;
2686 case X86_INS_LEA:
2687 op->type = R_ANAL_OP_TYPE_LEA;
2688 switch (INSOP(1).type) {
2689 case X86_OP_MEM:
2690 // op->type = R_ANAL_OP_TYPE_ULEA;
2691 op->disp = INSOP(1).mem.disp;
2692 op->refptr = INSOP(1).size;
2693 switch (INSOP(1).mem.base) {
2694 case X86_REG_RIP:
2695 op->ptr = addr + op->size + op->disp;
2696 break;
2697 case X86_REG_RBP:
2698 case X86_REG_EBP:
2699 op->stackop = R_ANAL_STACK_GET;
2700 op->stackptr = regsz;
2701 break;
2702 default:
2703 /* unhandled */
2704 break;
2705 }
2706 break;
2707 case X86_OP_IMM:
2708 if (INSOP(1).imm > 10) {
2709 op->ptr = INSOP(1).imm;
2710 }
2711 break;
2712 default:
2713 break;
2714 }
2715 break;
2716 case X86_INS_PUSHAW:
2717 // pushal, popal - push/pop EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI
2718 case X86_INS_PUSHAL:
2719 op->ptr = UT64_MAX;
2720 op->type = R_ANAL_OP_TYPE_UPUSH;
2721 op->stackop = R_ANAL_STACK_INC;
2722 op->stackptr = regsz * 8;
2723 break;
2724 case X86_INS_ENTER:
2725 case X86_INS_PUSH:
2726 case X86_INS_PUSHF:
2727 case X86_INS_PUSHFD:
2728 case X86_INS_PUSHFQ:
2729 switch (INSOP(0).type) {
2730 case X86_OP_MEM:
2731 if (INSOP(0).mem.disp && !INSOP(0).mem.base && !INSOP(0).mem.index) {
2732 op->val = op->ptr = INSOP(0).mem.disp;
2733 op->type = R_ANAL_OP_TYPE_PUSH;
2734 } else {
2735 op->type = R_ANAL_OP_TYPE_UPUSH;
2736 }
2737 op->cycles = CYCLE_REG + CYCLE_MEM;
2738 break;
2739 case X86_OP_IMM:
2740 op->val = op->ptr = INSOP(0).imm;
2741 op->type = R_ANAL_OP_TYPE_PUSH;
2742 op->cycles = CYCLE_REG + CYCLE_MEM;
2743 break;
2744 case X86_OP_REG:
2745 op->type = R_ANAL_OP_TYPE_RPUSH;
2746 op->cycles = CYCLE_REG + CYCLE_MEM;
2747 break;
2748 default:
2749 op->type = R_ANAL_OP_TYPE_UPUSH;
2750 op->cycles = CYCLE_MEM + CYCLE_MEM;
2751 break;
2752 }
2753 op->stackop = R_ANAL_STACK_INC;
2754 op->stackptr = regsz;
2755 break;
2756 case X86_INS_LEAVE:
2757 op->type = R_ANAL_OP_TYPE_POP;
2758 op->stackop = R_ANAL_STACK_INC;
2759 op->stackptr = -regsz;
2760 break;
2761 case X86_INS_POP:
2762 case X86_INS_POPF:
2763 case X86_INS_POPFD:
2764 case X86_INS_POPFQ:
2765 op->type = R_ANAL_OP_TYPE_POP;
2766 op->stackop = R_ANAL_STACK_INC;
2767 op->stackptr = -regsz;
2768 break;
2769 case X86_INS_POPAW:
2770 case X86_INS_POPAL:
2771 op->type = R_ANAL_OP_TYPE_POP;
2772 op->stackop = R_ANAL_STACK_INC;
2773 op->stackptr = -regsz * 8;
2774 break;
2775 case X86_INS_IRET:
2776 case X86_INS_IRETD:
2777 case X86_INS_IRETQ:
2778 case X86_INS_SYSRET:
2779 op->family = R_ANAL_OP_FAMILY_PRIV;
2780 /* fallthrough */
2781 case X86_INS_RET:
2782 case X86_INS_RETF:
2783 case X86_INS_RETFQ:
2784 op->type = R_ANAL_OP_TYPE_RET;
2785 op->stackop = R_ANAL_STACK_INC;
2786 op->stackptr = -regsz;
2787 op->cycles = CYCLE_MEM + CYCLE_JMP;
2788 break;
2789 #if CS_API_MAJOR >= 4
2790 case X86_INS_UD0:
2791 #endif
2792 case X86_INS_UD2:
2793 #if CS_API_MAJOR == 4
2794 case X86_INS_UD2B:
2795 #endif
2796 case X86_INS_INT3:
2797 op->type = R_ANAL_OP_TYPE_TRAP; // TRAP
2798 break;
2799 case X86_INS_INT1:
2800 op->type = R_ANAL_OP_TYPE_SWI;
2801 op->val = 1;
2802 break;
2803 case X86_INS_INT:
2804 op->type = R_ANAL_OP_TYPE_SWI;
2805 op->val = (int)INSOP(0).imm;
2806 break;
2807 case X86_INS_SYSCALL:
2808 case X86_INS_SYSENTER:
2809 op->type = R_ANAL_OP_TYPE_SWI;
2810 op->cycles = CYCLE_JMP;
2811 break;
2812 case X86_INS_SYSEXIT:
2813 op->type = R_ANAL_OP_TYPE_SWI;
2814 op->family = R_ANAL_OP_FAMILY_PRIV;
2815 break;
2816 case X86_INS_INTO:
2817 op->type = R_ANAL_OP_TYPE_SWI;
2818 // int4 if overflow bit is set , so this is an optional swi
2819 op->type |= R_ANAL_OP_TYPE_COND;
2820 break;
2821 case X86_INS_VMCALL:
2822 case X86_INS_VMMCALL:
2823 op->type = R_ANAL_OP_TYPE_TRAP;
2824 break;
2825 case X86_INS_JL:
2826 case X86_INS_JLE:
2827 case X86_INS_JA:
2828 case X86_INS_JAE:
2829 case X86_INS_JB:
2830 case X86_INS_JBE:
2831 case X86_INS_JCXZ:
2832 case X86_INS_JECXZ:
2833 case X86_INS_JRCXZ:
2834 case X86_INS_JO:
2835 case X86_INS_JNO:
2836 case X86_INS_JS:
2837 case X86_INS_JNS:
2838 case X86_INS_JP:
2839 case X86_INS_JNP:
2840 case X86_INS_JE:
2841 case X86_INS_JNE:
2842 case X86_INS_JG:
2843 case X86_INS_JGE:
2844 case X86_INS_LOOP:
2845 case X86_INS_LOOPE:
2846 case X86_INS_LOOPNE:
2847 op->type = R_ANAL_OP_TYPE_CJMP;
2848 op->jump = INSOP(0).imm;
2849 op->fail = addr + op->size;
2850 op->cycles = CYCLE_JMP;
2851 switch (insn->id) {
2852 case X86_INS_JL:
2853 case X86_INS_JLE:
2854 case X86_INS_JS:
2855 case X86_INS_JG:
2856 case X86_INS_JGE:
2857 op->sign = true;
2858 break;
2859 }
2860 break;
2861 case X86_INS_CALL:
2862 case X86_INS_LCALL:
2863 op->cycles = CYCLE_JMP + CYCLE_MEM;
2864 switch (INSOP(0).type) {
2865 case X86_OP_IMM:
2866 op->type = R_ANAL_OP_TYPE_CALL;
2867 // TODO: what if UCALL?
2868 if (INSOP(1).type == X86_OP_IMM) {
2869 ut64 seg = INSOP(0).imm;
2870 ut64 off = INSOP(1).imm;
2871 op->ptr = INSOP (0).mem.disp;
2872 op->jump = (seg << a->seggrn) + off;
2873 } else {
2874 op->jump = INSOP(0).imm;
2875 }
2876 op->fail = addr + op->size;
2877 break;
2878 case X86_OP_MEM:
2879 op->type = R_ANAL_OP_TYPE_UCALL;
2880 op->jump = UT64_MAX;
2881 op->ptr = INSOP (0).mem.disp;
2882 op->disp = INSOP (0).mem.disp;
2883 op->reg = NULL;
2884 op->ireg = NULL;
2885 op->cycles += CYCLE_MEM;
2886 if (INSOP (0).mem.index == X86_REG_INVALID) {
2887 if (INSOP (0).mem.base != X86_REG_INVALID) {
2888 op->reg = cs_reg_name (*handle, INSOP (0).mem.base);
2889 op->type = R_ANAL_OP_TYPE_IRCALL;
2890 }
2891 } else {
2892 op->ireg = cs_reg_name (*handle, INSOP (0).mem.index);
2893 op->scale = INSOP(0).mem.scale;
2894 }
2895 if (INSOP (0).mem.base == X86_REG_RIP) {
2896 op->ptr += addr + insn->size;
2897 op->refptr = 8;
2898 }
2899 break;
2900 case X86_OP_REG:
2901 op->reg = cs_reg_name (*handle, INSOP (0).reg);
2902 op->type = R_ANAL_OP_TYPE_RCALL;
2903 op->ptr = UT64_MAX;
2904 op->cycles += CYCLE_REG;
2905 break;
2906 default:
2907 op->type = R_ANAL_OP_TYPE_UCALL;
2908 op->jump = UT64_MAX;
2909 break;
2910 }
2911 break;
2912 case X86_INS_JMP:
2913 case X86_INS_LJMP:
2914 // TODO: what if UJMP?
2915 switch (INSOP(0).type) {
2916 case X86_OP_IMM:
2917 if (INSOP(1).type == X86_OP_IMM) {
2918 ut64 seg = INSOP(0).imm;
2919 ut64 off = INSOP(1).imm;
2920 op->ptr = INSOP (0).mem.disp;
2921 op->jump = (seg << a->seggrn) + off;
2922 } else {
2923 op->jump = INSOP(0).imm;
2924 }
2925 op->type = R_ANAL_OP_TYPE_JMP;
2926 op->cycles = CYCLE_JMP;
2927 break;
2928 case X86_OP_MEM:
2929 // op->type = R_ANAL_OP_TYPE_UJMP;
2930 op->type = R_ANAL_OP_TYPE_MJMP;
2931 op->ptr = INSOP (0).mem.disp;
2932 op->disp = INSOP (0).mem.disp;
2933 op->reg = NULL;
2934 op->ireg = NULL;
2935 op->cycles = CYCLE_JMP + CYCLE_MEM;
2936 if (INSOP(0).mem.base != X86_REG_INVALID) {
2937 if (INSOP (0).mem.base != X86_REG_INVALID) {
2938 op->reg = cs_reg_name (*handle, INSOP (0).mem.base);
2939 op->type = R_ANAL_OP_TYPE_IRJMP;
2940 }
2941 }
2942 if (INSOP (0).mem.index == X86_REG_INVALID) {
2943 op->ireg = NULL;
2944 } else {
2945 op->type = R_ANAL_OP_TYPE_UJMP;
2946 op->ireg = cs_reg_name (*handle, INSOP (0).mem.index);
2947 op->scale = INSOP (0).mem.scale;
2948 }
2949 if (INSOP(0).mem.base == X86_REG_RIP) {
2950 op->ptr += addr + insn->size;
2951 op->refptr = 8;
2952 }
2953 break;
2954 case X86_OP_REG:
2955 {
2956 op->cycles = CYCLE_JMP + CYCLE_REG;
2957 op->reg = cs_reg_name (gop.handle, INSOP(0).reg);
2958 op->type = R_ANAL_OP_TYPE_RJMP;
2959 op->ptr = UT64_MAX;
2960 }
2961 break;
2962 //case X86_OP_FP:
2963 default: // other?
2964 op->type = R_ANAL_OP_TYPE_UJMP;
2965 op->ptr = UT64_MAX;
2966 break;
2967 }
2968 break;
2969 case X86_INS_IN:
2970 case X86_INS_INSW:
2971 case X86_INS_INSD:
2972 case X86_INS_INSB:
2973 op->type = R_ANAL_OP_TYPE_IO;
2974 op->type2 = 0;
2975 break;
2976 case X86_INS_OUT:
2977 case X86_INS_OUTSB:
2978 case X86_INS_OUTSD:
2979 case X86_INS_OUTSW:
2980 op->type = R_ANAL_OP_TYPE_IO;
2981 op->type2 = 1;
2982 break;
2983 case X86_INS_VXORPD:
2984 case X86_INS_VXORPS:
2985 case X86_INS_VPXORD:
2986 case X86_INS_VPXORQ:
2987 case X86_INS_VPXOR:
2988 case X86_INS_XORPS:
2989 case X86_INS_KXORW:
2990 case X86_INS_PXOR:
2991 op->type = R_ANAL_OP_TYPE_XOR;
2992 break;
2993 case X86_INS_XOR:
2994 op->type = R_ANAL_OP_TYPE_XOR;
2995 // TODO: Add stack indexing handling chang
2996 op0_memimmhandle (op, insn, addr, regsz);
2997 op1_memimmhandle (op, insn, addr, regsz);
2998 break;
2999 case X86_INS_OR:
3000 // The OF and CF flags are cleared; the SF, ZF, and PF flags are
3001 // set according to the result. The state of the AF flag is
3002 // undefined.
3003 op->type = R_ANAL_OP_TYPE_OR;
3004 // TODO: Add stack indexing handling chang
3005 op0_memimmhandle (op, insn, addr, regsz);
3006 op1_memimmhandle (op, insn, addr, regsz);
3007 break;
3008 case X86_INS_INC:
3009 // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
3010 // are set according to the result.
3011 op->type = R_ANAL_OP_TYPE_ADD;
3012 op->val = 1;
3013 break;
3014 case X86_INS_DEC:
3015 // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
3016 // are set according to the result.
3017 op->type = R_ANAL_OP_TYPE_SUB;
3018 op->val = 1;
3019 break;
3020 case X86_INS_NEG:
3021 op->type = R_ANAL_OP_TYPE_SUB;
3022 op->family = R_ANAL_OP_FAMILY_CPU;
3023 break;
3024 case X86_INS_NOT:
3025 op->type = R_ANAL_OP_TYPE_NOT;
3026 op->family = R_ANAL_OP_FAMILY_CPU;
3027 break;
3028 case X86_INS_PSUBB:
3029 case X86_INS_PSUBW:
3030 case X86_INS_PSUBD:
3031 case X86_INS_PSUBQ:
3032 case X86_INS_PSUBSB:
3033 case X86_INS_PSUBSW:
3034 case X86_INS_PSUBUSB:
3035 case X86_INS_PSUBUSW:
3036 op->type = R_ANAL_OP_TYPE_SUB;
3037 break;
3038 case X86_INS_SUB:
3039 op->type = R_ANAL_OP_TYPE_SUB;
3040 op_stackidx (op, insn, false);
3041 op0_memimmhandle (op, insn, addr, regsz);
3042 op1_memimmhandle (op, insn, addr, regsz);
3043 break;
3044 case X86_INS_SBB:
3045 // dst = dst - (src + cf)
3046 op->type = R_ANAL_OP_TYPE_SUB;
3047 break;
3048 case X86_INS_LIDT:
3049 op->type = R_ANAL_OP_TYPE_LOAD;
3050 op->family = R_ANAL_OP_FAMILY_PRIV;
3051 break;
3052 case X86_INS_SIDT:
3053 op->type = R_ANAL_OP_TYPE_STORE;
3054 op->family = R_ANAL_OP_FAMILY_PRIV;
3055 break;
3056 case X86_INS_RDRAND:
3057 case X86_INS_RDSEED:
3058 case X86_INS_RDMSR:
3059 case X86_INS_RDPMC:
3060 case X86_INS_RDTSC:
3061 case X86_INS_RDTSCP:
3062 case X86_INS_CRC32:
3063 case X86_INS_SHA1MSG1:
3064 case X86_INS_SHA1MSG2:
3065 case X86_INS_SHA1NEXTE:
3066 case X86_INS_SHA1RNDS4:
3067 case X86_INS_SHA256MSG1:
3068 case X86_INS_SHA256MSG2:
3069 case X86_INS_SHA256RNDS2:
3070 case X86_INS_AESDECLAST:
3071 case X86_INS_AESDEC:
3072 case X86_INS_AESENCLAST:
3073 case X86_INS_AESENC:
3074 case X86_INS_AESIMC:
3075 case X86_INS_AESKEYGENASSIST:
3076 // AES instructions
3077 op->family = R_ANAL_OP_FAMILY_CRYPTO;
3078 op->type = R_ANAL_OP_TYPE_MOV; // XXX
3079 break;
3080 case X86_INS_ANDN:
3081 case X86_INS_ANDPD:
3082 case X86_INS_ANDPS:
3083 case X86_INS_ANDNPD:
3084 case X86_INS_ANDNPS:
3085 op->type = R_ANAL_OP_TYPE_AND;
3086 break;
3087 case X86_INS_AND:
3088 op->type = R_ANAL_OP_TYPE_AND;
3089 // TODO: Add stack register change operation
3090 op0_memimmhandle (op, insn, addr, regsz);
3091 op1_memimmhandle (op, insn, addr, regsz);
3092 break;
3093 case X86_INS_IDIV:
3094 op->type = R_ANAL_OP_TYPE_DIV;
3095 break;
3096 case X86_INS_DIV:
3097 op->type = R_ANAL_OP_TYPE_DIV;
3098 break;
3099 case X86_INS_IMUL:
3100 op->type = R_ANAL_OP_TYPE_MUL;
3101 op->sign = true;
3102 break;
3103 case X86_INS_AAM:
3104 case X86_INS_MUL:
3105 case X86_INS_MULX:
3106 case X86_INS_MULPD:
3107 case X86_INS_MULPS:
3108 case X86_INS_MULSD:
3109 case X86_INS_MULSS:
3110 op->type = R_ANAL_OP_TYPE_MUL;
3111 break;
3112 case X86_INS_PACKSSDW:
3113 case X86_INS_PACKSSWB:
3114 case X86_INS_PACKUSWB:
3115 op->type = R_ANAL_OP_TYPE_MOV;
3116 op->family = R_ANAL_OP_FAMILY_MMX;
3117 break;
3118 case X86_INS_PADDB:
3119 case X86_INS_PADDD:
3120 case X86_INS_PADDW:
3121 case X86_INS_PADDSB:
3122 case X86_INS_PADDSW:
3123 case X86_INS_PADDUSB:
3124 case X86_INS_PADDUSW:
3125 op->type = R_ANAL_OP_TYPE_ADD;
3126 op->family = R_ANAL_OP_FAMILY_MMX;
3127 break;
3128 case X86_INS_XCHG:
3129 op->type = R_ANAL_OP_TYPE_MOV;
3130 op->family = R_ANAL_OP_FAMILY_CPU;
3131 break;
3132 case X86_INS_XADD: /* xchg + add */
3133 op->type = R_ANAL_OP_TYPE_ADD;
3134 op->family = R_ANAL_OP_FAMILY_CPU;
3135 break;
3136 case X86_INS_FADD:
3137 #if CS_API_MAJOR == 4
3138 case X86_INS_FADDP:
3139 #endif
3140 op->family = R_ANAL_OP_FAMILY_FPU;
3141 op->type = R_ANAL_OP_TYPE_ADD;
3142 break;
3143 case X86_INS_ADDPS:
3144 case X86_INS_ADDSD:
3145 case X86_INS_ADDSS:
3146 case X86_INS_ADDSUBPD:
3147 case X86_INS_ADDSUBPS:
3148 case X86_INS_ADDPD:
3149 // The OF, SF, ZF, AF, CF, and PF flags are set according to the
3150 // result.
3151 op->type = R_ANAL_OP_TYPE_ADD;
3152 op_stackidx (op, insn, true);
3153 op->val = INSOP(1).imm;
3154 break;
3155 case X86_INS_ADD:
3156 // The OF, SF, ZF, AF, CF, and PF flags are set according to the
3157 // result.
3158 op->type = R_ANAL_OP_TYPE_ADD;
3159 op_stackidx (op, insn, true);
3160 op0_memimmhandle (op, insn, addr, regsz);
3161 op1_memimmhandle (op, insn, addr, regsz);
3162 break;
3163 case X86_INS_ADC:
3164 op->type = R_ANAL_OP_TYPE_ADD;
3165 break;
3166 /* Direction flag */
3167 case X86_INS_CLD:
3168 op->type = R_ANAL_OP_TYPE_MOV;
3169 break;
3170 case X86_INS_STD:
3171 op->type = R_ANAL_OP_TYPE_MOV;
3172 break;
3173 case X86_INS_SUBSD: //cvtss2sd
3174 case X86_INS_CVTSS2SD: //cvtss2sd
3175 break;
3176 }
3177 if (cs_insn_group (*handle, insn, X86_GRP_MMX)) {
3178 op->family = R_ANAL_OP_FAMILY_MMX;
3179 }
3180 // TODO: add SSE* families?
3181 if (cs_insn_group (*handle, insn, X86_GRP_SSE1)) {
3182 op->family = R_ANAL_OP_FAMILY_SSE;
3183 }
3184 if (cs_insn_group (*handle, insn, X86_GRP_SSE2)) {
3185 op->family = R_ANAL_OP_FAMILY_SSE;
3186 }
3187 if (cs_insn_group (*handle, insn, X86_GRP_SSE3)) {
3188 op->family = R_ANAL_OP_FAMILY_SSE;
3189 }
3190 }
3191
cs_len_prefix_opcode(uint8_t * item)3192 static int cs_len_prefix_opcode(uint8_t *item) {
3193 int i, len = 0;
3194 for (i = 0; i < 4; i++) {
3195 len += (item[i] != 0) ? 1 : 0;
3196 }
3197 return len;
3198 }
3199
analop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)3200 static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
3201 static int omode = 0;
3202 #if USE_ITER_API
3203 static
3204 #endif
3205 cs_insn *insn = NULL;
3206 int mode = (a->bits==64)? CS_MODE_64:
3207 (a->bits==32)? CS_MODE_32:
3208 (a->bits==16)? CS_MODE_16: 0;
3209 int n, ret;
3210
3211 if (handle && mode != omode) {
3212 if (handle != 0) {
3213 cs_close (&handle);
3214 handle = 0;
3215 }
3216 }
3217 omode = mode;
3218 if (handle == 0) {
3219 ret = cs_open (CS_ARCH_X86, mode, &handle);
3220 if (ret != CS_ERR_OK) {
3221 handle = 0;
3222 return 0;
3223 }
3224 }
3225 op->cycles = 1; // aprox
3226 cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON);
3227 // capstone-next
3228 #if USE_ITER_API
3229 {
3230 ut64 naddr = addr;
3231 size_t size = len;
3232 if (!insn) {
3233 insn = cs_malloc (handle);
3234 }
3235 n = cs_disasm_iter (handle, (const uint8_t**)&buf,
3236 &size, (uint64_t*)&naddr, insn);
3237 }
3238 #else
3239 n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn);
3240 #endif
3241 if (n < 1) {
3242 op->type = R_ANAL_OP_TYPE_ILL;
3243 if (mask & R_ANAL_OP_MASK_DISASM) {
3244 op->mnemonic = strdup ("invalid");
3245 }
3246 } else {
3247 if (mask & R_ANAL_OP_MASK_DISASM) {
3248 op->mnemonic = r_str_newf ("%s%s%s",
3249 insn->mnemonic,
3250 insn->op_str[0]?" ":"",
3251 insn->op_str);
3252 }
3253 // int rs = a->bits / 8;
3254 //const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip";
3255 //const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp";
3256 //const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp";
3257 op->nopcode = cs_len_prefix_opcode (insn->detail->x86.prefix)
3258 + cs_len_prefix_opcode (insn->detail->x86.opcode);
3259 op->size = insn->size;
3260 op->id = insn->id;
3261 op->family = R_ANAL_OP_FAMILY_CPU; // almost everything is CPU
3262 op->prefix = 0;
3263 op->cond = cond_x862r2 (insn->id);
3264 switch (insn->detail->x86.prefix[0]) {
3265 case X86_PREFIX_REPNE:
3266 op->prefix |= R_ANAL_OP_PREFIX_REPNE;
3267 break;
3268 case X86_PREFIX_REP:
3269 op->prefix |= R_ANAL_OP_PREFIX_REP;
3270 break;
3271 case X86_PREFIX_LOCK:
3272 op->prefix |= R_ANAL_OP_PREFIX_LOCK;
3273 op->family = R_ANAL_OP_FAMILY_THREAD; // XXX ?
3274 break;
3275 }
3276 anop (a, op, addr, buf, len, &handle, insn);
3277 set_opdir (op, insn);
3278 if (mask & R_ANAL_OP_MASK_ESIL) {
3279 anop_esil (a, op, addr, buf, len, &handle, insn);
3280 }
3281 if (mask & R_ANAL_OP_MASK_OPEX) {
3282 opex (&op->opex, insn, mode);
3283 }
3284 if (mask & R_ANAL_OP_MASK_VAL) {
3285 op_fillval (a, op, &handle, insn, mode);
3286 }
3287 }
3288 //#if X86_GRP_PRIVILEGE>0
3289 if (insn) {
3290 #if HAVE_CSGRP_PRIVILEGE
3291 if (cs_insn_group (handle, insn, X86_GRP_PRIVILEGE)) {
3292 op->family = R_ANAL_OP_FAMILY_PRIV;
3293 }
3294 #endif
3295 #if !USE_ITER_API
3296 cs_free (insn, n);
3297 #endif
3298 }
3299 //cs_close (&handle);
3300 return op->size;
3301 }
3302
3303 #if 0
3304 static int x86_int_0x80(RAnalEsil *esil, int interrupt) {
3305 int syscall;
3306 ut64 eax, ebx, ecx, edx;
3307 if (!esil || (interrupt != 0x80))
3308 return false;
3309 r_anal_esil_reg_read (esil, "eax", &eax, NULL);
3310 r_anal_esil_reg_read (esil, "ebx", &ebx, NULL);
3311 r_anal_esil_reg_read (esil, "ecx", &ecx, NULL);
3312 r_anal_esil_reg_read (esil, "edx", &edx, NULL);
3313 syscall = (int) eax;
3314 switch (syscall) {
3315 case 3:
3316 {
3317 char *dst = calloc (1, (size_t)edx);
3318 (void)read ((ut32)ebx, dst, (size_t)edx);
3319 r_anal_esil_mem_write (esil, ecx, (ut8 *)dst, (int)edx);
3320 free (dst);
3321 return true;
3322 }
3323 case 4:
3324 {
3325 char *src = malloc ((size_t)edx);
3326 r_anal_esil_mem_read (esil, ecx, (ut8 *)src, (int)edx);
3327 write ((ut32)ebx, src, (size_t)edx);
3328 free (src);
3329 return true;
3330 }
3331 }
3332 eprintf ("syscall %d not implemented yet\n", syscall);
3333 return false;
3334 }
3335 #endif
3336
3337 #if 0
3338 static int esil_x86_cs_intr(RAnalEsil *esil, int intr) {
3339 if (!esil) return false;
3340 eprintf ("INTERRUPT 0x%02x HAPPENS\n", intr);
3341 return true;
3342 }
3343 #endif
3344
esil_x86_cs_init(RAnalEsil * esil)3345 static int esil_x86_cs_init(RAnalEsil *esil) {
3346 if (!esil) {
3347 return false;
3348 }
3349 // XXX. this depends on kernel
3350 // r_anal_esil_set_interrupt (esil, 0x80, x86_int_0x80);
3351 /* disable by default */
3352 // r_anal_esil_set_interrupt (esil, 0x80, NULL); // this is stupid, don't do this
3353 return true;
3354 }
3355
init(void * p)3356 static int init(void *p) {
3357 handle = 0;
3358 return true;
3359 }
3360
fini(void * p)3361 static int fini(void *p) {
3362 if (handle != 0) {
3363 // SEGFAULTS RANDOMLY, better leak on exit.. lets try it out again
3364 cs_close (&handle);
3365 handle = 0;
3366 }
3367 return true;
3368 }
3369
esil_x86_cs_fini(RAnalEsil * esil)3370 static int esil_x86_cs_fini(RAnalEsil *esil) {
3371 return true;
3372 }
3373
get_reg_profile(RAnal * anal)3374 static char *get_reg_profile(RAnal *anal) {
3375 const char *p = NULL;
3376 switch (anal->bits) {
3377 case 16: p =
3378 "=PC ip\n"
3379 "=SP sp\n"
3380 "=BP bp\n"
3381 "=A0 ax\n"
3382 "=A1 bx\n"
3383 "=A2 cx\n"
3384 "=A3 dx\n"
3385 "=A4 si\n"
3386 "=A5 di\n"
3387 "=SN ah\n"
3388 "gpr ip .16 48 0\n"
3389 "gpr ax .16 24 0\n"
3390 "gpr ah .8 25 0\n"
3391 "gpr al .8 24 0\n"
3392 "gpr bx .16 0 0\n"
3393 "gpr bh .8 1 0\n"
3394 "gpr bl .8 0 0\n"
3395 "gpr cx .16 4 0\n"
3396 "gpr ch .8 5 0\n"
3397 "gpr cl .8 4 0\n"
3398 "gpr dx .16 8 0\n"
3399 "gpr dh .8 9 0\n"
3400 "gpr dl .8 8 0\n"
3401 "gpr sp .16 60 0\n"
3402 "gpr bp .16 20 0\n"
3403 "gpr si .16 12 0\n"
3404 "gpr di .16 16 0\n"
3405 "seg cs .16 52 0\n"
3406 "seg ss .16 54 0\n"
3407 "seg ds .16 56 0\n"
3408 "seg es .16 58 0\n"
3409 "gpr flags .16 56 0\n"
3410 "flg cf .1 .448 0\n"
3411 "flg pf .1 .449 0\n"
3412 "flg af .1 .450 0\n"
3413 "flg zf .1 .451 0\n"
3414 "flg sf .1 .452 0\n"
3415 "flg tf .1 .453 0\n"
3416 "flg if .1 .454 0\n"
3417 "flg df .1 .455 0\n"
3418 "flg of .1 .456 0\n"
3419 "flg rf .1 .457 0\n";
3420 #if 0
3421 "drx dr0 .32 0 0\n"
3422 "drx dr1 .32 4 0\n"
3423 "drx dr2 .32 8 0\n"
3424 "drx dr3 .32 12 0\n"
3425 //"drx dr4 .32 16 0\n"
3426 //"drx dr5 .32 20 0\n"
3427 "drx dr6 .32 24 0\n"
3428 "drx dr7 .32 28 0\n"
3429 #endif
3430 break;
3431 case 32: p =
3432 "=PC eip\n"
3433 "=SP esp\n"
3434 "=BP ebp\n"
3435 "=A0 eax\n"
3436 "=A1 ebx\n"
3437 "=A2 ecx\n"
3438 "=A3 edx\n"
3439 "=A4 esi\n"
3440 "=A5 edi\n"
3441 "=SN eax\n"
3442 "gpr oeax .32 44 0\n"
3443 "gpr eax .32 24 0\n"
3444 "gpr ax .16 24 0\n"
3445 "gpr ah .8 25 0\n"
3446 "gpr al .8 24 0\n"
3447 "gpr ebx .32 0 0\n"
3448 "gpr bx .16 0 0\n"
3449 "gpr bh .8 1 0\n"
3450 "gpr bl .8 0 0\n"
3451 "gpr ecx .32 4 0\n"
3452 "gpr cx .16 4 0\n"
3453 "gpr ch .8 5 0\n"
3454 "gpr cl .8 4 0\n"
3455 "gpr edx .32 8 0\n"
3456 "gpr dx .16 8 0\n"
3457 "gpr dh .8 9 0\n"
3458 "gpr dl .8 8 0\n"
3459 "gpr esi .32 12 0\n"
3460 "gpr si .16 12 0\n"
3461 "gpr edi .32 16 0\n"
3462 "gpr di .16 16 0\n"
3463 "gpr esp .32 60 0\n"
3464 "gpr sp .16 60 0\n"
3465 "gpr ebp .32 20 0\n"
3466 "gpr bp .16 20 0\n"
3467 "gpr eip .32 48 0\n"
3468 "gpr ip .16 48 0\n"
3469 "seg xfs .32 36 0\n"
3470 "seg xgs .32 40 0\n"
3471 "seg xcs .32 52 0\n"
3472 "seg cs .16 52 0\n"
3473 "seg xss .32 52 0\n"
3474 "flg eflags .32 .448 0 c1p.a.zstido.n.rv\n"
3475 "flg flags .16 .448 0\n"
3476 "flg cf .1 .448 0\n"
3477 "flg pf .1 .450 0\n"
3478 "flg af .1 .452 0\n"
3479 "flg zf .1 .454 0\n"
3480 "flg sf .1 .455 0\n"
3481 "flg tf .1 .456 0\n"
3482 "flg if .1 .457 0\n"
3483 "flg df .1 .458 0\n"
3484 "flg of .1 .459 0\n"
3485 "flg nt .1 .462 0\n"
3486 "flg rf .1 .464 0\n"
3487 "flg vm .1 .465 0\n"
3488 "drx dr0 .32 0 0\n"
3489 "drx dr1 .32 4 0\n"
3490 "drx dr2 .32 8 0\n"
3491 "drx dr3 .32 12 0\n"
3492 //"drx dr4 .32 16 0\n"
3493 //"drx dr5 .32 20 0\n"
3494 "drx dr6 .32 24 0\n"
3495 "drx dr7 .32 28 0\n";
3496 break;
3497 case 64:
3498 {
3499 const char *cc = r_anal_cc_default (anal);
3500 const char *args_prof = cc && !strcmp (cc, "ms")
3501 ? // Microsoft x64 CC
3502 "# RAX return value\n"
3503 "# RCX argument 1\n"
3504 "# RDX argument 2\n"
3505 "# R8 argument 3\n"
3506 "# R9 argument 4\n"
3507 "# R10-R11 syscall/sysret\n"
3508 "# R12-R15 GP preserved\n"
3509 "# RSI preserved source\n"
3510 "# RDI preserved destination\n"
3511 "# RSP stack pointer\n"
3512 "=PC rip\n"
3513 "=SP rsp\n"
3514 "=BP rbp\n"
3515 "=A0 rcx\n"
3516 "=A1 rdx\n"
3517 "=A2 r8\n"
3518 "=A3 r9\n"
3519 "=SN rax\n"
3520 : // System V AMD64 ABI
3521 "=PC rip\n"
3522 "=SP rsp\n"
3523 "=BP rbp\n"
3524 "=A0 rdi\n"
3525 "=A1 rsi\n"
3526 "=A2 rdx\n"
3527 "=A3 rcx\n"
3528 "=A4 r8\n"
3529 "=A5 r9\n"
3530 "=A6 r10\n"
3531 "=A7 r11\n"
3532 "=SN rax\n";
3533 char *prof = r_str_newf ("%s%s", args_prof,
3534 "gpr rax .64 80 0\n"
3535 "gpr eax .32 80 0\n"
3536 "gpr ax .16 80 0\n"
3537 "gpr al .8 80 0\n"
3538 "gpr ah .8 81 0\n"
3539 "gpr rbx .64 40 0\n"
3540 "gpr ebx .32 40 0\n"
3541 "gpr bx .16 40 0\n"
3542 "gpr bl .8 40 0\n"
3543 "gpr bh .8 41 0\n"
3544 "gpr rcx .64 88 0\n"
3545 "gpr ecx .32 88 0\n"
3546 "gpr cx .16 88 0\n"
3547 "gpr cl .8 88 0\n"
3548 "gpr ch .8 89 0\n"
3549 "gpr rdx .64 96 0\n"
3550 "gpr edx .32 96 0\n"
3551 "gpr dx .16 96 0\n"
3552 "gpr dl .8 96 0\n"
3553 "gpr dh .8 97 0\n"
3554 "gpr rsi .64 104 0\n"
3555 "gpr esi .32 104 0\n"
3556 "gpr si .16 104 0\n"
3557 "gpr sil .8 104 0\n"
3558 "gpr rdi .64 112 0\n"
3559 "gpr edi .32 112 0\n"
3560 "gpr di .16 112 0\n"
3561 "gpr dil .8 112 0\n"
3562 "gpr r8 .64 72 0\n"
3563 "gpr r8d .32 72 0\n"
3564 "gpr r8w .16 72 0\n"
3565 "gpr r8b .8 72 0\n"
3566 "gpr r9 .64 64 0\n"
3567 "gpr r9d .32 64 0\n"
3568 "gpr r9w .16 64 0\n"
3569 "gpr r9b .8 64 0\n"
3570 "gpr r10 .64 56 0\n"
3571 "gpr r10d .32 56 0\n"
3572 "gpr r10w .16 56 0\n"
3573 "gpr r10b .8 56 0\n"
3574 "gpr r11 .64 48 0\n"
3575 "gpr r11d .32 48 0\n"
3576 "gpr r11w .16 48 0\n"
3577 "gpr r11b .8 48 0\n"
3578 "gpr r12 .64 24 0\n"
3579 "gpr r12d .32 24 0\n"
3580 "gpr r12w .16 24 0\n"
3581 "gpr r12b .8 24 0\n"
3582 "gpr r13 .64 16 0\n"
3583 "gpr r13d .32 16 0\n"
3584 "gpr r13w .16 16 0\n"
3585 "gpr r13b .8 16 0\n"
3586 "gpr r14 .64 8 0\n"
3587 "gpr r14d .32 8 0\n"
3588 "gpr r14w .16 8 0\n"
3589 "gpr r14b .8 8 0\n"
3590 "gpr r15 .64 0 0\n"
3591 "gpr r15d .32 0 0\n"
3592 "gpr r15w .16 0 0\n"
3593 "gpr r15b .8 0 0\n"
3594 "gpr rip .64 128 0\n"
3595 "gpr rbp .64 32 0\n"
3596 "gpr ebp .32 32 0\n"
3597 "gpr bp .16 32 0\n"
3598 "gpr bpl .8 32 0\n"
3599 "seg cs .64 136 0\n"
3600 "flg rflags .64 144 0 c1p.a.zstido.n.rv\n"
3601 "flg eflags .32 144 0 c1p.a.zstido.n.rv\n"
3602 "flg cf .1 144.0 0 carry\n"
3603 "flg pf .1 144.2 0 parity\n"
3604 //"gpr cf .1 .1152 0 carry\n"
3605 //"gpr pf .1 .1154 0 parity\n"
3606 "flg af .1 144.4 0 adjust\n"
3607 "flg zf .1 144.6 0 zero\n"
3608 "flg sf .1 144.7 0 sign\n"
3609 "flg tf .1 .1160 0 trap\n"
3610 "flg if .1 .1161 0 interrupt\n"
3611 "flg df .1 .1162 0 direction\n"
3612 "flg of .1 .1163 0 overflow\n"
3613
3614 "gpr rsp .64 152 0\n"
3615 "gpr esp .32 152 0\n"
3616 "gpr sp .16 152 0\n"
3617 "gpr spl .8 152 0\n"
3618 "seg ss .64 160 0\n"
3619 "seg fs_base .64 168 0\n"
3620 "seg gs_base .64 176 0\n"
3621 "seg ds .64 184 0\n"
3622 "seg es .64 192 0\n"
3623 "seg fs .64 200 0\n"
3624 "seg gs .64 208 0\n"
3625 "drx dr0 .64 0 0\n"
3626 "drx dr1 .64 8 0\n"
3627 "drx dr2 .64 16 0\n"
3628 "drx dr3 .64 24 0\n"
3629 // dr4 32
3630 // dr5 40
3631 "drx dr6 .64 48 0\n"
3632 "drx dr7 .64 56 0\n"
3633
3634 /*0030 struct user_fpregs_struct
3635 0031 {
3636 0032 __uint16_t cwd;
3637 0033 __uint16_t swd;
3638 0034 __uint16_t ftw;
3639 0035 __uint16_t fop;
3640 0036 __uint64_t rip;
3641 0037 __uint64_t rdp;
3642 0038 __uint32_t mxcsr;
3643 0039 __uint32_t mxcr_mask;
3644 0040 __uint32_t st_space[32]; // 8*16 bytes for each FP-reg = 128 bytes
3645 0041 __uint32_t xmm_space[64]; // 16*16 bytes for each XMM-reg = 256 bytes
3646 0042 __uint32_t padding[24];
3647 0043 };
3648 */
3649 "fpu cwd .16 0 0\n"
3650 "fpu swd .16 2 0\n"
3651 "fpu ftw .16 4 0\n"
3652 "fpu fop .16 6 0\n"
3653 "fpu frip .64 8 0\n"
3654 "fpu frdp .64 16 0\n"
3655 "fpu mxcsr .32 24 0\n"
3656 "fpu mxcr_mask .32 28 0\n"
3657
3658 "fpu st0 .64 32 0\n"
3659 "fpu st1 .64 48 0\n"
3660 "fpu st2 .64 64 0\n"
3661 "fpu st3 .64 80 0\n"
3662 "fpu st4 .64 96 0\n"
3663 "fpu st5 .64 112 0\n"
3664 "fpu st6 .64 128 0\n"
3665 "fpu st7 .64 144 0\n"
3666
3667 "xmm@fpu xmm0 .128 160 4\n"
3668 "fpu xmm0h .64 160 0\n"
3669 "fpu xmm0l .64 168 0\n"
3670
3671 "xmm@fpu xmm1 .128 176 4\n"
3672 "fpu xmm1h .64 176 0\n"
3673 "fpu xmm1l .64 184 0\n"
3674
3675 "xmm@fpu xmm2 .128 192 4\n"
3676 "fpu xmm2h .64 192 0\n"
3677 "fpu xmm2l .64 200 0\n"
3678
3679 "xmm@fpu xmm3 .128 208 4\n"
3680 "fpu xmm3h .64 208 0\n"
3681 "fpu xmm3l .64 216 0\n"
3682
3683 "xmm@fpu xmm4 .128 224 4\n"
3684 "fpu xmm4h .64 224 0\n"
3685 "fpu xmm4l .64 232 0\n"
3686
3687 "xmm@fpu xmm5 .128 240 4\n"
3688 "fpu xmm5h .64 240 0\n"
3689 "fpu xmm5l .64 248 0\n"
3690
3691 "xmm@fpu xmm6 .128 256 4\n"
3692 "fpu xmm6h .64 256 0\n"
3693 "fpu xmm6l .64 264 0\n"
3694
3695 "xmm@fpu xmm7 .128 272 4\n"
3696 "fpu xmm7h .64 272 0\n"
3697 "fpu xmm7l .64 280 0\n"
3698 "fpu x64 .64 288 0\n");
3699 return prof;
3700 }
3701 #if 0
3702 default: p= /* XXX */
3703 "=PC rip\n"
3704 "=SP rsp\n"
3705 "=BP rbp\n"
3706 "=A0 rax\n"
3707 "=A1 rbx\n"
3708 "=A2 rcx\n"
3709 "=A3 rdx\n"
3710 "# no profile defined for x86-64\n"
3711 "gpr r15 .64 0 0\n"
3712 "gpr r14 .64 8 0\n"
3713 "gpr r13 .64 16 0\n"
3714 "gpr r12 .64 24 0\n"
3715 "gpr rbp .64 32 0\n"
3716 "gpr ebp .32 32 0\n"
3717 "gpr rbx .64 40 0\n"
3718 "gpr ebx .32 40 0\n"
3719 "gpr bx .16 40 0\n"
3720 "gpr bh .8 41 0\n"
3721 "gpr bl .8 40 0\n"
3722 "gpr r11 .64 48 0\n"
3723 "gpr r10 .64 56 0\n"
3724 "gpr r9 .64 64 0\n"
3725 "gpr r8 .64 72 0\n"
3726 "gpr rax .64 80 0\n"
3727 "gpr eax .32 80 0\n"
3728 "gpr rcx .64 88 0\n"
3729 "gpr ecx .32 88 0\n"
3730 "gpr rdx .64 96 0\n"
3731 "gpr edx .32 96 0\n"
3732 "gpr rsi .64 104 0\n"
3733 "gpr esi .32 104 0\n"
3734 "gpr rdi .64 112 0\n"
3735 "gpr edi .32 112 0\n"
3736 "gpr oeax .64 120 0\n"
3737 "gpr rip .64 128 0\n"
3738 "seg cs .64 136 0\n"
3739 //"flg eflags .64 144 0\n"
3740 "gpr eflags .32 144 0 c1p.a.zstido.n.rv\n"
3741 "flg cf .1 .1152 0\n"
3742 "flg pf .1 .1153 0\n"
3743 "flg af .1 .1154 0\n"
3744 "flg zf .1 .1155 0\n"
3745 "flg sf .1 .1156 0\n"
3746 "flg tf .1 .1157 0\n"
3747 "flg if .1 .1158 0\n"
3748 "flg df .1 .1159 0\n"
3749 "flg of .1 .1160 0\n"
3750 "flg rf .1 .1161 0\n"
3751 "gpr rsp .64 152 0\n"
3752 "seg ss .64 160 0\n"
3753 "seg fs_base .64 168 0\n"
3754 "seg gs_base .64 176 0\n"
3755 "seg ds .64 184 0\n"
3756 "seg es .64 192 0\n"
3757 "seg fs .64 200 0\n"
3758 "seg gs .64 208 0\n"
3759 "drx dr0 .32 0 0\n"
3760 "drx dr1 .32 4 0\n"
3761 "drx dr2 .32 8 0\n"
3762 "drx dr3 .32 12 0\n"
3763 "drx dr6 .32 24 0\n"
3764 "drx dr7 .32 28 0\n";
3765 break;
3766 #endif
3767 }
3768 return (p && *p)? strdup (p): NULL;
3769 }
3770
archinfo(RAnal * anal,int q)3771 static int archinfo(RAnal *anal, int q) {
3772 switch (q) {
3773 case R_ANAL_ARCHINFO_ALIGN:
3774 return 0;
3775 case R_ANAL_ARCHINFO_MAX_OP_SIZE:
3776 return 16;
3777 case R_ANAL_ARCHINFO_MIN_OP_SIZE:
3778 return 1;
3779 }
3780 return 0;
3781 }
3782
anal_preludes(RAnal * anal)3783 static RList *anal_preludes(RAnal *anal) {
3784 #define KW(d,ds,m,ms) r_list_append (l, r_search_keyword_new((const ut8*)d,ds,(const ut8*)m, ms, NULL))
3785 RList *l = r_list_newf ((RListFree)r_search_keyword_free);
3786 switch (anal->bits) {
3787 case 32:
3788 KW ("\x8b\xff\x55\x8b\xec", 5, NULL, 0);
3789 KW ("\x55\x89\xe5", 3, NULL, 0);
3790 KW ("\x55\x8b\xec", 3, NULL, 0);
3791 KW ("\xf3\x0f\x1e\xfb", 4, NULL, 0); // endbr32
3792 break;
3793 case 64:
3794 KW ("\x55\x48\x89\xe5", 4, NULL, 0);
3795 KW ("\x55\x48\x8b\xec", 4, NULL, 0);
3796 KW ("\xf3\x0f\x1e\xfa", 4, NULL, 0); // endbr64
3797 break;
3798 default:
3799 r_list_free (l);
3800 l = NULL;
3801 break;
3802 }
3803 return l;
3804 }
3805
3806 RAnalPlugin r_anal_plugin_x86_cs = {
3807 .name = "x86",
3808 .desc = "Capstone X86 analysis",
3809 .esil = true,
3810 .license = "BSD",
3811 .arch = "x86",
3812 .bits = 16|32|64,
3813 .op = &analop,
3814 .preludes = anal_preludes,
3815 .archinfo = archinfo,
3816 .get_reg_profile = &get_reg_profile,
3817 .init = init,
3818 .fini = fini,
3819 .esil_init = esil_x86_cs_init,
3820 .esil_fini = esil_x86_cs_fini,
3821 // .esil_intr = esil_x86_cs_intr,
3822 };
3823
3824 #ifndef R2_PLUGIN_INCORE
3825 R_API RLibStruct radare_plugin = {
3826 .type = R_LIB_TYPE_ANAL,
3827 .data = &r_anal_plugin_x86_cs,
3828 .version = R2_VERSION
3829 };
3830 #endif
3831