Refactor instruction $variables under $i ##shell

* "$in", ":{n}", "address of nth instruction forward",
* "$ip", ":{n}", "address of nth instruction backward (s $I1@$Fe) #last instr in bb",
* "$is", "[:{n}]", "N instruction size",
* "$ij", "", "jump address (e.g. jmp 0x10, jz 0x10 => 0x10)",
* "$if", "", "jump fail address (e.g. jz 0x10 => next instruction)",
* "$ir", "", "instruction reference pointer value (e.g. lea rax, 0x8010 => 0x8010)",
* "$iv", "", "opcode immediate value (e.g. lui a0,0x8010 => 0x8010)",
This commit is contained in:
pancake 2024-10-30 20:18:01 +01:00 committed by GitHub
parent 536effe6ce
commit e70fb866b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 198 additions and 99 deletions

View File

@ -7920,7 +7920,7 @@ static void r_anal_aefa(RCore *core, const char *arg) {
r_core_cmdf (core, "aepc 0x%08"PFMT64x, at);
r_core_cmd_call (core, "aeso");
r_core_seek (core, at, true);
int delta = r_num_get (core->num, "$l");
int delta = r_num_get (core->num, "$is");
if (delta < 1) {
break;
}

View File

@ -338,6 +338,16 @@ static RCoreHelpMessage help_msg_question_v = {
"$?", "", "last comparison value",
"$alias", "=value", "alias commands (simple macros)",
"$b", "", "block size (see b command and the @! operator)",
"$k", "{kv}", "get value of an sdb query value",
"$in", ":{n}", "address of nth instruction forward",
"$ip", ":{n}", "address of nth instruction backward (s $I1@$Fe) #last instr in bb",
"$is", "[:{n}]", "N instruction size",
"$ij", "", "jump address (e.g. jmp 0x10, jz 0x10 => 0x10)",
"$if", "", "jump fail address (e.g. jz 0x10 => next instruction)",
"$ir", "", "instruction reference pointer value (e.g. lea rax, 0x8010 => 0x8010)",
"$iv", "", "opcode immediate value (e.g. lui a0,0x8010 => 0x8010)",
"$B", "", "base address (aligned lowest map address)",
"$c", "", "get terminal width in character columns",
"$Cn", "", "get nth call of function",
@ -347,7 +357,6 @@ static RCoreHelpMessage help_msg_question_v = {
"$Dn", "", "get nth data reference in function",
"$e", "", "1 if end of block, else 0",
"$e", "{flag}", "end of flag (flag->offset + flag->size)",
"$f", "", "jump fail address (e.g. jz 0x10 => next instruction)",
"$F", "", "same as $FB",
"$Fb", "", "begin of basic block",
"$FB", "", "begin of function",
@ -357,18 +366,13 @@ static RCoreHelpMessage help_msg_question_v = {
"$Fi", "", "basic block instructions",
"$FI", "", "function instructions",
"$Fj", "", "function jump destination",
"$fl", "", "flag length (size) at current address (fla; pD $l @ entry0)",
"$fl", "", "flag length (size) at current address (fla; pD $is @ entry0)",
"$FS", "", "function size (linear length)",
"$Fs", "", "size of the current basic block",
"$FSS", "", "function size (sum bb sizes)",
"$i", "{n}", "address of nth instruction forward",
"$I", "{n}", "address of nth instruction backward (s $I1@$Fe) #last instr in bb",
"$j", "", "jump address (e.g. jmp 0x10, jz 0x10 => 0x10)",
"$Ja", "", "get nth jump of function",
"$k", "{kv}", "get value of an sdb query value",
"$l", "", "opcode length",
"$M", "", "map address (lowest map address)",
"$m", "", "opcode memory reference (e.g. mov eax,[0x10] => 0x10)",
"$MM", "", "map size (lowest map address)",
"$o", "", "here (current disk io offset)",
"$p", "", "getpid()",
@ -379,7 +383,6 @@ static RCoreHelpMessage help_msg_question_v = {
"$S", "", "section offset",
"$SS", "", "section size",
"$s", "{flag}", "get size of flag",
"$v", "", "opcode immediate value (e.g. lui a0,0x8010 => 0x8010)",
"$w", "", "get word size, 4 if asm.bits=32, 8 if 64, ...",
"$Xn", "", "get nth xref of function",
"RNum", "", "$variables usable in math expressions",
@ -1160,9 +1163,10 @@ static int cmd_help(void *data, const char *input) {
int i = 0;
const char *vars[] = {
"$$", "$$c", "$$$", "$$$c", "$?", "$B", "$b", "$c", "$Cn", "$D", "$DB", "$DD", "$Dn",
"$is", "$ij", "$if", "$ir", "$iv", "$in", "$ip",
"$e", "$f", "$F", "$Fb", "$FB", "$Fe", "$FE", "$Ff", "$Fi", "$FI", "$Fj",
"$fl", "$FS", "$Fs", "$FSS", "$i", "$j", "$Ja", "$l", "$M", "$m", "$MM",
"$o", "$p", "$P", "$r", "$s", "$S", "$SS", "$v", "$w", "$Xn", NULL
"$fl", "$FS", "$Fs", "$FSS", "$Ja", "$M", "$MM",
"$o", "$p", "$P", "$s", "$S", "$SS", "$w", "$Xn", NULL
};
const bool wideOffsets = r_config_get_i (core->config, "scr.wideoff");
while (vars[i]) {

View File

@ -4,9 +4,6 @@
#include <r_core.h>
#include <r_vec.h>
#if R2__UNIX__
#include <signal.h>
#endif
#define DB core->sdb
@ -466,15 +463,18 @@ static const char *str_callback(RNum *user, ut64 off, int *ok) {
return NULL;
}
static ut64 numvar_instruction_backward(RCore *core, const char *input) {
static ut64 invalid_numvar(RCore *core, const char *str) {
core->num->nc.errors ++;
core->num->nc.calc_err = str;
return 0;
}
static ut64 numvar_instruction_prev(RCore *core, int n, int *ok) {
if (ok) {
*ok = true;
}
// N forward instructions
int i, ret;
int n = 1;
if (isdigit ((unsigned char)input[0])) {
n = atoi (input);
} else if (input[0] == '{') {
n = atoi (input + 1);
}
if (n < 1) {
R_LOG_ERROR ("Invalid negative value");
n = 1;
@ -514,21 +514,12 @@ static ut64 numvar_instruction_backward(RCore *core, const char *input) {
return val;
}
static ut64 numvar_instruction(RCore *core, const char *input) {
static ut64 numvar_instruction_next(RCore *core, ut64 addr, int n, int *ok) {
RAnalOp op;
ut64 addr = core->offset;
// N forward instructions
ut8 data[32];
int i;
ut64 val = addr;
int n = 1;
if (input[0] == '{') {
n = atoi (input + 1);
}
if (n < 1) {
R_LOG_ERROR ("Invalid negative value");
n = 1;
}
for (i = 0; i < n; i++) {
r_io_read_at (core->io, val, data, sizeof (data));
r_anal_op_init (&op);
@ -540,14 +531,79 @@ static ut64 numvar_instruction(RCore *core, const char *input) {
val += op.size;
r_anal_op_fini (&op);
}
if (ok) {
*ok = true;
}
return val;
}
static ut64 invalid_numvar(RCore *core, const char *str) {
core->num->nc.errors ++;
core->num->nc.calc_err = str;
return 0;
static ut64 numvar_instruction(RCore *core, const char *str, int *ok) {
#if 0
* `$j` -> `$ij` jump destination
* `$f` -> `$if` fail destination
* `$i` -> `$in` next instruction (WIP)
* `$l` -> `$is` opcode length (RFC) why not use `s` instead?
* `$m` -> `$ir` memory opcode reference address
* `$v` -> `$iv` opcode immediate (RFC)
#endif
const char ch0 = *str;
int count = 1;
if (ch0) {
const char ch1 = str[1];
if (ch1 == ':') {
count = r_num_math (NULL, str + 2);
} else if (ch1 == '{') {
count = r_num_math (NULL, str + 2);
} else if (isdigit (ch1)) {
count = r_num_math (NULL, str + 1);
} else if (ch1) {
return invalid_numvar (core, "expected :,{ after $i?");
}
}
if (ch0 == 'n') { // "$in"
return numvar_instruction_next (core, core->offset, count, ok);
}
if (ch0 == 'p') { // "$ip"
return numvar_instruction_prev (core, count, ok);
}
if (ch0 == 's') { // "$is"
return numvar_instruction_next (core, 0, count, ok);
}
if (count != 1) {
return invalid_numvar (core, "expected :,{ after $i?");
}
if (ok) {
*ok = true;
}
ut64 ret = 0;
RAnalOp op;
r_anal_op_init (&op);
r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize, R_ARCH_OP_MASK_BASIC);
r_anal_op_fini (&op); // we don't need strings or pointers, just values, which are not nullified in fini
switch (ch0) {
case 'j': // "$ij" instruction jump
ret = op.jump;
break;
case 'f': // "$if" instruction fail
ret = op.fail;
break;
case 's': // "$is" instruction size
ret = op.size;
break;
case 'r': // "$ir" instruction reference
ret = op.ptr;
break;
case 'v': // "$iv" instruction value
ret = op.val;
break;
default:
if (ok) {
*ok = false;
}
break;
}
return ret;
}
static ut64 numvar_k(RCore *core, const char *str, int *ok) {
@ -588,6 +644,28 @@ static ut64 numvar_k(RCore *core, const char *str, int *ok) {
return invalid_numvar (core, "unknown $k{key}");
}
static ut64 numvar_dollar(RCore *core, const char *str, int *ok) {
if (!strcmp (str, "$$")) {
return core->offset;
}
if (!strcmp (str, "$$c")) {
if (core->print->cur_enabled) {
return core->offset + core->print->cur;
}
return core->offset;
}
if (!strcmp (str, "$$$")) {
return core->prompt_offset;
}
if (!strcmp (str, "$$$c")) {
if (core->print->cur_enabled) {
return core->prompt_offset + core->print->cur;
}
return core->prompt_offset;
}
return invalid_numvar (core, str);
}
static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
RCore *core = (RCore *)userptr; // XXX ?
RAnalFunction *fcn;
@ -688,13 +766,16 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
if (ok) {
*ok = true;
}
// must be deprecated
switch (str[1]) {
case 'e':
#if 0
case 'j':
case 'f':
case 'm':
case 'v':
case 'l':
#endif
r_anal_op_init (&op);
r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize, R_ARCH_OP_MASK_BASIC);
r_anal_op_fini (&op); // we don't need strings or pointers, just values, which are not nullified in fini
@ -705,15 +786,7 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
// XXX the above line is assuming op after fini keeps jump, fail, ptr, val, size and r_anal_op_is_eob()
switch (str[1]) {
case 'i': // "$i"
if (ok) {
*ok = true;
}
return numvar_instruction (core, str + 2);
case 'I': // "$I"
if (ok) {
*ok = true;
}
return numvar_instruction_backward (core, str + 2);
return numvar_instruction (core, str + 2, ok);
case '.': // can use pc, sp, a0, a1, ...
return r_debug_reg_get (core->dbg, str + 2);
case 'k': // "$k{ey}" "$k:ey"
@ -784,23 +857,18 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
return UT64_MAX;
}
return r_anal_op_is_eob (&op);
case 'j': // $j jump address
return op.jump;
case 'p': // $p
return r_sys_getpid ();
case 'P': // $P
return core->dbg->pid > 0 ? core->dbg->pid : 0;
case 'f': // $f jump fail address
if (str[2] == 'l') { // $fl flag length
{
RFlagItem *fi = r_flag_get_i (core->flags, core->offset);
if (fi) {
return fi->size;
}
return 0;
}
return op.fail;
case 'm': // $m memref
return op.ptr;
case 'B': // $B base address
case 'M': { // $M map address
ut64 lower = UT64_MAX;
@ -823,10 +891,6 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
return (lower == UT64_MAX)? 0LL: lower;
}
break;
case 'v': // $v immediate value
return op.val;
case 'l': // $l opcode length
return op.size;
case 'b': // "$b" block size
return core->blocksize;
case 's': // $s file size
@ -876,22 +940,7 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
case '?': // $?
return core->num->value; // rc;
case '$': // $$ offset
if (!strcmp (str, "$$")) {
return core->offset;
} else if (!strcmp (str, "$$c")) {
if (core->print->cur_enabled) {
return core->offset + core->print->cur;
}
return core->offset;
} else if (!strcmp (str, "$$$")) {
return core->prompt_offset;
} else if (!strcmp (str, "$$$c")) {
if (core->print->cur_enabled) {
return core->prompt_offset + core->print->cur;
}
return core->prompt_offset;
}
return invalid_numvar (core, str);
return numvar_dollar (core, str, ok);
case 'o': // $o
{
RBinSection *s = r_bin_get_section_at (r_bin_cur_object (core->bin), core->offset, true);

View File

@ -17,7 +17,7 @@ CMDS=<<EOF
e asm.arch=x86
e asm.bits=16
wx 9a34002001
?v $j
?v $ij
EOF
EXPECT=<<EOF
0x1234
@ -30,7 +30,7 @@ CMDS=<<EOF
e asm.arch=x86
e asm.bits=16
wx ea34002001
?v $j
?v $ij
EOF
EXPECT=<<EOF
0x1234

View File

@ -163,7 +163,7 @@ CMDS=<<EOF
wx e9010f
e asm.arch=x86
e asm.bits=16
?vi $l
?vi $is
pi 1
ao 1~size[1]
EOF

View File

@ -1,5 +1,6 @@
NAME=f_123
FILE=-
ARGS=-1
CMDS=<<EOF
f _foo=123
f _123=_foo
@ -15,18 +16,17 @@ f $foo=456
?v $foo
EOF
EXPECT=<<EOF
ERROR: Invalid flag name '123'
ERROR: Invalid flag name '$123'
ERROR: Invalid flag name '$foo'
0x7b
0x7b
0x141
0x7b
0xffffffffffffffff
0xffffffffffffffff
EOF
EXPECT_ERR=<<EOF
ERROR: Invalid flag name '123'
ERROR: Invalid flag name '$123'
ERROR: Invalid flag name '$foo'
0x0
0x0
EOF
EXPECT_ERR=
RUN
NAME=f?flag

View File

@ -57,10 +57,10 @@ FILE=bins//mach0/ired-arm64
CMDS=<<EOF
afr
?v $Fe
s $I1@$Fe
s $ip:1@$Fe
pi 1
?v $Fb
s $i1
s $in:1
pi 1
?v $Fb
EOF

View File

@ -145,18 +145,18 @@ EXPECT=<<EOF
EOF
RUN
NAME=$j (malloc)
NAME=$ij (malloc)
FILE=malloc://1024
CMDS=<<EOF
e asm.bits=32
e asm.arch = x86
e anal.arch = x86
wa jmp 0x30
?v $j
?v $ij
wa jz 0x01
?v $j
?v $ij
wa xor eax, eax
?v $j
?v $ij
?e
EOF
EXPECT=<<EOF
@ -167,18 +167,18 @@ EXPECT=<<EOF
EOF
RUN
NAME=$f (malloc)
NAME=$if (malloc)
FILE=malloc://1024
CMDS=<<EOF
e asm.bits=32
e asm.arch = x86
e anal.arch = x86
wx eb2e
?v $f
?v $if
wx 0f84fbffffff
?v $f
?v $if
wx 31c0
?v $f
?v $if
EOF
EXPECT=<<EOF
0xffffffffffffffff
@ -187,15 +187,15 @@ EXPECT=<<EOF
EOF
RUN
NAME=$m (malloc)
NAME=$ir (malloc)
FILE=malloc://1024
CMDS=<<EOF
e asm.arch=x86
e asm.bits=32
wa mov eax, [0x500]
?v $m
?v $ir
wa mov eax, ebx
?v $m
?v $ir
?e
EOF
EXPECT=<<EOF
@ -205,18 +205,18 @@ EXPECT=<<EOF
EOF
RUN
NAME=$l (malloc)
NAME=$is (malloc)
FILE=malloc://1024
CMDS=<<EOF
e asm.bits=32
e asm.arch = x86
e anal.arch = x86
wa xor eax, eax
?v $l
?v $is
wa mov esp, 0x1
?v $l
?v $is
wx c3
?v $l
?v $is
EOF
EXPECT=<<EOF
0x2

View File

@ -101,3 +101,49 @@ plus one
EOF
RUN
NAME=num instruction vars
FILE=malloc://0x4000
ARGS=-1 -a x86 -b32
CMDS=<<EOF
'wa call 32;nop;mov eax,33;int 0x33;ret
?e jump call 32
?vi $ij
?e fail call 32
?vi $if
?e instr pos 1 2 3
?vi $in
?vi $in:1
?vi $in:2
?vi $in:3
?e instr size 1 2 3
?vi $is
?vi $is{-1}
?vi $is:1
?vi $is:2
?vi $is:3
2so
?e mov33
?vi $iv
EOF
EXPECT=<<EOF
INFO: Written 14 byte(s) (call 32;nop;mov eax,33;int 0x33;ret) = wx e81b00000090b821000000cd33c3 @ 0x00000000
jump call 32
32
fail call 32
5
instr pos 1 2 3
5
5
6
11
instr size 1 2 3
5
-1
5
6
11
mov33
33
EOF
RUN

View File

@ -25,7 +25,7 @@ NAME=ljmp follow
FILE=bins/firmware/bios_64k.bin
CMDS=<<EOF
e asm.bits
s $j
s $ij
? $$
e anal.cs=0xfff0
? $$~segm