/* radare - LGPL - Copyright 2009-2015 - pancake */ #include #include #include R_LIB_VERSION (r_reg); static const char *types[R_REG_TYPE_LAST+1] = { "gpr", "drx", "fpu", "mmx", "xmm", "flg", "seg", NULL }; R_API const char *r_reg_get_type(int idx) { if (idx>=0 && idxname); free (item->flags); free (item); } R_API int r_reg_get_name_idx(const char *type) { if (type && *type != '\0') switch (*type | (type[1]<<8)) { /* flags */ case 'z'+('f'<<8): return R_REG_NAME_ZF; case 's'+('f'<<8): return R_REG_NAME_SF; case 'c'+('f'<<8): return R_REG_NAME_CF; case 'o'+('f'<<8): return R_REG_NAME_OF; /* gpr */ case 'p'+('c'<<8): return R_REG_NAME_PC; case 's'+('r'<<8): return R_REG_NAME_SR; case 's'+('p'<<8): return R_REG_NAME_SP; case 'b'+('p'<<8): return R_REG_NAME_BP; case 's'+('n'<<8): return R_REG_NAME_SN; /* args */ case 'a'+('0'<<8): return R_REG_NAME_A0; case 'a'+('1'<<8): return R_REG_NAME_A1; case 'a'+('2'<<8): return R_REG_NAME_A2; case 'a'+('3'<<8): return R_REG_NAME_A3; case 'a'+('4'<<8): return R_REG_NAME_A4; case 'a'+('5'<<8): return R_REG_NAME_A5; case 'a'+('6'<<8): return R_REG_NAME_A6; } return -1; } R_API int r_reg_set_name(RReg *reg, int role, const char *name) { if (role>=0 && rolename[role] = r_str_dup (reg->name[role], name); return R_TRUE; } return R_FALSE; } R_API const char *r_reg_get_name(RReg *reg, int role) { if (reg && role>=0 && rolename[role]; return NULL; } R_API void r_reg_free_internal(RReg *reg) { int i; free (reg->reg_profile_str); reg->reg_profile_str = NULL; for (i = 0; i < R_REG_NAME_LAST; i++) { if (reg->name[i]) { free (reg->name[i]); reg->name[i] = NULL; } } for (i = 0; iregset[i].regs); reg->regset[i].regs = r_list_newf ((RListFree)r_reg_item_free); } reg->size = 0; } R_API void r_reg_free(RReg *reg) { int i; if (!reg) return; for (i = 0; i < R_REG_TYPE_LAST; i++) { r_list_purge (reg->regset[i].pool); reg->regset[i].pool = NULL; } r_reg_free_internal (reg); free (reg); } R_API RReg *r_reg_new() { RRegArena *arena; RReg *reg = R_NEW0 (RReg); int i; for (i=0; iregset[i].pool = r_list_newf ((RListFree)r_reg_arena_free); reg->regset[i].regs = r_list_newf ((RListFree)r_reg_item_free); reg->regset[i].arena = arena; //r_list_append (reg->regset[i].pool, arena); } /* swap arena back and forth to avoid lost reg sets */ r_reg_arena_swap (reg, R_FALSE); r_reg_arena_swap (reg, R_FALSE); return reg; } R_API ut64 r_reg_setv(RReg *reg, const char *name, ut64 val) { return r_reg_set_value (reg, r_reg_get (reg, name, -1), val); } R_API ut64 r_reg_getv(RReg *reg, const char *name) { return r_reg_get_value (reg, r_reg_get (reg, name, -1)); } R_API RRegItem *r_reg_get(RReg *reg, const char *name, int type) { RListIter *iter; RRegItem *r; int i, e; if (!reg || !name) return NULL; if (type == -1) { i = 0; e = R_REG_TYPE_LAST; } else { i = type; e = type+1; } for (; iregset[i].regs, iter, r) { if (r->name && !strcmp (r->name, name)) { return r; } } } return NULL; } R_API RList *r_reg_get_list(RReg *reg, int type) { if (type < 0 || type > (R_REG_TYPE_LAST-1)) return NULL; return reg->regset[type].regs; } R_API ut64 r_reg_cmp(RReg *reg, RRegItem *item) { ut64 ret, ret2; RListIter *it; int ptr = !(reg->iters%2); int len = (item->size/8); // TODO: must use r_mem_bitcmp or so.. flags not correctly checked int off = BITS2BYTES (item->offset); RRegArena *dst, *src; it = r_list_head (reg->regset[item->type].pool); if (!it || !it->n) return UT64_MAX; src = r_list_head (reg->regset[item->type].pool)->data; dst = it->n->data; if (off+len>src->size) len = src->size-off; if (off+len>dst->size) len = dst->size-off; if (len>1 && memcmp (dst->bytes+off, src->bytes+off, len)) { r_reg_arena_set (reg, ptr, 0); ret = r_reg_get_value (reg, item); r_reg_arena_set (reg, !ptr, 0); ret2 = r_reg_get_value (reg, item); return ret-ret2; } return 0LL; } // TODO regsize is in bits, delta in bytes, maybe we should standarize this.. R_API RRegItem *r_reg_get_at (RReg *reg, int type, int regsize, int delta) { RList *list = r_reg_get_list (reg, type); RRegItem *ri; RListIter *iter; r_list_foreach (list, iter, ri) { if (ri->size == regsize) { if (BITS2BYTES(ri->offset) == delta) return ri; } } return NULL; } /* return the next register in the current regset that differs from */ R_API RRegItem *r_reg_next_diff(RReg *reg, int type, const ut8* buf, int buflen, RRegItem *prev_ri, int regsize) { int bregsize = BITS2BYTES (regsize); RRegArena *arena; int delta; if (type < 0 || type > (R_REG_TYPE_LAST-1)) return NULL; arena = reg->regset[type].arena; delta = prev_ri? prev_ri->offset+prev_ri->size: 0; for (;;) { if (delta+bregsize>=arena->size || delta+bregsize >= buflen) break; if (memcmp (arena->bytes+delta, buf+delta, bregsize)) { RRegItem *ri = r_reg_get_at (reg, type, regsize, delta); if (ri) return ri; } delta += bregsize; } return NULL; } R_API RRegSet *r_reg_regset_get(RReg *r, int type) { RRegSet *rs; if (type<0 || type>=R_REG_TYPE_LAST) return NULL; rs = &r->regset[type]; if (rs->arena) return rs; return NULL; }