【软件分析/静态分析】chapter5 课程07 过程间分析(Interprocedural Analysis)

news2024/9/23 7:21:08

🔗 课程链接:李樾老师和谭天老师的:

南京大学《软件分析》课程07(Interprocedural Analysis)_哔哩哔哩_bilibili


目录

第五章 过程间分析

5.1 为什么需要过程间分析

5.2 Call Graph 

5.2.1 调用图的概念

5.2.2 调用图的应用

5.2.3 针对面向对象语言的调用图的构造方法

5.2.4 预备知识

1. Java中的方法调用

2. Virtual Calls 的关键步骤:method dispatch 的基本概念

3. 实现 Method Dispatch 的具体过程

4. Dispatch: An Example

5.2.5 Class Hierarchy Analysis  (CHA)

1. 基本概念

2. CHA的具体实现过程

3. CHA: An Example🌰

4. CHA的特征

5.2.6 Call Graph 的构造(via CHA)⭐

1. 步骤

2. 算法

 3. 举个栗子🌰

5.3 过程间控制流图 (Interprocedural Control-Flow Graph, ICFG)

5.3.1 ICFG与CFG对比

5.3.1 ICFG: An Example🌰

5.4 过程间数据流分析(Interprocedural Data-Flow Analysis)

5.4.1 过程间与过程内对比

5.4.2 举个例子🌰


第五章 过程间分析

5.1 为什么需要过程间分析

1. 过程内分析intraprocedural

  • 不处理方法调用,
  • 面对方法调用进行最保守的假设,以进行safe-approximation
  • 过于保守的假设容易导致 source of imprecision(不精确)

如下图所示,在常量传播分析中,变量 n 调用了方法ten(),虽然该方法返回值是常量,但是过程内调用采用最保守的假设,会认为这个值可能是不固定的,讲n=NAC

2. 过程间分析interprocedural:

  • 处理方法调用
  • 沿过程间控制流边传播数据流信息(调用边call edges返回边return edges
  • 重要的方式:调用图

如下图所示:

5.2 Call Graph 

5.2.1 调用图的概念

        调用图是程序中的调用关系的表示。从本质上讲,调用图是一组从调用点到其目标方法(callees)的调用边(call edges)

        如下图所示,foo函数中,调用到了ten和addOne函数,调用图如右图所示。

        

5.2.2 调用图的应用

调用图是非常重要的程序信息

  • 所有过程间分析的基础
  • 程序优化、理解、debugging、测试等等

5.2.3 针对面向对象语言的调用图的构造方法

        构造调用图的算法,这四种方法,越往下精度越高,越往上速度越快。

  • class hierarchy analysis (CHA)
  • Rapid type analysis (RTA)
  • Variable type analyss (VTA)
  • Pointer analysis(k-CFA)

在这一章中会介绍第一种方法CHA,下一章会介绍最后一种Pointer analysis

5.2.4 预备知识

1. Java中的方法调用

        Java中的调用主要分为三大类,对应了四种指令,(Java8开始还引入了invokedynamic,主要用于实现动态类型语言的,在这里我们不进行讨论)

        

  • invokestatic
    • 调用的目标方法是static methods (静态方法)。所以没有reciever object
    • 目标个数只有一个,在编译期可以确定。

后两种调用的都是instance(实例)方法:

  • invokespecial
    • 有三个用途:调用构造函数、调用私有的实例方法、调用父类的实例方法,
    • 它的目标个数也是只有1个,在编译期可以确定。
  • invokeinterface和invokevirtual 
    • 调用其他的实例方法,
    • 因为有多态的存在,所以可能调用不同的方法,因此目标方法可能大于一个,具体调用的方法要在运行时才能确定。

因为前两类处理起来相对比较简单,所以我们过程间分析的关键是对于第三种Virtual call的分析。

2. Virtual Calls 的关键步骤:method dispatch 的基本概念

        在程序运行中,有一个virtual call,具体调用的方法是动态调用的时候的需要去解的,求解动态的时候具体目标方法的过程叫做method dispatch,这个过程中涉及到两个要素

  • 接收对象的类型(例如说函数指向的具体对象的类型): c 
  • call site这一点上的方法签名method signature : m

        通过签名 signature,我们可以唯一地确定一个具体的方法,具体组成如下:

  •  signature有三个部分组成:class type + method name + descriptor
  • descriptor 又有两部分组成:return type + parameter types 

     

3. 实现 Method Dispatch 的具体过程

        接下来,我们就可以定义一个函数Dispatch(c, m),它模拟了动态时method dispatch的过程。他有两个参数 c m,这两个参数就是前边所提到的method dispatch的两个要素。

        具体的过程如下所示:

        

         如果class c 里包含一个和m有着相同名字descriptor的非抽象方法m’(因为dispatch要找的是一个具体的能被调用的方法,所以必须是非抽象),那么就直接返回m’,我们就认为dispatch找到了目标函数。如果c 中没有满足条件的方法,那么我们就去c的父类里面找,重复这个过程直到找到为止。

        由此可以看出,在方法签名中,起决定性作用的就是名字和discriptor。

4. Dispatch: An Example

        如下图所示,对Dispatch(B, A.foo()) 是在B里找foo方法,B里没有,就会去其父类A中找,所以是A.foo(),而第二个Dispatch(C, A.foo())是在C里找foo方法,C里又,所以是C.foo()

        

        通过这个例子其实能大致看出CHA的作用,就是一个程序中可能有很多个foo,这个算法就是为了找到这里使用的foo函数是在哪儿定义i的,找到了之后可以根据具体找到的那个方法的返回值来确定此处的数据,从而提高数据流分析的准确性。

5.2.5 Class Hierarchy Analysis  (CHA)

1. 基本概念

       这个方法可以用来解call graph,需要整个程序中的class层次的信息(例如父类、子类信息),根据call site的receiver variable(接收变量)declared type(声明类型)来解析virtual call(虚拟调用)。

        如下图所示,这里的call site 为a点,其声明类型为A,所以CHA就会根据A的方式来算它的目标方法。
        

        具体思想:假设变量a可以指向A类以及所有A类的子类的对象,CHA去解目标方法的过程就是去查询A类的继承结构class hierarchy。

CHA论文出处:

*Jeffrey Dean, David Grove, Craig Chambers, "Optimization of Object-Oriented Programs Using Static Class Hierarchy Analysis". ECOOP 1995.

2. CHA的具体实现过程

        这里,我们定义了一个方法Resolve(cs),该方法通过CHA解析调用点(call site, cs)的可能目标方法(possible target methods)。

        算法的总体情况如下,传入的参数为调用点cs;初始化T为空,存放目标方法;用m保存cs点处的方法签名。

        

        算法的核心为红色框框圈起来的部分,前边预备知识中提到,函数调用有三种类型,算法里的三个if分支也是分别对应3中调用情况。接下来,就针对每种情况来解决调用问题:

① static call 静态调用

        如下图,对于static call 而言,目标方法就是写在call site中的方法,如图所示,直接用类C调用方法而不需要定义对象c,因此很明显调用的就是当前类的方法,所以可以直接加到集合T中。

        

 ② special call 特殊调用

        special call 需要处理三种情况:父类方法、构造函数、私有方法。

        这里先以父类方法为例,如图所示,C类继承B类,C类里有一个super调用,这个foo()虽然在当前类有定义,但是实际使用的是父类B的foo(),因此需要使用Dispatch函数(因为B类不一定就有这个foo方法,B继承自A,foo方法不一定时B 的,所以需要再用dispatch),其中的foo()的签名m由编译器返回信息可以知道是B的,那么获取foo()返回值的c也指向B,也就相当于在父类中寻找了。

        

         另外两种special call 的方法:私有方法和构造函数,如下图所示,对于这两种方法,目标方法其实于static call一样,就是写在签名里的m,但是因为父类方法的调用是比较特殊的,所以为了能够处理这三种情况,需要用一下dispatch。

        例如调用私有函数this.bar(),此时编译器返回的信息能算法知道此时m指向的仍是C,那么Dispatch(cm,m)得到的仍然是这个私有方法C.bar()。

        

         因为Dispatch返回的目标方法是唯一的,这也就是为什么之前说special call目标个数也是唯一的。

③ virtual call

        对virtual call 的处理方式,也是CHA与其他算法的不同之处,除了上述提到的情况之外,其他的情况都用virtual call 来处理,

  • 首先会取出cs位置上的接收变量的声明类型(declared type),这里是C,
  • 接下来会对 C 及其所有的直接子类及其子类的子类(这里定义为c'),调用Dispatch(c', m),并将所有的结果都加到T中。

        

         因为除了super会将m的类类型指定为父类以外,别的都是当前类,所以该算法会对此方法做一个Dispatch(c,m)并将c的所有子集以及子集的子集全都做一次Dispatch(c’,m)。直观来看,可以分为两步,第一步是对本身做一次Dispatch,看看当前类中是否有foo(),没有的话就到父类中递归地找;第二步是在当前类地所有子集中找到所有的foo(),然后将这些foo同第一步找到的foo全都加入T中。

3. CHA: An Example🌰

        如下图所示,有4个类,其中A有foo方法,C、D都复写了foo方法 

         

        Q: 这里有3个call site,如下图所示,求每个call site的目标方法

         

答案:
1. Resolve(c.foo()) = {C.foo()} 

// 这里是virtual call,所以会把C及其子类进行dispatch,又因为C没有子节点,所以只需要对C进行dispatch(dispatch的作用是遍历这个class 看看有没有对应函数,没有的话再遍历其父类),C有foo,不需要遍历其父节点,所以答案为{C.foo()}

2. Resolve(a.foo()) = {A.foo(), C.foo(), D.foo()

// 同理,会对A及其子类进行dispatch,也就是对A B C D 进行dispatch,对A dispatch的结果就是A,对B dispatch的时候,B没有foo,所以会找其父类,结果也是A,再对B 的子类 C D 分别进行dispatch,结果加入CD,所以答案为 A C D

3. Resolve(b.foo()) = {A.foo(), C.foo(), D.foo()} 

// 注意,这里会先对B, C, D分别进行 dispatch,对B dispatch的时候,B 没有foo,所以会找到其父类A,A有foo()函数,所以结果加入A,在对C D 进行dispatch,同理,所以答案也是 A C D 

        Q:假如第3个情况中, B b = new B() 呢?

        

答案:

4. Resolve(b.foo()) = {A.foo(), C.foo(), D.foo()}

// 注意,按照算法,CHA只考虑变量的声明类型,对于这个情况,哪怕写了B b =  new B(),这里还是会根据其声明类型B来解目标方法,所以答案仍是A C D

这也是CHA的一个问题,C.foo() 和D.foo()对于这个情况来说是虚假的目标方法(spurious call targets)。CHA只考虑声明类型,这样就会导致精度的下降。

4. CHA的特征

  • 优势:fast 快
    • Only consider the declared type of receiver variableat the call-site, and its inheritance hierarchy 只考虑在调用点上接收变量的声明类型及其继承层次结构。
    • Ignore data- and control-flow information. 忽略数据和控制流信息
  • 缺点:imprecise 不精确
    • Easily introduce spurious target methods 容易导致假的目标方法(解决这个问题,会在后续的几节课中,用别的方法解决)

        CHA最常用的场景就是IDE中,如下图所示,在idea,可以提醒目标方法。

        

IDEA->导航(navigate)->方法层次结构

5.2.6 Call Graph 的构造(via CHA)⭐

上边讲的都是为单个函数某个程序点构造调用关系的方法,接下来看一下为整个程序构造调用图的步骤

1. 步骤

  • 从入口方法开始(一般是Amin方法)
  • 对每个可到达的方法m,通过CHA算法 Resolve(cs) 为m中每个调用点cs求解目标方法
  • 每遇到一个新方法就重复上述步骤,直到没有新方法被发现

        如下图所示,从main出发构造调用图,但是可能会有一些方法也是不可达的

        

2. 算法

        算法名字叫BuildCallGraph,传入的参数为程序的入口,具体算法如下图所示:

        

 3. 举个栗子🌰

       

        过程还是很简单的,这里就不再赘述,大概就是从main开始,对call site 进行resolve分析,找到目标方法放入WL中,并加上调用边。然后循环再对WL中的方法进行分析,直到WL为空。

5.3 过程间控制流图 (Interprocedural Control-Flow Graph, ICFG)

5.3.1 ICFG与CFG对比

  • CFG表示单个方法的结构
  • ICFG表示整个程序的结构
    • 有了ICFG,我们就可以做过程间的分析
  • 一个ICFG是由程序中各个方法的CFG所构成,并需要加上两种额外的边
    • 调用边 (Call edges) : 从调用点call sites 连接到 其目标方法callees的入口entry nodes
    • 返回边 (Return edges): 从return 语句 连接到 紧跟着的调用点call sites的下一个语句(i.e., 返回点return sites
  • ICFG = CFGs + call & return edges

    • 连接这两种边的信息来自call graph

5.3.1 ICFG: An Example🌰

        

         如上图所示,ICFG就是CFG加上两种边,但是这里有一个问题,为什么还要保留黄色部分的边呢?这个边(从call site 到return site的边)叫做call-to-return edge,这个边可以用来在ICFG中传播本地数据流(就是函数内部的数据流)。

        如果没有这条边,我们需要跨越其他方法来传播本地数据流,这是非常低效的。(如下图所示,其实这个图上的x,a ,b 等数据信息时会在5.4.2中介绍到的)

        

5.4 过程间数据流分析(Interprocedural Data-Flow Analysis)

5.4.1 过程间与过程内对比

        过程间的数据流分析就是对有方法调用的整个程序,基于这个程序的ICFG进行数据流分析。

        

         如上图所示,对比过程内和过程间,在程序表述上,过程内主要是关注每个CFG,而过程间需要加上调用和返回边,在转换函数中,过程间还需要加上两种边的转换函数edge transfer

  • Call edge transfer: 将数据流从call node 传送到被调用节点callee (沿着call edges,传递参数值)
  • Return edge transfer: 将数据流从callee上的return node传送到return site(沿着return edges,传递返回值)

        对于过程间调用的node transfer:

  • node transfer:与之前提到的传递函数基本一样,但是多了一个性质:

    • 对于每个调用节点call node (例如b=addOne(a)),会将等式左侧的数值kill掉,然后在下一步中由返回边传递函数重新赋值。这个操作可以在返回值与原值不同时防止数据冲突。

5.4.2 举个例子🌰

        如下图,显示了如何对左边的程序进行过程间的常量传播分析,用黄色节点表示IN数据流,蓝色表示OUT数据流。

        

         例如,对于 b= ten() 节点,OUT处会把b=7删掉,因为如果不删除,等return流分析完之后b=10就会与b=7冲突,当成merge操作,将b定义为NAC,导致精度下降。

        

        当然这个例子是比较简单的,没有复杂的control merge操作,但是也可以很好的理解 call edge 与 return edge 上需要进行的操作,也可以很好地理解call-to-return edge 的作用。


其他的写的很好的博主的文章:

【软件分析/静态程序分析学习笔记】6.过程间分析(Interprocedural Analysis)_童年梦的博客-CSDN博客

https://www.cnblogs.com/crossain/p/12720612.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/732582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023 年 GitHub 上最火的 Java 面试宝典正式上线

笔记特点:条理清晰,含图像化表示更加易懂。 内容概要:包括 Java 集合、JVM、多线程、并发编程、设计模式、Spring 全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Ne…

Vue实现拖拽鼠标圈选、划区域、框选组件sgRectSelect:矩形区域选中checkbox,并回调相关选中、取消选中的操作

边框线虚线动画效果请参阅边框虚线滚动动画特效_虚线滚动效果_你挚爱的强哥的博客-CSDN博客【代码】边框虚线滚动动画特效。_虚线滚动效果https://blog.csdn.net/qq_37860634/article/details/130507289 碰撞检测原理请前往 原生JS完成“一对一、一对多”矩形DIV碰撞检测、碰撞…

车载以太网 - SomeIP - 协议用例 - RPC

目录 RPC Protocol specification 1、Cleint和Server端应该为一个服务实例的所有的Methodsevents使用一个TCP连接

AtCoder Regular Contest 163 C. Harmonic Mean(构造 补写法)

题目 t(t<500)组case&#xff0c; 给定一个数n(n<500)&#xff0c;构造一个长为n的数组 思路来源 官方题解 题解 注意到 ... 右边累加&#xff0c;等于1-最后一项&#xff0c;可以把最后一项挪到左边 所以&#xff0c; 1. 当n没有在前面的序列里出现过时&#xf…

centos7.6安装mysql

卸载mariadb 解决安装mysql与mariadb冲突问题&#xff08;卸载干净mariadb&#xff09;_何妨徐行的博客-CSDN博客 安装rpm包前可能需要的命令&#xff1a; yum install openssl-devel用于管理rpm包的工具 yum install lrzsz -y 文件传输缺乏rz 下载安装包 去mysql官网 把…

<Linux开发>驱动开发 -之- Linux I2C 驱动

&#xff1c;Linux开发&#xff1e;驱动开发 -之- Linux I2C 驱动 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植 uboot移植过程详细…

[MMDetection]VOC数据格式转为COCO数据格式

以下脚本可以根据创建VOC格式数据集转换为COCO数据集 其中文件组织格式如下 VOC2007 ------Annotations ------***********.xml ------***********.xml -------ImageSets ------train.txt ------test.txt -------JPEGImages ------***********.jpg ------***********.jpg CO…

【Spring】SpringBoot参数验证10个技巧

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 前言 1.使用验证注解 2 使用自定义验证注解 3 在服务器端验证 4 提供有意义的错误信息 5 将 i18n 用于错误消息 6 使用分组验证 7 对复杂逻辑使用跨域验证 8 对验证错误使…

通过smtp发送邮件及执行异常解决

在日常中遇到了需要实现一个发送邮件的需求&#xff0c;完成之后记录下实现方法及自己遇到的一些问题及解决办法。 常用SMTP服务相关地址及端口 一、通过javax.mail实现发送邮件 1.引入相关坐标 <!-- 发送邮件--><dependency><groupId>org.projec…

矩阵系统源码智能回复私信场景开发

抖音矩阵系统源码智能回复私信场景开发 一、要想开发私信功能开发者需要准备的工作 开发者需要先对接官方api接口以及去申请api提交审核&#xff0c;目前需要了解官方对开发者对该能力开发权限的功能符合开发需求&#xff0c;其次需要了解官方私信触达的规则 1.申请流程&…

基于GPT构建单细胞多组学基础模型

生成式预训练模型在自然语言处理和计算机视觉等各个领域取得了显著的成功。特别是将大规模多样化的数据集与预训练的Transformer相结合&#xff0c;已经成为开发基础模型的一种有前途的方法。文本由单词组成&#xff0c;细胞可以通过基因进行表征。这种类比启发作者探索细胞和基…

Lingo优化软件初步

一、Lingo软件介绍 1、lingo软件的简单介绍 美国芝加哥大学的Linus Schrage教授于1980年左右开发的专门用于求解最优化问题的软件包&#xff0c;后经多年完善与扩充&#xff0c;并成立了LINDO系统公司进行商业运作取得巨大成功。根据 LINDO公司主页&#xff08;http://www.li…

分布式监控系统之zabbix6.0二

分布式监控系统之zabbix6.0二 一、部署 zabbix 代理服务器二、部署 Zabbix 高可用集群三、Zabbix 监控 Windows 系统四、Zabbix 监控 java 应用五、Zabbix 监控 SNMP 一、部署 zabbix 代理服务器 分布式监控的作用&#xff1a; 分担 server 的集中式压力解决多机房之间的网络…

暑假第4天打卡

Java: &#xff08;1&#xff09;标识符命名规范&#xff1a; > 包名&#xff1a;多单词组成时所有字母都小写&#xff1a;xxxyyyzzz。 例如&#xff1a;java.lang、com.atguigu.bean > 类名、接口名&#xff1a;多单词组成时&#xff0c;所有单词的首字母大写&#xf…

【一步到位】Jenkins的安装、部署、启动(完整教程)

一、测试环境 Linux系统 Centos 7 二、安装步骤&#xff1a; 1、安装jdk 我安装的是jdk8&#xff0c;此处就不多说了&#xff0c;自己百度哈&#xff0c;很简单 2、安装jenkins 首先依次执行如下三个命令&#xff1a; 2.1、导入镜像&#xff1a; [rootcentos7 ~]# sudo …

阿里P6跟P7有什么区别?

在互联网领域&#xff0c;阿里的职级和腾讯的职级体系相当于行业标准了&#xff0c;所以技术人还是需要学习一下/对标一下&#xff0c;从而知道自己目前在哪里&#xff0c;努力的方向是哪里&#xff1f;那么&#xff0c;阿里 P7 级别到底需要哪些能力呢&#xff1f;如下图思维导…

指针和数组笔试题解析

目录 数组笔试题 一维数组 字符数组 题 一 题 二 题 三 题 四 题 五 题 六 二维数组 指针笔试题 笔试题一 笔试题二 笔试题三 笔试题四 笔试题五 笔试题六 笔试题七 本篇博文&#xff0c;将从指针和数组来为大家分析一些笔试题&#xff0c;设计内…

IDEA+SpringBoot+mybatis+SSM+layui+Mysql客户管理系统源码

IDEASpringBootmybatisSSMlayuiMysql客户管理系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.修改密码3.客户管理4.添加客户5.充值记录管理6.消费记录管理7.客户类型8.添加客户类型 三、部分代码UserMapper.javaLoginController.javaUser.java 四、其他获取源码 一、…

【ElasticSearch】ES案例:旅游酒店搜索

文章目录 一、项目分析二、需求1&#xff1a;酒店搜索功能三、需求2&#xff1a;添加过滤功能四、需求3&#xff1a;我附近的酒店五、需求4&#xff1a;置顶花广告费的酒店 一、项目分析 启动hotel-demo项目&#xff0c;访问localhost:servicePort&#xff0c;即可访问static下…

不停服迭代更新-服务网格

系列文章目录 本章将根据多年经验&#xff0c;进行规划讲解 文章目录 系列文章目录前言一、如何做到 不停服更新、 不停服更新的机制有什么好处&#xff0c; 前言 服务迭代发版、少不了的就是停服更新&#xff0c;为了不影响 用户体验&#xff0c;大部分公司选择半夜更新迭代&…