static int parse(RParse *p, const char *data, char *str) { char w0[256], w1[256], w2[256]; int i, len = strlen(data); char *buf, *ptr, *optr; ADDR_TYPE atype; if (len >= sizeof(w0)) { return false; } // malloc can be slow here :? if ((buf = malloc(len + 1)) == NULL) { return false; } memcpy(buf, data, len + 1); if (*buf) { atype = addr_type(buf); r_str_replace_char(buf, '(', ' '); r_str_replace_char(buf, ')', ' '); *w0 = *w1 = *w2 = '\0'; ptr = strchr(buf, ' '); if (ptr == NULL) { ptr = strchr(buf, '\t'); } if (ptr) { *ptr = '\0'; for (++ptr; *ptr == ' '; ptr++) ; strncpy(w0, buf, sizeof(w0) - 1); strncpy(w1, ptr, sizeof(w1) - 1); optr = ptr; ptr = strchr(ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr == ' '; ptr++) ; strncpy(w1, optr, sizeof(w1) - 1); strncpy(w2, ptr, sizeof(w2) - 1); } } else { strncpy(w0, buf, sizeof(w0) - 1); } const char *wa[] = {w0, w1, w2}; int nw = 0; for (i = 0; i < 3; i++) { if (wa[i][0]) { nw++; } } replace(nw, wa, str, atype); } free(buf); return true; }
R_API int r_num_conditional(RNum *num, const char *str) { char *lgt, *t, *p, *s = strdup (str); int res = 0; ut64 n, a, b; p = s; do { t = strchr (p, ','); if (t) *t = 0; lgt = strchr (p, '<'); if (lgt) { *lgt = 0; a = r_num_math (num, p); if (lgt[1]=='=') { b = r_num_math (num, lgt+2); if (a>b) goto fail; } else { b = r_num_math (num, lgt+1); if (a>=b) goto fail; } } else { lgt = strchr (p, '>'); if (lgt) { *lgt = 0; a = r_num_math (num, p); if (lgt[1]=='=') { b = r_num_math (num, lgt+2); if (a<b) goto fail; } else { b = r_num_math (num, lgt+1); if (a<=b) goto fail; } } else { lgt = strchr (p, '='); if (lgt && lgt > p) { lgt--; if (*lgt=='!') { r_str_replace_char (p, '!', ' '); r_str_replace_char (p, '=', '-'); n = r_num_math (num, p); if (!n) goto fail; } } lgt = strstr (p, "=="); if (lgt) *lgt = ' '; r_str_replace_char (p, '=', '-'); n = r_num_math (num, p); if (n) goto fail; } } p = t+1; } while (t); res = 1; fail: free (s); return res; }
bool test_r_str_replace_char(void) { char* str = strdup ("hello world"); (void) r_str_replace_char (str, 'l', 'x'); mu_assert_streq (str, "hexxo worxd", "error, replace char multi failed"); free (str); mu_end; }
R_API void r_cons_pal_list(int rad, const char *arg) { char *name, **color; const char *hasnext; int i; if (rad == 'j') { r_cons_print ("{"); } for (i = 0; keys[i].name; i++) { RColor *rcolor = RCOLOR_AT (i); color = COLOR_AT (i); switch (rad) { case 'j': hasnext = (keys[i + 1].name) ? "," : ""; r_cons_printf ("\"%s\":[%d,%d,%d]%s", keys[i].name, rcolor->r, rcolor->g, rcolor->b, hasnext); break; case 'c': { const char *prefix = r_str_trim_ro (arg); if (!prefix) { prefix = ""; } hasnext = (keys[i + 1].name) ? "\n" : ""; // TODO Need to replace the '.' char because this is not valid CSS char *name = strdup (keys[i].name); int j, len = strlen (name); for (j = 0; j < len; j++) { if (name[j] == '.') { name[j] = '_'; } } r_cons_printf (".%s%s { color: rgb(%d, %d, %d); }%s", prefix, name, rcolor->r, rcolor->g, rcolor->b, hasnext); free (name); } break; case 'h': name = strdup (keys[i].name); r_str_replace_char (name, '.', '_'); r_cons_printf (".%s { color:#%02x%02x%02x }\n", name, rcolor->r, rcolor->g, rcolor->b); free (name); break; case '*': case 'r': case 1: r_cons_printf ("ec %s rgb:%02x%02x%02x\n", keys[i].name, rcolor->r, rcolor->g, rcolor->b); break; default: r_cons_printf (" %s##"Color_RESET" %s\n", *color, keys[i].name); } } if (rad == 'j') { r_cons_print ("}\n"); } }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { cs_insn* insn; int mode, n, ret = -1; mode = CS_MODE_BIG_ENDIAN; if (!op) { return 0; } // mode |= (a->bits == 64)? CS_MODE_64: CS_MODE_32; memset (op, 0, sizeof (RAsmOp)); op->size = 4; if (cd != 0) { cs_close (&cd); } ret = cs_open (CS_ARCH_TMS320C64X, mode, &cd); if (ret) { goto fin; } if (a->syntax == R_ASM_SYNTAX_REGNUM) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); } else { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT); } cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (cd, (ut8*)buf, len, a->pc, 1, &insn); if (n < 1) { strcpy (op->buf_asm, "invalid"); op->size = 4; goto beach; } else { ret = 4; } if (insn->size < 1) { goto beach; } op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); // r_str_replace_in (op->buf_asm, sizeof (op->buf_asm), "*+", "", 1); // nasty, the disasm output comes with tabs and uppercase :( r_str_replace_char (op->buf_asm, '\t', 0); // r_str_replace_in (op->buf_asm, sizeof (op->buf_asm), "\t", "", 1); r_str_case (op->buf_asm, false); cs_free (insn, n); beach: // cs_close (&cd); fin: return op->size; }
R_API bool r_run_parse(RRunProfile *pf, const char *profile) { if (!pf || !profile) { return false; } char *p, *o, *str = strdup (profile); if (!str) { return false; } r_str_replace_char (str, '\r',0); for (p = str; (o = strchr (p, '\n')); p = o) { *o++ = 0; r_run_parseline (pf, p); } free (str); return true; }
static int typelist (void *p, const char *k, const char *v) { r_cons_printf ("tk %s = %s\n", k, v); #if 0 if (!strcmp (v, "func")) { const char *rv = sdb_const_get (DB, sdb_fmt (0, "func.%s.ret", k), 0); r_cons_printf ("# %s %s(", rv, k); for (i = 0; i < 16; i++) { char *av = sdb_get (DB, sdb_fmt (0, "func.%s.arg.%d", k, i), 0); if (!av) break; r_str_replace_char (av, ',', ' '); r_cons_printf ("%s%s", i? ", ": "", av); free (av); } r_cons_printf (");\n"); // signature in pf for asf r_cons_printf ("asf %s=", k); // formats for (i = 0; i < 16; i++) { const char *fmt; char *comma, *av = sdb_get (DB, sdb_fmt (0, "func.%s.arg.%d", k, i), 0); if (!av) break; comma = strchr (av, ','); if (comma) *comma = 0; fmt = sdb_const_get (DB, sdb_fmt (0, "type.%s", av), 0); r_cons_printf ("%s", fmt); if (comma) *comma = ','; free (av); } // names for (i = 0; i < 16; i++) { char *comma, *av = sdb_get (DB, sdb_fmt (0, "func.%s.arg.%d", k, i), 0); if (!av) break; comma = strchr (av, ','); if (comma) *comma++ = 0; r_cons_printf (" %s", comma); free (av); } r_cons_newline (); } #endif return 1; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { csh handle; cs_insn* insn; int mode, n, ret = -1; mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (a->cpu && *a->cpu) { if (!strcmp (a->cpu, "gp64")) { mode |= CS_MODE_MIPSGP64; } else if (!strcmp (a->cpu, "micro")) { mode |= CS_MODE_MICRO; } else if (!strcmp (a->cpu, "r6")) { mode |= CS_MODE_MIPS32R6; } else if (!strcmp (a->cpu, "v3")) { mode |= CS_MODE_MIPS3; } } mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32; memset (op, 0, sizeof (RAsmOp)); op->size = 4; ret = cs_open (CS_ARCH_MIPS, mode, &handle); if (ret) goto fin; if (a->syntax == R_ASM_SYNTAX_REGNUM) { cs_option (handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); } else cs_option (handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT); cs_option (handle, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (handle, (ut8*)buf, len, a->pc, 1, &insn); if (n<1) { strcpy (op->buf_asm, "invalid"); op->size = 4; ret = -1; goto beach; } else ret = 4; if (insn->size<1) goto beach; op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); // remove the '$'<registername> in the string r_str_replace_char (op->buf_asm, '$', 0); cs_free (insn, n); beach: cs_close (&handle); fin: return op->size; }
static int tms320c64x_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { cs_insn* insn; int n = -1, ret = -1; int mode = 0; if (op) { memset (op, 0, sizeof (RAsmOp)); op->size = 4; } if (cd != 0) { cs_close (&cd); } ret = cs_open (CS_ARCH_TMS320C64X, mode, &cd); if (ret) { goto fin; } cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); if (!op) { return 0; } n = cs_disasm (cd, buf, len, a->pc, 1, &insn); if (n < 1) { r_asm_op_set_asm (op, "invalid"); op->size = 4; ret = -1; goto beach; } else { ret = 4; } if (insn->size < 1) { goto beach; } op->size = insn->size; char *buf_asm = sdb_fmt ("%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); r_str_replace_char (buf_asm, '%', 0); r_str_case (buf_asm, false); r_asm_op_set_asm (op, buf_asm); cs_free (insn, n); beach: // cs_close (&cd); fin: return ret; }
static int cmd_eval(void *data, const char *input) { char *p; RCore *core = (RCore *)data; switch (input[0]) { case 't': // env if (input[1]==' ' && input[2]) { RConfigNode *node = r_config_node_get (core->config, input+2); if (node) { const char *type = r_config_node_type (node); if (type && *type) { r_cons_printf ("%s\n", type); } } } else { eprintf ("Usage: et [varname] ; show type of eval var\n"); } break; case 'n': // env if (!strchr (input, '=')) { char *var, *p; var = strchr (input, ' '); if (var) while (*var==' ') var++; p = r_sys_getenv (var); if (p) { r_cons_printf ("%s\n", p); free (p); } else { char **e = r_sys_get_environ (); while (e && *e) { r_cons_printf ("%s\n", *e); e++; } } } else if (strlen (input)>3) { char *v, *k = strdup (input+3); if (!k) break; v = strchr (k, '='); if (v) { *v++ = 0; r_sys_setenv (k, v); } free (k); } return true; case 'x': // exit return cmd_quit (data, ""); case 'j': r_config_list (core->config, NULL, 'j'); break; case '\0': r_config_list (core->config, NULL, 0); break; case 'c': switch (input[1]) { case 'h': // echo if (( p = strchr (input, ' ') )) { r_cons_strcat (p+1); r_cons_newline (); } break; case 'd': r_cons_pal_init (NULL); break; case '?': { const char *helpmsg[] = { "Usage ec[s?] [key][[=| ]fg] [bg]","","", "ec","","list all color keys", "ec*","","same as above, but using r2 commands", "ecd","","set default palette", "ecr","","set random palette", "ecs","","show a colorful palette", "ecj","","show palette in JSON", "ecc","","show palette in CSS", "eco"," dark|white","load white color scheme template", "ecn","","load next color theme", "ec"," prompt red","change color of prompt", "ec"," prompt red blue","change color and background of prompt", ""," ","", "colors:","","rgb:000, red, green, blue, ...", "e scr.rgbcolor","=1|0","for 256 color cube (boolean)", "e scr.truecolor","=1|0","for 256*256*256 colors (boolean)", "$DATADIR/radare2/cons","","~/.config/radare2/cons ./", NULL}; r_core_cmd_help (core, helpmsg); } break; case 'o': // "eco" if (input[2] == ' ') { bool failed = false; char *home, path[512]; snprintf (path, sizeof (path), ".config/radare2/cons/%s", input+3); home = r_str_home (path); snprintf (path, sizeof (path), R2_DATDIR"/radare2/" R2_VERSION"/cons/%s", input+3); if (!r_core_cmd_file (core, home)) { if (r_core_cmd_file (core, path)) { //curtheme = r_str_dup (curtheme, path); curtheme = r_str_dup (curtheme, input + 3); } else { if (r_core_cmd_file (core, input+3)) { curtheme = r_str_dup (curtheme, input + 3); } else { eprintf ("eco: cannot open colorscheme profile (%s)\n", path); failed = true; } } } free (home); } else { nextpal (core, 'l'); } break; case 's': r_cons_pal_show (); break; case '*': r_cons_pal_list (1); break; case 'j': r_cons_pal_list ('j'); break; case 'c': r_cons_pal_list ('c'); break; case '\0': r_cons_pal_list (0); break; case 'r': // "ecr" r_cons_pal_random (); break; case 'n': // "ecn" nextpal (core, 'n'); break; default: { char *p = strdup (input + 2); char *q = strchr (p, '='); if (!q) q = strchr (p, ' '); if (q) { // set *q++ = 0; r_cons_pal_set (p, q); } else { const char *k = r_cons_pal_get (p); if (k) eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, k); } free (p); } } break; case 'e': if (input[1]==' ') { char *p; const char *val, *input2 = strchr (input+2, ' '); if (input2) input2++; else input2 = input+2; val = r_config_get (core->config, input2); p = r_core_editor (core, NULL, val); if (p) { r_str_replace_char (p, '\n', ';'); r_config_set (core->config, input2, p); } } else eprintf ("Usage: ee varname\n"); break; case '!': input = r_str_chop_ro (input+1); if (!r_config_toggle (core->config, input)) eprintf ("r_config: '%s' is not a boolean variable.\n", input); break; case '-': r_core_config_init (core); //eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n"); break; case 'v': eprintf ("Invalid command '%s'. Use 'e?'\n", input); break; case '*': r_config_list (core->config, NULL, 1); break; case '?': switch (input[1]) { case '?': r_config_list (core->config, input+2, 2); break; default: r_config_list (core->config, input+1, 2); break; case 0:{ const char* help_msg[] = { "Usage:", "e[?] [var[=value]]", "Evaluable vars", "e","?asm.bytes", "show description", "e", "??", "list config vars with description", "e", "", "list config vars", "e-", "", "reset config vars", "e*", "", "dump config vars in r commands", "e!", "a", "invert the boolean value of 'a' var", "ee", "var", "open editor to change the value of var", "er", " [key]", "set config key as readonly. no way back", "ec", " [k] [color]", "set color for given key (prompt, offset, ...)", "et", " [key]", "show type of given config variable", "e", " a", "get value of var 'a'", "e", " a=b", "set var 'a' the 'b' value", "env", " [k[=v]]", "get/set environment variable", NULL}; r_core_cmd_help (core, help_msg); } } break; case 'r': if (input[1]) { const char *key = input+((input[1]==' ')?2:1); if (!r_config_readonly (core->config, key)) eprintf ("cannot find key '%s'\n", key); } else eprintf ("Usage: er [key]\n"); break; case ' ': r_config_eval (core->config, input+1); break; default: r_config_eval (core->config, input); break; } return 0; }
R_API void r_cons_pal_list (int rad, const char *arg) { RConsPalette *pal = & (r_cons_singleton ()->pal); ut8 r, g, b, *p = (ut8*)pal; char *name, **color, rgbstr[32]; const char *hasnext; int i; if (rad == 'j') r_cons_print ("{"); for (i = 0; keys[i].name; i++) { color = (char**) (p + keys[i].off); switch (rad) { case 'j': r = g = b = 0; r_cons_rgb_parse (*color, &r, &g, &b, NULL); hasnext = (keys[i + 1].name) ? "," : ""; r_cons_printf ("\"%s\":[%d,%d,%d]%s", keys[i].name, r, g, b, hasnext); break; case 'c': { const char *prefix = r_str_chop_ro (arg); if (!prefix) { prefix = ""; } r = g = b = 0; r_cons_rgb_parse (*color, &r, &g, &b, NULL); hasnext = (keys[i + 1].name) ? "\n" : ""; //Need to replace the '.' char because this is not //valid CSS char *name = strdup (keys[i].name); int j, len = strlen (name); for (j = 0; j < len; j++) { if (name[j] == '.') { name[j] = '_'; } } r_cons_printf (".%s%s { color: rgb(%d, %d, %d); }%s", prefix, name, r, g, b, hasnext); free (name); } break; case 'h': r = g = b = 0; r_cons_rgb_parse (*color, &r, &g, &b, NULL); rgbstr[0] = 0; name = strdup (keys[i].name); r_str_replace_char (name, '.', '_'); r_cons_printf (".%s { color:#%02x%02x%02x }\n", name, r, g, b); free (name); break; case '*': case 'r': case 1: r = g = b = 0; r_cons_rgb_parse (*color, &r, &g, &b, NULL); rgbstr[0] = 0; r_cons_rgb_str (rgbstr, r, g, b, 0); r_cons_printf ("ec %s rgb:%02x%02x%02x\n", keys[i].name, r, g, b); break; default: r_cons_printf (" %s##"Color_RESET" %s\n", *color, keys[i].name); } } if (rad == 'j') r_cons_print ("}\n"); }
static int parse(RParse *p, const char *data, char *str) { int i, len = strlen (data); char w0[WSZ]; char w1[WSZ]; char w2[WSZ]; char w3[WSZ]; char w4[WSZ]; char *buf, *ptr, *optr; if (!strcmp (data, "jr ra")) { strcpy (str, "ret"); return true; } // malloc can be slow here :? if (!(buf = malloc (len + 1))) { return false; } memcpy (buf, data, len+1); r_str_replace_char (buf, '(', ','); r_str_replace_char (buf, ')', ' '); r_str_trim (buf); if (*buf) { w0[0]='\0'; w1[0]='\0'; w2[0]='\0'; w3[0]='\0'; w4[0]='\0'; ptr = strchr (buf, ' '); if (!ptr) { ptr = strchr (buf, '\t'); } if (ptr) { *ptr = '\0'; for (++ptr; *ptr == ' '; ptr++) { ; } strncpy (w0, buf, WSZ - 1); strncpy (w1, ptr, WSZ - 1); optr=ptr; ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr == ' '; ptr++) { ; } strncpy (w1, optr, WSZ - 1); strncpy (w2, ptr, WSZ - 1); optr=ptr; ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr == ' '; ptr++) { ; } strncpy (w2, optr, WSZ - 1); strncpy (w3, ptr, WSZ - 1); optr=ptr; // bonus ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr == ' '; ptr++) { ; } strncpy (w3, optr, WSZ - 1); strncpy (w4, ptr, WSZ - 1); } } } } else { strncpy (w0, buf, WSZ - 1); } { const char *wa[] = { w0, w1, w2, w3, w4 }; int nw = 0; for (i=0; i<4; i++) { if (wa[i][0] != '\0') { nw++; } } replace (nw, wa, str); { char *p = strdup (str); p = r_str_replace (p, "+ -", "- ", 0); p = r_str_replace (p, " + ]", " + 0]", 0); p = r_str_replace (p, "zero", "0", 1); if (!strncmp (p, "0 = ", 4)) { *p = 0; // nop } if (!strcmp (w1, w2)) { char a[32], b[32]; #define REPLACE(x,y) do { \ int snprintf_len1_ = snprintf (a, 32, x, w1, w1); \ int snprintf_len2_ = snprintf (b, 32, y, w1); \ if (snprintf_len1_ < 32 && snprintf_len2_ < 32) { \ p = r_str_replace (p, a, b, 0); \ } \ } while (0) // TODO: optimize REPLACE ("%s = %s +", "%s +="); REPLACE ("%s = %s -", "%s -="); REPLACE ("%s = %s &", "%s &="); REPLACE ("%s = %s |", "%s |="); REPLACE ("%s = %s ^", "%s ^="); REPLACE ("%s = %s >>", "%s >>="); REPLACE ("%s = %s <<", "%s <<="); } p = r_str_replace (p, ":", "0000", 0); strcpy (str, p); free (p); } } } free (buf); return true; }
static int cmd_eval(void *data, const char *input) { char *p; RCore *core = (RCore *)data; switch (input[0]) { case 't': // env if (input[1] == 'a') { r_cons_printf ("%s\n", (r_num_rand (10) % 2)? "wen": "son"); } else if (input[1]==' ' && input[2]) { RConfigNode *node = r_config_node_get (core->config, input+2); if (node) { const char *type = r_config_node_type (node); if (type && *type) { r_cons_println (type); } } } else { eprintf ("Usage: et [varname] ; show type of eval var\n"); } break; case 'n': // env if (!strchr (input, '=')) { char *var, *p; var = strchr (input, ' '); if (var) while (*var==' ') var++; p = r_sys_getenv (var); if (p) { r_cons_println (p); free (p); } else { char **e = r_sys_get_environ (); while (e && *e) { r_cons_println (*e); e++; } } } else if (strlen (input)>3) { char *v, *k = strdup (input+3); if (!k) break; v = strchr (k, '='); if (v) { *v++ = 0; r_sys_setenv (k, v); } free (k); } return true; case 'x': // exit // XXX we need headers for the cmd_xxx files. return cmd_quit (data, ""); case 'j': // json r_config_list (core->config, NULL, 'j'); break; case 'v': // verbose r_config_list (core->config, input + 1, 'v'); break; case 'q': // quiet list of eval keys r_config_list (core->config, NULL, 'q'); break; case '\0': // "e" r_config_list (core->config, NULL, 0); break; case 'c': // "ec" switch (input[1]) { case 'd': r_cons_pal_init (NULL); break; case '?': { const char *helpmsg[] = { "Usage ec[s?] [key][[=| ]fg] [bg]","","", "ec","","list all color keys", "ec*","","same as above, but using r2 commands", "ecd","","set default palette", "ecr","","set random palette (see also scr.randpal)", "ecs","","show a colorful palette", "ecj","","show palette in JSON", "ecc"," [prefix]","show palette in CSS", "eco"," dark|white","load white color scheme template", "ecp","","load previous color theme", "ecn","","load next color theme", "ecH","[?]","highlight word or instruction", "ec"," prompt red","change color of prompt", "ec"," prompt red blue","change color and background of prompt", ""," ","", "colors:","","rgb:000, red, green, blue, ...", "e scr.rgbcolor","=1|0","for 256 color cube (boolean)", "e scr.truecolor","=1|0","for 256*256*256 colors (boolean)", "$DATADIR/radare2/cons","","~/.config/radare2/cons ./", NULL}; r_core_cmd_help (core, helpmsg); } break; case 'o': // "eco" if (input[2] == 'j') { nextpal (core, 'j'); } else if (input[2] == ' ') { bool failed = false; char *home, path[512]; snprintf (path, sizeof (path), ".config/radare2/cons/%s", input + 3); home = r_str_home (path); snprintf (path, sizeof (path), R2_DATDIR"/radare2/" R2_VERSION"/cons/%s", input + 3); if (!load_theme (core, home)) { if (load_theme (core, path)) { //curtheme = r_str_dup (curtheme, path); curtheme = r_str_dup (curtheme, input + 3); } else { if (load_theme (core, input + 3)) { curtheme = r_str_dup (curtheme, input + 3); } else { char *absfile = r_file_abspath (input + 3); eprintf ("eco: cannot open colorscheme profile (%s)\n", absfile); free (absfile); failed = true; } } } free (home); if (failed) { eprintf ("Something went wrong\n"); } } else if (input[2] == '?') { eprintf ("Usage: eco [themename] ;load theme from "R2_DATDIR"/radare2/"R2_VERSION"/cons/\n"); } else { nextpal (core, 'l'); } break; case 's': r_cons_pal_show (); break; // "ecs" case '*': r_cons_pal_list (1, NULL); break; // "ec*" case 'h': // echo if (( p = strchr (input, ' ') )) { r_cons_strcat (p+1); r_cons_newline (); } else { // "ech" r_cons_pal_list ('h', NULL); } break; case 'j': // "ecj" r_cons_pal_list ('j', NULL); break; case 'c': // "ecc" r_cons_pal_list ('c', input + 2); break; case '\0': // "ec" r_cons_pal_list (0, NULL); break; case 'r': // "ecr" r_cons_pal_random (); break; case 'n': // "ecn" nextpal (core, 'n'); break; case 'p': // "ecp" nextpal (core, 'p'); break; case 'H': { // "ecH" char *color_code = NULL; char *word = NULL; int argc = 0; char** argv = r_str_argv (input + 4, &argc); switch (input[2]) { case '?': { const char *helpmsg[] = { "Usage ecH[iw-?]","","", "ecHi","[color]","highlight current instruction with 'color' background", "ecHw","[word] [color]","highlight 'word ' in current instruction with 'color' background", "ecH-","","remove all highlights on current instruction", NULL }; r_core_cmd_help (core, helpmsg); } break; case '-': r_meta_set_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset, ""); return false; case '\0': case 'i': // "ecHi if (argc) { char *dup = r_str_newf ("bgonly %s", argv[0]); color_code = r_cons_pal_parse (dup); R_FREE (dup); } break; case 'w': // "ecHw" if (!argc) { eprintf ("Usage: echw word [color]\n"); r_str_argv_free (argv); return true; } word = strdup (argv[0]); if (argc > 1) { char *dup = r_str_newf ("bgonly %s", argv[1]); color_code = r_cons_pal_parse (dup); if (!color_code) { eprintf ("Unknown color %s\n", argv[1]); r_str_argv_free (argv); free (dup); free (word); return true; } R_FREE (dup); } break; default: eprintf ("See ecH?\n"); r_str_argv_free (argv); return true; } char *str = r_meta_get_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset); char *dup = r_str_newf ("%s \"%s%s\"", str?str:"", word?word:"", color_code?color_code:r_cons_pal_get ("highlight")); r_meta_set_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset, dup); r_str_argv_free (argv); R_FREE (word); R_FREE (dup); break; } default: { char *p = strdup (input + 2); char *q = strchr (p, '='); if (!q) { q = strchr (p, ' '); } if (q) { // set *q++ = 0; r_cons_pal_set (p, q); } else { const char *k = r_cons_pal_get (p); if (k) { eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, k); } } free (p); } } break; case 'e': if (input[1] == ' ') { char *p; const char *val, *input2 = strchr (input+2, ' '); if (input2) input2++; else input2 = input+2; val = r_config_get (core->config, input2); p = r_core_editor (core, NULL, val); if (p) { r_str_replace_char (p, '\n', ';'); r_config_set (core->config, input2, p); } } else { eprintf ("Usage: ee varname\n"); } break; case '!': input = r_str_chop_ro (input+1); if (!r_config_toggle (core->config, input)) eprintf ("r_config: '%s' is not a boolean variable.\n", input); break; case 's': r_config_list (core->config, (input[1])? input + 1: NULL, 's'); break; case '-': r_core_config_init (core); //eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n"); break; case '*': r_config_list (core->config, NULL, 1); break; case '?': switch (input[1]) { case '?': r_config_list (core->config, input+2, 2); break; default: r_config_list (core->config, input+1, 2); break; case 0: r_core_cmd_help (core, help_msg_e); } break; case 'r': if (input[1]) { const char *key = input+((input[1]==' ')?2:1); if (!r_config_readonly (core->config, key)) { eprintf ("cannot find key '%s'\n", key); } } else { eprintf ("Usage: er [key]\n"); } break; case ' ': r_config_eval (core->config, input+1); break; default: r_config_eval (core->config, input); break; } return 0; }
static int replace(int argc, const char *argv[], char *newstr) { int i,j,k; struct { int narg; char *op; char *str; } ops[] = { { 0, "abs", "1 = abs(1)"}, { 0, "adc", "1 = 2 + 3"}, { 3, "add", "1 = 2 + 3"}, { 2, "add", "1 += 2"}, { 2, "adds", "1 += 2"}, { 3, "adds", "1 = 2 + 3"}, { 3, "addw", "1 = 2 + 3"}, { 3, "add.w", "1 = 2 + 3"}, { 0, "adf", "1 = 2 + 3"}, { 0, "adrp", "1 = 2"}, { 0, "and", "1 = 2 & 3"}, { 0, "ands", "1 &= 2"}, { 0, "asls", "1 = 2 << 3"}, { 0, "asl", "1 = 2 << 3"}, { 0, "asrs", "1 = 2 >> 3"}, { 0, "asr", "1 = 2 >> 3"}, { 0, "b", "jmp 1"}, { 0, "cbz", "if !1 jmp 2"}, { 0, "cbnz", "if 1 jmp 2"}, { 0, "b.w", "jmp 1"}, { 0, "b.gt", "jmp ifgt 1"}, { 0, "b.le", "jmp ifle 1"}, { 0, "beq lr", "ifeq ret"}, { 0, "beq", "je 1"}, { 0, "call", "1()"}, { 0, "bl", "1()"}, { 0, "blx", "1()"}, { 0, "bx lr", "ret"}, { 0, "bxeq", "je 1"}, { 0, "cmf", "if (1 == 2)"}, { 0, "cmp", "if (1 == 2)"}, { 0, "tst", "if (1 == 2)"}, { 0, "dvf", "1 = 2 / 3"}, { 0, "eor", "1 = 2 ^ 3"}, { 0, "fdv", "1 = 2 / 3"}, { 0, "fml", "1 = 2 * 3"}, { 2, "ldr", "1 = 2"}, { 2, "ldrb", "1 = (byte) 2"}, { 2, "ldrsb", "1 = (byte) 2"}, { 2, "ldr.w", "1 = 2"}, { 2, "ldrsw", "1 = 2"}, { 3, "ldr", "1 = 2 + 3"}, { 3, "ldrb", "1 = (byte) 2 + 3"}, { 3, "ldrsb", "1 = (byte) 2 + 3"}, { 3, "ldr.w", "1 = 2 + 3"}, { 3, "ldrsw", "1 = 2 + 3"}, { 0, "lsl", "1 = 2 << 3"}, { 0, "lsr", "1 = 2 >> 3"}, { 0, "mov", "1 = 2"}, { 0, "mvn", "1 = ~2"}, { 0, "movz", "1 = 2"}, { 0, "movk", "1 = 2"}, { 0, "movn", "1 = 2"}, { 0, "vmov.i32", "1 = 2"}, { 0, "muf", "1 = 2 * 3"}, { 0, "mul", "1 = 2 * 3"}, { 0, "muls", "1 = 2 * 3"}, { 0, "orr", "1 = 2 | 3"}, { 0, "rmf", "1 = 2 % 3"}, { 0, "bge", "(>=) goto 1"}, { 0, "sbc", "1 = 2 - 3"}, { 0, "sqt", "1 = sqrt(2)"}, { 0, "lsrs", "1 = 2 >> 3"}, { 0, "lsls", "1 = 2 << 3"}, { 0, "lsr", "1 = 2 >> 3"}, { 0, "lsl", "1 = 2 << 3"}, { 2, "str", "2 = 1"}, { 2, "strb", "2 = (byte) 1"}, { 2, "strh", "2 = (half) 1"}, { 2, "strh.w", "2 = (half) 1"}, { 3, "str", "2 + 3 = 1"}, { 3, "strb", "2 + 3 = (byte) 1"}, { 3, "strh", "2 + 3 = (half) 1"}, { 3, "strh.w", "2 + 3 = (half) 1"}, { 3, "sub", "1 = 2 - 3"}, { 3, "subs", "1 = 2 - 3"}, { 2, "sub", "1 -= 2"}, // THUMB { 2, "subs", "1 -= 2"}, // THUMB { 0, "swp", "swap(1, 2)"}, /* arm thumb */ { 0, "movs", "1 = 2"}, { 0, "movw", "1 = 2"}, { 0, "movt", "1 |= 2 << 16"}, { 0, "vmov", "1 = (float) 2 . 3"}, { 0, "vdiv.f64", "1 = (float) 2 / 3" }, { 0, "addw", "1 = 2 + 3"}, { 0, "sub.w", "1 = 2 - 3"}, { 0, "tst.w", "if (1 == 2)"}, { 0, "lsr.w", "1 = 2 >> 3"}, { 0, "lsl.w", "1 = 2 << 3"}, { 0, "pop.w", "pop 1"}, { 0, "vpop", "pop 1"}, { 0, "vpush", "push 1"}, { 0, "push.w", "push 1"}, { 0, NULL } }; if (!newstr) { return false; } for (i = 0; ops[i].op != NULL; i++) { if (ops[i].narg) { if (argc-1 != ops[i].narg) { continue; } } if (!strcmp (ops[i].op, argv[0])) { for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) { if (IS_DIGIT(ops[i].str[j])) { int idx = ops[i].str[j]-'0'; if (idx < argc) { const char *w = argv[idx]; if (w) { strcpy (newstr + k, w); k += strlen (w) - 1; } } } else { newstr[k] = ops[i].str[j]; } } newstr[k] = '\0'; r_str_replace_char (newstr, '{', '('); r_str_replace_char (newstr, '}', ')'); return true; } } /* TODO: this is slow */ newstr[0] = '\0'; for (i = 0; i < argc; i++) { strcat (newstr, argv[i]); strcat (newstr, (!i || i == argc - 1)? " " : ","); } r_str_replace_char (newstr, '{', '('); r_str_replace_char (newstr, '}', ')'); return false; }
static ut64 num_callback(RNum *userptr, const char *str, int *ok) { RCore *core = (RCore *)userptr; // XXX ? RAnalFunction *fcn; char *ptr, *bptr; RFlagItem *flag; RIOSection *s; RAnalOp op; ut64 ret = 0; if (ok) *ok = R_FALSE; if (*str=='[') { int refsz = (core->assembler->bits & R_SYS_BITS_64)? 8: 4; const char *p = strchr (str+5, ':'); ut64 n; // TODO: honor endian if (p) { refsz = atoi (str+1); str = p; } // push state { char *o = strdup (str+1); const char *q = r_num_calc_index (core->num, NULL); r_str_replace_char (o, ']', 0); n = r_num_math (core->num, o); r_num_calc_index (core->num, q); free (o); } // pop state switch (refsz) { case 8: { ut64 num = 0; r_io_read_at (core->io, n, (ut8*)&num, sizeof (num)); return num; } case 4: { ut32 num = 0; r_io_read_at (core->io, n, (ut8*)&num, sizeof (num)); return num; } case 2: { ut16 num = 0; r_io_read_at (core->io, n, (ut8*)&num, sizeof (num)); return num; } case 1: { ut8 num = 0; r_io_read_at (core->io, n, (ut8*)&num, sizeof (num)); return num; } default: eprintf ("Invalid reference size: %d (%s)\n", refsz, str); break; } } else if (str[0]=='$') { if (ok) *ok = 1; // TODO: group analop-dependant vars after a char, so i can filter r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); switch (str[1]) { case '.': // can use pc, sp, a0, a1, ... return r_debug_reg_get (core->dbg, str+2); case '{': bptr = strdup (str+2); ptr = strchr (bptr, '}'); if (ptr != NULL) { ut64 ret; ptr[0] = '\0'; ret = r_config_get_i (core->config, bptr); free (bptr); return ret; } break; case 'h': { int rows; r_cons_get_size (&rows); return rows; } case 'e': return op.eob; case 'j': return op.jump; case 'f': return op.fail; case 'r': return op.ref; case 'l': return op.length; case 'b': return core->blocksize; case 's': return core->file->size; case 'w': return r_config_get_i (core->config, "asm.bits") / 8; case 'S': s = r_io_section_get (core->io, r_io_section_vaddr_to_offset (core->io, core->offset)); return s? (str[2]=='S'? s->size: s->offset): 0; case '?': return core->num->value; case '$': return core->offset; case 'o': return core->io->off; case 'C': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_CALL); case 'J': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_CODE); case 'D': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_DATA); case 'X': return getref (core, atoi (str+2), 'x', R_ANAL_REF_TYPE_CALL); case 'I': fcn = r_anal_fcn_find (core->anal, core->offset, 0); return fcn? fcn->ninstr: 0; case 'F': fcn = r_anal_fcn_find (core->anal, core->offset, 0); return fcn? fcn->size: 0; } } else if (*str>'A') { if ((flag = r_flag_get (core->flags, str))) { ret = flag->offset; if (ok) *ok = R_TRUE; } } return ret; }
static bool varsub (RParse *p, RAnalFunction *f, ut64 addr, int oplen, char *data, char *str, int len) { RList *regs, *bpargs, *spargs; RAnalVar *reg, *bparg, *sparg; RListIter *regiter, *bpargiter, *spiter; char oldstr[64], newstr[64]; char *tstr = strdup (data); if (!tstr) { return false; } bool att = strchr (data, '%'); if (p->relsub) { if (att) { char *rip = (char *) r_str_casestr (tstr, "(%rip)"); if (rip) { *rip = 0; char *pre = tstr; char *pos = rip + 6; char *word = strchr (tstr, ' '); if (word) { *word++ = 0; *rip = 0; st64 n = r_num_math (NULL, word); ut64 repl_num = oplen + addr + n; char *tstr_new = r_str_newf ("%s 0x%08"PFMT64x"%s", pre, repl_num, pos); *rip = '('; free (tstr); tstr = tstr_new; } } } else { char *rip = (char *) r_str_casestr (tstr, "[rip"); if (rip) { char *ripend = strchr (rip + 3, ']'); const char *plus = strchr (rip, '+'); const char *neg = strchr (rip, '-'); char *tstr_new; ut64 repl_num = oplen + addr; if (!ripend) { ripend = "]"; } if (plus) { repl_num += r_num_get (NULL, plus + 1); } if (neg) { repl_num -= r_num_get (NULL, neg + 1); } rip[1] = '\0'; tstr_new = r_str_newf ("%s0x%08"PFMT64x"%s", tstr, repl_num, ripend); free (tstr); tstr = tstr_new; if (!strncasecmp (tstr, "lea", 3)) { r_str_replace_char (tstr, '[', 0); r_str_replace_char (tstr, ']', 0); } } } } if (!p->varlist) { free (tstr); return false; } regs = p->varlist (p->anal, f, 'r'); bpargs = p->varlist (p->anal, f, 'b'); spargs = p->varlist (p->anal, f, 's'); /*iterate over stack pointer arguments/variables*/ bool ucase = *tstr >= 'A' && *tstr <= 'Z'; if (ucase && tstr[1]) { ucase = tstr[1] >= 'A' && tstr[1] <= 'Z'; } r_list_foreach (spargs, spiter, sparg) { // assuming delta always positive? mk_reg_str (p->anal->reg->name[R_REG_NAME_SP], sparg->delta, true, att, oldstr, sizeof (oldstr)); if (ucase) { r_str_case (oldstr, true); } parse_localvar (p, newstr, sizeof (newstr), sparg->name, p->anal->reg->name[R_REG_NAME_SP], '+', att); if (ucase) { char *plus = strchr (newstr, '+'); if (plus) { *plus = 0; r_str_case (newstr, true); *plus = '+'; } else { r_str_case (newstr, true); } } char *ptr = strstr(tstr, oldstr); if (ptr && (!att || *(ptr - 1) == ' ')) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } else { r_str_case (oldstr, false); ptr = strstr(tstr, oldstr); if (ptr && (!att || *(ptr - 1) == ' ')) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } } }
static int parse(RParse *p, const char *data, char *str) { int i, n; char w0[32]; char w1[32]; char w2[32]; char w3[32]; char *buf, *ptr, *optr, *num; // malloc can be slow here :? buf = strdup (data); r_str_trim_head (buf); ptr = strchr (buf, '#'); if (ptr) { *ptr = 0; r_str_chop (buf); } if (*buf == '.' || buf[strlen(buf)-1] == ':') { free (buf); strcpy (str, data); return R_TRUE; } r_str_replace_char (buf, '$', 0); r_str_replace_char (buf, '%', 0); r_str_replace_char (buf, '\t', ' '); r_str_replace_char (buf, '(', '['); r_str_replace_char (buf, ')', ']'); ptr = strchr (buf, '['); if (ptr) { *ptr = 0; num = (char*)r_str_lchr (buf, ' '); if (!num) num = (char*)r_str_lchr (buf, ','); if (num) { n = atoi (num+1); *ptr = '['; memmove (num+1, ptr, strlen (ptr)+1); ptr = (char*)r_str_lchr (buf, ']'); if (n && ptr) { char *rest = strdup (ptr+1); if(n>0) sprintf (ptr, "+%d]%s", n, rest); else sprintf (ptr, "%d]%s", n, rest); free (rest); } } else *ptr = '['; } if (*buf) { *w0 = *w1 = *w2 = *w3 = 0; ptr = strchr (buf, ' '); if (ptr == NULL) ptr = strchr (buf, '\t'); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w0, buf, sizeof(w0) - 1); strncpy (w1, ptr, sizeof(w1) - 1); optr = ptr; ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w1, optr, sizeof(w1)-1); strncpy (w2, ptr, sizeof(w2)-1); ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w2, optr, sizeof(w2)-1); strncpy (w3, ptr, sizeof(w3)-1); } } } { const char *wa[] = { w0, w1, w2, w3 }; int nw = 0; for (i=0; i<4; i++) { if (wa[i][0] != '\0') nw++; } replace (nw, wa, str); } } free (buf); return R_TRUE; }
static int parse(RParse *p, const char *data, char *str) { int i, len = strlen (data); char w0[WSZ]; char w1[WSZ]; char w2[WSZ]; char w3[WSZ]; char w4[WSZ]; char *buf, *ptr, *optr; if (!strcmp (data, "jr ra")) { strcpy (str, "ret"); return R_TRUE; } // malloc can be slow here :? if ((buf = malloc (len+1)) == NULL) return R_FALSE; memcpy (buf, data, len+1); r_str_replace_char (buf, '(', ','); r_str_replace_char (buf, ')', ' '); r_str_chop (buf); if (*buf) { w0[0]='\0'; w1[0]='\0'; w2[0]='\0'; w3[0]='\0'; w4[0]='\0'; ptr = strchr (buf, ' '); if (ptr == NULL) ptr = strchr (buf, '\t'); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w0, buf, WSZ - 1); strncpy (w1, ptr, WSZ - 1); optr=ptr; ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w1, optr, WSZ - 1); strncpy (w2, ptr, WSZ - 1); optr=ptr; ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w2, optr, WSZ - 1); strncpy (w3, ptr, WSZ - 1); optr=ptr; // bonus ptr = strchr (ptr, ','); if (ptr) { *ptr = '\0'; for (++ptr; *ptr==' '; ptr++); strncpy (w3, optr, WSZ - 1); strncpy (w4, ptr, WSZ - 1); } } } } { const char *wa[] = { w0, w1, w2, w3, w4 }; int nw = 0; for (i=0; i<4; i++) { if (wa[i][0] != '\0') nw++; } replace (nw, wa, str); { char *p = strdup (str); p = r_str_replace (p, "+ -", "- ", 0); #if EXPERIMENTAL_ZERO p = r_str_replace (p, "zero", "0", 0); if (!memcmp (p, "0 = ", 4)) *p = 0; // nop #endif if (!strcmp (w1, w2)) { char a[32], b[32]; #define REPLACE(x,y) \ sprintf (a, x, w1, w1); \ sprintf (b, y, w1); \ p = r_str_replace (p, a, b, 0); // TODO: optimize REPLACE ("%s = %s +", "%s +="); REPLACE ("%s = %s -", "%s -="); REPLACE ("%s = %s &", "%s &="); REPLACE ("%s = %s |", "%s |="); REPLACE ("%s = %s ^", "%s ^="); REPLACE ("%s = %s >>", "%s >>="); REPLACE ("%s = %s <<", "%s <<="); } p = r_str_replace (p, ":", "0000", 0); strcpy (str, p); free (p); } } } free (buf); return R_TRUE; }
static ut64 num_callback(RNum *userptr, const char *str, int *ok) { RCore *core = (RCore *)userptr; // XXX ? RAnalFunction *fcn; char *ptr, *bptr, *out; RFlagItem *flag; RIOSection *s; RAnalOp op; ut64 ret = 0; if (ok) *ok = R_FALSE; switch (*str) { case '[': { ut64 n = 0LL; int refsz = (core->assembler->bits & R_SYS_BITS_64)? 8: 4; const char *p = NULL; if (strlen (str)>5) p = strchr (str+5, ':'); // TODO: honor LE if (p) { refsz = atoi (str+1); str = p; } // push state { if (str[0] && str[1]) { const char *q; char *o = strdup (str+1); if (o) { q = r_num_calc_index (core->num, NULL); if (q) { if (r_str_replace_char (o, ']', 0)>0) { n = r_num_math (core->num, o); r_num_calc_index (core->num, q); } } free (o); } } } // pop state if (ok) *ok = 1; ut32 num = 0; switch (refsz) { case 8: case 4: case 2: case 1: (void)r_io_read_at (core->io, n, (ut8*)&num, refsz); r_mem_copyendian ((ut8*)&num, (ut8*)&num, refsz, !core->assembler->big_endian); return num; default: eprintf ("Invalid reference size: %d (%s)\n", refsz, str); return 0LL; } } break; case '$': if (ok) *ok = 1; // TODO: group analop-dependant vars after a char, so i can filter r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); switch (str[1]) { case '.': // can use pc, sp, a0, a1, ... return r_debug_reg_get (core->dbg, str+2); case 'k': if (str[2]!='{') { eprintf ("Expected '{' after 'k'.\n"); break; } bptr = strdup (str+3); ptr = strchr (bptr, '}'); if (ptr == NULL) { // invalid json free (bptr); break; } *ptr = '\0'; ret = 0LL; out = sdb_querys (core->sdb, NULL, 0, bptr); if (out && *out) { if (strstr (out, "$k{")) { eprintf ("Recursivity is not permitted here\n"); } else { ret = r_num_math (core->num, out); } } free (bptr); free (out); return ret; break; case '{': bptr = strdup (str+2); ptr = strchr (bptr, '}'); if (ptr != NULL) { ut64 ret; ptr[0] = '\0'; ret = r_config_get_i (core->config, bptr); free (bptr); return ret; } free (bptr); break; case 'c': return r_cons_get_size (NULL); case 'r': { int rows; r_cons_get_size (&rows); return rows; } case 'e': return r_anal_op_is_eob (&op); case 'j': return op.jump; case 'p': return r_sys_getpid (); case 'P': return (core->dbg->pid>0)? core->dbg->pid: 0; case 'f': return op.fail; case 'm': return op.ptr; // memref case 'v': return op.val; // immediate value case 'l': return op.size; case 'b': return core->blocksize; case 's': if (core->file) { return r_io_desc_size (core->io, core->file->desc); } return 0LL; case 'w': return r_config_get_i (core->config, "asm.bits") / 8; case 'S': s = r_io_section_vget (core->io, core->offset); return s? (str[2]=='S'? s->size: s->vaddr): 3; case '?': return core->num->value; case '$': return core->offset; case 'o': return r_io_section_vaddr_to_offset (core->io, core->offset); case 'C': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_CALL); case 'J': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_CODE); case 'D': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_DATA); case 'X': return getref (core, atoi (str+2), 'x', R_ANAL_REF_TYPE_CALL); case 'I': fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); return fcn? fcn->ninstr: 0; case 'F': fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); return fcn? fcn->size: 0; } break; default: if (*str>'A') { // NOTE: functions override flags RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, str); if (fcn) { if (ok) *ok = R_TRUE; return fcn->addr; } #if 0 ut64 addr = r_anal_fcn_label_get (core->anal, core->offset, str); if (addr != 0) { ret = addr; } else { ... } #endif if ((flag = r_flag_get (core->flags, str))) { ret = flag->offset; if (ok) *ok = R_TRUE; } } break; }
static bool varsub (RParse *p, RAnalFunction *f, ut64 addr, int oplen, char *data, char *str, int len) { RAnalVar *reg, *bparg, *sparg; RListIter *regiter, *bpargiter, *spiter; char oldstr[64], newstr[64]; char *tstr = strdup (data); if (!tstr) return false; RList *regs, *bpargs, *spargs; if (p->relsub) { char *rip = strstr (tstr, "[rip"); if (rip) { char *ripend = strchr (rip + 3, ']'); const char *plus = strchr (rip, '+'); const char *neg = strchr (rip, '-'); char *tstr_new; ut64 repl_num = oplen + addr; if (!ripend) ripend = "]"; if (plus) repl_num += r_num_get (NULL, plus + 1); if (neg) repl_num -= r_num_get (NULL, neg + 1); rip[1] = '\0'; tstr_new = r_str_newf ("%s0x%08"PFMT64x"%s", tstr, repl_num, ripend); free (tstr); tstr = tstr_new; if (!strncmp (tstr, "lea", 3)) { r_str_replace_char (tstr, '[', 0); r_str_replace_char (tstr, ']', 0); } } } if (!p->varlist) { free (tstr); return false; } regs = p->varlist (p->anal, f, 'v'); bpargs = p->varlist (p->anal, f, 'a'); spargs = p->varlist (p->anal, f, 'e'); /*iterate over stack pointer arguments/variables*/ r_list_foreach (spargs, spiter,sparg) { if (sparg->delta < 10) { snprintf (oldstr, sizeof (oldstr)-1, "[%s + %d]", p->anal->reg->name[R_REG_NAME_SP], sparg->delta); } else { snprintf (oldstr, sizeof (oldstr)-1, "[%s + 0x%x]", p->anal->reg->name[R_REG_NAME_SP], sparg->delta); } snprintf (newstr, sizeof (newstr)-1, "[%s + %s]", p->anal->reg->name[R_REG_NAME_SP], sparg->name); if (strstr (tstr, oldstr)) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } else { r_str_case (oldstr, false); if (strstr (tstr, oldstr)) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } } } /* iterate over base pointer args/vars */ r_list_foreach (bpargs, bpargiter, bparg) { char sign = '+'; if (bparg->delta < 0) { sign = '-'; bparg->delta = -bparg->delta; } if (bparg->delta < 10) snprintf (oldstr, sizeof (oldstr)-1, "[%s %c %d]", p->anal->reg->name[R_REG_NAME_BP], sign, bparg->delta); else snprintf (oldstr, sizeof (oldstr)-1, "[%s %c 0x%x]", p->anal->reg->name[R_REG_NAME_BP], sign, bparg->delta); snprintf (newstr, sizeof (newstr)-1, "[%s %c %s]", p->anal->reg->name[R_REG_NAME_BP], sign, bparg->name); if (strstr (tstr, oldstr) != NULL) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } else { r_str_case (oldstr, false); if (strstr (tstr, oldstr) != NULL) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } } // Try with no spaces snprintf (oldstr, sizeof (oldstr)-1, "[%s%c0x%x]", p->anal->reg->name[R_REG_NAME_BP], sign, bparg->delta); if (strstr (tstr, oldstr) != NULL) { tstr = r_str_replace (tstr, oldstr, newstr, 1); break; } }