软件分析课笔记——中间表示

这是南京大学《软件分析》第二讲
(十分感谢南大能将这么好的课公开出来,十分感谢李越、谭添老师这么认真的备课,收获很多。笔记中大部分的图都是从老师的视频中截图所得,会添上自己的理解,以及一定的修改)
ps:笔记是上课过程中的记录,所以会有语法、语义等方面的错误,请大家包容和提出,我会时常来看看和修改。

1.编译器和静态分析器

主要讲:静态分析和编译器的关系

编译器

功能:是将程序员写的程序翻译成机器能理解的代码,还要对问题进行报错

  • 源码 -> scanner -> 进行词法分析,规则为常规表达。如果每一个都是合理的就产生一个token。传给下一步
  • tokens -> parser -> 进行语法分析,按照语法规则进行,规则为上下文无关语法。语法检查通过之后,就会产生抽象语法树(AST)
  • AST -> type checker -> 进行语义分析,就是语义是否合理,这边只能检查很简单的语义,规则为属性语法。如果通过之后,就会生成装饰过的AST(decorated AST)
  • 如果还要继续做优化,需要进行转化: decorated AST -> Translator -> 进行转化,生成IR(常常规形式是3地址码)。
  • IR -> Code Generator -> 机器码:最终转换为机器能够识别的代码
    编译器流程
    => 所以,静态分析器就是处于Translator到Code Generator之间。输入的是IR。

所以可以将转换器之前的称为静态分析器的前端、之后称为静态分析器的后端。

但是前端不可缺少,因为之前检查的都是基本的表达式、词法、语法的分析,如果这些都无法通过,就没有必要进行静态分析

2.AST(抽象语法树)和IR

主要讲IR和AST的区别,以及为什么在静态分析器中使用IR,而不是使用AST。

  1. 抽象语法树的举例:

    一个do…while循环:
    举例

  2. IR

    三地址码表示一个do…while循环:
    举例

  3. 区别:

    • AST,高级,和语法形式很接近;IR,低级,和机器码很接近(参考汇编代码)
    • AST,通常语言依赖比较强(语法和语言挂钩);IR,通常和语言无关
    • AST适合快速的类型检查;IR更压缩和统一
    • AST缺少控制流的信息;IR包含控制流信息
    • IR通常作为静态分析器的基础

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

主要解释了3AC的常规形式和命名原因等。

  1. 3-地址码没有一个形式化的定义。通常的格式是,指令右侧最多只有一个操作符。

    举例:
    举例

  2. 3AC最多包含三个地址

    地址的类型可以是:变量名,a,b类似的;常量,3,5类似的;编译器产生的临时变量,t1类似的。

    每一种指令都会对应不同的3-地址码

  3. 常见的3AC形式和解释
    常见的形式和解释

4.3AC in Real Static Analyzer:Soot

这一块由于我JAVA没有学好,所以听的不是很懂,之后会认真研究一下,然后来补这一节(所以,这部分主要以贴图为主)
主要就是介绍最流行的JAVA静态分析器:Soot,来更好的理解3AC

以举例为主来进行介绍:

  1. for循环
    for循环举例

  2. do…while
    do...while循环举例

  3. 函数调用
    函数调用
    JVM的

    • invokespecial:调用构造函数、调用父类方法、调用私用方法
    • invokevirtual:常用的方法调用
    • invokeinterface: 不能优化,检查是否实现(和virtual类似)
    • invokestatic:调用常量的方法
    • invokedynamic:让动态语言在JVM上跑

  4. 类的调用

5.Static Single Assignment(SSA)

经典的IR的转换格式。

SSA中的所有操作都会给定一个特有的名字

  1. 每个定义都给一个新的名字
  2. 给定的新名字会在后面使用的地方使用到
  3. 每一个变量有且只有一个定义

举例:
举例
如果该定义出现在控制流中的选择后的合并操作,该如何解决呢?
合并操作
引入一个** ϕ \phi 方法**,用来处理合并节点的值的选择问题: ϕ ( x 0 , x 1 ) \phi(x_0,x_1) 含义为如果控制流经过true部分该函数的值为 x 0 x_0 ,否则函数值为 x 1 x_1 .

SSA的优劣:

=>优点:流信息能够通过独特的变量名字来间接结合起来;定义-使用对是很显然的

=>缺点:会引入太多的变量,也会引入太多的 ϕ \phi 方法;并且将其转换为机器码的时候可能会引入性能上的问题。

6.BAISC BLOCK(BB)

主要介绍,什么是BB

CFG的结点可以是一个单独的3-地址码,也可以是一个基础块(常见)

Basic Block的定义:最大连续的3-地址码的序列。

性质:有且只有一个入口,就是BB中的第一句指令;有且只有一个出口,最后一个指令就是出口。

如下图就是一个BB:第一句就是唯一的入口,最后一句就是唯一的出口 => 满足
举例
通过一个举例来发现该BB的实现算法:

  • 算法的输入:3-地址码指令所代表的程序P

  • 算法的输出:程序P的一组BBs

  • 算法实现:

    (1)找到程序P的leaders,就是每个BB的入口

    ​ 哪些属于leader呢?

    ​ 1> 程序P的第一个指令;

    ​ 2>每个条件跳转/无条件跳转的目标地址,就是一个leader。(如果该句话和上面语句归并,该语句就会有两个入口:上一个语句到该语句;jump跳转过来的语句)

    ​ 3>每个条件跳转/无条件跳转的下一条语句,就是一个leader。(如果将该句话和跳转归并,jump语句就有两个出口:jump目标地址和当前语句)

    (2)创建BBs:一个leader到另一个leader之前的都是一个BB

    举例:

    如图的leaders:(1);(3)、(7)、(12);(5)、(11)、(12)
    i举例

7.Control Flow Graph(CFG)

主要讲CFG的概念、格式等

从静态分析器的流程来讲,需要知道如何根据3-地址码变成CFG

CFG的地位:是静态分析的基础结构。

CFG的每个结点都是BB。所以在上部分获得BBs之后添加边之后就获得了CFG。

添加边的条件:

  • 条件跳转/无条件跳转,从跳转指令所在的BB到目的地址是有边连接的。
    添加边的条件
  • A、B之间紧密相连,则需要添边;但是,如果A的最后依据是无条件跳转语句,就不能给边。
    添边的条件2
    注意例外:(无条件跳转的,顺序A、B之间不能相连)
    不能加边
  • 将指令之间的跳转转换为块之间的跳转:所以指令内容需要变,如下图:
    添边之后内容变化
    所以,如果有部分指令变化了,对于CFG实际上是不会变化的,只有在BB内部才发生变化。

举例:
举例
命名:

  • A、B之间有边相连,A到B:所以A是B的前驱,B是A的后继。BB可以有多个前驱、多个后继

  • 增加两个结点:入口和出口。——但是与实际运行并无关系。

    入口和第一条指令的BB有边相连。出口和最后一条指令的BB有边相连。

发布了4 篇原创文章 · 获赞 4 · 访问量 147

猜你喜欢

转载自blog.csdn.net/hahahaqwe123/article/details/105689689