* 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:
pancake 2010-06-16 09:42:46 +02:00
parent a129564c1c
commit a580ff4fa8
15 changed files with 585 additions and 101 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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
View 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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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))

View File

@ -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, &reg->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, &reg->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, &reg->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, &reg->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, &reg->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 &reg->regset[type].regs;
}

View File

@ -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
View 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
};