rizin/libr/anal/p/anal_ebc.c

179 lines
3.4 KiB
C

/* radare - LGPL - Copyright 2012-2013 - pancake, fedor.sakharov */
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include <r_anal.h>
#include <ebc_disas.h>
static void ebc_anal_jmp8(RAnalOp *op, ut64 addr, const ut8 *buf) {
int jmpadr = (int8_t)buf[1];
op->jump = addr + 2 + (jmpadr * 2);
op->addr = addr;
op->fail = addr + 2;
if (TEST_BIT(buf[0], 7)) {
op->type = R_ANAL_OP_TYPE_CJMP;
} else {
op->type = R_ANAL_OP_TYPE_JMP;
}
}
static void ebc_anal_jmp(RAnalOp *op, ut64 addr, const ut8 *buf) {
op->fail = addr + 6;
op->jump = (ut64)*(int32_t*)(buf + 2);
if (TEST_BIT(buf[1], 4))
op->jump += addr + 6;
if (buf[1] & 0x7) {
op->type = R_ANAL_OP_TYPE_UJMP;
} else {
if (TEST_BIT(buf[1], 7)) {
op->type = R_ANAL_OP_TYPE_CJMP;
} else {
op->type = R_ANAL_OP_TYPE_JMP;
}
}
}
static void ebc_anal_call(RAnalOp *op, ut64 addr, const ut8 *buf) {
int32_t addr_call;
op->fail = addr + 6;
if ((buf[1] & 0x7) == 0 && TEST_BIT(buf[0], 6) == 0
&& TEST_BIT(buf[0], 7)) {
addr_call = *(int32_t*)(buf + 2);
if (TEST_BIT(buf[1], 4)) {
op->jump = (addr + 6 + addr_call);
} else {
op->jump = addr_call;
}
op->type = R_ANAL_OP_TYPE_CALL;
} else {
op->type = R_ANAL_OP_TYPE_UCALL;
}
}
static int ebc_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
int ret;
ebc_command_t cmd;
ut8 opcode = buf[0] & EBC_OPCODE_MASK;
if (op == NULL)
return 2;
memset(op, 0, sizeof (RAnalOp));
op->addr = addr;
op->jump = op->fail = -1;
op->ptr = op->val = -1;
ret = op->size = ebc_decode_command(buf, &cmd);
if (ret < 0)
return ret;
switch (opcode) {
case EBC_JMP8:
ebc_anal_jmp8(op, addr, buf);
break;
case EBC_JMP:
ebc_anal_jmp(op, addr, buf);
break;
case EBC_MOVBW:
case EBC_MOVWW:
case EBC_MOVDW:
case EBC_MOVQW:
case EBC_MOVBD:
case EBC_MOVWD:
case EBC_MOVDD:
case EBC_MOVQD:
case EBC_MOVSNW:
case EBC_MOVSND:
case EBC_MOVQQ:
case EBC_MOVNW:
case EBC_MOVND:
case EBC_MOVI:
case EBC_MOVIN:
case EBC_MOVREL:
op->type = R_ANAL_OP_TYPE_MOV;
break;
case EBC_RET:
op->type = R_ANAL_OP_TYPE_RET;
break;
case EBC_CMPEQ:
case EBC_CMPLTE:
case EBC_CMPGTE:
case EBC_CMPULTE:
case EBC_CMPUGTE:
case EBC_CMPIEQ:
case EBC_CMPILTE:
case EBC_CMPIGTE:
case EBC_CMPIULTE:
case EBC_CMPIUGTE:
op->type = R_ANAL_OP_TYPE_CMP;
break;
case EBC_SHR:
op->type = R_ANAL_OP_TYPE_SHR;
break;
case EBC_SHL:
op->type = R_ANAL_OP_TYPE_SHL;
break;
case EBC_OR:
op->type = R_ANAL_OP_TYPE_OR;
break;
case EBC_XOR:
op->type = R_ANAL_OP_TYPE_XOR;
break;
case EBC_MUL:
op->type = R_ANAL_OP_TYPE_MUL;
break;
case EBC_PUSH:
op->type = R_ANAL_OP_TYPE_PUSH;
break;
case EBC_POP:
op->type = R_ANAL_OP_TYPE_POP;
break;
case EBC_AND:
op->type = R_ANAL_OP_TYPE_AND;
break;
case EBC_ADD:
op->type = R_ANAL_OP_TYPE_ADD;
break;
case EBC_SUB:
op->type = R_ANAL_OP_TYPE_SUB;
break;
case EBC_NEG:
op->type = R_ANAL_OP_TYPE_SUB;
break;
case EBC_CALL:
ebc_anal_call(op, addr, buf);
break;
case EBC_BREAK:
op->type = R_ANAL_OP_TYPE_SWI;
break;
default:
op->type = R_ANAL_OP_TYPE_UNK;
break;
}
return ret;
}
struct r_anal_plugin_t r_anal_plugin_ebc = {
.name = "ebc",
.desc = "EBC code analysis plugin",
.license = "LGPL3",
.arch = "ebc",
.bits = 64,
.op = &ebc_op,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_ebc,
.version = R2_VERSION
};
#endif