diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index c035c70a67..0d6464c914 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -30,6 +30,7 @@ R_API RAnalFunction *r_anal_fcn_new() { fcn->diff = r_anal_diff_new (); fcn->args = NULL; fcn->locs = NULL; + fcn->locals = NULL; return fcn; } @@ -51,6 +52,7 @@ R_API void r_anal_fcn_free(void *_fcn) { r_list_free (fcn->vars); r_list_free (fcn->locs); r_list_free (fcn->bbs); + r_list_free (fcn->locals); free (fcn->fingerprint); r_anal_diff_free (fcn->diff); free (fcn->args); @@ -61,10 +63,10 @@ R_API int r_anal_fcn_xref_add (RAnal *anal, RAnalFunction *fcn, ut64 at, ut64 ad RAnalRef *ref; if (!fcn || !anal || !(ref = r_anal_ref_new ())) return R_FALSE; - ref->at = at; // from + ref->at = at; // from ref->addr = addr; // to ref->type = type; -r_anal_xrefs_set (anal, type=='d'?"data":"code", addr, at); + r_anal_xrefs_set (anal, type=='d'?"data":"code", addr, at); // TODO: ensure we are not dupping xrefs r_list_append (fcn->refs, ref); return R_TRUE; @@ -85,6 +87,47 @@ R_API int r_anal_fcn_xref_del (RAnal *anal, RAnalFunction *fcn, ut64 at, ut64 ad return R_FALSE; } +R_API int r_anal_fcn_local_add (RAnal *anal, RAnalFunction *fcn, ut64 addr, const char *name) { + RAnalFcnLocal *l = R_NEW0 (RAnalFcnLocal); + if (!fcn || !anal) { + return R_FALSE; + } + l->addr = addr; + l->name = strdup (name); + // TODO: do not allow duplicate locals! + if (!fcn->locals) + fcn->locals = r_list_new(); + r_list_append (fcn->locals, l); + return R_TRUE; +} + +R_API int r_anal_fcn_local_del_name (RAnal *anal, RAnalFunction *fcn, const char *name) { + RAnalFcnLocal *l; + RListIter *iter; + /* No need for _safe loop coz we return immediately after the delete. */ + r_list_foreach (fcn->locals, iter, l) { + if (!strcmp(l->name, name)) { + r_list_delete (fcn->locals, iter); + return R_TRUE; + } + } + return R_FALSE; +} + +R_API int r_anal_fcn_local_del_addr (RAnal *anal, RAnalFunction *fcn, ut64 addr) { + RAnalFcnLocal *l; + RListIter *iter; + /* No need for _safe loop coz we return immediately after the delete. */ + r_list_foreach (fcn->locals, iter, l) { + if (addr == 0UL || addr == l->addr) { + r_list_delete (fcn->locals, iter); + return R_TRUE; + } + } + return R_FALSE; +} + + R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int reftype) { RAnalOp op = {0}; char *varname; @@ -284,6 +327,17 @@ R_API RAnalFunction *r_anal_fcn_find(RAnal *anal, ut64 addr, int type) { #endif } +R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name) { + RAnalFunction *fcn = NULL; + RListIter *iter; + r_list_foreach (anal->fcns, iter, fcn) { + if (!strcmp(name, fcn->name)) + return fcn; + } + return NULL; +} + + /* rename RAnalFunctionBB.add() */ R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, int type, RAnalDiff *diff) { RAnalBlock *bb = NULL, *bbi; diff --git a/libr/cons/pal.c b/libr/cons/pal.c index 50d11fed77..7580af8e3a 100644 --- a/libr/cons/pal.c +++ b/libr/cons/pal.c @@ -10,6 +10,8 @@ R_API void r_cons_pal_init(const char *foo) { cons->pal.input = Color_WHITE; cons->pal.comment = Color_CYAN; cons->pal.fname = Color_CYAN; + cons->pal.flag = Color_CYAN; + cons->pal.label = Color_CYAN; cons->pal.flow = Color_CYAN; cons->pal.b0x00 = Color_GREEN; cons->pal.b0x7f = Color_YELLOW; @@ -87,6 +89,8 @@ struct { } keys[] = { { "comment", r_offsetof (RConsPalette, comment) }, { "fname", r_offsetof (RConsPalette, fname) }, + { "flag", r_offsetof (RConsPalette, flag) }, + { "label", r_offsetof (RConsPalette, label) }, { "flow", r_offsetof (RConsPalette, flow) }, { "prompt", r_offsetof (RConsPalette, prompt) }, { "offset", r_offsetof (RConsPalette, offset) }, diff --git a/libr/core/anal.c b/libr/core/anal.c index 248d7cee1a..c519ccf504 100644 --- a/libr/core/anal.c +++ b/libr/core/anal.c @@ -586,6 +586,18 @@ static void fcn_list_bbs(RAnalFunction *fcn) { } } +R_API void r_core_anal_fcn_local_list(RAnalFunction *fcn) { + if (fcn && fcn->locals) { + RAnalFcnLocal *loc; + RListIter *iter; + r_list_foreach (fcn->locals, iter, loc) { + if ((loc != NULL) && (loc->name != NULL)) + r_cons_printf (" %s at [%s + %lld] (0x%08llx)\n", loc->name, + fcn->name, loc->addr - fcn->addr, loc->addr); + } + } +} + R_API int r_core_anal_fcn_list(RCore *core, const char *input, int rad) { ut64 addr = r_num_math (core->num, input+1); RListIter *iter, *iter2; diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index 4c4b42d1c0..5ef007ddb6 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -870,7 +870,7 @@ static int cmd_anal(void *data, const char *input) { } break; case 'k': - { + { const char *r = r_anal_data_kind (core->anal, core->offset, core->block, core->blocksize); r_cons_printf ("%s\n", r); diff --git a/libr/core/cmd_flag.c b/libr/core/cmd_flag.c index 0afbe5f543..925101db88 100644 --- a/libr/core/cmd_flag.c +++ b/libr/core/cmd_flag.c @@ -40,7 +40,28 @@ static int cmd_flag(void *data, const char *input) { break; case '+': case ' ': { - char *s = NULL, *s2 = NULL, *eq = strchr (str, '='); + char *s = strchr (str, ' '), *s2 = NULL, *eq = strchr (str, '='); + if (s[1] == '.') { // local label, e.g. '.return' + RAnalFunction *fcn; + *s = '\0'; + s2 = strchr (s+1, ' '); + if (s2) { + *s2 = '\0'; + if (s2[1]&&s2[2]) + off = r_num_math (core->num, s2+1); + } + char *name = s + 1; + if (*name) { + fcn = r_anal_fcn_find (core->anal, off, + R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM); + if (fcn) { + eprintf ("Adding %s to fcn %s at 0x%08llx\n", name, fcn->name, off); + r_anal_fcn_local_add (core->anal, fcn, off, name); + } else eprintf ("Cannot find function at 0x%08llx\n", off); + } else eprintf ("Usage: f+ [.name] [addr]\n"); + break; + } + ut32 bsze = 1; //core->blocksize; if (eq) { // TODO: add support for '=' char in flag comments @@ -70,6 +91,18 @@ static int cmd_flag(void *data, const char *input) { else r_flag_unset (core->flags, flagname, NULL); } else r_flag_unset_i (core->flags, off, NULL); break; + case '.': + { + RAnalFunction *fcn; + char *name = strdup (input+2); + if (*name) { + fcn = r_anal_fcn_find_name (core->anal, name); + if (fcn) { + r_core_anal_fcn_local_list (fcn); + } else eprintf ("Cannot find function %s\n", name); + } else eprintf ("Usage: f. [fname]\n"); + } + break; case 'l': if (input[1] == ' ') { RFlagItem *item = r_flag_get_i (core->flags, @@ -248,8 +281,10 @@ static int cmd_flag(void *data, const char *input) { " f name 12 33 ; same as above\n" " f name 12 33 cmt ; same as above + set flag comment\n" " f+name 12 @ 33 ; like above but creates new one if doesnt exist\n" + " f+ .name 12 ; add local label at 12 offset, if it is inside function\n" " f-name ; remove flag 'name'\n" " f-@addr ; remove flag at address expression\n" + " f. fname ; list all local labels for the given function\n" " fd addr ; return flag+delta\n" //" fc [name] [cmt] ; set execution command for a specific flag\n" " fC [name] [cmt] ; set comment for given flag\n" diff --git a/libr/core/disasm.c b/libr/core/disasm.c index ddbea0fef4..e5adb2c228 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -139,6 +139,8 @@ R_API int r_core_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int l const char *color_comment = P(comment): Color_CYAN; const char *color_fname = P(fname): Color_CYAN; //const char *color_flow = P(flow): Color_CYAN; + const char *color_flag = P(flag): Color_CYAN; + const char *color_label = P(label): Color_CYAN; const char *color_nop = P(nop): Color_BLUE; const char *color_bin = P(bin): Color_YELLOW; const char *color_math = P(math): Color_YELLOW; @@ -467,6 +469,23 @@ toro: pre = "__"; // ignored? if (f) { //eprintf ("fun 0x%llx 0x%llx\n", at, f->addr+f->size-analop.length); + if (f->locals != NULL) { + RAnalFcnLocal *f_loc; + RListIter *l_iter; + r_list_foreach (f->locals, l_iter, f_loc) { + if (f_loc && f_loc->addr == at) { + if (show_lines && refline) + r_cons_strcat (refline); + if (show_offset) + r_cons_printf ("; -------- "); + if (show_color) + r_cons_printf ("%s %s\n", color_label, f_loc->name?f_loc->name:"unk"); + else + r_cons_printf (" %s\n", f_loc->name?f_loc->name:"unk"); + } + } + } + if (f->addr == at) { char *sign = r_anal_fcn_to_string (core->anal, f); if (f->type == R_ANAL_FCN_TYPE_LOC) { @@ -504,6 +523,8 @@ toro: if (show_flags) { flag = r_flag_get_i (core->flags, at); if (flag) { + if (show_color) + r_cons_printf("%s", color_flag); if (show_lines && refline) r_cons_strcat (refline); if (show_offset) diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 97da881193..96f705fd05 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -287,6 +287,11 @@ typedef struct r_anal_locals_t { RAnalType *items; } RAnalLocals; +typedef struct r_anal_fcn_local_t { + ut64 addr; + char* name; +} RAnalFcnLocal; + typedef struct r_anal_attr_t RAnalAttr; struct r_anal_attr_t { char *key; @@ -321,9 +326,10 @@ typedef struct r_anal_type_function_t { int depth; RAnalType *args; // list of arguments RAnalVarSub varsubs[R_ANAL_VARSUBS]; - RList *locs; // list of local variables ut8 *fingerprint; // TODO: make is fuzzy and smarter RAnalDiff *diff; + RList *locs; // list of local variables + RList *locals; // list of local labels RList *bbs; RList *vars; RList *refs; @@ -720,6 +726,7 @@ R_API const char *r_anal_op_to_esil_string(RAnal *anal, RAnalOp *op); R_API RAnalFunction *r_anal_fcn_new(); R_API int r_anal_fcn_is_in_offset (RAnalFunction *fcn, ut64 addr); R_API RAnalFunction *r_anal_fcn_find(RAnal *anal, ut64 addr, int type); +R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name); R_API RList *r_anal_fcn_list_new(); R_API int r_anal_fcn_insert(RAnal *anal, RAnalFunction *fcn); R_API void r_anal_fcn_free(void *fcn); @@ -731,6 +738,9 @@ R_API int r_anal_fcn_del(RAnal *anal, ut64 addr); R_API int r_anal_fcn_del_locs(RAnal *anal, ut64 addr); R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, int type, RAnalDiff *diff); +R_API int r_anal_fcn_local_add(RAnal *anal, RAnalFunction *fcn, ut64 addr, const char *name); +R_API int r_anal_fcn_local_del_name(RAnal *anal, RAnalFunction *fcn, const char *name); +R_API int r_anal_fcn_local_del_addr(RAnal *anal, RAnalFunction *fcn, ut64 addr); R_API int r_anal_fcn_cc(RAnalFunction *fcn); R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr); R_API int r_anal_fcn_overlap_bb(RAnalFunction *fcn, RAnalBlock *bb); diff --git a/libr/include/r_cons.h b/libr/include/r_cons.h index 91025fe984..2b82917f16 100644 --- a/libr/include/r_cons.h +++ b/libr/include/r_cons.h @@ -60,6 +60,8 @@ typedef struct r_cons_palette_t { char *offset; char *comment; char *fname; + char *flag; + char *label; char *flow; char *input; char *reset; diff --git a/libr/include/r_core.h b/libr/include/r_core.h index 0bb2236db7..ac58800101 100644 --- a/libr/include/r_core.h +++ b/libr/include/r_core.h @@ -232,6 +232,7 @@ R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head); R_API int r_core_anal_bb_seek(RCore *core, ut64 addr); R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth); R_API int r_core_anal_fcn_list(RCore *core, const char *input, int rad); +R_API void r_core_anal_fcn_local_list(RAnalFunction *fcn); R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts); R_API int r_core_anal_graph_fcn(RCore *core, char *input, int opts); R_API RList* r_core_anal_graph_to(RCore *core, ut64 addr, int n);