【软件分析/静态程序分析学习笔记】6.过程间分析(Interprocedural Analysis)

写在前面的话

本渣有幸成为南京大学软件学院研究生,在前往仙林校区蹭课的时候偶然发现了这门宝藏课程,听了以后感觉深有收获,但又因为课程难度较大,国庆假期归来发现遗忘较多,因此开了一坑来记录自己对每节课知识点的理解。也由于这是本人第一次开坑写博客,结构内容自有诸多不合理之处,希望有问题的地方大家可以指出。

前面四篇文章讲了数据流分析的算法和比较底层的知识,不过那些算法都是适用于单个函数内的数据流分析,本文会将其扩展到函数间或者说过程间的分析,更加接近一个完整的程序。


系列文章目录

1.静态程序分析(Static Program Analysis)介绍
2.中间表示(Intermediate Representation)
3.数据流分析(Data Flow Analysis) (上):可达性分析(Reaching Definitions)
4.数据流分析Data Flow Analysis) (下):存活变量分析(Live Variables Analysis)及可用表达式分析(Available Expressions Analysis)
5.数据流分析基础(Data Flow Analysis-Foundations)
6.过程间分析(Interprocedural Analysis)
7.指针分析(Pointer Analysis)入门
8.指针分析基础知识(Pointer Analysis Foundations)


一、过程间分析的动机

首先举个例子说明一下我们为何要用过程间分析而不是过程内分析:
在这里插入图片描述
如图所示,如果使用过程内分析,由于分析比较保守,所以最后得到的结果都是NAC,而使用过程间分析以后就不一样了,是可以获得正确的分析值。


二、调用图构造(Call Graph Construction)

2.1 什么是调用图

本质上来说,一个调用图就是从调用点到目标方法(callee)的一系列调用边
在这里插入图片描述
如上图所示就是一个调用图,每个节点分为上下两层,上层是此处所处的方法,下层是本方法内使用的别的方法,然后从下层的方法延申一条调用边到被调函数上。
而这个调用图的用处如下:

  • 这是过程间分析的基础
  • 可用于程序优化、理解、debug、测试等
    在这里插入图片描述
    调用图构造主要作用于OO语言,即以Java为代表的,面向对象的语言。一般用到如图四种算法,其中CHA是最快的,指针分析K-CHA是最准的,本文主要将CHA,后面的文章会讲指针分析。

2.2 Java中的方法调用形式

在这里插入图片描述
调用方法可以分为三种,前二者是静态分析时可以判断出的,每个方法会指向唯一的被调函数,所以目标数为1;而virtual call主要是为了多态设计的,因此目标数量大于等于1,而前面的图中四种调用图构造方法的主要区别也是对virtual call的处理方式的区别。

2.3 Virtual Call的方法调度函数(Dispatch)

程序运行时,一个virtual call被确定是具体调用哪个由以下两点决定:
1. virtual call返回内容的接收对象是谁:c
2. 调用点处的方法签名:m
此处的函数调用形式为:o1.foo(…)2
其中的方法签名指的是一个能够标志方法的标识符形式
在这里插入图片描述
如图所示方法签名如图所示,由类名方法名描述符=返回类型+参数类型 组成,为了表示简单,可以缩写为C.foo(…)
我们定义Dispatch(c,m)函数来描述函数间的分派关系(其中c和m可以在上图的上方两个“决定函数是谁的”地方看到)
在这里插入图片描述
函数如图,简单来说,就是先在调用了这个方法的对象/类中找有没有这个方法,找得到就返回这个方法,否则就在这个类的父类中找。(总能找到,否则在之前编译的过程中就会报错了)

2.4 Class Hierarchy Analysis(CHA)

上面函数的作用直白地说,就是一个程序中可能有多处定义了foo方法,这个算法就是为了寻找此处使用的foo方法到底是在哪定义的,找到了以后才能根据那个方法的返回值来确定此处数据类,从而提高数据流分析的准确性。
而如何找到这个o.foo(…)具体是谁定义的,就要分析o的类O的层次结构(Class Hierarchy),因此这个算法叫做CHA,精度较低而速度极快,IDEA中看代码的时候,按住Ctrl后将鼠标放在一个方法调用上,能看到一堆这个方法可能所处位置,用的就是这种算法。

回想一下之前提到的三种方法调用类型,写下来将分别对其进行分析。

2.4.1 static call

在这里插入图片描述
首先是static call,可以简单翻译为静态调用,主要用于静态调用方法,如图所示,直接用类C调用方法而不需要定义对象c,因此很明显调用的就是当前类的方法,所以直接加到集合T中。

2.4.2 special call

在这里插入图片描述
然后是special call,特殊调用,主要分为三种情况,这是第一种使用super类的调用方法那么这个foo()虽然在当前类有定义,但是实际使用的是父类的foo(),因此需要使用Dispatch函数,其中的foo()的签名m由编译器返回信息可以知道是B的,那么获取foo()返回值的c也指向B,也就相当于在父类中寻找了。
在这里插入图片描述
这是special call中的另外两种情况,构造函数和私有函数,其中构造函数暂时可以忽略,所以先看私有函数,此时编译器返回的信息能算法知道此时m指向的仍是C,那么Dispatch(cm,m)得到的仍然是这个私有方法C.bar()。

2.4.3 virtual call

在这里插入图片描述
最后是对virtual call的处理方式,这也是CHA区别于其他算法的主要之处。除了以上提到的四种情况以外,其他情况都是用virtual call来处理,因为除了super会将m的类类型指定为父类以外,别的都是当前类,所以该算法会对此方法做一个Dispatch(c,m)并将c的所有子集以及子集的子集全都做一次Dispatch(c’,m)。直观来看,可以分为两步,第一步是对本身做一次Dispatch,看看当前类中是否有foo(),没有的话就到父类中递归地找;第二步是在当前类地所有子集中找到所有的foo(),然后将这些foo同第一步找到的foo全都加入T中。

2.4.4 一个例子

例子
举例如图,根据之前的算法走一遍就能懂了。
上面可以看出,这个算法速度是很快的,但是因为virtual call啥都不管地将所有子集全都加到T里面,所以精度很低。

2.5 构造调用图

分为三步:

  1. 从入口方法进入,一般是main方法
  2. 对于每个可到达的方法m,通过CHA算法找出点调用的方法m’可能是在哪的
  3. 对于每个m(以及新加入的m’)都进行第二步,知道不再有新的方法被发现
    通过以上过程便可以构造调用图,算法如下:
    在这里插入图片描述
    再举个例子,大家可以跟着走一遍:
    在这里插入图片描述

三、过程间控制流图

先前使用的CFG图,只能分析单个方法,而需要将之扩展到可以分析整个程序结构的ICFG,需要为之添加两个附加边

  • 调用边:从调用点call site到被调方法callee的入口
  • 返回边:从callee的返回语句到call site 的下一句
    在这里插入图片描述
    图示便是过程间的控制流图,ICFG本质还是CFG,应该用三地址码构成的Basic Block构成,但是此处为了清晰分析,所以还是将BB拆开来分析。

四、过程间数据流分析

在这里插入图片描述
先比较一下过程内与过程间的区别,主要就是过程间分析多了一个调用返回边,及对应的传递函数。

  • Call edge transfer:调用边传递函数,用于传递参数值
  • Return edge transfer:返回边传递函数,用于传递返回值
  • Node transfer:与前面文章提到的传递函数基本一样,但是多了一个性质,对于每次调用(例如b=foo(a))会将等式左侧的数值kill掉,然后在下一步中有返回边传递函数重新赋值。这个操作可以在返回值与原值不同时防止数据冲突。
    在这里插入图片描述
    这是一个完整的过程间数据流分析的过程,跟着走一遍还是很简单的。不过这个例子我第一次走的时候感觉缺了点东西,仔细想了一下,发现一个是这个里面函数没有继承关系,所以不需要Dispatch操作,第二点这个例子不需要meet或join操作(通常与循环、分支等相关),所以这个例子很简单,但是实际操作中可能比较麻烦,不过算法思想都是一样的。

五、总结

本文内容比较简单,只是将单个方法内的数据流分析扩展到数个方法中,之前的内容看懂的话这个还是很容易理解的,传递函数还是比较简单,就不多说啦。

  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值