mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 05:09:43 +00:00
Improve aesue feedback and add tests ##esil
This commit is contained in:
parent
8c447c7129
commit
b09ebceba4
52
doc/esil.md
52
doc/esil.md
@ -7,7 +7,7 @@ These strings can be evaluated in order to emulate code.
|
||||
|
||||
Each element of an esil expression is separated by a comma. The VM can be described as this:
|
||||
|
||||
while ((word=haveCommand())) {
|
||||
while ((word = haveCommand())) {
|
||||
if (word.isKeyword()) {
|
||||
esilCommands[word](esil);
|
||||
} else {
|
||||
@ -130,8 +130,7 @@ As discussed on irc, current implementation works like this:
|
||||
|
||||
This approach is more readable, but it's less stack-friendly
|
||||
|
||||
Special instructions
|
||||
====================
|
||||
# Special instructions
|
||||
|
||||
NOPs are represented as empty strings. Unknown or invalid instructions
|
||||
|
||||
@ -143,8 +142,7 @@ Traps are implemented with the `<trap>,<code>,$$` command. They are used to
|
||||
throw exceptions like invalid instructions, division by zero, memory read
|
||||
error, etc.
|
||||
|
||||
Quick analysis
|
||||
==============
|
||||
# Quick analysis
|
||||
|
||||
Here's a list of some quick checks to retrieve information from an esil string.
|
||||
Relevant information will be probably found in the first expression of the
|
||||
@ -165,7 +163,7 @@ list.
|
||||
indexOf("LOOP") -> is a loop (rep?)
|
||||
equalsTo("") -> empty string, means: nop (wrong, if we append pc+=x)
|
||||
|
||||
Common operations:
|
||||
## Common operations:
|
||||
|
||||
* Check dstreg
|
||||
* Check srcreg
|
||||
@ -175,13 +173,11 @@ Common operations:
|
||||
* Evulate
|
||||
* Is syscall
|
||||
|
||||
CPU Flags
|
||||
=========
|
||||
# CPU Flags
|
||||
|
||||
CPU flags are usually defined as 1 bit registers in the RReg profile. and sometimes under the 'flg' register type.
|
||||
|
||||
ESIL Flags
|
||||
==========
|
||||
# ESIL Flags
|
||||
|
||||
ESIL VM have an internal state flags that can are read only and can be used to
|
||||
export those values to the underlying CPU flags. This is because the ESIL vm
|
||||
@ -198,8 +194,7 @@ p - parity
|
||||
r - regsize ( asm.bits/8 )
|
||||
```
|
||||
|
||||
Variables
|
||||
=========
|
||||
# Variables
|
||||
|
||||
1. No predefined bitness (should be easy to extend them to 128,256 and 512bits, e.g. for MMX, SSE, AVX, Neon)
|
||||
2. Infinite number (for SSA-form compatibility)
|
||||
@ -207,12 +202,12 @@ Variables
|
||||
4. Numbers can be specified in any base supported by RNum (dec, hex, oct, binary ...)
|
||||
5. Each ESIL backend should have an associated RReg profile to describe the esil register specs
|
||||
|
||||
Bitarrays
|
||||
=========
|
||||
# Bitarrays
|
||||
|
||||
What to do with them? What about bit arithmetic if use variables instead of registers?
|
||||
|
||||
Arithmetic
|
||||
===========
|
||||
# Arithmetic
|
||||
|
||||
1. ADD ("+")
|
||||
2. MUL ("*")
|
||||
3. SUB ("-")
|
||||
@ -220,8 +215,8 @@ Arithmetic
|
||||
5. MOD ("%")
|
||||
|
||||
|
||||
Bit arithmetic
|
||||
===============
|
||||
# Bit arithmetic
|
||||
|
||||
1. AND "&"
|
||||
2. OR "|"
|
||||
3. XOR "^"
|
||||
@ -231,8 +226,7 @@ Bit arithmetic
|
||||
7. ROR ">>>"
|
||||
8. NEG "!"
|
||||
|
||||
Floating point
|
||||
==============
|
||||
# Floating point
|
||||
|
||||
_TODO_
|
||||
|
||||
@ -252,15 +246,15 @@ take care to not reuse any of the following:
|
||||
Usage example:
|
||||
|
||||
### rep cmpsb
|
||||
---------
|
||||
|
||||
ecx,!,?{,BREAK,},edi,[1],esi,[1],==,$z,zf,:=,8,$b,cf,:=,$p,pf,:=,7,$s,sf,:=,edi,[1],0x80,-,!,7,$o,^,of,:=,3,$b,af,:=,df,?{,1,edi,-=,1,esi,-=,}{,1,edi,+=,1,esi,+=,},ecx,--=,zf,!,?{,BREAK,},0,GOTO
|
||||
```
|
||||
ecx,!,?{,BREAK,},edi,[1],esi,[1],==,$z,zf,:=,8,$b,cf,:=,$p,pf,:=,7,$s,sf,:=,edi,[1],0x80,-,!,7,$o,^,of,:=,3,$b,af,:=,df,?{,1,edi,-=,1,esi,-=,}{,1,edi,+=,1,esi,+=,},ecx,--=,zf,!,?{,BREAK,},0,GOTO
|
||||
```
|
||||
|
||||
## Executing r2 commands
|
||||
|
||||
|
||||
## Unimplemented/unhandled instructions
|
||||
====================================
|
||||
|
||||
Those are expressed with the 'TODO' command. which acts as a 'BREAK', but
|
||||
displaying a warning message describing which instruction is not implemented
|
||||
@ -270,8 +264,7 @@ For example:
|
||||
|
||||
fmulp ST(1), ST(0) => TODO,fmulp ST(1),ST(0)
|
||||
|
||||
Disassembly example:
|
||||
====================
|
||||
## Disassembly example:
|
||||
|
||||
```
|
||||
[0x1000010f8]> e asm.esil=true
|
||||
@ -301,8 +294,7 @@ Disassembly example:
|
||||
│ │││ 0x100001147 48394a38 rdx,56,+,[8],rcx,==,cz,?=
|
||||
```
|
||||
|
||||
Radare anal ESIL code example
|
||||
==============================
|
||||
# Radare anal ESIL code example
|
||||
|
||||
As an example implementation of ESIL analysis for the AVR family of
|
||||
microcontrollers there is a `avr_op` function in `/libr/arch/p/avr/plugin.c`
|
||||
@ -336,8 +328,7 @@ Looking at other architectures which already have mature ESIL support such as
|
||||
x86 can help in understanding the syntax and conventions of radare's ESIL.
|
||||
|
||||
|
||||
Introspection
|
||||
=============
|
||||
# Introspection
|
||||
|
||||
To ease esil parsing we should have a way to express introspection expressions
|
||||
to extract the data we want. For example. We want to get the target address of
|
||||
@ -360,8 +351,7 @@ expressions to get:
|
||||
- all regs modified (write)
|
||||
- all regs accessed (read)
|
||||
|
||||
API HOOKS
|
||||
=========
|
||||
# API HOOKS
|
||||
|
||||
It is important for emulation to be able to setup hooks in the parser, so we
|
||||
can extend the parser to implement the analysis without having to write the
|
||||
|
@ -5963,7 +5963,8 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
startTime = r_time_now_mono ();
|
||||
}
|
||||
r_cons_break_push (NULL, NULL);
|
||||
for (; ; r_anal_op_fini (&op)) {
|
||||
for (; true; r_anal_op_fini (&op)) {
|
||||
R_LOG_DEBUG ("esil step at 0x%08"PFMT64x, addr);
|
||||
if (r_cons_is_breaked ()) {
|
||||
R_LOG_INFO ("[+] ESIL emulation interrupted at 0x%08" PFMT64x, addr);
|
||||
return_tail (0);
|
||||
@ -6012,6 +6013,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
r_core_cmd0 (core, pincmd);
|
||||
ut64 pc = r_reg_getv (core->anal->reg, pcname);
|
||||
if (addr != pc) {
|
||||
eprintf ("pincmd fail\n");
|
||||
return_tail (1);
|
||||
}
|
||||
}
|
||||
@ -6022,7 +6024,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_UNALIGNED);
|
||||
}
|
||||
if (breakoninvalid) {
|
||||
r_cons_printf ("[ESIL] Stopped execution in an unaligned instruction (see e??esil.breakoninvalid)\n");
|
||||
R_LOG_INFO ("Execution stopped on unaligned instruction (see e?esil.breakoninvalid)");
|
||||
return_tail (0);
|
||||
}
|
||||
}
|
||||
@ -6038,7 +6040,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_INVALID);
|
||||
}
|
||||
if (breakoninvalid) {
|
||||
R_LOG_INFO ("[ESIL] Stopped execution in an invalid instruction (see e??esil.breakoninvalid)");
|
||||
R_LOG_INFO ("Stopped execution in an invalid instruction (see e??esil.breakoninvalid)");
|
||||
return_tail (0);
|
||||
}
|
||||
op.size = 1; // avoid inverted stepping
|
||||
@ -6061,6 +6063,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
r_reg_setv (core->anal->reg, pcname, op.addr + op.size);
|
||||
r_reg_setv (core->dbg->reg, pcname, op.addr + op.size);
|
||||
}
|
||||
eprintf ("blaaa\n");
|
||||
return_tail (1);
|
||||
}
|
||||
}
|
||||
@ -6092,6 +6095,13 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
core->dbg->reg = reg;
|
||||
} else if (R_STR_ISNOTEMPTY (e)) {
|
||||
r_esil_parse (esil, e);
|
||||
if (esil->trap) {
|
||||
R_LOG_WARN ("ESIL TRAP ON %s at 0x%08"PFMT64x, e,addr );
|
||||
if (r_config_get_b (core->config, "esil.exectrap")) {
|
||||
R_LOG_INFO ("ESIL TRAP ignored");
|
||||
esil->trap = false;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// XXX thats not related to arch plugins, and wonder if its useful at all or we want it as part of the anal or esil plugs
|
||||
if (core->anal->cur && core->anal->cur->esil_post_loop) {
|
||||
@ -6139,6 +6149,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
const char *e = R_STRBUF_SAFEGET (&op2.esil);
|
||||
if (R_STR_ISNOTEMPTY (e)) {
|
||||
r_esil_parse (esil, e);
|
||||
esil->trap = false; // ignore traps on delayed instructions for now
|
||||
}
|
||||
} else {
|
||||
R_LOG_ERROR ("Invalid instruction at 0x%08"PFMT64x, naddr);
|
||||
@ -6167,7 +6178,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
}
|
||||
// check breakpoints
|
||||
if (r_bp_get_at (core->dbg->bp, pc)) {
|
||||
r_cons_printf ("[ESIL] hit breakpoint at 0x%"PFMT64x "\n", pc);
|
||||
R_LOG_INFO ("esil breakpoint hit at 0x%"PFMT64x, pc);
|
||||
return_tail (0);
|
||||
}
|
||||
// check addr
|
||||
@ -6177,15 +6188,19 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#if 1
|
||||
if (esil->trap) {
|
||||
R_LOG_DEBUG ("TRAP");
|
||||
R_LOG_INFO ("TRAP");
|
||||
return_tail (0);
|
||||
}
|
||||
#endif
|
||||
if (until_expr) {
|
||||
// eprintf ("CHK %s\n", until_expr);
|
||||
if (r_esil_condition (esil, until_expr)) {
|
||||
R_LOG_DEBUG ("ESIL BREAK!");
|
||||
R_LOG_INFO ("ESIL BREAK!");
|
||||
return_tail (0);
|
||||
}
|
||||
esil->trap = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@ -7609,7 +7624,7 @@ static void cmd_anal_esil(RCore *core, const char *input, bool verbose) {
|
||||
r_core_cmd_help_match (core, help_msg_aes, "aesu", true);
|
||||
} else switch (input[2]) {
|
||||
case 'e': // "aesue"
|
||||
until_expr = input + 3;
|
||||
until_expr = r_str_trim_head_ro (input + 3);
|
||||
break;
|
||||
case ' ': // "aesu"
|
||||
until_addr = r_num_math (core->num, input + 2);
|
||||
|
@ -597,3 +597,18 @@ EXPECT=<<EOF
|
||||
0x00000000000000000000000000000001
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=step until esil
|
||||
FILE=bins/mach0/ls-m1
|
||||
ARGS=-a arm -b 64
|
||||
CMDS=<<EOF
|
||||
aeim
|
||||
ar?pc
|
||||
aesue pc,0x100003ad0,==,$z
|
||||
ar?pc
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x100003a90
|
||||
0x100003ad0
|
||||
EOF
|
||||
RUN
|
||||
|
Loading…
Reference in New Issue
Block a user