From 0e0ec6592bcdb0e083c2334eef9bfc80d6b64cbe Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Mon, 25 Jun 2018 21:38:36 +0200 Subject: [PATCH 1/4] Fold cases of switch in the same address --- libr/anal/fcn.c | 2 +- libr/core/disasm.c | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 8687f32c60716..3b84a18463d42 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -443,7 +443,7 @@ static void queue_case(RAnal *anal, ut64 switch_addr, ut64 case_addr, ut64 id, u // id, case_addr); anal->cmdtail = r_str_appendf (anal->cmdtail, "f case.%d.0x%"PFMT64x " 1 @ 0x%08"PFMT64x "\n", - id, case_addr, case_addr); + id, switch_addr, case_addr); } static int try_walkthrough_jmptbl(RAnal *anal, RAnalFunction *fcn, int depth, ut64 ip, ut64 jmptbl_loc, ut64 jmptbl_off, ut64 sz, ut64 jmptbl_size, ut64 default_case, int ret0) { diff --git a/libr/core/disasm.c b/libr/core/disasm.c index d8417d956aeec..9ac60315fcba5 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -1848,6 +1848,9 @@ static void ds_show_flags(RDisasmState *ds) { } RCore *core = ds->core; // f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL); + char addr[64]; + ut64 switch_addr; + int case_start = -1, case_prev = 0, case_current = 0; f = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL); flaglist = r_flag_get_list (core->flags, ds->at); RList *uniqlist = r_list_uniq (flaglist, flagCmp); @@ -1856,6 +1859,20 @@ static void ds_show_flags(RDisasmState *ds) { // do not show flags that have the same name as the function continue; } + if (!strncmp (flag->name, "case.", 5)) { + sscanf (flag->name + 5, "%d.%s", &case_current, addr); + ut64 saddr = r_num_math (core->num, addr); + if (case_start == -1) { + switch_addr = saddr; + case_prev = case_current; + case_start = case_current; + continue; + } + if (case_current == case_prev + 1 && switch_addr == saddr) { + case_prev = case_current; + continue; + } + } ds_begin_json_line (ds); if (ds->show_flgoff) { ds_beginline (ds); @@ -1881,10 +1898,24 @@ static void ds_show_flags(RDisasmState *ds) { } } if (ds->asm_demangle && flag->realname) { - const char *lang = r_config_get (core->config, "bin.lang"); - char *name = r_bin_demangle (core->bin->cur, lang, flag->realname, flag->offset); - r_cons_printf ("%s:", name? name: flag->realname); - R_FREE (name); + if (!strncmp (flag->name, "case.", 5)) { + if (case_prev != case_start) { + r_cons_printf ("cases %d...%d (%s):", case_start, case_prev, addr); + if (iter != uniqlist->head) { + iter = iter->p; + } + case_start = case_current; + } else { + r_cons_printf ("case %d (%s):", case_prev, addr); + case_start = -1; + } + case_prev = case_current; + } else { + const char *lang = r_config_get (core->config, "bin.lang"); + char *name = r_bin_demangle (core->bin->cur, lang, flag->realname, flag->offset); + r_cons_printf ("%s:", name? name: flag->realname); + R_FREE (name); + } } else { r_cons_printf ("%s:", flag->name); } From e525bed9a5e0214c1f979a2785ecc06da856bca4 Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Mon, 25 Jun 2018 21:59:40 +0200 Subject: [PATCH 2/4] Fix default case missing --- libr/core/disasm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 9ac60315fcba5..1cde1003c0235 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -1866,7 +1866,9 @@ static void ds_show_flags(RDisasmState *ds) { switch_addr = saddr; case_prev = case_current; case_start = case_current; - continue; + if (iter != uniqlist->tail) { + continue; + } } if (case_current == case_prev + 1 && switch_addr == saddr) { case_prev = case_current; @@ -1899,7 +1901,9 @@ static void ds_show_flags(RDisasmState *ds) { } if (ds->asm_demangle && flag->realname) { if (!strncmp (flag->name, "case.", 5)) { - if (case_prev != case_start) { + if (!strncmp (flag->name + 5, "default", 7)) { + r_cons_printf ("%s:", flag->name); + } else if (case_prev != case_start) { r_cons_printf ("cases %d...%d (%s):", case_start, case_prev, addr); if (iter != uniqlist->head) { iter = iter->p; From e72d5e705faffff8e85611c43e6b192d6b2a023e Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Mon, 25 Jun 2018 22:14:31 +0200 Subject: [PATCH 3/4] Fix possible buffer overflow when scanning address --- libr/core/disasm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 1cde1003c0235..72bb1426a2ae3 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -1860,7 +1860,7 @@ static void ds_show_flags(RDisasmState *ds) { continue; } if (!strncmp (flag->name, "case.", 5)) { - sscanf (flag->name + 5, "%d.%s", &case_current, addr); + sscanf (flag->name + 5, "%d.%63s", &case_current, addr); ut64 saddr = r_num_math (core->num, addr); if (case_start == -1) { switch_addr = saddr; From 7928f72f8d269ac405db4753f6a7d8de844bc0cd Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Tue, 26 Jun 2018 13:34:49 +0200 Subject: [PATCH 4/4] change cases flag format --- libr/anal/fcn.c | 4 ++-- libr/core/disasm.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 3b84a18463d42..a9b4782811874 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -442,8 +442,8 @@ static void queue_case(RAnal *anal, ut64 switch_addr, ut64 case_addr, ut64 id, u // "CCu case %d: @ 0x%"PFMT64x "\n", // id, case_addr); anal->cmdtail = r_str_appendf (anal->cmdtail, - "f case.%d.0x%"PFMT64x " 1 @ 0x%08"PFMT64x "\n", - id, switch_addr, case_addr); + "f case.0x%"PFMT64x ".%d 1 @ 0x%08"PFMT64x "\n", + switch_addr, id, case_addr); } static int try_walkthrough_jmptbl(RAnal *anal, RAnalFunction *fcn, int depth, ut64 ip, ut64 jmptbl_loc, ut64 jmptbl_off, ut64 sz, ut64 jmptbl_size, ut64 default_case, int ret0) { diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 72bb1426a2ae3..dc88ac9b7b100 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -1860,7 +1860,7 @@ static void ds_show_flags(RDisasmState *ds) { continue; } if (!strncmp (flag->name, "case.", 5)) { - sscanf (flag->name + 5, "%d.%63s", &case_current, addr); + sscanf (flag->name + 5, "%63[^.].%d", addr, &case_current); ut64 saddr = r_num_math (core->num, addr); if (case_start == -1) { switch_addr = saddr;