没有合适的资源?快使用搜索试试~ 我知道了~
静态程序分析(七):过程间分析
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 114 浏览量
2022-06-19
22:25:05
上传
评论
收藏 3.11MB PDF 举报
温馨提示
试读
19页
一、为什么需要过程间分析 前面的数据流分析学习中,我们接触到的都是过程内 intraprocedural 的分析,在过程内 分析遇到函数调用如何处理的呢? 在过程内分析的情况下,对函数调用的通常的做法是:对方法的调用做最保守的估计, 认为方法调用可以做任何事情,以确保安全近似,举例如下: 对于常量传播的例子来说,如下程序片段: 过程内分析不对函数调用进行处理,在 foo()中对函数 bar()时,静态分析认为 bar()函数 输入的参数是任何值,所以 x = NAC,y=NAC,foo 函数中调用 bar 后的返回值也认为是任何 值,所以 n = NAC。而实际的运行情况来看,n 的值是 10,x 就是 42,y 就是 43。过程内分 析丢失了精度。 为提高分析的精度,就需要进行过程间的分析,数据流通过过程间的控制流边进行传递, 如下图所示:
资源推荐
资源详情
资源评论
1
静态程序分析(七):过程间分析 CHA
一、为什么需要过程间分析
前面的数据流分析学习中,我们接触到的都是过程内 intraprocedural 的分析,在过程内
分析遇到函数调用如何处理的呢?
在过程内分析的情况下,对函数调用的通常的做法是:对方法的调用做最保守的估计,
认为方法调用可以做任何事情,以确保安全近似,举例如下:
对于常量传播的例子来说,如下程序片段:
过程内分析不对函数调用进行处理,在 foo()中对函数 bar()时,静态分析认为 bar()函数
输入的参数是任何值,所以 x = NAC,y=NAC,foo 函数中调用 bar 后的返回值也认为是任何
值,所以 n = NAC。而实际的运行情况来看,n 的值是 10,x 就是 42,y 就是 43。过程内分
析丢失了精度。
为提高分析的精度,就需要进行过程间的分析,数据流通过过程间的控制流边进行传递,
如下图所示:
过程间分析与过程内保守分析不同,遇到方法调用的时候,会有过程间的调用边存在,
如上图。在调用函数 bar 的调用点,存在 call edge 和 return edge 两条调用边,一个表示调
用,一个表示调用的返回。过程间分析就会顺着调用边和返回边传递数据流。在执行 n =
bar(42)时,就会把实参 42 通过数据流传递到形参 x,bar 函数返回时会把 10 传递到变量 n。
因此,我们得到了精确的分析结果 x=42,y=43,n=10。
二、调用图 Call Graph
为了执行过程间分析,我们需要得到程序的调用图 call graph。
调用图是程序中函数调用关系的表示。实质上,一个调用图就是调用边的集合,而调用
边就是从调用点 call-sites 到目标函数 callees 的边。
2
如下图示例:
foo 方法中有两个 call-sites,一个是调用 bar()方法,一个是调用 baz(123)方法,所以在
foo 方法中的两个调用点到 bar 和 baz 方法的调用边。在 bar 方法内部又存在一个调用点
baz(666)调用 baz 方法,所以在方法 bar 内部存在调用点 baz(666)到函数 baz 的一个调用边,
从而形成了一个调用图。
三、调用图 Call Graph 是所有过程间分析算法的基础
用于程序优化,程序理解,程序调试,程序测试,等等。
构建调用图的算法有多种,以 java 为例,如下:
• Class hierarchy analysis (CHA)
• Rapid type analysis (RTA)
• Variable type analysis (VTA)
• Pointer analysis (k-CFA)
本节以 java 为例,讲 CHA 精度最低但效率最高的算法,后面指针分析讲 k-CFA 精度最
高但是效率最低的算法。
四、Java 中方法调用机制
Java 语言中,有三种函数调用机制,分别是:Static call 静态方法调用,Special call 特别
方法调用,Virtual call 虚方法调用,分别解释如下:
3
(1)Static call。直接调用类的静态方法,不需要实例化对象即可进行调用。目标方法
只有一个。在编译阶段就可确定具体方法。在 JVM 字节码执行引擎中采用 invokestatic 进行
调用。
(2)Special call。需要实例化一个类的对象(如 new B())进行调用,有三种情况:①
实例化时调用类 B 的构造函数;②在类 B 的函数内部(包括构造函数)调用该类的私有方
法以及父类的方法;③实例化一个类 B 对象时将其赋值给一个另一个与 B 相同类型的变量
B b = new B(),再通过 b 调用类 B 的父类方法。Special call 在编译阶段就可确定具体方法。
在 JVM 字节码执行引擎中采用 invokespecial 调用。
(3)Virtual Call。首先需要定义一个申明类型的变量如 A a,然后实例化一个对象如 new
B(),将 new B()对象赋值给申明类型的变量 a, a = newB(),B 是 A 的子类或者就是类 A。通过
a 调用方法 a.foo(),foo 方法在类 A 中一定有定义,B 类重写 A 的 foo,称为 Virtual call,运
行时实际调用的是 B 的 foo。在运行阶段才能确定具体的调用方法。在 JVM 字节码执行引擎
中采用 invokeinterface 或 invokevirtual 调用。
五、Virtual Calls 的 Dispatch 机制
在运行阶段,一个虚函数到底执行的是那个函数基于以下两点:
(1)接受对象的类型。就是指实际 new 出对象的所在类型。如 new B(),则接受对象
类型就类 B。
(2)方法的签名。方法的签名作为一个方法的标识,包括:调用该方法的对象所在的
类(就是申明对象变量的类型),方法名,方法描述(包括参数和方法的返回值,其中参数
包括参数顺序、参数类型、参数名称)。要特别注意方法签名前面的类型问题,是指调用该
方法的对象所在的类,如 A c = new B(),A 是 B 的一个父类或 B 类实现了接口 A,则调用 c.foo()
时,方法签名的类型是 A,接受对象的类型是 B。
4
虚方法的 Dispatch 机制:
定义方法 Dispatch(c,m),用来模拟动态运行时派发实际的方法调用,该方法返回实际调
用的方法签名。c 是指接受对象的类型,如 new C(),则接受对象类型就类 C。m 是指方法
签名,如:A a = new C(),A 是 C 的一个父类或 C 类实现了接口 A,则调用 a.foo()时,方法签
名的类型是 A。也可以是:C a = new C(),再调用 a.foo(),方法签名的类型是 C。
(1)如果接受对象的类型 c 中包含了一个非抽象方法 m’,其方法名和描述与 m 相同,
则得到方法 m’作为目标方法。
(2)其他情况,就是 C 中包括了抽象方法 m’(其方法名和描述与 m 相同)或者没有方法
名和描述与 m 相同的方法,则调用 Dispatch(c’,m),其中 c’是 c 的直接父类。
Dispatch 得到目标方法是唯一的。
如下示例:
剩余18页未读,继续阅读
资源评论
manok
- 粉丝: 2386
- 资源: 20
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功