【静态分析】过程间分析(Interprocedural Analysis)

本文结合两篇文章对过程间分析做一个简单的了解,相关资源:
【软件分析/静态程序分析学习笔记】6.过程间分析(Interprocedural Analysis)
软件分析笔记:3.过程分析(Interprocedural Analysis)
这两篇文章也是南京大学《软件分析》课程的记录

1. 使用过程间分析的原因

在这里插入图片描述

过程内分析Intra-procedural Analysis

  • 只考虑过程内部语句,不考虑过程调用
  • 目前的所有分析都是过程内的

过程间分析Inter-procedural Analysis

  • 考虑过程调用的分析
  • 有时又称为全程序分析Whole Program Analysis
  • Call edges和Return edges
  • 需要call graph

2. 调用图Call Graph

2.1 调用图的概念

简单来说,一个调用图就是从调用点到目标方法(target methods或者callees)的一系列调用边。
在这里插入图片描述
调用图就是由调用点引出的箭头指向被调用的方法。每个节点分为上下两层,上层是此处所处的方法,下层是本方法内使用的别的方法,然后从下层的方法延申一条调用边到被调函数上。

2.2 调用图的使用

  • 理论上所有过程间(跨函数)分析的基础
  • 程序的优化
  • 程序理解
  • 程序debugging
  • 程序测试

2.3 针对面向对象语言的调用图构造

2.3.1 调用图构造算法

在这里插入图片描述

  • 调用方法可以分为三种,前二者是静态分析时可以判断出的,每个方法会指向唯一的被调函数,所以目标数为1;而virtual call主要是为了多态设计的,因此目标数量大于等于1,而前面的图中四种调用图构造方法的主要区别也是对virtual call的处理方式的区别。
  • invokestatic调用的目标方法是static methods,就是静态方法。所以它是没有reciever object,目标个数只有一个,在编译期可以确定。
  • 后两种调用的都是instance(实例)方法:
  • invokespecial调用的方法有构造函数、私有的实例方法以及父类的实例方法,它的目标个数也是只有一个,在编译期可以确定。
  • invokeinterface和invokevirtual调用其他的方法,因为有多态的存在,所以可能调用不同的方法,因此目标方法可能大于一个,具体调用的方法要在运行时才能确定。
  • 因为前两类相对来说比较简单,所以我们过程间分析的关键是对于第三种Virtual call的分析。
  • 在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如上图所示,第一行对算法进行了初始化,先是将入口方法添加到Work List里,然后将CG和RM两个集合清空。整个算法是一个大的while循环,我们不断从WL中取出方法m并将它添加到RM中(代表此方法已经被分析)并对m中的调用点进行分析,利用CHA找到对应的目标方法和调用边,将目标方法添加到WL中,并将它和调用边组成调用图。
在这里插入图片描述
如图所示,三个方法对应了三个CFG,将这三个CFG用Call edges和Return edges连结到一起。
在这里插入图片描述
在这里插入图片描述
这部分很好理解,唯一需要注意的是图上两条黄色背景的边,这两条边并不是可有可无的,上面说到的node transfer提过对于每一个方法调用节点将等号左边部分去掉,也就是说从“b=addOne(a)"语句到"c=b-3"语句我们是将a的值传递了过去,而b的值由addOne()传递,如果去掉这条边的话就意味着a的值只能通过addOne()传播,而addOne()中对a并没有更改,这样会额外消耗系统资源,另外在第二个黄色边中,如果不去除掉b的值,那么最后一个节点得到的b就为NAC,出现错误,所以我们才会要求去掉等号左边的元素。
过程间分析相较于过程内分析的精度更高,因此在实际项目中,我们应该更倾向于使用过程间分析。

猜你喜欢

转载自blog.csdn.net/weixin_44121966/article/details/120802085