1.Compilers and Static Analyzers

编译器流程:

语法分析:

词法分析的主要任务从左向右逐行扫描源程序的字符,识别出各个单词,确定单词的类型。将识别出的单词转换成统一的机内表示词法单元(token)形式token:<种别码,属性值>

Snipaste_2020-09-06_20-10-50

词法分析后得到的token序列:

Snipaste_2020-09-06_20-13-09词法分析的实现:

暴力求解或者DFA算法

2.AST & IR

AST

IR

高级 更接近于语法结构

低级 更接近于机器码

依赖语言种类

不依赖

适用于快速检查

压缩且简洁

缺少控制流信息

包含控制流信息

通常用作程序分析的基础

为什么使用IR作为程序分析的基础:

1、语言无关;

2、包含控制流信息。

3.IR:Three-Address Code(3AC)

中间语言的一种,每个三地址码指令,都可以被分解成一个四元组

运算符、操作数1,操作数2,结果

𝑧=𝑥 𝑜𝑝 𝑦

𝑥=𝑜𝑝 𝑦

𝑥=𝑦

𝑔𝑜𝑡𝑜 𝐿

𝑖𝑓 𝑥 𝑔𝑜𝑡𝑜 𝐿

𝑖𝑓 𝑥 𝑜𝑝 𝑦 𝑔𝑜𝑡𝑜 𝐿

4.3AC in Real Static Analyzer:Soot

  1. 基于栈

    java语言的字节码表示本来就是栈的,而象Dalvik 是基于寄存器的,在这点上Jimple基于栈

  2. 有类型

    每一个参数都定义了Type,并且类型精度没有丢失,比如int $i0

  3. 基于三地址分析

    三地址解析中会出现很多的中间变量

    三地址同时会拆解一些高级特性,被分解成多个单位,包含一些低级操作,支持低端指令一般而言,三地址代码将包含大部分低级操作,即目标机所支持的指令。

invokespecial : call constructor, call superclass methos, call private methods

构造函数

Method Signature

<class name : return type <method name> >(params);

invokevirtual: instance methods call(virtual dispath)

java7 : invokedynamic

clinit

5.Static Single Assignment(SSA)

静态单赋值(Static Single Assignment,SSA) 是另一种IR的形式,它和3AC的区别是,在每次赋值的时候都会创建一个新的变量,也就是说,在SSA中,每个变量(包括原始变量和新创建的变量)都只有唯一的一次定义。

3ac-ssa当控制流汇合(Merge)的时候,我们会用一个特殊的操作符表示汇和后的定义:

fei

关于SSA,我们只要简单了解一下定义和优缺点就可以了,之后还是用3AC比较多。

  • 优点:

    • 控制流的信息间接地被包含在了独特的变量名之中

      • 当我们做一些对控制流敏感的分析的时候,这些信息可能会有帮助

    • 定义和使用的关系明确

  • 缺点:

    • 可能会引入过多的变量名和ϕ函数

    • 被翻译成机器码的时候效率低,因为有太多对于程序执行来说不必要的赋值

6.Basic Blocks(BB)

INPUT: A sequence of three-address instructions of P

OUTPUT: A list of basic block of P

METHOD: Determine the leader

简单理解,基块就是满足如下性质的最长指令序列:

  • 程序的控制流只能从首指令进入

  • 程序的控制流只能从尾指令流出

于是我们可以直观的感受到,跳转指令会将一个完整的程序块切割为几个基块,如果我们能够把基块的分隔点找出来,那么整个程序P就可以被我们转化成许多的基块了。

7.Control Flow Graphs(CFG)

The nodes of CFG are basic blocks

CFG的节点是基块

There is an edge from block A to block B if and only if :

  • 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

It is normal to replace the jumps to instruction labels by jumps to basic blocks

从A到B有一条边当且仅当:

  • 从基块A的结束到基块B的开始存在条件跳转和无条件跳转

  • 基块B按照指令的原始顺序紧跟在基块A之后,而基块A不会以无条件跳转结束

通常将跳转到标签替换为跳转到basic block

于是我们可以直观的感受到,跳转指令会将一个完整的程序块切割为几个基块,如果我们能够把基块的分隔点找出来,那么整个程序P就可以被我们转化成许多的基块了。

简单理解,一个基块的领导者就是这个基块的首指令,整个程序中的领导者有如下3种:

  • 整个程序的首指令;

  • 跳转指令(包括条件跳转和无条件跳转)的目标指令;

  • 跳转指令(包括条件跳转和无条件跳转)紧接着的下一条指令。

(1) x = input
(2) y = x -1
(3) z = x * y
(4) if z< x goto (7)
(5) p = x / y
(6) q = p + y
(7) a = q 
(8) b = x + a
(9) c = 2a -b
(10) if p == q goto (12)
(11) goto (3)
(12) return

一、The first instruction in P is a leader.
(1)
二、Any target instruction of a conditional or unconditional jump is a leader.
(3)(7)(12)
三、Any instruction that immediately follows a conditional or unconditional jump is a leader.
(5)(11)(12)

Leader : (1)(3)(5)(7)(11)(12)

BB1 :(1)(2)
BB2 :(3)(4)
BB3 : (5)(6)
BB4 :(7)(8)(9)(10)
BB5: (11)
BB6: (12)

所以可以得出CFG:

文章作者: TestNet
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 TestNet
喜欢就支持一下吧