Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update 8051 anal plugin #15321

Merged
merged 9 commits into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 78 additions & 85 deletions libr/anal/p/anal_8051.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <r_anal.h>

#include <8051_ops.h>
#include <8051_disas.h>

typedef struct {
const char *name;
Expand Down Expand Up @@ -880,111 +881,105 @@ static ut32 map_direct_addr(RAnal *anal, ut8 addr) {
static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
set_cpu_model (anal, false);

op->delay = 0;

int i = 0;
while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) {
i++;
}

op->size = _8051_ops[i].len;
op->jump = op->fail = -1;
op->ptr = op->val = -1;

ut8 arg1 = _8051_ops[i].arg1;
ut8 arg2 = _8051_ops[i].arg2;

op->delay = 0;
op->cycles = _8051_ops[i].cycles;
op->failcycles = _8051_ops[i].cycles;
op->nopcode = 1;
op->size = _8051_ops[i].len;
op->type = _8051_ops[i].type;
op->family = R_ANAL_OP_FAMILY_CPU; // maybe also FAMILY_IO...
op->id = i;

switch (_8051_ops[i].instr) {
default:
op->cond = R_ANAL_COND_AL;
break;
case OP_CJNE:
case OP_DJNZ:
case OP_JB:
case OP_JBC:
case OP_JNZ:
op->cond = R_ANAL_COND_NE;
break;
case OP_JNB:
case OP_JZ:
op->cond = R_ANAL_COND_EQ;
break; case OP_JC:
op->cond = R_ANAL_COND_HS;
break; case OP_JNC:
op->cond = R_ANAL_COND_LO;
}

switch (_8051_ops[i].instr) {
default:
op->eob = false;
break;
case OP_CJNE:
case OP_DJNZ:
case OP_JB:
case OP_JBC:
case OP_JC:
case OP_JMP:
case OP_JNB:
case OP_JNC:
case OP_JNZ:
case OP_JZ:
op->eob = true;
}

// TODO: op->datatype

switch (arg1) {
case A_DIRECT:
default:
break; case A_DIRECT:
op->ptr = map_direct_addr (anal, buf[1]);
break;
case A_BIT:
break; case A_BIT:
op->ptr = map_direct_addr (anal, arg_bit (buf[1]));
break;
case A_IMMEDIATE:
break; case A_IMMEDIATE:
op->val = buf[1];
break;
case A_IMM16:
break; case A_IMM16:
op->val = buf[1] * 256 + buf[2];
op->ptr = op->val + i8051_reg_read (anal->reg, "_xdata"); // best guess, it's a XRAM pointer
break;
default:
break;
}

switch (arg2) {
case A_DIRECT:
default:
break; case A_DIRECT:
if (arg1 == A_RI || arg1 == A_RN) {
op->ptr = map_direct_addr (anal, buf[1]);
} else if (arg1 != A_DIRECT) {
op->ptr = map_direct_addr (anal, buf[2]);
}
break;
case A_BIT:
break; case A_BIT:
op->ptr = arg_bit ((arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]);
op->ptr = map_direct_addr (anal, op->ptr);
break;
case A_IMMEDIATE:
break; case A_IMMEDIATE:
op->val = (arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2];
break;
default:
break;
}

switch(_8051_ops[i].instr) {
case OP_PUSH:
op->type = R_ANAL_OP_TYPE_PUSH;
default:
break; case OP_PUSH:
op->stackop = R_ANAL_STACK_INC;
op->stackptr = 1;
break;
case OP_POP:
op->type = R_ANAL_OP_TYPE_POP;
break; case OP_POP:
op->stackop = R_ANAL_STACK_INC;
op->stackptr = -1;
break;
case OP_RET:
op->type = R_ANAL_OP_TYPE_RET;
break; case OP_RET:
op->stackop = R_ANAL_STACK_INC;
op->stackptr = -2;
break;
case OP_NOP:
op->type = R_ANAL_OP_TYPE_NOP;
break;
case OP_INC:
case OP_ADD:
case OP_ADDC:
op->type = R_ANAL_OP_TYPE_ADD;
break;
case OP_DEC:
case OP_SUBB:
op->type = R_ANAL_OP_TYPE_SUB;
break;
case OP_ANL:
op->type = R_ANAL_OP_TYPE_AND;
break;
case OP_ORL:
op->type = R_ANAL_OP_TYPE_OR;
break;
case OP_XRL:
op->type = R_ANAL_OP_TYPE_XOR;
break;
case OP_CPL:
op->type = R_ANAL_OP_TYPE_CPL;
break;
case OP_XCH:
op->type = R_ANAL_OP_TYPE_XCHG;
break;
case OP_MOV:
op->type = R_ANAL_OP_TYPE_MOV;
break;
case OP_MUL:
op->type = R_ANAL_OP_TYPE_MUL;
break;
case OP_DIV:
op->type = R_ANAL_OP_TYPE_DIV;
break;
case OP_CALL:
op->type = R_ANAL_OP_TYPE_CALL;
break; case OP_CALL:
op->stackop = R_ANAL_STACK_INC;
op->stackptr = 2;
if (arg1 == A_ADDR11) {
Expand All @@ -994,9 +989,7 @@ static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len
op->jump = 0x100 * buf[1] + buf[2];
op->fail = addr + op->size;
}
break;
case OP_JMP:
op->type = R_ANAL_OP_TYPE_JMP;
break; case OP_JMP:
if (arg1 == A_ADDR11) {
op->jump = arg_addr11 (addr + op->size, buf);
op->fail = addr + op->size;
Expand All @@ -1007,7 +1000,7 @@ static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len
op->jump = arg_offset (addr + op->size, buf[1]);
op->fail = addr + op->size;
}
break;
break;
case OP_CJNE:
case OP_DJNZ:
case OP_JC:
Expand All @@ -1017,20 +1010,8 @@ static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len
case OP_JB:
case OP_JBC:
case OP_JNB:
op->type = R_ANAL_OP_TYPE_CJMP;
if (op->size == 2) {
op->jump = arg_offset (addr + 2, buf[1]);
} else if (op->size == 3) {
op->jump = arg_offset (addr + 3, buf[2]);
}
op->jump = arg_offset (addr + op->size, buf[op->size - 1]);
op->fail = addr + op->size;
break;
case OP_INVALID:
op->type = R_ANAL_OP_TYPE_ILL;
break;
default:
op->type = R_ANAL_OP_TYPE_UNK;
break;
}

if (op->ptr != -1 && op->refptr == 0) {
Expand All @@ -1043,6 +1024,18 @@ static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len
analop_esil (anal, op, addr, copy);
}

// It fills RAnalop->mnemonic // should be RAnalOp->disasm // only from r_core_anal_op()
if (mask & R_ANAL_OP_MASK_DISASM) {
RAsmOp*aop = r_asm_op_new ();
r_8051_disas (addr, aop, buf, len);
op->mnemonic = strdup(r_strbuf_get (&aop->buf_asm));
r_asm_op_free (aop);
}

if (mask & R_ANAL_OP_MASK_HINT) {
// TODO: op->hint
}

return op->size;
}

Expand Down
4 changes: 2 additions & 2 deletions libr/asm/arch/8051/8051_disas.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static const char *_8051_regs[] = {
0, 0, 0, 0, 0, 0, 0, 0 // 0xf8
};

char* _replace_register (char* disasm, ut8 arg, ut8 val) {
static char* _replace_register (char* disasm, ut8 arg, ut8 val) {
char key[10];
char subst[10];
if (arg == A_DIRECT) {
Expand All @@ -62,7 +62,7 @@ char* _replace_register (char* disasm, ut8 arg, ut8 val) {
return disasm;
}

int _8051_disas (ut64 pc, RAsmOp *op, const ut8 *buf, ut64 len) {
int r_8051_disas (ut64 pc, RAsmOp *op, const ut8 *buf, ut64 len) {
int i = 0;
while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) {
i++;
Expand Down
2 changes: 1 addition & 1 deletion libr/asm/arch/8051/8051_disas.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef R2_8051_DISAS_H
#define R2_8051_DISAS_H

int _8051_disas (ut64 pc, RAsmOp *op, const ut8 *buf, ut64 len);
R_API int r_8051_disas (ut64 pc, RAsmOp *op, const ut8 *buf, ut64 len);

#endif
Loading