angr/pyvex

ARM instruction over-optimized

Closed this issue · 1 comments

When lifting ARM instructions int IR, the current configuration over optimizes, resulting in unexpected results.

Disassembly:
0x1e01: ldr r1, [r3, #0x10]
0x1e03: str r2, [r3, #0x10]
0x1e05: str r0, [r3, #0x10]
0x1e07: ldr r1, [r3, #0xc]
0x1e09: str r2, [r3, #0xc]

IR:
IRSB {
t0:Ity_I32 t1:Ity_I32 t2:Ity_I32 t3:Ity_I32 t4:Ity_I32 t5:Ity_I32 t6:Ity_I32 t7:Ity_I32 t8:Ity_I32 t9:Ity_I32 t10:Ity_I32 t11:Ity_I32 t12:Ity_I32 t13:Ity_I32 t14:Ity_I32 t15:Ity_I1 t16:Ity_I32 t17:Ity_I32 t18:Ity_I32 t19:Ity_I1 t20:Ity_I32 t21:Ity_I32 t22:Ity_I32 t23:Ity_I1 t24:Ity_I32 t25:Ity_I32 t26:Ity_I32 t27:Ity_I1 t28:Ity_I32 t29:Ity_I32 t30:Ity_I32 t31:Ity_I1 t32:Ity_I32 t33:Ity_I32 t34:Ity_I32

00 | ------ IMark(0x1e00, 2, 1) ------
01 | t13 = GET:I32(a4)
02 | PUT(pc) = 0x00001e03
03 | ------ IMark(0x1e02, 2, 1) ------
04 | t16 = Add32(t13,0x00000010)
05 | t18 = GET:I32(r2)
06 | STle(t16) = t18
07 | PUT(pc) = 0x00001e05
08 | ------ IMark(0x1e04, 2, 1) ------
09 | t20 = t16
10 | t22 = GET:I32(r0)
11 | STle(t20) = t22
12 | PUT(pc) = 0x00001e07
13 | ------ IMark(0x1e06, 2, 1) ------
14 | t24 = Add32(t13,0x0000000c)
15 | t34 = LDle:I32(t24)
16 | PUT(r1) = t34
17 | PUT(pc) = 0x00001e09
18 | ------ IMark(0x1e08, 2, 1) ------
19 | t28 = t24
20 | STle(t28) = t18
21 | PUT(itstate) = 0x00000000
NEXT: PUT(pc) = 0x00001e0b; Ijk_Boring

Note the IR for 0x1e01: ldr r1, [r3, #0x10] doesn't contains a load operation. This indicates I cannot break/inspect on memory read operating at PC 0x1e01. When I pass opt_level = 0, it works fine.

Test case attached.
testcase.zip

this is intended behavior for vex optimization level 1. Use opt level 0 if you want semantics to match on a per-instruction level instead of a per-block level.