From 413437e2b6f3efbb3ac0b33782d88c24fa206ff7 Mon Sep 17 00:00:00 2001 From: pancake Date: Wed, 16 Sep 2020 19:16:24 +0200 Subject: [PATCH] Move arp gdb into arpg, improve error and parsing + tests ##debug (#17658) --- libr/core/cmd_debug.c | 47 +++++--- libr/core/core.c | 4 +- libr/include/r_reg.h | 2 +- libr/reg/profile.c | 55 +++++---- test/db/cmd/cmd_arp | 17 +++ test/scripts/gdb-reg-profile-invalid.txt | 36 ++++++ test/scripts/gdb-reg-profile.txt | 141 +++++++++++++++++++++++ 7 files changed, 255 insertions(+), 47 deletions(-) create mode 100644 test/db/cmd/cmd_arp create mode 100644 test/scripts/gdb-reg-profile-invalid.txt create mode 100644 test/scripts/gdb-reg-profile.txt diff --git a/libr/core/cmd_debug.c b/libr/core/cmd_debug.c index 0e473f3c03..1e44778287 100644 --- a/libr/core/cmd_debug.c +++ b/libr/core/cmd_debug.c @@ -2013,45 +2013,54 @@ static void show_drpi(RCore *core) { } } -static void cmd_reg_profile (RCore *core, char from, const char *str) { // "arp" and "drp" +static void cmd_reg_profile(RCore *core, char from, const char *str) { // "arp" and "drp" const char *ptr; RReg *r = r_config_get_i (core->config, "cfg.debug")? core->dbg->reg: core->anal->reg; switch (str[1]) { - case '\0': // "drp" + case '\0': // "drp" "arp" if (r->reg_profile_str) { r_cons_println (r->reg_profile_str); } else { eprintf ("No register profile defined. Try 'dr.'\n"); } break; - case 'c': // drpc + case 'c': // "drpc" "arpc" if (core->dbg->reg->reg_profile_cmt) { r_cons_println (r->reg_profile_cmt); } break; - case ' ': // "drp " - ptr = str + 2; - while (isspace ((ut8)*ptr)) { - ptr++; + case 'g': // "drpg" "arpg" + ptr = r_str_trim_head_ro (str + 2); + if (!R_STR_ISEMPTY (ptr)) { + char *r2profile = r_reg_parse_gdb_profile (ptr); + if (r2profile) { + r_cons_println (r2profile); + core->num->value = 0; + free (r2profile); + } else { + core->num->value = 1; + eprintf ("Warning: Cannot parse gdb profile.\n"); + } + } else { + eprintf ("Usage: arpg [gdb-reg-profile]\n"); } - if (r_str_startswith (ptr, "gdb ")) { - r_reg_parse_gdb_profile (ptr + 4); - break; - } - r_reg_set_profile (r, str + 2); - r_debug_plugin_set_reg_profile (core->dbg, str + 2); + break; + case ' ': // "drp " "arp " + ptr = r_str_trim_head_ro (str + 2); + r_reg_set_profile (r, ptr); + r_debug_plugin_set_reg_profile (core->dbg, ptr); break; case '.': { // "drp." RRegSet *rs = r_reg_regset_get (r, R_REG_TYPE_GPR); if (rs) { eprintf ("size = %d\n", rs->arena->size); } + } break; - } - case 'i': // "drpi" + case 'i': // "drpi" "arpi" show_drpi (core); break; - case 's': // "drps" + case 's': // "drps" "arps" if (str[2] == ' ') { ut64 n = r_num_math (core->num, str+2); // TODO: move this thing into the r_reg API @@ -2079,7 +2088,7 @@ static void cmd_reg_profile (RCore *core, char from, const char *str) { // "arp" } else eprintf ("Cannot find GPR register arena.\n"); } break; - case 'j': // "drpj" + case 'j': // "drpj" "arpj" { // "drpj" .. dup from "arpj" RListIter *iter; @@ -2118,10 +2127,10 @@ static void cmd_reg_profile (RCore *core, char from, const char *str) { // "arp" pj_free (pj); } break; - case '?': // "drp?" + case '?': // "drp?" "arp?" default: { - const char *from_a[] = { "arp", "arpi", "arp.", "arpj", "arps" }; + const char *from_a[] = { "arp", "arpi", "arpg", "arp.", "arpj", "arps" }; // TODO #7967 help refactor const char **help_msg = help_msg_drp; if (from == 'a') { diff --git a/libr/core/core.c b/libr/core/core.c index 0df72dd5d8..4824807c37 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -887,7 +887,7 @@ static const char *radare_argv[] = { "ao?", "ao", "aoj", "aoe", "aor", "aos", "aom", "aod", "aoda", "aoc", "ao*", "aO", "ap", "ar?", "ar", "ar0", "ara?", "ara", "ara+", "ara-", "aras", "arA", "arC", "arr", "arrj", "ar=", - "arb", "arc", "ard", "arn", "aro", "arp?", "arp", "arpi", "arp.", "arpj", "arps", + "arb", "arc", "ard", "arn", "aro", "arp?", "arp", "arpi", "arpg", "arp.", "arpj", "arps", "ars", "art", "arw", "as?", "as", "asc", "asca", "asf", "asj", "asl", "ask", "av?", "av", "avj", "av*", "avr", "avra", "avraj", "avrr", "avrD", @@ -2352,7 +2352,7 @@ static void __init_autocomplete_default (RCore* core) { }; const char *files[] = { ".", "..", ".*", "/F", "/m", "!", "!!", "#!c", "#!v", "#!cpipe", "#!vala", - "#!rust", "#!zig", "#!pipe", "#!python", "aeli", "arp", "dmd", "drp", "o", + "#!rust", "#!zig", "#!pipe", "#!python", "aeli", "arp", "arpg", "dmd", "drp", "drpg", "o", "idp", "idpi", "L", "obf", "o+", "oc", "r2", "rabin2", "rasm2", "rahash2", "rax2", "rafind2", "cd", "on", "op", "wf", "rm", "wF", "wp", "Sd", "Sl", "to", "pm", "/m", "zos", "zfd", "zfs", "zfz", "cat", "wta", "wtf", "wxf", "dml", "vi", diff --git a/libr/include/r_reg.h b/libr/include/r_reg.h index 45a2953773..7a85fc9575 100644 --- a/libr/include/r_reg.h +++ b/libr/include/r_reg.h @@ -146,7 +146,7 @@ R_API bool r_reg_set_name(RReg *reg, int role, const char *name); R_API bool r_reg_set_profile_string(RReg *reg, const char *profile); R_API char* r_reg_profile_to_cc(RReg *reg); R_API bool r_reg_set_profile(RReg *reg, const char *profile); -R_API bool r_reg_parse_gdb_profile(const char *profile); +R_API char *r_reg_parse_gdb_profile(const char *profile); R_API bool r_reg_is_readonly(RReg *reg, RRegItem *item); R_API RRegSet *r_reg_regset_get(RReg *r, int type); diff --git a/libr/reg/profile.c b/libr/reg/profile.c index 173b937968..e3d469da20 100644 --- a/libr/reg/profile.c +++ b/libr/reg/profile.c @@ -243,6 +243,7 @@ R_API bool r_reg_set_profile_string(RReg *reg, const char *str) { } R_API bool r_reg_set_profile(RReg *reg, const char *profile) { + r_return_val_if_fail (reg && profile, NULL); char *base, *file; char *str = r_file_slurp (profile, NULL); if (!str) { @@ -262,23 +263,25 @@ R_API bool r_reg_set_profile(RReg *reg, const char *profile) { return ret; } -static bool gdb_to_r2_profile(char *gdb) { - char *ptr = gdb, *ptr1, *gptr, *gptr1; +static char *gdb_to_r2_profile(const char *gdb) { + r_return_val_if_fail (gdb, NULL); + RStrBuf *sb = r_strbuf_new (""); + if (!sb) { + return NULL; + } + char *ptr1, *gptr, *gptr1; char name[16], groups[128], type[16]; const int all = 1, gpr = 2, save = 4, restore = 8, float_ = 16, sse = 32, vector = 64, system = 128, mmx = 256; int number, rel, offset, size, type_bits, ret; // Every line is - // Name Number Rel Offset Size Type Groups + char *ptr = r_str_trim_head_ro (gdb); - // Skip whitespace at beginning of line and empty lines - while (isspace ((ut8)*ptr)) { - ptr++; - } // It's possible someone includes the heading line too. Skip it if (r_str_startswith (ptr, "Name")) { if (!(ptr = strchr (ptr, '\n'))) { - return false; + return NULL; } ptr++; } @@ -297,9 +300,9 @@ static bool gdb_to_r2_profile(char *gdb) { &offset, &size, type, groups); // Groups is optional, others not if (ret < 6) { - eprintf ("Could not parse line: %s\n", ptr); - if (!ptr1) { - return true; + if (*ptr != '*') { + eprintf ("Could not parse line: %s\n", ptr); + return false; } ptr = ptr1 + 1; continue; @@ -307,7 +310,7 @@ static bool gdb_to_r2_profile(char *gdb) { // If name is '', then skip if (r_str_startswith (name, "''")) { if (!ptr1) { - return true; + break; } ptr = ptr1 + 1; continue; @@ -315,7 +318,7 @@ static bool gdb_to_r2_profile(char *gdb) { // If size is 0, skip if (size == 0) { if (!ptr1) { - return true; + break; } ptr = ptr1 + 1; continue; @@ -354,7 +357,7 @@ static bool gdb_to_r2_profile(char *gdb) { // If type is not defined, skip if (!*type) { if (!ptr1) { - return true; + break; } ptr = ptr1 + 1; continue; @@ -364,38 +367,40 @@ static bool gdb_to_r2_profile(char *gdb) { type_bits |= gpr; } // Print line - eprintf ("%s\t%s\t.%d\t%d\t0\n", + r_strbuf_appendf (sb, "%s\t%s\t.%d\t%d\t0\n", // Ref: Comment above about more register type mappings ((type_bits & mmx) || (type_bits & float_) || (type_bits & sse)) ? "fpu" : "gpr", name, size * 8, offset); // Go to next line if (!ptr1) { - return true; + break; } ptr = ptr1 + 1; continue; } - return true; + return r_strbuf_drain (sb); } -R_API bool r_reg_parse_gdb_profile(const char *profile_file) { +R_API char *r_reg_parse_gdb_profile(const char *profile_file) { char *base, *str = NULL; if (!(str = r_file_slurp (profile_file, NULL))) { - if ((base = r_sys_getenv (R_LIB_ENV))) { - char *file = r_str_append (base, profile_file); + char *base = r_sys_getenv (R_LIB_ENV); + if (base) { + char *file = r_str_appendf (base, R_SYS_DIR "%s", profile_file); if (file) { str = r_file_slurp (file, NULL); free (file); } + free (base); } } - if (!str) { - eprintf ("r_reg_parse_gdb_profile: Cannot find '%s'\n", profile_file); - return false; + if (str) { + char *ret = gdb_to_r2_profile (str); + free (str); + return ret; } - bool ret = gdb_to_r2_profile (str); - free (str); - return ret; + eprintf ("r_reg_parse_gdb_profile: Cannot find '%s'\n", profile_file); + return NULL; } R_API char *r_reg_profile_to_cc(RReg *reg) { diff --git a/test/db/cmd/cmd_arp b/test/db/cmd/cmd_arp new file mode 100644 index 0000000000..7b19a0e770 --- /dev/null +++ b/test/db/cmd/cmd_arp @@ -0,0 +1,17 @@ +NAME=arpg +FILE=- +CMDS=< $a +?v $? +$a~? +arpg scripts/gdb-reg-profile-invalid.txt > $b +?v $? +$b~? +EOF +EXPECT=<