Skip to content

Commit

Permalink
Fold same-typed variables if there are more than 3 (#3770)
Browse files Browse the repository at this point in the history
  • Loading branch information
PeiweiHu authored Aug 19, 2023
1 parent a91169e commit 03dd2d2
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 10 deletions.
16 changes: 16 additions & 0 deletions librz/core/cconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,19 @@ static void update_syscall_ns(RzCore *core) {
}
}

static bool cb_asm_varfold(void *core, void *node) {
char *choice[] = { "none", "group", "hide" };
RzConfigNode *n = node;
const char *user_choice = n->value;
for (int i = 0; i < sizeof(choice) / sizeof(choice[0]); i++) {
if (!strcmp(choice[i], user_choice)) {
return true;
}
}
RZ_LOG_ERROR("asm.var.fold: Invalid choice. Only support `none, group, hide`\n");
return false;
}

static bool cb_asmarch(void *user, void *data) {
char asmparser[32];
RzCore *core = (RzCore *)user;
Expand Down Expand Up @@ -3142,6 +3155,9 @@ RZ_API int rz_core_config_init(RzCore *core) {
SETBPREF("asm.var.access", "false", "Show accesses of local variables");
SETBPREF("asm.sub.var", "true", "Substitute variables in disassembly");
SETI("asm.var.summary", 0, "Show variables summary instead of full list in disasm (0, 1, 2)");
n = NODECB("asm.var.fold", "none", &cb_asm_varfold);
SETDESC(n, "Fold same-typed variables (support none, group, hide)");
SETOPTIONS(n, "none", "group", "hide", NULL);
SETBPREF("asm.sub.varonly", "true", "Substitute the entire variable expression with the local variable name (e.g. [local10h] instead of [ebp+local10h])");
SETBPREF("asm.sub.reg", "false", "Substitute register names with their associated role name (drp~=)");
SETBPREF("asm.sub.rel", "true", "Substitute pc relative expressions in disasm");
Expand Down
96 changes: 86 additions & 10 deletions librz/core/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ typedef struct {
bool show_fcnsize;
bool hinted_line;
int show_varsum;
const char *fold_var;
int midflags;
bool midbb;
bool midcursor;
Expand Down Expand Up @@ -615,6 +616,7 @@ static RzDisasmState *ds_init(RzCore *core) {
ds->show_fcnsize = rz_config_get_b(core->config, "asm.fcn.size");
ds->show_vars = rz_config_get_b(core->config, "asm.var");
ds->show_varsum = rz_config_get_i(core->config, "asm.var.summary");
ds->fold_var = rz_config_get(core->config, "asm.var.fold");
ds->show_varaccess = rz_config_get_b(core->config, "asm.var.access");
ds->maxrefs = rz_config_get_i(core->config, "asm.xrefs.max");
ds->maxflags = rz_config_get_i(core->config, "asm.flags.limit");
Expand Down Expand Up @@ -1742,6 +1744,79 @@ static void printVarSummary(RzDisasmState *ds, RzList /*<RzAnalysisVar *>*/ *lis
ds_newline(ds);
}

/**
* \brief Fold same-typed variables, set by asm.var.fold
* \return the steps that original iter needs to go forward
**/
static ut32 fold_variables(RzCore *core, RzDisasmState *ds, RzListIter /*<RzAnalysisVar *>*/ *iter) {
ut32 iter_mov = 0;
RzAnalysisVar *var = iter->data;
if (!strcmp(ds->fold_var, "none") || rz_analysis_var_is_arg(var)) {
return iter_mov;
}
char *vartype = rz_type_as_string(core->analysis->typedb, var->type);
RzListIter *temp_it = iter->n;
ut32 same_type_cnt = 1;
while (temp_it) {
RzAnalysisVar *temp_var = temp_it->data;
if (!temp_var) {
break;
}
char *temp_vartype = rz_type_as_string(core->analysis->typedb, temp_var->type);
if (!temp_vartype) {
break;
}
if (strcmp(temp_vartype, vartype) || rz_analysis_var_is_arg(temp_var)) {
free(temp_vartype);
break;
}
same_type_cnt += 1;
free(temp_vartype);
temp_it = temp_it->n;
}

// fold if more than 3 same-typed variables
if (same_type_cnt < 3) {
free(vartype);
return iter_mov;
}
RzStrBuf *sb = rz_strbuf_new(NULL);
rz_strbuf_appendf(sb, "var %s [", vartype);
// fold_var = group -> group every three var
// fold_var = hide -> group the first two var with ellipsis in tail
ut32 group_num = strcmp(ds->fold_var, "group") ? 2 : 3;
while (iter_mov < group_num) {
RzAnalysisVar *temp_var = iter->data;
const RzStackAddr off = temp_var->storage.stack_off;
const char sign = off >= 0 ? '+' : '-';
rz_strbuf_appendf(sb, "%s @ stack %c 0x%" PFMT64x "; ", temp_var->name, sign, RZ_ABS(off));
iter_mov++;
iter = iter->n;
}
// remove extra "; " in tail
rz_strbuf_slice(sb, 0, sb->len - 2);
if (!strcmp(ds->fold_var, "hide")) {
// add ellipsis
rz_strbuf_append(sb, " ...");
// boost iter to proper position
while (iter_mov < same_type_cnt) {
iter_mov++;
}
}
rz_strbuf_append(sb, "]");

ds_begin_line(ds);
ds_pre_xrefs(ds, false);
rz_cons_printf("%s; ", COLOR_ARG(ds, func_var));
char *line = rz_strbuf_drain(sb);
rz_cons_print(line);
rz_cons_print(COLOR_RESET(ds));
ds_newline(ds);
free(line);
free(vartype);
return iter_mov;
}

static void ds_show_functions(RzDisasmState *ds) {
RzAnalysisFunction *f;
RzCore *core = ds->core;
Expand Down Expand Up @@ -1839,25 +1914,26 @@ static void ds_show_functions(RzDisasmState *ds) {
}

if (ds->show_vars) {
if (ds->show_varsum && ds->show_varsum != -1) {
if (ds->show_varsum && ds->show_varsum != -1) { // show_varsum = 1 and 2
RzList *all_vars = vars_cache.stackvars;
rz_list_join(all_vars, vars_cache.regvars);
printVarSummary(ds, all_vars);
} else {
char spaces[32];
} else { // show_varum = 0 and -1
RzAnalysisVar *var;
RzListIter *iter;
RzList *all_vars = vars_cache.regvars;
rz_list_join(all_vars, vars_cache.stackvars);
rz_list_foreach (all_vars, iter, var) {
ds_begin_line(ds);
int idx;
memset(spaces, ' ', sizeof(spaces));
idx = 12 - strlen(var->name);
if (idx < 0) {
idx = 0;
// fold same-typed variables
ut32 iter_mov = fold_variables(core, ds, iter);
if (iter_mov > 0) {
int cnt = 0;
while (cnt++ < iter_mov - 1) {
iter = iter->n;
}
continue;
}
spaces[idx] = 0;
ds_begin_line(ds);
ds_pre_xrefs(ds, false);

if (ds->show_flgoff) {
Expand Down

0 comments on commit 03dd2d2

Please sign in to comment.