mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-02 19:55:14 +00:00
* Initial implementation of the subclassed RLFList class
- Implements a serialized RFList inside a RList container - Allows faster scans on contents * Initial import of the RAnalCond/Value code - Not yet usable..just refactoring.. - Handle null pointers in reg classes * Added not-yet-working emit_arm.c for r2rc tool
This commit is contained in:
parent
a129564c1c
commit
a580ff4fa8
@ -7,7 +7,7 @@ PFX=${DESTDIR}${PREFIX}
|
||||
|
||||
# Libraries
|
||||
LIBLIST=util cons line lib io meta lang flags bin hash config syscall socket
|
||||
LIBLIST+=cmd asm anal print parse search diff bp reg sign vm th db crypto debug core
|
||||
LIBLIST+=cmd reg asm anal print parse search diff bp sign vm th db crypto debug core
|
||||
|
||||
# TODO : generate single library linking against the rest
|
||||
#LIBSO=libr.so
|
||||
|
@ -1,5 +1,5 @@
|
||||
NAME=r_anal
|
||||
DEPS=r_util r_lib
|
||||
DEPS=r_util r_lib r_reg
|
||||
CFLAGS+=-DCORELIB -Iarch
|
||||
|
||||
include ../config.mk
|
||||
|
@ -25,6 +25,7 @@ R_API RAnal *r_anal_new() {
|
||||
RAnal *anal = R_NEW (RAnal);
|
||||
if (anal) {
|
||||
memset (anal, 0, sizeof (RAnal));
|
||||
anal->reg = NULL;
|
||||
anal->bbs = r_anal_bb_list_new ();
|
||||
anal->fcns = r_anal_fcn_list_new ();
|
||||
anal->vartypes = r_anal_var_type_list_new ();
|
||||
@ -63,8 +64,8 @@ R_API void r_anal_set_user_ptr(RAnal *anal, void *user) {
|
||||
|
||||
R_API int r_anal_add(RAnal *anal, RAnalPlugin *foo) {
|
||||
if (foo->init)
|
||||
foo->init(anal->user);
|
||||
list_add_tail(&(foo->list), &(anal->anals));
|
||||
foo->init (anal->user);
|
||||
list_add_tail (&(foo->list), &(anal->anals));
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
|
@ -67,14 +67,16 @@ R_API int r_anal_bb(RAnal *anal, RAnalBlock *bb, ut64 addr, ut8 *buf, ut64 len,
|
||||
case R_ANAL_OP_TYPE_CMP:
|
||||
bb->cond = r_anal_cond_new ();
|
||||
// TODO fill conditional information
|
||||
//bb->cond->type = 0; // UNKNOWN
|
||||
bb->cond->arg[0] = r_anal_value_new_from_aop(aop, 0);
|
||||
bb->cond->arg[1] = r_anal_value_new_from_aop(aop, 1);
|
||||
// bb->src = { 0,0,0,0,0 }
|
||||
// bb->dst = { 0,0,0,0,0 }
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
if (bb->cond) {
|
||||
// TODO: get values from anal backend
|
||||
bb->cond->type = R_ANAL_COND_TYPE_Z;
|
||||
bb->cond->negate = 0;
|
||||
bb->cond->type = R_ANAL_COND_EQ;
|
||||
} else eprintf ("Unknown conditional for block 0x%"PFMT64x"\n", bb->addr);
|
||||
bb->fail = aop->fail;
|
||||
bb->jump = aop->jump;
|
||||
|
@ -8,3 +8,47 @@ R_API RAnalCond *r_anal_cond_new() {
|
||||
memset (cond, 0, sizeof (RAnalCond));
|
||||
return cond;
|
||||
}
|
||||
|
||||
// XXX?
|
||||
R_API RAnalCond *r_anal_cond_clone(RAnalCond *cond) {
|
||||
RAnalCond *c = R_NEW (RAnalCond);
|
||||
memcpy (c, cond, sizeof (RAnalCond));
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline const char *condstring(RAnalCond *cond) {
|
||||
const char *condstr_single[] = { "!", "", "0<", "0<=", "0>", "0>=" };
|
||||
const char *condstr[] = { "==", "!=", ">=", ">", "<=", "<" };
|
||||
return (cond->arg[1])?condstr [cond->type%sizeof (condstr)]:
|
||||
condstr_single [cond->type%sizeof (condstr_single)];
|
||||
}
|
||||
|
||||
R_API int r_anal_cond_eval(RAnalCond *cond) {
|
||||
ut64 arg0 = 0;
|
||||
ut64 arg1 = 0;
|
||||
// TODO: collect register values and return true if matching
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API char *r_anal_cond_to_string(RAnalCond *cond) {
|
||||
char *out = NULL;
|
||||
const char *cnd = condstring (cond);
|
||||
char *val0 = r_anal_value_to_string (cond->arg[0]);
|
||||
char *val1 = r_anal_value_to_string (cond->arg[1]);
|
||||
if (val0) {
|
||||
if (R_ANAL_COND_SINGLE(cond)) {
|
||||
if ( (out = malloc (strlen (val0) + 10)) )
|
||||
sprintf (out, "%s%s", cnd, val0);
|
||||
} else if ( (out = malloc (strlen (val0) + strlen (val1)+10)) )
|
||||
sprintf (out, "%s %s %s", val0, cnd, val1);
|
||||
}
|
||||
free (val0);
|
||||
free (val1);
|
||||
return out;
|
||||
}
|
||||
|
||||
R_API RAnalCond *r_anal_cond_new_from_string(const char *str) {
|
||||
RAnalCond *cond = R_NEW (RAnalCond);
|
||||
// TODO: find '<','=','>','!'...
|
||||
return cond;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2009 */
|
||||
/* radare - LGPL - Copyright 2009-2010 */
|
||||
/* pancake<nopcode.org> */
|
||||
/* nibble<.ds@gmail.com> */
|
||||
|
||||
@ -30,7 +30,7 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
ut8 *buf = (ut8*)data;
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
memset (aop, '\0', sizeof (RAnalOp));
|
||||
memset (aop, 0, sizeof (RAnalOp));
|
||||
aop->type = R_ANAL_OP_TYPE_UNK;
|
||||
aop->addr = addr;
|
||||
aop->jump = -1;
|
||||
@ -66,7 +66,7 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
break;
|
||||
case 0x88:
|
||||
case 0x89: // move
|
||||
switch(buf[1]) {
|
||||
switch (buf[1]) {
|
||||
case 0x45:
|
||||
case 0x4d: // 894de0 mov [ebp-0x20], ecx
|
||||
case 0x55:
|
||||
@ -94,7 +94,6 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
case 0xcb: // lret
|
||||
case 0xcf: // iret
|
||||
aop->type = R_ANAL_OP_TYPE_RET;
|
||||
// aop->length = 1;
|
||||
aop->eob = 1;
|
||||
break;
|
||||
//case 0xea: // far jmp
|
||||
@ -105,10 +104,29 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
case 0x39:
|
||||
case 0x3c:
|
||||
case 0x3d:
|
||||
case 0x85:
|
||||
aop->type = R_ANAL_OP_TYPE_CMP;
|
||||
aop->type = R_ANAL_OP_TYPE_CMP;
|
||||
aop->length = 2;
|
||||
break;
|
||||
case 0x85:
|
||||
aop->type = R_ANAL_OP_TYPE_CMP;
|
||||
if (buf[1]>=0xc0 && buf[1]<=0xff) { // test eax, eax
|
||||
static const char *testregs[] = {
|
||||
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
|
||||
int src = buf[1]&7;
|
||||
int dst = (buf[1]&0x38)>>3;
|
||||
aop->src[0] = r_reg_get (anal->reg, testregs[src%8], R_REG_TYPE_GPR);
|
||||
aop->src[1] = r_reg_get (anal->reg, testregs[dst%8], R_REG_TYPE_GPR);
|
||||
if (aop->src[0] == aop->src[1])
|
||||
aop->src[1] = NULL;
|
||||
// eprintf ("0x%"PFMT64x": (%02x) %d %d\n", addr, buf[1], src, dst);
|
||||
} else if (buf[1]<0xc0) { // test [eax+delta], eax
|
||||
/* not yet supported */
|
||||
}
|
||||
// c0-c7 : eax, ecx, edx, ebx, esp, ebp, esi, edi
|
||||
// 83f821 cmp eax, 0x21
|
||||
// 85c0 test eax, eax
|
||||
// 85c9 test ecx, ecx
|
||||
break;
|
||||
case 0x90:
|
||||
aop->type = R_ANAL_OP_TYPE_NOP;
|
||||
aop->length = 1;
|
||||
@ -276,6 +294,11 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
aop->stackop = R_ANAL_STACK_INCSTACK;
|
||||
aop->stackptr = aop->value;
|
||||
break;
|
||||
case 0xf8:
|
||||
// 83f821 cmp eax, 0x21
|
||||
aop->type = R_ANAL_OP_TYPE_CMP;
|
||||
aop->length = 3;
|
||||
break;
|
||||
case 0xec:
|
||||
/* sub $0x????????, $esp*/
|
||||
aop->value = (ut64)(unsigned char)buf[2];
|
||||
@ -283,7 +306,7 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
aop->stackptr = aop->value;
|
||||
break;
|
||||
case 0xbd: /* 837dfc02 cmp dword [ebp-0x4], 0x2 */
|
||||
switch(buf[2]) {
|
||||
switch (buf[2]) {
|
||||
case 0xe0: // ebp
|
||||
if ((char)buf[2]>0) {
|
||||
aop->stackop = R_ANAL_STACK_GET;
|
||||
|
46
libr/anal/value.c
Normal file
46
libr/anal/value.c
Normal file
@ -0,0 +1,46 @@
|
||||
/* radare - LGPL - Copyright 2010 */
|
||||
/* pancake<nopcode.org> */
|
||||
|
||||
#include <r_anal.h>
|
||||
|
||||
R_API RAnalValue *r_anal_value_new() {
|
||||
RAnalValue *cond = R_NEW (RAnalValue);
|
||||
memset (cond, 0, sizeof (RAnalValue));
|
||||
return cond;
|
||||
}
|
||||
|
||||
R_API RAnalValue *r_anal_value_new_from_string(const char *str) {
|
||||
/* TODO */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: move into .h as #define free
|
||||
R_API void r_anal_value_free(RAnalValue *value) {
|
||||
free (value);
|
||||
}
|
||||
|
||||
R_API st64 r_anal_value_eval(RAnalValue *value) {
|
||||
/* OMFG TODO.. this is done by r_num_shit */
|
||||
// r_num_math (anal->num, ...);
|
||||
}
|
||||
|
||||
R_API char *r_anal_value_to_string (RAnalValue *value) {
|
||||
char *out = r_str_new ("");
|
||||
if (value->memref) out = r_str_concat (out, "[");
|
||||
if (value->mul) out = r_str_concatf (out, "%d*", value->mul);
|
||||
if (value->regbase) out = r_str_concatf (out, "%s+", value->regbase->name);
|
||||
if (value->regdelta) out = r_str_concatf (out, "%s+", value->regdelta->name);
|
||||
if (value->base!=0) out = r_str_concatf (out, "0x%"PFMT64x, value->base);
|
||||
if (value->delta>0) out = r_str_concatf (out, "+%d", value->delta);
|
||||
else if (value->delta<0) out = r_str_concatf (out, "%d", value->delta);
|
||||
if (value->memref) out = r_str_concat (out, "]");
|
||||
return out;
|
||||
}
|
||||
|
||||
R_API RAnalValue *r_anal_value_new_from_aop(RAnalOp *op, int idx) {
|
||||
RAnalValue *v = R_NEW (RAnalValue);
|
||||
if (idx<0 || idx> sizeof(op->arg) || !op->arg[idx])
|
||||
return NULL;
|
||||
TODO
|
||||
return v;
|
||||
}
|
@ -158,6 +158,7 @@ R_API int r_core_init(RCore *core) {
|
||||
core->flags = r_flag_new ();
|
||||
core->dbg = r_debug_new (R_TRUE);
|
||||
core->dbg->anal = core->anal; // XXX: dupped instance.. can cause lost pointerz
|
||||
core->dbg->anal->reg = core->anal->reg; // XXX: dupped instance.. can cause lost pointerz
|
||||
core->sign->printf = r_cons_printf;
|
||||
core->io->printf = r_cons_printf;
|
||||
core->dbg->printf = r_cons_printf;
|
||||
|
@ -13,7 +13,7 @@ static int r_debug_recoil(RDebug *dbg) {
|
||||
if (ri) {
|
||||
ut64 addr = r_reg_get_value (dbg->reg, ri);
|
||||
recoil = r_bp_recoil (dbg->bp, addr);
|
||||
eprintf ("Breakpoint recoil = %d\n", recoil);
|
||||
eprintf ("Recoil at 0x%"PFMT64x" = %d\n", addr, recoil);
|
||||
recoil = 1; // XXX hack
|
||||
if (recoil) {
|
||||
r_reg_set_value (dbg->reg, ri, addr-recoil);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <r_types.h>
|
||||
#include <list.h>
|
||||
#include <r_reg.h>
|
||||
#include <r_list.h>
|
||||
#include <r_util.h>
|
||||
|
||||
@ -58,12 +59,12 @@ enum {
|
||||
|
||||
/* TODO: what to do with signed/unsigned conditionals? */
|
||||
enum {
|
||||
R_ANAL_OP_COND_EQ = 0,
|
||||
R_ANAL_OP_COND_NE,
|
||||
R_ANAL_OP_COND_GE,
|
||||
R_ANAL_OP_COND_GT,
|
||||
R_ANAL_OP_COND_LE,
|
||||
R_ANAL_OP_COND_LT,
|
||||
R_ANAL_COND_EQ = 0,
|
||||
R_ANAL_COND_NE,
|
||||
R_ANAL_COND_GE,
|
||||
R_ANAL_COND_GT,
|
||||
R_ANAL_COND_LE,
|
||||
R_ANAL_COND_LT,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -125,62 +126,49 @@ typedef struct r_anal_t {
|
||||
RList *bbs;
|
||||
RList *fcns;
|
||||
RList *vartypes;
|
||||
RRegister *reg;
|
||||
struct r_anal_ctx_t *ctx;
|
||||
struct r_anal_plugin_t *cur;
|
||||
struct list_head anals;
|
||||
struct list_head anals; // XXX: use RList here
|
||||
} RAnal;
|
||||
|
||||
typedef struct r_anal_aop_t {
|
||||
char *mnemonic; /* mnemonic */
|
||||
ut64 addr; /* address */
|
||||
int type; /* type of opcode */
|
||||
int stackop; /* operation on stack? */
|
||||
int cond; /* condition type */
|
||||
int length; /* length in bytes of opcode */
|
||||
int nopcode; /* number of opcodes */
|
||||
int family; /* family of opcode */
|
||||
int eob; /* end of block (boolean) */
|
||||
ut64 jump; /* true jmp */
|
||||
ut64 fail; /* false jmp */
|
||||
st64 ref; /* reference to memory */ /* XXX signed? */
|
||||
ut64 value; /* reference to value */ /* XXX signed? */
|
||||
st64 stackptr; /* stack pointer */
|
||||
int r_dst[R_ANAL_MAXREG]; /* register arguments */
|
||||
ut64 i_dst[R_ANAL_MAXREG]; /* inmediate arguments */
|
||||
char *mnemonic; /* mnemonic */
|
||||
ut64 addr; /* address */
|
||||
int type; /* type of opcode */
|
||||
int stackop; /* operation on stack? */
|
||||
int cond; /* condition type */
|
||||
int length; /* length in bytes of opcode */
|
||||
int nopcode; /* number of opcodes */
|
||||
int family; /* family of opcode */
|
||||
int eob; /* end of block (boolean) */
|
||||
ut64 jump; /* true jmp */
|
||||
ut64 fail; /* false jmp */
|
||||
st64 ref; /* reference to memory */ /* XXX signed? */
|
||||
ut64 value; /* reference to value */ /* XXX signed? */
|
||||
st64 stackptr; /* stack pointer */
|
||||
RRegisterItem *src[3];
|
||||
RRegisterItem *dst;
|
||||
int refptr;
|
||||
} RAnalOp;
|
||||
|
||||
//mov 0x8175780(,%eax,4),%eax
|
||||
// value+regbase+regidx+delta
|
||||
typedef struct r_anal_value_t {
|
||||
int memref; // is memory reference? or value?
|
||||
ut64 base ; // numeric address
|
||||
int delta; // numeric delta
|
||||
int regbase; // register index used (-1 if no reg)
|
||||
int regdelta; // register index used (-1 if no reg)
|
||||
int mul; // multiplier (reg*4+base)
|
||||
// TODO: add multiplier
|
||||
RRegisterItem *regbase; // register index used (-1 if no reg)
|
||||
RRegisterItem *regdelta; // register index used (-1 if no reg)
|
||||
} RAnalValue;
|
||||
|
||||
enum {
|
||||
R_ANAL_COND_TYPE_Z = 0, //'z', // only 'src' used
|
||||
R_ANAL_COND_TYPE_E = 1,
|
||||
R_ANAL_COND_TYPE_G = 2,
|
||||
R_ANAL_COND_TYPE_GE = 1|2,
|
||||
};
|
||||
|
||||
// 80f92f cmp cl, 0x2f
|
||||
// 7543 jnz 0xb78b2dc0
|
||||
// cmp byte [ecx+eax-0x1], 0x2f
|
||||
// RAnalCond = {
|
||||
// .type = R_ANAL_COND_TYPE_Z,
|
||||
// .negate = 1,
|
||||
// .src = {
|
||||
#define R_ANAL_COND_SINGLE(x) (!x->arg[1] || x->arg[0]==x->arg[1])
|
||||
|
||||
typedef struct r_anal_cond_t {
|
||||
// filled by CJMP opcode
|
||||
int type;
|
||||
int negate;
|
||||
// filled by 'cmp' opcode
|
||||
RAnalValue src;
|
||||
RAnalValue dst;
|
||||
int type; // filled by CJMP opcode
|
||||
RAnalValue *arg[2]; // filled by CMP opcode
|
||||
} RAnalCond;
|
||||
|
||||
typedef struct r_anal_bb_t {
|
||||
@ -328,6 +316,10 @@ R_API RAnalVarAccess *r_anal_var_access_get(RAnal *anal, RAnalVar *var, ut64 fro
|
||||
|
||||
R_API RAnalCond *r_anal_cond_new();
|
||||
#define r_anal_cond_free(x) free(x);
|
||||
R_API int r_anal_cond_eval(RAnalCond *cond);
|
||||
R_API char *r_anal_cond_to_string(RAnalCond *cond);
|
||||
R_API char *r_anal_value_to_string (RAnalValue *value);
|
||||
R_API RAnalCond *r_anal_cond_new_from_string(const char *str);
|
||||
|
||||
/* reflines.c */
|
||||
R_API struct r_anal_refline_t *r_anal_reflines_get(RAnal *anal,
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef _INCLUDE_R_LIST_H_
|
||||
#define _INCLUDE_R_LIST_H_
|
||||
|
||||
#include <r_flist.h>
|
||||
|
||||
typedef void (*RListFree)(void *ptr);
|
||||
|
||||
typedef struct r_list_iter_t {
|
||||
@ -14,6 +16,12 @@ typedef struct r_list_t {
|
||||
RListFree free;
|
||||
} RList;
|
||||
|
||||
#define RListFList_Parent RList
|
||||
typedef struct r_lflist_t {
|
||||
RListFList_Parent super; // super class
|
||||
RFList *list;
|
||||
} RLFList;
|
||||
|
||||
#ifdef R_API
|
||||
#define r_list_foreach(list, it, pos) \
|
||||
for (it = list->head; it && (pos = it->data); it = it->n)
|
||||
@ -40,6 +48,26 @@ R_API RListIter *r_list_item_new (void *data);
|
||||
R_API void r_list_unlink (RList *list, void *ptr);
|
||||
R_API void r_list_split (RList *list, void *ptr);
|
||||
R_API void r_list_split_iter (RList *list, RListIter *iter);
|
||||
|
||||
/* rlistflist */
|
||||
#define r_lflist_new(x)
|
||||
#define r_lflist_length(x,y) r_list_length(x,y)
|
||||
#define r_lflist_destroy(x) r_lflist_deserialize(x), r_list_destroy(x)
|
||||
#define r_lflist_free(x) r_lflist_deserialize(x), r_list_free(x)
|
||||
#define r_lflist_append(x,y) r_lflist_deserialize(x), r_list_append(x,y)
|
||||
#define r_lflist_prepend(x,y) r_lflist_deserialize(x), r_list_prepend(x,y)
|
||||
#define r_lflist_delete(x,y) r_lflist_deserialize(x), r_list_delete(x,y)
|
||||
#define r_lflist_array(x) x->array?x->array:(x->array=r_lflist_serialize(x)),x->array
|
||||
#define r_lflist_deserialize(x) \
|
||||
free(x->array-1),x->array=0
|
||||
#define r_lflist_serialize(x) \
|
||||
x->array = r_flist_new(r_list_length(x)), { \
|
||||
int idx = 0; \
|
||||
void *ptr; \
|
||||
RListIter *iter; \
|
||||
r_list_foreach (x, iter, ptr) \
|
||||
r_flist_set (x->array, idx++, ptr); \
|
||||
} x->array;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -53,7 +53,7 @@ typedef struct r_reg_set_t {
|
||||
typedef struct r_reg_t {
|
||||
char *profile;
|
||||
char *name[R_REG_NAME_LAST];
|
||||
struct r_reg_set_t regset[R_REG_TYPE_LAST];
|
||||
RRegisterSet regset[R_REG_TYPE_LAST];
|
||||
} RRegister;
|
||||
|
||||
#define r_reg_new() r_reg_init (R_NEW (RRegister))
|
||||
|
@ -16,15 +16,14 @@ R_API const char *r_reg_get_type(int idx) {
|
||||
|
||||
static void r_reg_free_internal(struct r_reg_t *reg) {
|
||||
struct list_head *pos, *n;
|
||||
struct r_reg_item_t *r;
|
||||
RRegisterItem *r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
list_for_each_safe (pos, n, ®->regset[i].regs) {
|
||||
r = list_entry (pos, struct r_reg_item_t, list);
|
||||
list_del (&r->list);
|
||||
free (r);
|
||||
}
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++)
|
||||
list_for_each_safe (pos, n, ®->regset[i].regs) {
|
||||
r = list_entry (pos, RRegisterItem, list);
|
||||
list_del (&r->list);
|
||||
free (r);
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,14 +63,14 @@ R_API int r_reg_get_name_idx(const char *type) {
|
||||
R_API int r_reg_set_name(struct r_reg_t *reg, int role, const char *name) {
|
||||
int ret = R_TRUE;
|
||||
// TODO: ensure this range check in a define.. somewhere
|
||||
if (role>=0 && role<R_REG_NAME_LAST) {
|
||||
if (role>=0 && role<R_REG_NAME_LAST)
|
||||
reg->name[role] = r_str_dup (reg->name[role], name);
|
||||
} else ret = R_FALSE;
|
||||
else ret = R_FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API const char *r_reg_get_name(struct r_reg_t *reg, int role) {
|
||||
if (role>=0 && role<R_REG_NAME_LAST)
|
||||
if (reg && role>=0 && role<R_REG_NAME_LAST)
|
||||
return reg->name[role];
|
||||
return NULL;
|
||||
}
|
||||
@ -84,6 +83,7 @@ R_API struct r_reg_t *r_reg_free(struct r_reg_t *reg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: must be deprecated.. use from _new()
|
||||
R_API struct r_reg_t *r_reg_init(struct r_reg_t *reg) {
|
||||
int i;
|
||||
if (!reg)
|
||||
@ -102,18 +102,17 @@ R_API struct r_reg_t *r_reg_init(struct r_reg_t *reg) {
|
||||
return reg;
|
||||
}
|
||||
|
||||
static struct r_reg_item_t *r_reg_item_new() {
|
||||
struct r_reg_item_t *item = R_NEW (struct r_reg_item_t);
|
||||
memset (item, 0, sizeof(RRegisterItem));
|
||||
static RRegisterItem *r_reg_item_new() {
|
||||
RRegisterItem *item = R_NEW (RRegisterItem);
|
||||
memset (item, 0, sizeof (RRegisterItem));
|
||||
return item;
|
||||
}
|
||||
|
||||
R_API int r_reg_type_by_name(const char *str) {
|
||||
int i;
|
||||
for (i=0; types[i] && i<R_REG_TYPE_LAST; i++) {
|
||||
for (i=0; types[i] && i<R_REG_TYPE_LAST; i++)
|
||||
if (!strcmp (types[i], str))
|
||||
return i;
|
||||
}
|
||||
if (!strcmp (str, "all"))
|
||||
return R_REG_TYPE_ALL;
|
||||
eprintf ("Unknown register type: '%s'\n", str);
|
||||
@ -121,7 +120,7 @@ R_API int r_reg_type_by_name(const char *str) {
|
||||
}
|
||||
|
||||
/* TODO: make this parser better and cleaner */
|
||||
static int r_reg_set_word(struct r_reg_item_t *item, int idx, char *word) {
|
||||
static int r_reg_set_word(RRegisterItem *item, int idx, char *word) {
|
||||
int ret = R_TRUE;
|
||||
switch(idx) {
|
||||
case 0:
|
||||
@ -154,7 +153,7 @@ static int r_reg_set_word(struct r_reg_item_t *item, int idx, char *word) {
|
||||
}
|
||||
|
||||
/* TODO: make this parser better and cleaner */
|
||||
R_API int r_reg_set_profile_string(struct r_reg_t *reg, const char *str) {
|
||||
R_API int r_reg_set_profile_string(RRegister *reg, const char *str) {
|
||||
RRegisterItem *item;
|
||||
int setname = -1;
|
||||
int ret = R_FALSE;
|
||||
@ -163,7 +162,7 @@ R_API int r_reg_set_profile_string(struct r_reg_t *reg, const char *str) {
|
||||
int word = 0;
|
||||
char buf[256];
|
||||
|
||||
if (!str)
|
||||
if (!str||!reg)
|
||||
return R_FALSE;
|
||||
buf[0] = '\0';
|
||||
/* format file is: 'type name size offset packedsize' */
|
||||
@ -185,17 +184,15 @@ R_API int r_reg_set_profile_string(struct r_reg_t *reg, const char *str) {
|
||||
if (setname == -1)
|
||||
eprintf ("Invalid register type: '%s'\n", buf+1);
|
||||
} else
|
||||
if (lastchar != ' ' && lastchar != '\t') {
|
||||
if (lastchar != ' ' && lastchar != '\t')
|
||||
r_reg_set_word (item, word, buf);
|
||||
}
|
||||
chidx = 0;
|
||||
word++;
|
||||
break;
|
||||
case '\n':
|
||||
if (setname != -1) {
|
||||
if (setname != -1)
|
||||
r_reg_set_name (reg, setname, buf);
|
||||
} else
|
||||
if (word>3) {
|
||||
else if (word>3) {
|
||||
r_reg_set_word (item, word, buf);
|
||||
if (item->name != NULL) {
|
||||
list_add_tail(&item->list, ®->regset[item->type].regs);
|
||||
@ -206,7 +203,7 @@ R_API int r_reg_set_profile_string(struct r_reg_t *reg, const char *str) {
|
||||
setname = -1;
|
||||
break;
|
||||
default:
|
||||
if (chidx > 128) // WTF!!
|
||||
if (chidx>128) // WTF!!
|
||||
return R_FALSE;
|
||||
buf[chidx++] = *str;
|
||||
buf[chidx] = 0;
|
||||
@ -229,27 +226,26 @@ R_API int r_reg_set_profile(struct r_reg_t *reg, const char *profile) {
|
||||
const char *base;
|
||||
char *str, *file;
|
||||
/* TODO: append .regs extension to filename */
|
||||
str = r_file_slurp (profile, NULL);
|
||||
if (str == NULL) {
|
||||
if ((str = r_file_slurp (profile, NULL))==NULL) {
|
||||
// XXX we must define this varname in r_lib.h /compiletime/
|
||||
base = r_sys_getenv ("LIBR_PLUGINS");
|
||||
if (base) {
|
||||
file = r_str_concat (strdup(base), profile);
|
||||
file = r_str_concat (strdup (base), profile);
|
||||
str = r_file_slurp (file, NULL);
|
||||
free(file);
|
||||
free (file);
|
||||
}
|
||||
}
|
||||
if (str)
|
||||
ret = r_reg_set_profile_string(reg, str);
|
||||
if (str) ret = r_reg_set_profile_string (reg, str);
|
||||
else eprintf ("r_reg_set_profile: Cannot find '%s'\n", profile);
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name, int type) {
|
||||
R_API RRegisterItem *r_reg_get(struct r_reg_t *reg, const char *name, int type) {
|
||||
struct list_head *pos;
|
||||
struct r_reg_item_t *r;
|
||||
RRegisterItem *r;
|
||||
int i, e;
|
||||
|
||||
if (!reg)
|
||||
return NULL;
|
||||
if (type == -1) {
|
||||
i = 0;
|
||||
e = R_REG_TYPE_LAST;
|
||||
@ -258,18 +254,19 @@ R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name, int
|
||||
e = type+1;
|
||||
}
|
||||
|
||||
for (; i<e; i++) {
|
||||
list_for_each (pos, ®->regset[i].regs) {
|
||||
r = list_entry (pos, struct r_reg_item_t, list);
|
||||
if (!strcmp (r->name, name))
|
||||
return r;
|
||||
}
|
||||
// TODO: use RList here
|
||||
for (; i<e; i++)
|
||||
list_for_each (pos, ®->regset[i].regs) {
|
||||
r = list_entry (pos, RRegisterItem, list);
|
||||
if (!strcmp (r->name, name))
|
||||
return r;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: deprecate.. must use RList here
|
||||
R_API struct list_head *r_reg_get_list(struct r_reg_t *reg, int type) {
|
||||
if (type < 0 || type > R_REG_TYPE_LAST)
|
||||
if (type<0 || type>R_REG_TYPE_LAST)
|
||||
return NULL;
|
||||
return ®->regset[type].regs;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ PFX=${DESTDIR}${PREFIX}
|
||||
|
||||
all: r2rc
|
||||
|
||||
r2rc: r2rc.o emit_x86.o emit_x64.o out.o
|
||||
r2rc: r2rc.o emit_x86.o emit_x64.o emit_arm.o out.o
|
||||
gcc -I. out.o r2rc.o emit*.o -o r2rc
|
||||
|
||||
test:
|
||||
|
350
r2rc/emit_arm.c
Normal file
350
r2rc/emit_arm.c
Normal file
@ -0,0 +1,350 @@
|
||||
/* TODO */
|
||||
/* pancake // nopcode.org 2010 -- emit module for rcc */
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
#define EMIT_NAME emit_arm
|
||||
#define R_ARCH "arm"
|
||||
#define R_SZ 8
|
||||
#define R_SP "r14"
|
||||
#define R_BP "rbp" // XXX
|
||||
#define R_AX "r0"
|
||||
#define R_GP { "r0", "r1", "r2", "r3" }
|
||||
#define R_NGP 4
|
||||
|
||||
static char *regs[] = R_GP;
|
||||
|
||||
#if 0
|
||||
static void emit_sc (int num) {
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" sc $0x%x\n", num);
|
||||
#else
|
||||
rcc_printf (" sc 0x%x\n", num);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void emit_frame (int sz) {
|
||||
if (sz>0) rcc_printf (
|
||||
#if SYNTAX_ATT
|
||||
" push %%"R_BP"\n"
|
||||
" mov %%"R_SP", %%"R_BP"\n"
|
||||
" sub $%d, %%"R_SP"\n", sz);
|
||||
#else
|
||||
" push "R_BP"\n"
|
||||
" mov "R_BP", "R_SP"\n"
|
||||
" sub "R_SP", %d\n", sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_frame_end (int sz, int ctx) {
|
||||
if (sz>0) {
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" add $%d, %%"R_SP"\n", sz);
|
||||
rcc_printf (" pop %%"R_BP"\n");
|
||||
#else
|
||||
rcc_printf (" add "R_SP", %d\n", sz);
|
||||
rcc_printf (" pop "R_BP"\n");
|
||||
#endif
|
||||
}
|
||||
if (ctx>0)
|
||||
rcc_puts (" ret\n");
|
||||
}
|
||||
|
||||
static void emit_comment(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
va_start (ap, fmt);
|
||||
vsnprintf (buf, sizeof (buf), fmt, ap);
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" /* %s */\n", buf);
|
||||
#else
|
||||
rcc_printf ("# %s\n", buf);
|
||||
#endif
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
static void emit_equ (const char *key, const char *value) {
|
||||
rcc_printf (".equ %s,%s\n", key, value);
|
||||
}
|
||||
|
||||
static void emit_syscall_args(int nargs) {
|
||||
int j, k;
|
||||
for (j=0; j<nargs; j++) {
|
||||
k = j*R_SZ;
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" mov %d(%%"R_SP"), %%%s\n", k, regs[j+1]);
|
||||
#else
|
||||
rcc_printf (" mov %s, dword ["R_SP"%c%d]\n", regs[j+1], k>0?'+':' ', k);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_set_string(const char *dstvar, const char *str, int j) {
|
||||
char *p, str2[64];
|
||||
int i, oj = j;
|
||||
for (i=0; i<oj; i+=4) {
|
||||
/* XXX endian and 32/64bit issues */
|
||||
int *n = (int *)(str+i);
|
||||
p = mk_var (str2, dstvar, j);
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" movl $0x%x, %s\n", *n, p);
|
||||
#else
|
||||
rcc_printf (" mov %s, 0x%x\n", p, *n);
|
||||
#endif
|
||||
j -= 4;
|
||||
}
|
||||
p = mk_var (str2, dstvar, oj);
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" lea %s, %%"R_AX"\n", p);
|
||||
#else
|
||||
rcc_printf (" lea "R_AX", %s\n", p);
|
||||
#endif
|
||||
p = mk_var(str2, dstvar, 0);
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" mov %%"R_AX", %s\n", p);
|
||||
#else
|
||||
rcc_printf (" mov %s, "R_AX"\n", p);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_call(const char *str, int atr) {
|
||||
#if SYNTAX_ATT
|
||||
if (atr) rcc_printf(" call *%s\n", str);
|
||||
#else
|
||||
if (atr) rcc_printf(" call [%s]\n", str);
|
||||
#endif
|
||||
else rcc_printf(" call %s\n", str);
|
||||
}
|
||||
|
||||
static void emit_arg (int xs, int num, const char *str) {
|
||||
int d = atoi (str);
|
||||
#if !SYNTAX_ATT
|
||||
if (*str=='$')
|
||||
str = str +1;
|
||||
#endif
|
||||
switch(xs) {
|
||||
case 0:
|
||||
rcc_printf (" push %s\n", str);
|
||||
break;
|
||||
case '*':
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" push (%s)\n", str);
|
||||
#else
|
||||
rcc_printf (" push [%s]\n", str);
|
||||
#endif
|
||||
break;
|
||||
case '&':
|
||||
#if SYNTAX_ATT
|
||||
if (d != 0) rcc_printf (" addl $%d, %%"R_BP"\n", d);
|
||||
rcc_printf (" pushl %%"R_BP"\n");
|
||||
if (d != 0) rcc_printf (" subl $%d, %%"R_BP"\n", d);
|
||||
#else
|
||||
if (d != 0) rcc_printf (" add "R_BP", %d\n", d);
|
||||
rcc_printf (" push "R_BP"\n");
|
||||
if (d != 0) rcc_printf (" sub "R_BP", %d\n", d);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_get_result(const char *ocn) {
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" mov %%"R_AX", %s\n", ocn);
|
||||
#else
|
||||
rcc_printf (" mov %s, "R_AX"\n", ocn);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_restore_stack (int size) {
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf(" add $%d, %%"R_SP" /* args */\n", size);
|
||||
#else
|
||||
rcc_printf(" add "R_SP", %d\n", size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_get_while_end (char *str, const char *ctxpush, const char *label) {
|
||||
#if SYNTAX_ATT
|
||||
sprintf (str, " push %s\n jmp %s /* ---- */\n", ctxpush, label);
|
||||
#else
|
||||
sprintf (str, " push %s\n jmp %s\n", ctxpush, label);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_while_end (const char *labelback) {
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" pop %%"R_AX"\n");
|
||||
rcc_printf (" cmp $0, %%"R_AX"\n"); // XXX MUST SUPPORT != 0 COMPARE HERE
|
||||
rcc_printf (" jnz %s\n", labelback);
|
||||
#else
|
||||
rcc_printf (" pop "R_AX"\n");
|
||||
rcc_printf (" test "R_AX", "R_AX"\n"); // XXX MUST SUPPORT != 0 COMPARE HERE
|
||||
rcc_printf (" jnz %s\n", labelback);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_get_var (int type, char *out, int idx) {
|
||||
switch (type) {
|
||||
#if SYNTAX_ATT
|
||||
case 0: sprintf (out, "%d(%%"R_BP")", -idx); break; /* variable */
|
||||
case 1: sprintf(out, "%d(%%"R_SP")", idx); break; /* argument */
|
||||
#else
|
||||
case 0: sprintf (out, "dword ["R_BP"%c%d]", idx>0?' ':'+', -idx); break; /* variable */
|
||||
case 1: sprintf(out, "dword ["R_SP"%c%d]", idx>0?'+':' ', idx); break; /* argument */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_trap () {
|
||||
rcc_printf (" int3\n");
|
||||
}
|
||||
|
||||
static void emit_load_ptr(const char *dst) {
|
||||
int d = atoi (dst);
|
||||
eprintf ("HACK HACK HACK\n");
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" leal %d(%%"R_BP"), %%"R_AX"\n", d);
|
||||
#else
|
||||
// XXX: 32/64bit care
|
||||
rcc_printf (" leal "R_AX", dword ["R_BP"+%d]\n", d);
|
||||
#endif
|
||||
//rcc_printf (" movl %%"R_BP", %%"R_AX"\n");
|
||||
//rcc_printf (" addl $%d, %%"R_AX"\n", d);
|
||||
}
|
||||
|
||||
static void emit_branch(char *b, char *g, char *e, char *n, int sz, const char *dst) {
|
||||
char *p, str[64];
|
||||
char *arg = NULL;
|
||||
char *op = "jz";
|
||||
/* NOTE that jb/ja are inverted to fit cmp opcode */
|
||||
if (b) {
|
||||
*b = '\0';
|
||||
if (e) op = "jae";
|
||||
else op = "ja";
|
||||
arg = b+1;
|
||||
} else
|
||||
if (g) {
|
||||
*g = '\0';
|
||||
if (e) op = "jbe";
|
||||
else op = "jb";
|
||||
arg = g+1;
|
||||
}
|
||||
if (arg == NULL) {
|
||||
if (e) {
|
||||
arg = e+1;
|
||||
op = "jne";
|
||||
} else {
|
||||
arg = "$0";
|
||||
if (n) op = "jnz";
|
||||
else op ="jz";
|
||||
}
|
||||
}
|
||||
|
||||
if (*arg=='=') arg++; /* for <=, >=, ... */
|
||||
p = mk_var (str, arg, 0);
|
||||
#if SYNTAX_ATT
|
||||
rcc_printf (" pop %%"R_AX"\n"); /* TODO: add support for more than one arg get arg0 */
|
||||
rcc_printf (" cmp%c %s, %%"R_AX"\n", sz, p);
|
||||
#else
|
||||
rcc_printf (" pop "R_AX"\n"); /* TODO: add support for more than one arg get arg0 */
|
||||
rcc_printf (" cmp %s, "R_AX"\n", p);
|
||||
#endif
|
||||
// if (context>0)
|
||||
rcc_printf (" %s %s\n", op, dst);
|
||||
}
|
||||
|
||||
static void emit_load(const char *dst, int sz) {
|
||||
#if SYNTAX_ATT
|
||||
switch (sz) {
|
||||
case 'l':
|
||||
rcc_printf (" movl %s, %%"R_AX"\n", dst);
|
||||
rcc_printf (" movl (%%"R_AX"), %%"R_AX"\n");
|
||||
case 'b':
|
||||
rcc_printf (" movl %s, %%"R_AX"\n", dst);
|
||||
rcc_printf (" movzb (%%"R_AX"), %%"R_AX"\n");
|
||||
break;
|
||||
default:
|
||||
// TODO: unhandled?!?
|
||||
rcc_printf (" mov%c %s, %%"R_AX"\n", sz, dst);
|
||||
rcc_printf (" mov%c (%%"R_AX"), %%"R_AX"\n", sz);
|
||||
}
|
||||
#else
|
||||
switch (sz) {
|
||||
case 'l':
|
||||
rcc_printf (" mov "R_AX", %s\n", dst);
|
||||
rcc_printf (" mov "R_AX", ["R_AX"]\n");
|
||||
case 'b':
|
||||
rcc_printf (" mov "R_AX", %s\n", dst);
|
||||
rcc_printf (" movz "R_AX", ["R_AX"]\n");
|
||||
break;
|
||||
default:
|
||||
// TODO: unhandled?!?
|
||||
rcc_printf (" mov "R_AX", %s\n", dst);
|
||||
rcc_printf (" mov "R_AX", ["R_AX"]\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void emit_mathop(int ch, int vs, int type, const char *eq, const char *p) {
|
||||
char *op;
|
||||
switch (ch) {
|
||||
case '^': op = "xor"; break;
|
||||
case '&': op = "and"; break;
|
||||
case '|': op = "or"; break;
|
||||
case '-': op = "sub"; break;
|
||||
case '+': op = "add"; break;
|
||||
case '*': op = "mul"; break;
|
||||
case '/': op = "div"; break;
|
||||
default: op = "mov"; break;
|
||||
}
|
||||
#if SYNTAX_ATT
|
||||
if (eq == NULL) eq = "%"R_AX;
|
||||
if (p == NULL) p = "%"R_AX;
|
||||
rcc_printf (" %s%c %c%s, %s\n", op, vs, type, eq, p);
|
||||
#else
|
||||
if (eq == NULL) eq = R_AX;
|
||||
if (p == NULL) p = R_AX;
|
||||
// TODO:
|
||||
eprintf ("TYPE = %c\n", type);
|
||||
eprintf (" %s%c %c%s, %s\n", op, vs, type, eq, p);
|
||||
eprintf (" %s %s, [%s]\n", op, p, eq);
|
||||
if (type == '*') {
|
||||
rcc_printf (" %s %s, [%s]\n", op, p, eq);
|
||||
} else rcc_printf (" %s %s, %s\n", op, p, eq);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* emit_regs(int idx) {
|
||||
return regs[idx%R_NGP];
|
||||
}
|
||||
|
||||
struct emit_t EMIT_NAME = {
|
||||
.arch = R_ARCH,
|
||||
.size = R_SZ,
|
||||
.call = emit_call,
|
||||
.equ = emit_equ,
|
||||
.regs = emit_regs,
|
||||
//.sc = emit_sc,
|
||||
.trap = emit_trap,
|
||||
.frame = emit_frame,
|
||||
.frame_end = emit_frame_end,
|
||||
.comment = emit_comment,
|
||||
.push_arg = emit_arg,
|
||||
.restore_stack = emit_restore_stack,
|
||||
.get_result = emit_get_result,
|
||||
.syscall_args = emit_syscall_args,
|
||||
.set_string = emit_set_string,
|
||||
.get_var = emit_get_var,
|
||||
.while_end = emit_while_end,
|
||||
.get_while_end = emit_get_while_end,
|
||||
.branch = emit_branch,
|
||||
.load = emit_load,
|
||||
.load_ptr = emit_load_ptr,
|
||||
.mathop = emit_mathop,
|
||||
#if SYNTAX_ATT
|
||||
.syscall_body = ": mov $`.arg`, %"R_AX"\n: int $0x80\n",
|
||||
#else
|
||||
.syscall_body = ": mov "R_AX", `.arg`\n: int 0x80\n",
|
||||
#endif
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user