R_API bool r_anal_op_fini(RAnalOp *op) { if (!op) { return false; } if (((ut64)(size_t)op) == UT64_MAX) { return false; } if (((ut64)(size_t)op->mnemonic) == UT64_MAX) { return false; } r_anal_var_free (op->var); r_anal_value_free (op->src[0]); r_anal_value_free (op->src[1]); r_anal_value_free (op->src[2]); r_anal_value_free (op->dst); r_strbuf_fini (&op->esil); r_anal_switch_op_free (op->switch_op); op->src[0] = NULL; op->src[1] = NULL; op->src[2] = NULL; op->dst = NULL; op->var = NULL; op->switch_op = NULL; R_FREE (op->mnemonic); R_FREE (op->reg); return true; }
R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, int mask) { //len will end up in memcmp so check for negative if (!anal || len < 0) { return -1; } anal->decode = mask & R_ANAL_OP_MASK_ESIL ? true : false; anal->fillval = mask & R_ANAL_OP_MASK_VAL ? true : false; if (anal->pcalign) { if (addr % anal->pcalign) { memset (op, 0, sizeof (RAnalOp)); op->type = R_ANAL_OP_TYPE_ILL; op->addr = addr; op->size = 1; return -1; } } memset (op, 0, sizeof (RAnalOp)); if (len > 0 && anal->cur && anal->cur->op) { //use core binding to set asm.bits correctly based on the addr //this is because of the hassle of arm/thumb if (anal && anal->coreb.archbits) { anal->coreb.archbits (anal->coreb.core, addr); } int ret = anal->cur->op (anal, op, addr, data, len); if (ret < 1) { op->type = R_ANAL_OP_TYPE_ILL; } op->addr = addr; /* consider at least 1 byte to be part of the opcode */ if (op->nopcode < 1) { op->nopcode = 1; } //free the previous var in op->var RAnalVar *tmp = get_used_var (anal, op); if (tmp) { r_anal_var_free (op->var); op->var = tmp; } return ret; } if (!memcmp (data, "\xff\xff\xff\xff", R_MIN (4, len))) { op->type = R_ANAL_OP_TYPE_ILL; return R_MIN (2, len); // HACK } op->type = R_ANAL_OP_TYPE_MOV; if (op->cycles == 0) { op->cycles = defaultCycles (op); } return R_MIN (2, len); // HACK }
R_API void r_anal_op_fini(RAnalOp *op) { if (!op) // || !op->mnemonic) return; if (((ut64)(size_t)op) == UT64_MAX) { return; } if (((ut64)(size_t)op->mnemonic) == UT64_MAX) { return; } r_anal_var_free (op->var); r_anal_value_free (op->src[0]); r_anal_value_free (op->src[1]); r_anal_value_free (op->src[2]); r_anal_value_free (op->dst); r_anal_switch_op_free (op->switch_op); free (op->mnemonic); memset (op, 0, sizeof (RAnalOp)); }
R_API bool r_anal_op_fini(RAnalOp *op) { if (!op) { return false; } r_anal_var_free (op->var); op->var = NULL; r_anal_value_free (op->src[0]); r_anal_value_free (op->src[1]); r_anal_value_free (op->src[2]); op->src[0] = NULL; op->src[1] = NULL; op->src[2] = NULL; r_anal_value_free (op->dst); op->dst = NULL; r_strbuf_fini (&op->opex); r_strbuf_fini (&op->esil); r_anal_switch_op_free (op->switch_op); R_FREE (op->mnemonic); return true; }
R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { int ret = 0; RAnalVar *tmp; //len will end up in memcmp so check for negative if (!anal || len < 0) { return -1; } if (anal->pcalign) { if (addr % anal->pcalign) { memset (op, 0, sizeof (RAnalOp)); op->type = R_ANAL_OP_TYPE_ILL; op->addr = addr; op->size = 1; return -1; } } memset (op, 0, sizeof (RAnalOp)); if (len > 0 && anal->cur && anal->cur->op && strcmp (anal->cur->name, "null")) { ret = anal->cur->op (anal, op, addr, data, len); op->addr = addr; //free the previous var in op->var tmp = get_used_var (anal, op); if (tmp) { r_anal_var_free (op->var); op->var = tmp; } if (ret < 1) { op->type = R_ANAL_OP_TYPE_ILL; } } else { if (!memcmp (data, "\xff\xff\xff\xff", R_MIN(4, len))) { op->type = R_ANAL_OP_TYPE_ILL; ret = 2; // HACK } else { op->type = R_ANAL_OP_TYPE_MOV; } } return ret; }
static void type_match(RCore *core, ut64 addr, char *name) { Sdb *trace = core->anal->esil->db_trace; RAnal *anal = core->anal; RAnalVar *v; char *fcn_name; if (r_anal_type_func_exist (anal, name)) { fcn_name = strdup (name); } else if (!(fcn_name = r_anal_type_func_guess (anal, name))) { eprintf ("can't find function prototype for %s\n", name); return; } const char* cc = r_anal_type_func_cc (anal, fcn_name); if (!cc || !r_anal_cc_exist (anal, cc)) { eprintf ("can't find %s calling convention %s\n", fcn_name, cc); return; } int i, j, max = r_anal_type_func_args_count (anal, fcn_name); int size = 0, idx = sdb_num_get (trace, "idx", 0); const char *sp_name = r_reg_get_name (anal->reg, R_REG_NAME_SP); const char *bp_name = r_reg_get_name (anal->reg, R_REG_NAME_BP); ut64 sp = r_reg_getv (anal->reg, sp_name); ut64 bp = r_reg_getv (anal->reg, bp_name); for (i = 0; i < max; i++) { char *type = r_anal_type_func_args_type (anal, fcn_name, i); const char *name =r_anal_type_func_args_name (anal, fcn_name, i); const char *place = r_anal_cc_arg (anal, cc, i + 1); if (!strcmp (place, "stack")) { // type_match_stack (); for (j = idx; j >= 0; j--) { ut64 write_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.mem.write", j), 0); if (write_addr == sp + size) { ut64 instr_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.addr", j), 0); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, instr_addr, sdb_fmt (-1, "%s %s", type, name)); char *tmp = sdb_fmt (-1, "%d.mem.read", j); int i2, array_size = sdb_array_size (trace, tmp); for (i2 = 0; i2 < array_size; i2++) { if (bp_name) { int bp_idx = sdb_array_get_num (trace, tmp, i2, 0) - bp; if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_BPV, 1, bp_idx))) { r_anal_var_retype (anal, addr, 1, bp_idx, R_ANAL_VAR_KIND_BPV, type, -1, v->name); r_anal_var_free (v); } } int sp_idx = sdb_array_get_num (trace, tmp, i2, 0) - sp; if ((v = r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_SPV, 1, sp_idx))) { r_anal_var_retype (anal, addr, 1, sp_idx, R_ANAL_VAR_KIND_SPV, type, -1, v->name); r_anal_var_free (v); } } break; } } size += r_anal_type_get_size (anal, type) / 8; } else if (!strcmp (place , "stack_rev")) { // type_match_stack_rev (); free (type); int k; for ( k = max -1; k >=i; k--) { type = r_anal_type_func_args_type (anal, fcn_name, k); name =r_anal_type_func_args_name (anal, fcn_name, k); place = r_anal_cc_arg (anal, cc, k + 1); if (strcmp (place ,"stack_rev")) { break; } for (j = idx; j >= 0; j--) { ut64 write_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.mem.write", j), 0); if (write_addr == sp + size) { ut64 instr_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.addr", j), 0); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, instr_addr, sdb_fmt (-1, "%s %s", type, name)); char *tmp = sdb_fmt (-1, "%d.mem.read", j); int i2, array_size = sdb_array_size (trace, tmp); for (i2 = 0; i2 < array_size; i2++) { if (bp_name) { int bp_idx = sdb_array_get_num (trace, tmp, i2, 0) - bp; if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_BPV, 1, bp_idx))) { r_anal_var_retype (anal, addr, 1, bp_idx, R_ANAL_VAR_KIND_BPV, type, -1, v->name); r_anal_var_free (v); } } int sp_idx = sdb_array_get_num (trace, tmp, i2, 0) - sp; if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_SPV, 1, sp_idx))) { r_anal_var_retype (anal, addr, 1, sp_idx, R_ANAL_VAR_KIND_SPV, type, -1, v->name); r_anal_var_free (v); } } break; } } size += r_anal_type_get_size (anal, type) / 8; } break; } else { // type_match_reg (); for (j = idx; j >= 0; j--) { if (sdb_array_contains (trace, sdb_fmt (-1, "%d.reg.write", j), place, 0)) { ut64 instr_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.addr", j), 0); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, instr_addr, sdb_fmt (-1, "%s %s", type, name)); char *tmp = sdb_fmt (-1, "%d.mem.read", j); int i2, array_size = sdb_array_size (trace, tmp); for (i2 = 0; i2 < array_size; i2++) { if (bp_name) { int bp_idx = sdb_array_get_num (trace, tmp, i2, 0) - bp; if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_BPV, 1, bp_idx))) { r_anal_var_retype (anal, addr, 1, bp_idx, R_ANAL_VAR_KIND_BPV, type, -1, v->name); r_anal_var_free (v); } } int sp_idx = sdb_array_get_num (trace, tmp, i2, 0) - sp; if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_SPV, 1, sp_idx))) { r_anal_var_retype (anal, addr, 1, sp_idx, R_ANAL_VAR_KIND_SPV, type, -1, v->name); r_anal_var_free (v); } } break; } } } free (type); } free (fcn_name); }
void r_comment_vars(RCore *core, const char *input) { //TODO enable base64 and make it the default for C* RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); int idx; char *oname = NULL, *name = NULL; char *oldcomment = NULL; char *heap_comment = NULL; RAnalVar *var; if (input[1] == '?' || (input[0] != 'b' && input[0] != 'r' && input[0] != 's') ) { r_comment_var_help (core, input[0]); return; } if (!fcn) { eprintf ("Cant find function here\n"); return; } oname = name = strdup (input + 2); while (*name == ' ') { name++; } switch (input[1]) { case '*': case '\0': { RList *var_list; RListIter *iter; var_list = r_anal_var_list (core->anal, fcn, input[0]); r_list_foreach (var_list, iter, var) { oldcomment = r_meta_get_var_comment (core->anal, input[0], var->delta, fcn->addr); if (!oldcomment) { continue; } if (!input[1]) { r_cons_printf ("%s : %s\n", var->name, oldcomment); } else { r_cons_printf ("\"Cv%c %s base64:%s @ 0x%08"PFMT64x"\"\n", input[0], var->name, sdb_encode ((const ut8 *) oldcomment, strlen(oldcomment)), fcn->addr); } } } break; case ' ': { // TODO check that idx exist char *comment = strstr (name, " "); if (comment) { // new comment given if (*comment) { *comment++ = 0; } if (!strncmp (comment, "base64:", 7)) { heap_comment = (char *)sdb_decode (comment + 7, NULL); comment = heap_comment; } } var = r_anal_var_get_byname (core->anal, fcn, name); if (var) { idx = var->delta; } else if (!strncmp (name, "0x", 2)) { idx = (int) r_num_get (NULL, name); } else if (!strncmp (name, "-0x", 3)) { idx = -(int) r_num_get (NULL, name+1); } else { eprintf ("cant find variable named `%s`\n",name); free (heap_comment); break; } r_anal_var_free (var); if (!r_anal_var_get (core->anal, fcn->addr, input[0], 1, idx)) { eprintf ("cant find variable at given offset\n"); } else { oldcomment = r_meta_get_var_comment (core->anal, input[0], idx, fcn->addr); if (oldcomment) { if (comment && *comment) { char *text = r_str_newf ("%s\n%s", oldcomment, comment); r_meta_set_var_comment (core->anal, input[0], idx, fcn->addr, text); free (text); } else { r_cons_println (oldcomment); } } else { r_meta_set_var_comment (core->anal, input[0], idx, fcn->addr, comment); } } free (heap_comment); } break; case '-': var = r_anal_var_get_byname (core->anal,fcn, name); if (var) { idx = var->delta; } else if (!strncmp (name, "0x", 2)) { idx = (int) r_num_get (NULL, name); } else if (!strncmp (name, "-0x", 3)) { idx = -(int) r_num_get (NULL, name+1); }else { eprintf ("cant find variable named `%s`\n",name); break; } r_anal_var_free (var); //XXX TODO here we leak a var if (!r_anal_var_get (core->anal, fcn->addr, input[0],1,idx)) { eprintf ("cant find variable at given offset\n"); break; } r_meta_var_comment_del (core->anal, input[0], idx, fcn->addr); break; case '!': { char *comment; var = r_anal_var_get_byname (core->anal,fcn, name); if (!var) { eprintf ("cant find variable named `%s`\n",name); break; } oldcomment = r_meta_get_var_comment (core->anal, input[0], var->delta, fcn->addr); comment = r_core_editor (core, NULL, oldcomment); if (comment) { r_meta_var_comment_del (core->anal, input[0], var->delta, fcn->addr); r_meta_set_var_comment (core->anal, input[0], var->delta, fcn->addr, comment); free (comment); } r_anal_var_free (var); } break; }