0x01 Compilers and Static Analyzers
编译器工作原理, 开始贴ppt:
IR之前前端, 之后称后端。 前端是词法、语法、简单的语义检查。 后端是在IR上分析一些高级的程序属性。(其实我觉得编译过程任何一个阶段的输出表示,都可以叫做IR(中间表示),一般IR指的是编译后段处理的目标内容形式,一般用3AC(三地址码)表示)。
0x02 AST vs. IR
重点来了, AST 和 IR做为编译过程中两个重要的中间表示,各自有什么意义与区别呢? 我们继续贴ppt...
这里提出了几点:
AST 贴合于上层代码,依赖于语言。 而IR贴近于底层,不依赖语言。 (多种语言可以翻译成同一种3AC?)。还有一个重要特点就是AST缺少控制流信息, 而3AC包含了控制流信息。
Each 4AC contains at most 3 addresses
- Name: a, b
- Constant: 3
- Compiler-generated temporary: t1, t2
常见3AC(三地址码)形式
x = y
bop
zx =
top
yx = y
goto
L
if x got
L
if x
rop
y goto L
其中, x, y, z表示地址。 bop
是二元运算符或逻辑运算符; uop
是一元操作符;L
是地址的label; rop
关系操作符。 goto L
无条件跳转; if...goto L
:条件跳转。
soot介绍略...
0x03 Static Single Assignment(SSA)
- Give each definition a fresh name
- Propagate fresh name to subsequent use
- Ever variable has exactly one definition
每一个variable在不同语句都给一个地址, 在control flow 汇合处就是这个变量的集合。
0x04 Control Flow Analysis
重点来了...
之前构造了3AC,那么在后端中需要在此之上构建控制流图进行控制流分析。 控制流图中, 每一个节点为一个基本快。
Basic Blokcs(BB)
一个基本块应该满足,唯一一个入口进,唯一一个出口出。
入口必须是第一条指令, 而出口必须是最后一条, 这样最大的块就是一个BB。
构建basic block
按视频给出的算法:
首先,标出跳转语句的目标
之后,标出紧接着jump之后的指令
找到了所有的leaders之后,构造基本块。
有了基本块, 建立控制流的边。
构建Control Flow Graph(CFG)
There is a conditional or unconditional jump from the end of A to the beginning of B(跳转添边)
B immediately follows A in the original order of instructions(依序添边) and A does not end in an unconditional jump(且A块出口并没有无条件跳转)
- It is normal to replace the jumps to instruction labels by jumps to basic blocks(很自然的将指令跳转转化为basic block 跳转)
(这里将goto 目标都换成了基本块label)
加上了CFG的入口和出口,形成一个完整的CFG。
说明:
- 红边有条件跳转, 蓝边无条件
- 黑边顺序执行,除无条件goto外都加
- A是B的前驱, B是A的后继
- 入口节点加入第一个,指向第一条执行的指令