Skip to content

Commit

Permalink
cr16: Adds anal support
Browse files Browse the repository at this point in the history
  • Loading branch information
montekki committed Mar 24, 2014
1 parent ef7363c commit 9007211
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 2 deletions.
2 changes: 1 addition & 1 deletion libr/anal/p/Makefile
Expand Up @@ -10,7 +10,7 @@ all: ${ALL_TARGETS} ;

ALL_TARGETS=
# TODO: rename to enabled plugins
ARCHS=x86_udis.mk ppc.mk arm.mk avr.mk csr.mk dalvik.mk sh.mk ebc.mk gb.mk malbolge.mk ws.mk h8300.mk
ARCHS=x86_udis.mk ppc.mk arm.mk avr.mk csr.mk dalvik.mk sh.mk ebc.mk gb.mk malbolge.mk ws.mk h8300.mk cr16.mk
include $(ARCHS)

clean:
Expand Down
143 changes: 143 additions & 0 deletions libr/anal/p/anal_cr16.c
@@ -0,0 +1,143 @@
/* radare - LGPL - Copyright 2012-2013 - pancake
2014 - Fedor Sakharov <fedor.sakharov@gmail.com> */

#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include <r_anal.h>
#include <r_util.h>

#include <cr16_disas.h>

static int cr16_op(RAnal *anal, RAnalOp *op, ut64 addr,
const ut8 *buf, int len)
{
int ret;
struct cr16_cmd cmd;

memset(&cmd, 0, sizeof (cmd));
ret = cr16_decode_command(buf, &cmd);

if (ret <= 0) {
return ret;
}

memset(op, 0, sizeof (RAnalOp));

op->addr = addr;
op->jump = op->fail = -1;
op->ptr = op->val = -1;

switch (cmd.type) {
case CR16_TYPE_MOV:
op->type = R_ANAL_OP_TYPE_MOV;
break;
case CR16_TYPE_ADD:
op->type = R_ANAL_OP_TYPE_ADD;
break;
case CR16_TYPE_MUL:
op->type = R_ANAL_OP_TYPE_MUL;
break;
case CR16_TYPE_SUB:
op->type = R_ANAL_OP_TYPE_SUB;
break;
case CR16_TYPE_CMP:
op->type = R_ANAL_OP_TYPE_CMP;
break;
case CR16_TYPE_BE:
case CR16_TYPE_BNE:
op->type = R_ANAL_OP_TYPE_CJMP;
break;
case CR16_TYPE_AND:
op->type = R_ANAL_OP_TYPE_AND;
break;
case CR16_TYPE_OR:
op->type = R_ANAL_OP_TYPE_OR;
break;
case CR16_TYPE_SCOND:
break;
case CR16_TYPE_XOR:
op->type = R_ANAL_OP_TYPE_XOR;
break;
case CR16_TYPE_SHIFT:
op->type = R_ANAL_OP_TYPE_SHR;
break;
case CR16_TYPE_BIT:
op->type = R_ANAL_OP_TYPE_MOV;
break;
case CR16_TYPE_SLPR:
op->type = R_ANAL_OP_TYPE_MOV;
break;
case CR16_TYPE_BCOND:
if (cmd.reladdr) {
op->jump = addr + cmd.reladdr;
op->fail = addr + 2;
}
op->type = R_ANAL_OP_TYPE_CJMP;
break;
case CR16_TYPE_BR:
case CR16_TYPE_BAL:
op->type = R_ANAL_OP_TYPE_UJMP;
break;
case CR16_TYPE_EXCP:
op->type = R_ANAL_OP_TYPE_SWI;
break;
case CR16_TYPE_JCOND:
case CR16_TYPE_JAL:
case CR16_TYPE_JUMP:
case CR16_TYPE_JUMP_UNK:
op->type = R_ANAL_OP_TYPE_JMP;
break;
case CR16_TYPE_RETX:
op->type = R_ANAL_OP_TYPE_RET;
break;
case CR16_TYPE_PUSH:
op->type = R_ANAL_OP_TYPE_PUSH;
break;
case CR16_TYPE_POP:
op->type = R_ANAL_OP_TYPE_POP;
break;
case CR16_TYPE_LOAD:
case CR16_TYPE_DI:
case CR16_TYPE_EI:
case CR16_TYPE_STOR:
op->type = R_ANAL_OP_TYPE_MOV;
break;
case CR16_TYPE_NOP:
op->type = R_ANAL_OP_TYPE_NOP;
break;
case CR16_TYPE_WAIT:
case CR16_TYPE_EWAIT:
op->type = R_ANAL_OP_TYPE_SWI;
break;
default:
op->type = R_ANAL_OP_TYPE_UNK;
}

return ret;
}

struct r_anal_plugin_t r_anal_plugin_cr16 = {
.name = "cr16",
.desc = "CR16 code analysis plugin",
.license = "LGPL3",
.arch = R_SYS_ARCH_CR16,
.bits = 16,
.init = NULL,
.fini = NULL,
.op = cr16_op,
.set_reg_profile = NULL,
.fingerprint_bb = NULL,
.fingerprint_fcn = NULL,
.diff_bb = NULL,
.diff_fcn = NULL,
.diff_eval = NULL,
};

#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_cr16,
};
#endif
12 changes: 12 additions & 0 deletions libr/anal/p/cr16.mk
@@ -0,0 +1,12 @@
OBJ_CR16=anal_cr16.o

STATIC_OBJ+=${OBJ_CR16}
OBJ_CR16+=../../../../../../../../../../../${LTOP}/asm/arch/cr16/cr16_disas.o
TARGET_CR16=anal_cr16.${EXT_SO}

ALL_TARGETS+=${TARGET_CR16}

${TARGET_CR16}: ${OBJ_CR16} ${SHARED_OBJ}
$(call pwd)
${CC} $(call libname,anal_cr16) ${CFLAGS} \
-I../../include/ -o ${TARGET_CR16} ${OBJ_CR16}
94 changes: 93 additions & 1 deletion libr/asm/arch/cr16/cr16_disas.c
Expand Up @@ -160,6 +160,8 @@ static inline int cr16_print_ld_sw_opcode(struct cr16_cmd *cmd, ut16 instr)
snprintf(cmd->instr, CR16_INSTR_MAXLEN - 1, "%s%c", ld_sw[opcode],
cr16_get_opcode_i(instr) ? 'w' : 'b');

cmd->type = CR16_TYPE_MOV;

cmd->instr[CR16_INSTR_MAXLEN - 1] = '\0';

return 0;
Expand Down Expand Up @@ -366,6 +368,8 @@ static int cr16_decode_stcbiti(const ut8 *instr, struct cr16_cmd *cmd)
return -1;
}

cmd->type = CR16_TYPE_BIT;

return ret;
}

Expand Down Expand Up @@ -393,6 +397,45 @@ static inline int cr16_print_4bit_opcode(struct cr16_cmd *cmd, ut16 instr)
return 0;
}

static inline void cr16_anal_4bit_opcode(const ut16 in, struct cr16_cmd *cmd)
{
switch (cr16_get_opcode_low(in)) {
case CR16_ADDU:
case CR16_ADD:
cmd->type = CR16_TYPE_ADD;
break;
case CR16_BITI:
cmd->type = CR16_TYPE_BIT;
break;
case CR16_MUL:
cmd->type = CR16_TYPE_MUL;
break;
case CR16_SUBC:
case CR16_SUB:
cmd->type = CR16_TYPE_SUB;
break;
case CR16_CMP:
cmd->type = CR16_TYPE_CMP;
break;
case CR16_XOR:
cmd->type = CR16_TYPE_XOR;
break;
case CR16_OR:
cmd->type = CR16_TYPE_OR;
break;
case CR16_ASHU:
case CR16_LSH:
cmd->type = CR16_TYPE_SHIFT;
break;
case CR16_MOV:
cmd->type = CR16_TYPE_MOV;
break;
case CR16_AND:
cmd->type = CR16_TYPE_AND;
break;
}
}

static inline int cr16_decode_i_r(const ut8 *instr, struct cr16_cmd *cmd)
{
int ret = 2;
Expand All @@ -407,6 +450,7 @@ static inline int cr16_decode_i_r(const ut8 *instr, struct cr16_cmd *cmd)
if (cr16_print_4biti_opcode(cmd, in)) {
return -1;
}
cr16_anal_4bit_opcode(in, cmd);
} else {
if (cr16_print_4bit_opcode(cmd, in)) {
return -1;
Expand Down Expand Up @@ -607,6 +651,8 @@ static int cr16_decode_slpr(const ut8 *instr, struct cr16_cmd *cmd)
break;
}

cmd->type = CR16_TYPE_SLPR;

return ret;
}

Expand All @@ -625,6 +671,7 @@ static int cr16_decode_r_r(const ut8 *instr, struct cr16_cmd *cmd)
if (cr16_print_4biti_opcode(cmd, c)) {
return -1;
}
cr16_anal_4bit_opcode(c, cmd);
} else {
if (cr16_print_4bit_opcode(cmd, c)) {
return -1;
Expand Down Expand Up @@ -699,6 +746,7 @@ static int cr16_decode_jmp(const ut8 *instr, struct cr16_cmd *cmd)
}
snprintf(cmd->instr, CR16_INSTR_MAXLEN - 1, "jal");
cr16_print_reg_reg(cmd, cr16_get_dstreg(c), cr16_get_srcreg(c));
cmd->type = CR16_TYPE_JUMP_UNK;
break;
case 0x0B:
if (!(c & 1)) {
Expand All @@ -720,6 +768,7 @@ static int cr16_decode_jmp(const ut8 *instr, struct cr16_cmd *cmd)
cr16_regs_names[cr16_get_srcreg(c) + 1],
cr16_regs_names[cr16_get_srcreg(c)]);
}
cmd->type = CR16_TYPE_JUMP_UNK;
break;
default:
return -1;
Expand Down Expand Up @@ -757,9 +806,24 @@ static int cr16_decode_bcond_br(const ut8 *instr, struct cr16_cmd *cmd)
ret = 4;
r_mem_copyendian((ut8*)&disp, instr + 2, 2, LIL_ENDIAN);
disp32 = disp | (((c >> 1) & 0x7) << 17) | (((c >> 4) & 1) << 16);
if (disp32 & 0x80000) {
disp32 |= 0xFFF00000;
cmd->reladdr = (st32)disp32;
} else {
cmd->reladdr = disp32;
}
snprintf(cmd->operands, CR16_INSTR_MAXLEN - 1, "0x%08x", disp32);
} else {
disp = (c & 0x1F) | ((c >> 4) & 0x1E0);

if (disp & 0x0100) {
disp |= 0xFE00;
cmd->reladdr = (st16)disp;
} else {
cmd->reladdr = disp;
}

cmd->reladdr = disp;
snprintf(cmd->operands, CR16_INSTR_MAXLEN - 1, "0x%04x", disp);
}
}
Expand All @@ -772,13 +836,27 @@ static int cr16_decode_bcond_br(const ut8 *instr, struct cr16_cmd *cmd)
if ((c >> 8) == CR16_BCOND_2) {
r_mem_copyendian((ut8*)&disp, instr + 2, 2, LIL_ENDIAN);
disp32 = disp | (GET_BIT(c, 4) << 16);

if (disp32 & 0x80000) {
disp32 |= 0xFFF00000;
cmd->reladdr = (st32)disp32;
} else {
cmd->reladdr = disp32;
}
ret = 4;
} else {
disp = (c & 0x1F) | ((c >> 4) & 0x1E0);

if (disp & 0x0100) {
disp |= 0xFE00;
cmd->reladdr = (st16)disp;
} else {
cmd->reladdr = disp;
}

disp32 = disp;
}

cmd->type = CR16_TYPE_BCOND;
snprintf(cmd->operands, CR16_INSTR_MAXLEN - 1, "0x%04x", disp32);
}

Expand Down Expand Up @@ -822,6 +900,8 @@ static int cr16_decode_bcond01i(const ut8 *instr, struct cr16_cmd *cmd)
cr16_regs_names[cr16_get_dstreg(c)],
(c >> 1) & 0xF);

cmd->type = CR16_TYPE_BCOND;

return ret;
}

Expand All @@ -836,21 +916,27 @@ static int cr16_decode_misc(const ut8 *instr, struct cr16_cmd *cmd)
switch (c) {
case CR16_RETX:
strncpy(cmd->instr, "retx", CR16_INSTR_MAXLEN - 1);
cmd->type = CR16_TYPE_RETX;
break;
case CR16_DI:
strncpy(cmd->instr, "di", CR16_INSTR_MAXLEN - 1);
cmd->type = CR16_TYPE_DI;
break;
case CR16_EI:
strncpy(cmd->instr, "ei", CR16_INSTR_MAXLEN - 1);
cmd->type = CR16_TYPE_EI;
break;
case CR16_NOP:
strncpy(cmd->instr, "nop", CR16_INSTR_MAXLEN - 1);
cmd->type = CR16_TYPE_NOP;
break;
case CR16_WAIT:
strncpy(cmd->instr, "wait", CR16_INSTR_MAXLEN - 1);
cmd->type = CR16_TYPE_WAIT;
break;
case CR16_EWAIT:
strncpy(cmd->instr, "eiwait", CR16_INSTR_MAXLEN - 1);
cmd->type = CR16_TYPE_EWAIT;
break;
default:
switch (c >> 5) {
Expand All @@ -859,6 +945,7 @@ static int cr16_decode_misc(const ut8 *instr, struct cr16_cmd *cmd)
snprintf(cmd->operands, CR16_INSTR_MAXLEN - 1,
"0x%x", (c >> 1) & 0xF);
break;
cmd->type = CR16_TYPE_EXCP;
default:
ret = -1;
}
Expand Down Expand Up @@ -915,6 +1002,8 @@ int cr16_decode_loadm_storm(const ut8 *instr, struct cr16_cmd *cmd)
snprintf(cmd->operands, CR16_INSTR_MAXLEN - 1, "$0x%x",
((c >> 5) & 0x3) + 1);

cmd->type = CR16_TYPE_MOV;

return ret;
}

Expand Down Expand Up @@ -1018,6 +1107,8 @@ int cr16_decode_scond(const ut8 *instr, struct cr16_cmd *cmd)
snprintf(cmd->operands, CR16_INSTR_MAXLEN - 1, "%s",
cr16_regs_names[cr16_get_srcreg(c)]);

cmd->type = CR16_TYPE_SCOND;

return ret;
}

Expand Down Expand Up @@ -1071,6 +1162,7 @@ int cr16_decode_biti(const ut8 *instr, struct cr16_cmd *cmd)
ret = -1;
}

cmd->type = CR16_TYPE_BIT;
return ret;
}

Expand Down

0 comments on commit 9007211

Please sign in to comment.