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 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 ut64 num_callback(RNum *userptr, const char *str, int *ok) { RCore *core = (RCore *)userptr; // XXX ? RFlagItem *flag; RAnalOp op; ut64 ret = 0; *ok = 0; if (str[0]=='[') { int refsz = (core->assembler->bits & R_SYS_BITS_64)? 8: 4; const char *p = strchr (str+1, ':'); ut64 n; // TODO: honor endian if (p) { refsz = atoi (str+1); str = p; } // push state { const char *q = r_num_calc_index (NULL); n = r_num_math (core->num, str+1); r_num_calc_index (q); } // 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\n", refsz); break; } } else if (str[0]=='$') { *ok = 1; r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); switch (str[1]) { case '{': { char *ptr, *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; } } return 0; 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 '?': return core->num->value; case '$': return core->offset; case 'o': return core->io->off; } } else if (*str>'A') { if ((flag = r_flag_get (core->flags, str))) { ret = flag->offset; *ok = R_TRUE; } else *ok = ret = 0; } return ret; }