radare2/libr/anal/p/esil_x86_udis.c

262 lines
10 KiB
C

/* radare - LGPL - Copyright 2013-2014 - batchdrake */
#include <r_lib.h>
#include <r_types.h>
#include <r_anal.h>
#include <r_util.h>
#include "udis86/types.h"
#include "udis86/extern.h"
#include "esil.h"
#define RPN
RPN UDIS86_ESIL (nop, ",");
RPN UDIS86_ESIL (jo, "of,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jno, "of,!,?{,%s,%s,}", dst, info->pc);
RPN UDIS86_ESIL (jb, "cf,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jae, "cf,?{,%s,%s,=,}", dst, info->pc);
// UDIS86_ESIL (je, "?zf,%s=%s", info->pc, dst);
RPN UDIS86_ESIL (je, "zf,?{,%s,%s,=,}", dst, info->pc);
// UDIS86_ESIL (jne, "?!zf,%s=%s", info->pc, dst);
RPN UDIS86_ESIL (jne, "zf,!,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (ja, "cf,!,zf,!,&,?{,%s,%s,}",dst, info->pc);
RPN UDIS86_ESIL (jbe, "zf,cf,&,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (js, "sf,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jns, "sf,!,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jp, "pf,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jnp, "pf,!,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jl, "of,sf,^,?{,%s,%s,}", dst, info->pc);
RPN UDIS86_ESIL (jge, "of,!,sf,^,?{,%s,%s,}", dst, info->pc);
RPN UDIS86_ESIL (jle, "of,sf,^,zf,|,%s,%s,=", dst, info->pc);
RPN UDIS86_ESIL (jg, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jcxz, "cx,!,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jecxz, "ecx,!,?{,%s,%s,=,}", dst, info->pc);
RPN UDIS86_ESIL (jrcxz, "rcx,!,?{,%s,%s,=,}", dst, info->pc);
// UDIS86_ESIL (jmp, "%s=%s", info->pc, dst);
RPN UDIS86_ESIL (jmp, "%s,%s,=", dst, info->pc);
RPN UDIS86_ESIL (call,
"%d,%s,+,"
"%d,%s,-=,%s,"
"=[],"
"%s,%s,=",
5, info->pc,
info->regsz, info->sp, info->sp,
dst, info->pc);
RPN UDIS86_ESIL (hlt, "hlt,TODO");
RPN UDIS86_ESIL (shl, "%s,%s,<<=,cz,$z,zf,=", src, dst);
RPN UDIS86_ESIL (shr, "%s,%s,>>=,cz,$z,zf,=", src, dst);
RPN UDIS86_ESIL (salc, "%s,%s,<<=,$z,zf,=", src, dst);
RPN UDIS86_ESIL (sar, "%s,%s,>>=,$z,zf,=", src, dst);
RPN UDIS86_ESIL (rol, "%s,%s,<<<=", src, dst);
RPN UDIS86_ESIL (ror, "%s,%s,>>>=", src, dst);
#if 0
RPN UDIS86_ESIL (rol, "%s,1,<<,%s,&,cf,=,%s,%s,>>=,%s,zf,=", src, dst, src, dst, dst)
RPN UDIS86_ESIL (ror, "%s,%d,-,1,<<,%s,&,cf,=,%s,%s,>>=,%s,zf,=", src, info->regsz*8, dst, src, dst, dst)
// UDIS86_ESIL (rol, "cf=%s&(1<<%s),%s>>=%s,zf=%s==0", dst, src, dst, src, dst);
UDIS86_ESIL (ror, "cf=%s&(1<<%d-%s),%s<<<=%s,zf=%s==0", dst, info->regsz * 8, src, dst, src, dst);
#endif
// UDIS86_ESIL (add, "cf=%s<=-%s&%s!=0,of=!((%s^%s)>>%d)&(((%s+%s)^%s)>>%d),%s+=%s,zf=%s==0,sf=%s>>%d", dst, src, src, dst, src, info->bits - 1, dst, src, src, info->bits - 1, dst, src, dst, dst, info->bits - 1);
// XXX: this is wrong coz add [rax], al -> al,[rax+0],= ;;; this is not valid esil
RPN UDIS86_ESIL (add, "%s,%s,+=", src, dst); //cf=%s<=-%s&%s!=0,of=!((%s^%s)>>%d)&(((%s+%s)^%s)>>%d),%s+=%s,zf=%s==0,sf=%s>>%d", dst, src, src, dst, src, info->bits - 1, dst, src, src, info->bits - 1, dst, src, dst, dst, info->bits - 1);
RPN UDIS86_ESIL (inc, "1,%s,+=,z,$z,zf,=", dst);
RPN UDIS86_ESIL (dec, "1,%s,-=,$z,zf,=,$o,of,=,$s,sf,=", dst);
// UDIS86_ESIL (inc, "of=(%s^(%s+1))>>%d,%s++,zf=%s==0,sf=%s>>%d", dst, dst, info->bits - 1, dst, dst, dst, info->bits - 1);
// UDIS86_ESIL (sub, "cf=%s<%s,of=!((%s^%s)>>%d)&(((%s+%s)^%s)>>%d),%s-=%s,zf=%s==0,sf=%s>>%d", dst, src, dst, src, info->bits - 1, dst, src, src, info->bits - 1, dst, src, dst, dst, info->bits - 1);
RPN UDIS86_ESIL (sub, "%s,%s,-=,$c,cf,=,$z,zf,=,$s,sf,=,$o,of,=", src, dst); // TODO: update flags
// UDIS86_ESIL (dec, "of=(%s^(%s-1))>>%d,%s--,zf=%s==0,sf=%s>>%d", dst, dst, info->bits - 1, dst, dst, dst, info->bits - 1);
// UDIS86_ESIL (cmp, "cf=%s<%s,zf=%s==%s", dst, src, dst, src);
RPN UDIS86_ESIL (cmp, "%s,%s,==,$z,zf,=", dst, src);
// UDIS86_ESIL (xor, "%s^=%s,zf=%s==0,sf=%s>>%d,cf=0,of=0", dst, src, dst, dst, info->bits - 1);
RPN UDIS86_ESIL (xor, "%s,%s,^=", dst, src);
// UDIS86_ESIL (or, "%s|=%s,zf=%s==0,sf=%s>>%d,cf=0,of=0", dst, src, dst, dst, info->bits - 1);
RPN UDIS86_ESIL (or, "%s,%s,|=", src, dst);
// UDIS86_ESIL (and, "%s&=%s,zf=%s==0,sf=%s>>%d,cf=0,of=0", dst, src, dst, dst, info->bits - 1);
RPN UDIS86_ESIL (and, "%s,%s,&=", src, dst);
#if 0
RPN UDIS86_ESIL (and, "%s,%s,&=,%s,!,zf,%s,%d,>>,sf,=,0,cf,=,0,of,=",
src, dst, dst, dst, info->bits-1);
#endif
// UDIS86_ESIL (test, "zf=%s&%s==0,sf=%s>>%d,cf=0,of=0", dst, src, dst, info->bits - 1);
RPN UDIS86_ESIL (test, "%s,%s,==,$z,zf,=", dst, src);
// UDIS86_ESIL (syscall, "$");
RPN UDIS86_ESIL (syscall, "$");
// UDIS86_ESIL (int3, "$3");
RPN UDIS86_ESIL (int3, "3,$");
// UDIS86_ESIL (int, "$0x%"PFMT64x, info->n);
RPN UDIS86_ESIL (int, "0x%"PFMT64x",$", info->n);
RPN UDIS86_ESIL (lea, "%s,%s,=", src, dst);
RPN UDIS86_ESIL (movzx, "%s,%s,=", src, dst); // not working? try 0fb63d55380000
RPN UDIS86_ESIL (mov, "%s,%s,=", src, dst);
// UDIS86_ESIL (push, "%s-=%d,%d[%s]=%s", info->sp, info->regsz, info->regsz, info->sp, dst);
RPN UDIS86_ESIL (push, "%s,%d,%s,-=,%s,=[%d]", dst, info->regsz, info->sp, info->sp, info->regsz);
// UDIS86_ESIL (pop, "%s=%d[%s],%s+=%d", dst, info->regsz, info->sp, info->sp, info->regsz);
RPN UDIS86_ESIL (pop, "%s,[%d],%s,=,%d,%s,+=",
info->sp, info->regsz, dst, info->regsz, info->sp);
RPN UDIS86_ESIL (leave, "%s,%s,=,%s,[%d],%s,%d,%s,-=",
info->bp, info->sp, info->sp, info->regsz, info->bp, info->regsz, info->sp);
RPN UDIS86_ESIL (ret, "%s,[%d],%s,=,%d,%s,+=", info->sp, info->regsz, info->pc, info->regsz, info->sp);
RPN UDIS86_ESIL (iretf, "%s,[%d],%s,=,%d,%s,+=", info->sp, info->regsz, info->pc, info->regsz, info->sp);
RPN UDIS86_ESIL (iretd, "%s,[%d],%s,=,%d,%s,+=", info->sp, info->regsz, info->pc, info->regsz, info->sp);
// UDIS86_ESIL (xchg, "%s^=%s,%s^=%s,%s^=%s", dst, src, src, dst, dst, src);
// TODO: add support for rpnesil tmp regs?
//RPN UDIS86_ESIL (xchg, "%s,%s,^=,%s,%s,^=,%s,%s,^=", src, dst, src, src, dst, dst);
RPN UDIS86_ESIL (xchg, "%s,%s,%s,=,%s,=", dst, src, dst, src);
UDIS86_ESIL (xadd, "%s^=%s,%s^=%s,%s^=%s,cf=%s<=-%s&%s!=0,of=!((%s^%s)>>%d)&(((%s+%s)^%s)>>%d),%s+=%s,zf=%s==0,sf=%s>>%d", dst, src, src, dst, dst, src, dst, src, src, dst, src, info->bits - 1, dst, src, src, info->bits - 1, dst, src, dst, dst, info->bits - 1);
UDIS86_ESIL (bt, "cf=%s&(1<<%d)!=0", dst, (int) info->n);
UDIS86_ESIL (btc, "cf=%s&(1<<%d)!=0,%s^=(1<<%d)", dst, (int) info->n, dst, (int) info->n);
UDIS86_ESIL (bts, "cf=%s&(1<<%d)!=0,%s|=(1<<%d)", dst, (int) info->n, dst, (int) info->n);
UDIS86_ESIL (btr, "cf=%s&(1<<%d)!=0,%s&=!(1<<%d)", dst, (int) info->n, dst, (int) info->n);
// UDIS86_ESIL (clc, "cf=0");
RPN UDIS86_ESIL (clc, "0,cf,=");
RPN UDIS86_ESIL (sti, "1,if,="); // interrupt flag
RPN UDIS86_ESIL (cli, "0,if,="); // interrupt flag
// UDIS86_ESIL (cld, "df=0");
RPN UDIS86_ESIL (std, "1,df,=");
RPN UDIS86_ESIL (cld, "0,df,=");
#define IS16 (info->bits==16)
#define IS32 (info->bits==32)
#define IS64 (info->bits==64)
#define RSZ (IS32?4:IS64?8:2)
RPN UDIS86_ESIL (pushad,
"%s"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]",
IS64?
"rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax"
: "edi,esi,ebp,esp,ebx,edx,ecx,eax",
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp
);
RPN UDIS86_ESIL (pusha,
"%s"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]"
",$r,%s,-=,%s,=[]",
IS64?
"rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax"
: "edi,esi,ebp,esp,ebx,edx,ecx,eax",
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp,
info->sp, info->sp
);
RPN UDIS86_ESIL (popad,
"%s", IS64?
"rsp,[],rdi,="
",8,rsp,+,[],rsi,="
",16,rsp,+,[],rbp,="
",24,rsp,+,[],rsp,="
",32,rsp,+,[],rbx,="
",40,rsp,+,[],rdx,="
",48,rsp,+,[],rcx,="
",56,rsp,+,[],rax,="
",64,rsp,+="
:
"esp,[],edi,="
",4,esp,+,[],esi,="
",8,esp,+,[],ebp,="
",12,esp,+,[],esp,="
",16,esp,+,[],ebx,="
",20,esp,+,[],edx,="
",24,esp,+,[],ecx,="
",28,esp,+,[],eax,="
",32,esp,+="
);
RPN UDIS86_ESIL (popa,
"%s", IS64?
"rsp,[],rdi,="
",8,rsp,+,[],rsi,="
",16,rsp,+,[],rbp,="
",24,rsp,+,[],rsp,="
",32,rsp,+,[],rbx,="
",40,rsp,+,[],rdx,="
",48,rsp,+,[],rcx,="
",56,rsp,+,[],rax,="
",64,rsp,+="
:
"esp,[],edi,="
",4,esp,+,[],esi,="
",8,esp,+,[],ebp,="
",12,esp,+,[],esp,="
",16,esp,+,[],ebx,="
",20,esp,+,[],edx,="
",24,esp,+,[],ecx,="
",28,esp,+,[],eax,="
",32,esp,+="
);
RPN UDIS86_ESIL (cmc, "cf,!=");
RPN UDIS86_ESIL (into, "of,?{,4,$,}");
RPN UDIS86_ESIL (lahf, "%s,ah,=", info->bits == 16 ? "flags" : (info->bits == 32 ? "eflags" : "rflags"));
RPN UDIS86_ESIL (loop, "1,%s,-=,!,?{%s,%s,=,}",
info->bits == 16 ? "cx" : IS32 ? "ecx" : "rcx",
dst, info->pc);
RPN UDIS86_ESIL (loope, "1,%s,-=,zf,?{,%s,%s,}",
info->bits == 16 ? "cx" : IS32 ? "ecx" : "rcx",
dst, info->pc);
RPN UDIS86_ESIL (loopne, "1,%s,-=,zf,!,?{,%s,%s,}",
info->bits == 16 ? "cx" : IS32 ? "ecx" : "rcx",
dst, info->pc);
#define OP(args, inst) [JOIN (UD_I, inst)] = {args, UDIS86_ESIL_HANDLER (inst)}
/* This is the fastest way I can think about to implement this list of handlers */
UDis86Esil udis86_esil_callback_table[ UD_MAX_MNEMONIC_CODE ] = {
OP (0, nop), OP (1, jo), OP (1, jno), OP (1, jb), OP (1, jae),
OP (1, je), OP (1, jne), OP (1, ja), OP (1, jbe), OP (1, js),
OP (1, jns), OP (1, jp), OP (1, jnp), OP (1, jl), OP (1, jge),
OP (1, jle), OP (1, jg), OP (1, jcxz),OP (1, jecxz),OP (1, jrcxz),
OP (1, jmp), OP (1, call), OP (2, shl), OP (2, rol), OP (2, ror),
OP (2, add), OP (1, inc), OP (2, sub), OP (1, dec), OP (2, cmp),
OP (2, xor), OP (2, or), OP (2, and), OP (2, test), OP (0, syscall),
OP (1, int), OP (2, lea), OP (2, mov), OP (1, push), OP (1, pop),
OP (0, leave),OP (0, ret), OP (2, xchg),OP (2, xadd), OP (2, bt),
OP (2, btc), OP (2, bts), OP (2, btr), OP (0, clc), OP (0, cli),
OP (0, cld), OP (0, cmc), OP (0, int3),OP (0, into), OP (0, lahf),
OP (1, loop), OP (1, loope),OP (1, loopne), OP(2,sar), OP (2, salc)
};
UDis86Esil * udis86_esil_get_handler (enum ud_mnemonic_code code) {
if (!udis86_esil_callback_table[code].callback)
return NULL;
return udis86_esil_callback_table + code;
}