Enhace 8085 disasm and add basic code analysis support
This commit is contained in:
parent
5285d1bdea
commit
469db755bf
|
@ -0,0 +1,12 @@
|
|||
OBJ_8051=anal_8051.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_8051}
|
||||
TARGET_8051=anal_8051.${EXT_SO}
|
||||
|
||||
ALL_TARGETS+=${TARGET_8051}
|
||||
#LDFLAGS+=-L../../lib -lr_lib
|
||||
#LDFLAGS+=-L../../syscall -lr_syscall
|
||||
#LDFLAGS+=-L../../diff -lr_diff
|
||||
|
||||
${TARGET_8051}: ${OBJ_8051}
|
||||
${CC} $(call libname,anal_z80) ${LDFLAGS} ${CFLAGS} -o anal_8051.${EXT_SO} ${OBJ_8051}
|
|
@ -0,0 +1,72 @@
|
|||
/* radare - LGPL - Copyright 2013 - pancake */
|
||||
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_anal.h>
|
||||
#include "../../asm/arch/8051/8051.c"
|
||||
|
||||
static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
|
||||
char buf_asm[64];
|
||||
Op8051 o = do8051struct (buf, len);
|
||||
if (!o.name) return 0; // invalid instruction
|
||||
do8051disasm (o, addr, buf_asm, sizeof (buf_asm));
|
||||
if (buf_asm[0]=='p') {
|
||||
op->type = buf_asm[1]=='u'?
|
||||
R_ANAL_OP_TYPE_PUSH:
|
||||
R_ANAL_OP_TYPE_POP;
|
||||
} else
|
||||
if (!strncmp (buf_asm, "nop", 3)) {
|
||||
op->type = R_ANAL_OP_TYPE_NOP;
|
||||
} else
|
||||
if (!strncmp (buf_asm, "inv", 3)) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
} else
|
||||
if (!strncmp (buf_asm, "inc", 3)) {
|
||||
op->type = R_ANAL_OP_TYPE_ADD;
|
||||
} else
|
||||
if (!strncmp (buf_asm, "dec", 3)) {
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
} else
|
||||
if (!strncmp (buf_asm+1, "call", 4)) {
|
||||
op->type = R_ANAL_OP_TYPE_CALL;
|
||||
op->jump = o.addr;
|
||||
op->fail = addr+o.length;
|
||||
} else
|
||||
if (!strncmp (buf_asm, "ret", 3)) {
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
} else
|
||||
if (buf_asm[0]=='j' || buf_asm[1] == 'j') {
|
||||
op->type = R_ANAL_OP_TYPE_JMP;
|
||||
if (o.operand == OFFSET)
|
||||
op->jump = o.addr+addr+o.length;
|
||||
else
|
||||
op->jump = o.addr;
|
||||
op->fail = addr+o.length;
|
||||
}
|
||||
return op->length = o.length;
|
||||
}
|
||||
|
||||
struct r_anal_plugin_t r_anal_plugin_8051 = {
|
||||
.name = "8051",
|
||||
.arch = R_SYS_ARCH_8051,
|
||||
.bits = 16,
|
||||
.desc = "8051 CPU code analysis plugin",
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.op = &i8051_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_8051
|
||||
};
|
||||
#endif
|
|
@ -9,4 +9,4 @@ ALL_TARGETS+=${TARGET_I8080}
|
|||
#LDFLAGS+=-L../../diff -lr_diff
|
||||
|
||||
${TARGET_I8080}: ${OBJ_I8080}
|
||||
${CC} $(call libname,anal_z80) ${LDFLAGS} ${CFLAGS} -o anal_z80.${EXT_SO} ${OBJ_I8080}
|
||||
${CC} $(call libname,anal_z80) ${LDFLAGS} ${CFLAGS} -o anal_i8080.${EXT_SO} ${OBJ_I8080}
|
||||
|
|
|
@ -65,8 +65,8 @@ enum {
|
|||
#define _OFFSET(x) OFFSET, ((x[1])), NULL, buf
|
||||
#define _DIRECT(x) DIRECT, (x[1]), NULL, x
|
||||
|
||||
static const char *arg[] = { "#immed", "direct", "@r0", "@r1", "r0",
|
||||
"r1", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
|
||||
static const char *arg[] = { "#immed", "#imm", "@r0", "@r1",
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
|
||||
static const char *ops[] = {
|
||||
"inc", // 0. 04 : immed=a
|
||||
"dec", // 1. 14 : immed=a
|
||||
|
@ -75,15 +75,15 @@ static const char *ops[] = {
|
|||
"orl a,", // 4.
|
||||
"anl a,", // 5.
|
||||
"xrl a,", // 6.
|
||||
"+#immed;mov", // 7. 74 == immed=a
|
||||
"+, $1;mov", // 7. 74 == immed=a
|
||||
"mov direct,", // 8. 84 == DIV AB
|
||||
"subb a,", // 9.
|
||||
"+direct;mov", // A. A4 == MUL AB
|
||||
"+, $1;mov", // A. A4 == MUL AB
|
||||
"+, $1, $2;cjne",
|
||||
// B4, B4 = {cjne a, {#immed,direct}, offset}
|
||||
// cjne arg, #immed, offset
|
||||
"xch a,", // C. C4 == SWAP A
|
||||
"+offset;djnz", // D. D4 = DA
|
||||
"+, $1;djnz", // D. D4 = DA
|
||||
// D5 = DJNZ d,off
|
||||
// D6,7 = XCHD A, r0,1
|
||||
"mov a,", // E. E4 == CLR A
|
||||
|
@ -103,14 +103,14 @@ Op8051 do8051struct(const ut8 *buf, int len) {
|
|||
case 0x50: return _{ "jnc", 2, _OFFSET(buf) };
|
||||
case 0x60: return _{ "jz", 2, _OFFSET(buf) };
|
||||
case 0x70: return _{ "jnz", 2, _OFFSET(buf) };
|
||||
case 0x80: return _{ "sjmp", 2, _OFFSET(buf) };
|
||||
case 0x80: return _{ "sjmp", 2, _OFFSET (buf) };
|
||||
|
||||
case 0x90: return _{ "mov dptr, #immed", 3, _ADDR16(buf) }; // XXX
|
||||
case 0x90: return _{ "mov dptr,", 3, _ADDR16(buf) }; // XXX
|
||||
case 0xa0: return _{ "orl c, /bin", 2, NONE };
|
||||
case 0xb0: return _{ "anl c, /bin", 2, NONE };
|
||||
|
||||
case 0xc0: return _{ "push direct", 2, NONE };
|
||||
case 0xd0: return _{ "pop direct", 2, NONE };
|
||||
case 0xc0: return _{ "push", 2, _DIRECT (buf)};
|
||||
case 0xd0: return _{ "pop", 2, _DIRECT (buf)};
|
||||
|
||||
case 0x02: return _{ "ljmp", 3, _ADDR16(buf) };
|
||||
case 0x12: return _{ "lcall", 3, _ADDR16(buf) };
|
||||
|
@ -118,7 +118,7 @@ Op8051 do8051struct(const ut8 *buf, int len) {
|
|||
case 0x32: return _{ "reti", 1, NONE };
|
||||
case 0x42: return _{ "orl direct, a", 2, _DIRECT (buf)};
|
||||
case 0x92: return _{ "+, c;mov", 2, _DIRECT (buf) };
|
||||
case 0xc2: return _{ "clr c", 1, _DIRECT (buf) };
|
||||
case 0xc2: return _{ "clr bit", 2, _DIRECT (buf) };
|
||||
case 0xd2: return _{ "setb", 2, _DIRECT (buf) };
|
||||
case 0xa2: return _{ "mov c,", 2, _DIRECT (buf) };
|
||||
|
||||
|
@ -141,6 +141,7 @@ Op8051 do8051struct(const ut8 *buf, int len) {
|
|||
case 0xf0: return _{ "movx @dptr, a", 1, NONE };
|
||||
case 0xf2: return _{ "movx @r0, a", 1, NONE };
|
||||
case 0xf3: return _{ "movx @r1, a", 1, NONE };
|
||||
case 0x74: return _{ "mov a,", 2, _DIRECT(buf) };
|
||||
}
|
||||
// general opcodes
|
||||
if ((op&0xf)>=4) {
|
||||
|
@ -151,18 +152,23 @@ Op8051 do8051struct(const ut8 *buf, int len) {
|
|||
int length = ((op&0xf)<6)? 2: 1;
|
||||
/* exceptions */
|
||||
switch (op) {
|
||||
case 0x04: length = 1; opstr = "inc a"; break;
|
||||
case 0x04: length = 1; opstr = "inc a"; argstr=""; break;
|
||||
case 0x14: length = 1; opstr = "dec a"; break;
|
||||
case 0x74: opstr = "mov a,"; break;
|
||||
case 0x78: length = 2; break;
|
||||
case 0xaa: length = 2; break;
|
||||
case 0x77: length = 2; break;
|
||||
case 0x7f: length = 2; break;
|
||||
case 0xa4: opstr = "mul ab"; break;
|
||||
case 0xa5: opstr = "reserved"; break;
|
||||
case 0x75: length = 3; break;
|
||||
// XXX: 75 opcode is wrong
|
||||
case 0x75: opstr = "mov $1, #RAM_D0"; argstr=""; length = 3; break;
|
||||
case 0xc4: opstr = "swap a"; break;
|
||||
case 0xd4: opstr = "da a"; break;
|
||||
case 0xd5: opstr = "djnz d, "; break;
|
||||
case 0xd6: opstr = "xchd a, r0"; break;
|
||||
case 0xd7: opstr = "xchd a, r1"; break;
|
||||
case 0xe4: opstr = "clr a"; break;
|
||||
case 0xd8: length = 2; break;
|
||||
case 0xe4: opstr = "clr a"; argstr=""; length = 1; break;
|
||||
case 0xf4: opstr = "cpl a"; break;
|
||||
}
|
||||
/* exceptions */
|
||||
|
@ -192,13 +198,20 @@ static char *strdup_filter (const char *str, const ut8 *buf) {
|
|||
return o;
|
||||
}
|
||||
|
||||
char *do8051disasm(Op8051 op, char *str, int len) {
|
||||
char *do8051disasm(Op8051 op, ut32 addr, char *str, int len) {
|
||||
char *tmp, *eof, *out = str? str: malloc ((len=32));
|
||||
switch (op.operand) {
|
||||
case NONE: strcpy (out, op.name); break;
|
||||
case ARG: snprintf (out, len, "%s %s", op.name, op.arg); break;
|
||||
case ARG:
|
||||
if (!strncmp (op.arg, "#imm", 4))
|
||||
snprintf (out, len, "%s 0x%x", op.name, op.buf[1]);
|
||||
else snprintf (out, len, "%s %s", op.name, op.arg);
|
||||
break;
|
||||
case ADDR11:
|
||||
case ADDR16: snprintf (out, len, "%s %d", op.name, op.addr); break;
|
||||
case ADDR16:
|
||||
case DIRECT: snprintf (out, len, "%s 0x%02x", op.name, op.addr); break;
|
||||
case OFFSET:
|
||||
snprintf (out, len, "%s 0x%02x", op.name, op.addr+addr+2); break;
|
||||
}
|
||||
if (*out == '+') {
|
||||
eof = strchr (out+1, ';');
|
||||
|
@ -209,6 +222,10 @@ char *do8051disasm(Op8051 op, char *str, int len) {
|
|||
strcat (out, tmp);
|
||||
free (tmp);
|
||||
} else eprintf ("do8051disasm: Internal bug\n");
|
||||
} else {
|
||||
tmp = strdup_filter (out, (const ut8*)op.buf);
|
||||
strcpy (out, tmp);
|
||||
free (tmp);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -223,7 +240,7 @@ int main() {
|
|||
char *str;
|
||||
ut8 buf[3] = {0xb3, 0x11, 0x22};
|
||||
Op8051 op = do8051struct (buf, sizeof (buf));
|
||||
str = do8051disasm (op, NULL, 0);
|
||||
str = do8051disasm (op, 0, NULL, 0);
|
||||
eprintf ("%s\n", str);
|
||||
free (str);
|
||||
return 0;
|
||||
|
|
|
@ -11,8 +11,9 @@
|
|||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
Op8051 o = do8051struct (buf, len);
|
||||
*op->buf_asm = 0;
|
||||
if (!o.name) return 0; // invalid instruction
|
||||
do8051disasm (o, op->buf_asm, sizeof (op->buf_asm));
|
||||
do8051disasm (o, a->pc, op->buf_asm, sizeof (op->buf_asm));
|
||||
return (op->inst_len = o.length);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ static int buf_fprintf(void *stream, const char *format, ...) {
|
|||
}
|
||||
|
||||
int decodeInstr (bfd_vma address, disassemble_info * info);
|
||||
static int disassemble(RAsm *a, struct r_asm_op_t *op, const ut8 *buf, int len) {
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
static struct disassemble_info disasm_obj;
|
||||
if (len<4) return -1;
|
||||
buf_global = op->buf_asm;
|
||||
|
|
|
@ -596,6 +596,7 @@ toro:
|
|||
case R_ANAL_OP_TYPE_SWI:
|
||||
r_cons_printf (Color_MAGENTA);
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_ILL:
|
||||
case R_ANAL_OP_TYPE_TRAP:
|
||||
r_cons_printf (Color_BRED);
|
||||
break;
|
||||
|
|
|
@ -881,6 +881,7 @@ extern RAnalPlugin r_anal_plugin_bf;
|
|||
extern RAnalPlugin r_anal_plugin_m68k;
|
||||
extern RAnalPlugin r_anal_plugin_z80;
|
||||
extern RAnalPlugin r_anal_plugin_i8080;
|
||||
extern RAnalPlugin r_anal_plugin_8051;
|
||||
extern RAnalPlugin r_anal_plugin_arc;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -228,6 +228,7 @@ enum {
|
|||
R_SYS_ARCH_ARC = 0x8000,
|
||||
R_SYS_ARCH_I8080 = 0x10000,
|
||||
R_SYS_ARCH_RAR = 0x20000,
|
||||
R_SYS_ARCH_8051 = 0x40000,
|
||||
};
|
||||
|
||||
/* os */
|
||||
|
|
|
@ -33,6 +33,7 @@ anal.x86_im
|
|||
anal.x86_udis
|
||||
anal.x86_simple
|
||||
anal.z80
|
||||
anal.8051
|
||||
anal.i8080
|
||||
anal.arm
|
||||
anal.arc
|
||||
|
|
Loading…
Reference in New Issue