【angr源码分析】9. VEX IR概述

参考链接:VEX IRcodument for pyvex VEXIR

VEX IR

VEX IR结构介绍

VEX IR是一种中间表达。结构包括:

1. Block

代码被分解为多个代码块(IRSB,IR super block)。

IRSB中包括三部分的内容:

  1. type environment :表明IRSB中临时变量的类型
  2. statement 列表
  3. IRSB的跳转(最后一条指令)

2. Statement

IRStmt,表示有副作用的操作(一个操作,如果会修改传入的操作数的值,就称其有副作用。),比如 store指令,write指令等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef 
enum {
Ist_NoOp=0x19000,
Ist_IMark, /* META */
Ist_AbiHint, /* META */
Ist_Put,
Ist_PutI,
Ist_WrTmp,
Ist_Store,
Ist_CAS,
Ist_LLSC,
Ist_Dirty,
Ist_MBE, /* META (maybe) */
Ist_Exit
}
IRStmtTag;

3. Expression

IRExpr,表示没有副作用的操作。比如:(3 + (4 * load(addr1))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef
enum {
Iex_Binder=0x15000,
Iex_Get,
Iex_GetI,
Iex_RdTmp,
Iex_Qop,
Iex_Triop,
Iex_Binop,
Iex_Unop,
Iex_Load,
Iex_Const,
Iex_Mux0X,
Iex_CCall
}
IRExprTag;

4. Guest state的存储

guest state 包含了guest机器的寄存器信息(比如我们正在模拟执行的机器,感觉有点像sim_state)。它默认存储在VEX库用户提供的内存块中 。为了操作寄存器必须先用GET获得 guest state中的临时变量信息,然后用PUT写入guest state。

比如说,addl %eax, %ebx会被翻译为如下:

1
2
3
4
5
------ IMark(0x24F275, 7, 0) ------
t3 = GET:I32(0) # get %eax, a 32-bit integer
t2 = GET:I32(12) # get %ebx, a 32-bit integer
t1 = Add32(t3,t2) # addl
PUT(0) = t1 # put %eax

简单起见,它忽略了条件代码的影响以及指令指针的更新。

------ IMark(0x24F275, 7, 0) ------“IMark” 是一个 IRStmt,但并不代表实际的代码(没有实际的操作)。相反,它表示原始指令的地址以及指令的长度。

GET:I32(0) 中的0表示的是寄存器eax,12表示的是寄存器ebx。

上述五条指令,都是”flattened”的指令。即:所有的表达式都是原子化的,不可分割的。相对的,就有 “unflattened”的版本:PUT(0) = Add32(GET:I32(0), GET:I32(12))。在机器翻译时IR应该是原子化的,这会让指令化转换更容易。

再看另一个栗子:addl %edx,4(%eax),翻译为如下:

1
2
3
4
5
6
------ IMark(0x4000ABA, 3, 0) ------
t3 = Add32(GET:I32(0),0x4:I32)
t2 = LDle:I32(t3)
t1 = GET:I32(8)
t0 = Add32(t2,t1)
STle(t3) = t0

LDle中的le表示的是 “little-endian”

5. No need for deadllocations

虽然为各种类型的结构建立了 分配函数, 但是并没有提供回收函数。因为VEX使用了自动回收内存机制。