Skip to content

Commit

Permalink
Added display of strings in disassembly for PIC binaries (#7112)
Browse files Browse the repository at this point in the history
* Added refs to disassembly

* Added comments for lea references

* Bug fixes

* arm and mips tests

* Fixed merge conflicts
  • Loading branch information
SrimantaBarua authored and radare committed Mar 27, 2017
1 parent 854cf38 commit 2ce093b
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 39 deletions.
5 changes: 1 addition & 4 deletions libr/core/canal.c
Original file line number Diff line number Diff line change
Expand Up @@ -3622,10 +3622,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
if (core->anal->cur && strcmp (core->anal->cur->arch, "arm")) {
if (cfg_anal_strings) {
if (CHECKREF (ESIL->cur)) {
r_anal_ref_add (core->anal, ESIL->cur, cur, 'd');
if ((target && ESIL->cur == ntarget) || !target) {
add_string_ref (core, ESIL->cur);
}
r_anal_ref_add (core->anal, ESIL->cur, cur, 's');
}
}
}
Expand Down
109 changes: 75 additions & 34 deletions libr/core/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,8 @@ static void ds_build_op_str(RDisasmState *ds) {
}
/* initialize */
core->parser->hint = ds->hint;
core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
core->parser->relsub_addr = 0;
if (ds->varsub && ds->opstr) {
ut64 at = ds->vat;
RAnalFunction *f = r_anal_get_fcn_in (core->anal, at, R_ANAL_FCN_TYPE_NULL);
Expand All @@ -700,6 +702,19 @@ static void ds_build_op_str(RDisasmState *ds) {
free (ds->opstr);
ds->opstr = strdup (ds->strsub);
}
if (core->parser->relsub) {
RList *list = r_anal_refs_get (core->anal, at);
RListIter *iter;
RAnalRef *ref;
r_list_foreach (list, iter, ref) {
if ((ref->type == R_ANAL_REF_TYPE_DATA
|| ref->type == R_ANAL_REF_TYPE_STRING)
&& ds->analop.type == R_ANAL_OP_TYPE_LEA) {
core->parser->relsub_addr = ref->addr;
break;
}
}
}
}
char *asm_str = colorize_asm_string (core, ds);
if (ds->decode) {
Expand Down Expand Up @@ -727,17 +742,20 @@ static void ds_build_op_str(RDisasmState *ds) {
core->parser->flagspace = -1;
}
}
RCore *core = ds->core;
core->parser->relsub_addr = 0;
if (ds->analop.refptr) {
ut64 num = r_io_read_i (core->io, ds->analop.ptr, 8);
core->parser->relsub_addr = num;
if (core->parser->relsub_addr == 0) {
core->parser->relsub_addr = num;
}
}
r_parse_filter (core->parser, core->flags, asm_str, ds->str, sizeof (ds->str), core->print->big_endian);
r_parse_filter (core->parser, core->flags, ds->opstr, ds->str, sizeof (ds->str), core->print->big_endian);
core->parser->flagspace = ofs;
free (ds->opstr);
ds->opstr = strdup (ds->str);
core->parser->flagspace = ofs; // ???
asm_str = colorize_asm_string (core, ds);
free (ds->opstr);
ds->opstr = strdup (asm_str);
//core->parser->flagspace = ofs; // ???
} else {
if (!ds->opstr) {
ds->opstr = strdup (asm_str? asm_str: "");
Expand Down Expand Up @@ -2427,7 +2445,7 @@ static void ds_print_core_vmode(RDisasmState *ds) {
if (shortcut) {
if (core->is_asmqjmps_letter) {
r_cons_printf (" ;[g%s]", shortcut);
} else {
} else {
r_cons_printf (" ;[%s]", shortcut);
}
free (shortcut);
Expand Down Expand Up @@ -2574,6 +2592,9 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
RCore *core = ds->core;
ut64 p = ds->analop.ptr;
ut64 v = ds->analop.val;
ut64 refaddr = p;
RFlagItem *f, *f2;
bool is_lea_str = false;;
char *esc = ds->show_comment_right? " ": "";
char *nl = ds->show_comment_right? "" : "\n";
bool string_found = false;
Expand All @@ -2585,22 +2606,40 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
ALIGN;
ds_comment (ds, true, "%s; '%c'%s", esc, ch, nl);
}
RList *list = NULL;
RListIter *iter;
RAnalRef *ref;
list = r_anal_refs_get (core->anal, ds->at);
r_list_foreach (list, iter, ref) {
if (ref->type == R_ANAL_REF_TYPE_STRING || ref->type == R_ANAL_REF_TYPE_DATA) {
if ((f = r_flag_get_i (core->flags, ref->addr))) {
refaddr = ref->addr;
is_lea_str = ref->type == 's';
break;
}
}
}
bool flag_printed = false;
if (p == UT64_MAX) {
/* do nothing */
} else if (((st64)p) > 0) {
} else if (((st64)p) > 0 || ((st64)refaddr) > 0) {
const char *kind;
char *msg = calloc (sizeof (char), len);
RFlagItem *f, *f2;
r_io_read_at (core->io, p, (ut8*)msg, len - 1);
if (((st64)p) > 0) {
f = r_flag_get_i (core->flags, p);
if (f) {
refaddr = p;
}
}
r_io_read_at (core->io, refaddr, (ut8*)msg, len - 1);
if (ds->analop.refptr) {
ut64 num = r_read_ble (msg, core->print->big_endian, ds->analop.refptr * 8);
st64 n = (st64)num;
st32 n32 = (st32)(n & UT32_MAX);
if (ds->analop.type == R_ANAL_OP_TYPE_LEA) {
const char *flag = "";
char str[128];
f = r_flag_get_i (core->flags, p);
f = r_flag_get_i (core->flags, refaddr);
if (f) {
flag = f->name;
} else if (ds->show_slow) {
Expand All @@ -2617,22 +2656,24 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
}
}
ALIGN;
if (ds->opstr && *flag && strstr (ds->opstr, flag)) {
ds_comment (ds, true, "%s; 0x%" PFMT64x "%s", esc, p, nl);
} else {
ds_comment (ds, true, "%s; 0x%" PFMT64x "%s%s%s", esc, p,
if (!is_lea_str) {
if (ds->opstr && *flag && strstr (ds->opstr, flag)) {
ds_comment (ds, true, "%s; 0x%" PFMT64x "%s", esc, refaddr, nl);
} else {
ds_comment (ds, true, "%s; 0x%" PFMT64x "%s%s%s", esc, refaddr,
*flag ? " ; " : "", flag, nl);
}
}
} else {
f = NULL;
if (n == UT32_MAX || n == UT64_MAX) {
ALIGN;
ds_comment (ds, true, "%s; [0x%" PFMT64x":%d]=-1%s",
esc, p, ds->analop.refptr, nl);
esc, refaddr, ds->analop.refptr, nl);
} else if (n == n32 && (n32 > -512 && n32 < 512)) {
ALIGN;
ds_comment (ds, true, "%s; [0x%" PFMT64x
":%d]=%"PFMT64d"%s", esc, p, ds->analop.refptr, n, nl);
":%d]=%"PFMT64d"%s", esc, refaddr, ds->analop.refptr, n, nl);
} else {
const char *kind, *flag = "";
char *msg2 = NULL;
Expand All @@ -2643,7 +2684,7 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
msg2 = calloc (sizeof (char), len);
r_io_read_at (core->io, n, (ut8*)msg2, len - 1);
msg2[len-1] = 0;
kind = r_anal_data_kind (core->anal, p, (const ut8*)msg2, len - 1);
kind = r_anal_data_kind (core->anal, refaddr, (const ut8*)msg2, len - 1);
if (kind && !strcmp (kind, "text")) {
r_str_filter (msg2, 0);
if (*msg2) {
Expand All @@ -2655,11 +2696,11 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
}
ALIGN;
ds_comment (ds, true, "%s; [0x%" PFMT64x":%d]=0x%" PFMT64x "%s%s%s",
esc, p, ds->analop.refptr, n, (flag && *flag) ? " " : "", flag, nl);
esc, refaddr, ds->analop.refptr, n, (flag && *flag) ? " " : "", flag, nl);
free (msg2);
}
// not just for LEA
f2 = r_flag_get_i (core->flags, p);
f2 = r_flag_get_i (core->flags, refaddr);
if (f2 && f != f2) {
ALIGN;
ds_comment (ds, true, "%s; LEA %s%s", esc, f2->name, nl);
Expand All @@ -2673,7 +2714,7 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
msg[len - 1] = 0;
}
#endif
f = r_flag_get_i (core->flags, p);
f = r_flag_get_i (core->flags, refaddr);
if (f) {
r_str_filter (msg, 0);
if (!strncmp (msg, "UH..", 4)) {
Expand All @@ -2698,10 +2739,10 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
i++;
}
}
ds_comment (ds, false, "\" @ 0x%"PFMT64x"%s", p, nl);
ds_comment (ds, false, "\" @ 0x%"PFMT64x"%s", refaddr, nl);
} else {
ALIGN;
ds_comment (ds, true, "%s; \"%s\" @ 0x%"PFMT64x"%s", esc, msg, p, nl);
ds_comment (ds, true, "%s; \"%s\" @ 0x%"PFMT64x"%s", esc, msg, refaddr, nl);
}
} else {
if (!flag_printed) {
Expand All @@ -2711,26 +2752,26 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
}
}
} else {
if (p == UT64_MAX || p == UT32_MAX) {
if (refaddr == UT64_MAX || refaddr == UT32_MAX) {
ALIGN;
ds_comment (ds, true, "%s; -1%s", esc, nl);
} else if (((char)p > 0) && p >= '!' && p <= '~') {
char ch = p;
} else if (((char)refaddr > 0) && refaddr >= '!' && refaddr <= '~') {
char ch = refaddr;
ALIGN;
ds_comment (ds, true, "%s; '%c'%s", esc, ch, nl);
} else if (p > 10) {
if ((st64)p < 0) {
} else if (refaddr > 10) {
if ((st64)refaddr < 0) {
// resolve local var if possible
RAnalVar *v = r_anal_var_get (core->anal, ds->at, 'v', 1, (int)p);
RAnalVar *v = r_anal_var_get (core->anal, ds->at, 'v', 1, (int)refaddr);
ALIGN;
if (v) {
ds_comment (ds, true, "%s; var %s%s", esc, v->name, nl);
r_anal_var_free (v);
} else {
ds_comment (ds, true, "%s; var %d%s", esc, (int)-p, nl);
ds_comment (ds, true, "%s; var %d%s", esc, (int)-refaddr, nl);
}
} else {
if (r_core_anal_address (core, p) & R_ANAL_ADDR_TYPE_ASCII) {
if (r_core_anal_address (core, refaddr) & R_ANAL_ADDR_TYPE_ASCII) {
int i = 0;
r_str_filter (msg, 0);
if (*msg) {
Expand All @@ -2751,17 +2792,17 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
i++;
}
}
ds_comment (ds, false, "\" 0x%08"PFMT64x"%s ", p, nl);
ds_comment (ds, false, "\" 0x%08"PFMT64x"%s ", refaddr, nl);
} else {
ALIGN;
ds_comment (ds, true, "%s; \"%s\" 0x%08"PFMT64x" %s", esc, msg, p, nl);
ds_comment (ds, true, "%s; \"%s\" 0x%08"PFMT64x" %s", esc, msg, refaddr, nl);
}
}
}
}
}
//XXX this should be refactored with along the above
kind = r_anal_data_kind (core->anal, p, (const ut8*)msg, len - 1);
kind = r_anal_data_kind (core->anal, refaddr, (const ut8*)msg, len - 1);
if (kind) {
if (!strcmp (kind, "text")) {
r_str_filter (msg, 0);
Expand Down Expand Up @@ -2793,7 +2834,7 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
}
}
} else if (!strcmp (kind, "invalid")) {
int *n = (int*)&p;
int *n = (int*)&refaddr;
ut64 p = ds->analop.val;
if (p == UT64_MAX || p == UT32_MAX) {
p = ds->analop.ptr;
Expand Down
2 changes: 1 addition & 1 deletion libr/parse/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static int filter(RParse *p, RFlag *f, char *data, char *str, int len, bool big_
if (!flag) {
flag = r_flag_get_i (f, off);
}
if (p->relsub_addr) {
if (!flag && p->relsub_addr) {
computed = true;
flag2 = r_flag_get_i2 (f, p->relsub_addr);
if (!flag2) {
Expand Down
15 changes: 15 additions & 0 deletions libr/util/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,7 @@ R_API char* r_print_colorize_opcode(char *p, const char *reg, const char *num) {
int i, j, k, is_mod, is_float = 0, is_arg = 0;
ut32 c_reset = strlen (Color_RESET);
int is_jmp = p && (*p == 'j' || ((*p == 'c') && (p[1] == 'a')))? 1: 0;
int is_num;
ut32 opcode_sz = p && *p? strlen (p) * 10 + 1: 0;

if (!p || !*p) {
Expand Down Expand Up @@ -1703,6 +1704,7 @@ R_API char* r_print_colorize_opcode(char *p, const char *reg, const char *num) {
// find if next ',' before ' ' is found
is_mod = 0;
is_float = 0;
is_num = 1;
for (k = i + 1; p[k]; k++) {
if (p[k] == 'e' && p[k + 1] == '+') {
is_float = 1;
Expand All @@ -1715,6 +1717,9 @@ R_API char* r_print_colorize_opcode(char *p, const char *reg, const char *num) {
is_mod = 1;
break;
}
if (!isdigit (p[k])) {
is_num = false;
}
}
if (is_float) {
strcpy (o + j, num);
Expand All @@ -1724,6 +1729,16 @@ R_API char* r_print_colorize_opcode(char *p, const char *reg, const char *num) {
is_mod = 1;
}
if (!is_jmp && is_mod) {
if (is_num) {
ut32 num_len = strlen (num);
if (num_len + j + 10 >= COLORIZE_BUFSIZE) {
eprintf ("r_print_colorize_opcode(): buffer overflow!\n");
return strdup (p);
}
strcpy (o + j, num);
j += strlen (num);
break;
}
// COLOR FOR REGISTER
ut32 reg_len = strlen (reg);
/* if (reg_len+j+10 >= opcode_sz) o = realloc_color_buffer (o, &opcode_sz, reg_len+100); */
Expand Down

0 comments on commit 2ce093b

Please sign in to comment.