【软件分析/静态分析】chapter6 课程08 指针分析(Pointer Analysis)

news2024/9/20 14:34:41

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

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


目录

第六章 指针分析(Pointer Analysis)

6.1 为什么需要指针分析

6.2 指针分析的基本概念

6.2.1 基础知识

6.2.2 例子

6.2.3 指针分析(Pointer Analysis)和别名分析(Alias Analysis)

6.2.4 指针分析的应用

6.3 指针分析的关键要素

 6.3.1 Heap Abstraction 堆抽象

6.3.2 Context Sensitivity 上下文敏感

6.3.3 Flow sensitivity 流敏感

6.3.4 Analysis Scope 分析范围

6.3.5 总结

6.4 指针分析关注的语句

6.4.1 分析什么?

6.4.2 关注的指针

6.4.3 关注的语句 ⭐


第六章 指针分析(Pointer Analysis)

6.1 为什么需要指针分析

        如下图所示的程序,如果用CHA对 int x = n.get() 进行分析,则会根据n的声明类型Number 进行resolve,Number有三个子类,所以就会有三个目标方法,如果在这个基础上进行常量传播分析,就会出现三个不同的return值返回给x,导致合并时将结果定为x=NAC,实际上这样是不准确的,CHA分析出来的3条路径中有2条都是假的,从而丢失了精度。

        

        如果我们用指针分析的方式对该程序进行分析,会根据n指向的对象new One()来建调用图,然后对new One 做dispatch,只得到One的get方法。如下图所示,这样分析的结果是准确的,没有false positive。

        

        指针分析可以很好的解决CHA引入假的调用边的问题。

6.2 指针分析的基本概念

6.2.1 基础知识

        指针分析主要有以下三方面的性质:

  • 一种基础的静态分析
    • 计算程序中的每个指针可以指向哪些内存的地址。
  • 对于OOP语言
    • 计算一个指针(variable or field)可以指向程序中的哪些对象
  • 看作是一个may-analysis
    • 计算每个变量指向哪些对象的时候是over-approximation的,会比实际指向的对象更多一点,可以看作是这样一个问题:“指针可能会指向哪些对象?”

论文出处:

William E.Weihl, "Interprocedural Data Flow Analysis in the Presence of Pointers,  Procedure Variables,  and Label Variables".POPL 1980.

现如今,指针分析仍是一个比较活跃的领域。

        指针分析对于不同的语言也是有所区别的,这里我们仍以OOP语言(object-oriented programs, 面向对象语言)为主 (主要是java)。

6.2.2 例子

        指针分析的主要问题:“Which objects a pointer can point to?”我们先通过一些例子感受一下指针分析。

        如下图,对左边的程序做指针分析,结果用右侧的指向关系(Points-to relations)来表示。

        

第1、2个:比较好理解,就是变量a 和x 所指向的new A 和new B

第3个的this为变量a调用A的setB时的,所以this,指向new A 

第4个:b 是变量a调用A的setB时声明的,是B类型的,所以指向new B

第5个:y是变量a调用getB之后的返回值this.b,即B类型的,所以指向newB

下边的new A.b 是class A 中 this.b,指向传入参数x的new B。

6.2.3 指针分析(Pointer Analysis)和别名分析(Alias Analysis)

这两个概念之间紧密相关但有所区别

  • 指针分析关注 “指针可以指向哪些对象?”
  • 别名分析关注 “程序中的两个指针是否会指向相同的对象?”

        假设两个指针,p和q,指向相同的对象,则称p和q互相之间为别名(aliases)

        如下图所示,p 和q  aliases,但是x和y不是。                
         

        别名信息可以通过指针分析的结果(points-to relations)推导出来。

6.2.4 指针分析的应用

        指针分析在很多方面有很多作用,例如:

  • 基础信息:调用图、别名信息、……
  • 编译优化:Virtual call inlining,……
  • bug 检测:空指针检测,……
  • 安全性分析:信息流分析,……
  • ……

        "Pointer analysis is one of the most fundamental static program analyses,on which virtually all others are built." 指针分析是最基本的静态程序分析之一,几乎所有其他程序都是建立在此基础上的。

        —— Point Analysis - Report from Dagstuhl Seminar 13162. 2013.

        

6.3 指针分析的关键要素

        指针分析是一个非常复杂的系统,有两个关键指标:精度(precision)和速度(efficiency),不同的因素影响着系统的这两个性能。针对不同的需求,指针分析需要做不同的取舍,为了取得比较好的平衡,就需要关注这些不同的因素,这里选择了4个对指针分析最关键的要素:

        

 6.3.1 Heap Abstraction 堆抽象

1. 解决的问题:How to model heap memory? 如何对程序中的堆内存进行建模?

        因为在程序动态执行时,如果程序中有循环或者递归,堆的对象的数量,理论上是无穷的。如果静态分析去处理无穷的对象,那就不能终止了。

        为了确保终止,提出了堆抽象技术,动态地将无穷的具体对象 抽象为 方便静态分析的有限的抽象对象(finite abstract object)。

        如下图所示,左边的原点表示动态时候产生的对象,随着程序的运行可能会产生无穷无尽的对象,使用堆抽象技术,会把这些动态产生的对象进行抽象,把具有某些共性的对象抽象成一个对象,通过这种抽象的方式限制静态分析处理的对象的个数,从而保证终止。

        

对抽象技术本身是一个很复杂的技术,有很多分支,出自于2016年的一篇文章,大概有两大流派,store based model,和storeless model,还有他们的混合。在本文的指针分析中,我们只学习store based model中的Allocation sites(调用点的抽象)

        

2.  Allocation-Sites Abstraction(调用点的抽象)

        Allocation-Sites Abstraction 是目前最常用的堆抽象技术。其主要思想如下:

  • 将动态对象建模的方式抽象成创建点
  • 每一个allocation site 创建一个抽象对象,来表示其分配的动态的时候创建的所有具体对象

        如下所示,假设这里有一个循环的程序,第2行有个创建点,这个循环动态的时候,会创建三次,也就是创建3个对象,如中间的Dynamic execution,用o_{2} 表示一个创建点,下标表示创建点所在的位置。如果采用allocation-sites abstraction 技术,来对这个程序的堆进行建模时,会抽象为一个对象,用着一个对象来表示所有具体的对象。

        

        通过这样的处理方式,一定可以保证抽象对象的个数是有限的,因为一个程序中allocation sites的个数是有限的。

6.3.2 Context Sensitivity 上下文敏感

1. 解决问题:How to model calling contexts? 指针分析的过程中,如何对调用上下文进行建模?

        通常有两种选择,上下文敏感 vs 上下文不敏感

        上下文敏感的思想:在做静态分析的时候,会模拟动态的上下文的方式,将一个方法的不同上下文区分开来进行分析,对同一个方法有多个上下文的情况,就会对每一个上下文分别进行分析。

        

         如上图所示,对于不同的调用foo,采用上下文敏感的方法,会分开上下文1 和上下文2 ,这样a.foo(x)的 实参就只会传入上下文1中的 p。对于上下文不敏感的情况,不会将不同上下文区分开,会将不同上下文中的数据流全都混在一起。每个方法只有一个上下文,这样可能会丢失精度。

        上下文敏感是一个非常有用的技术,对于提升指针分析的精度非常显著,在后续的课程中,也会有更详细的讲述。这里我们先从简单的上下文不敏感的技术学起。

6.3.3 Flow sensitivity 流敏感

1. 解决问题:How to model control flow? 如何对程序的控制流进行建模?

        与上下文敏感类似,通常也有两种做法:控制流敏感 vs 控制流不敏感:

        流敏感的基本思想:流敏感分析中,会尊重程序中语句执行的顺序,为了实现这一点,流敏感分析在程序中的每一点(每个语句上),都维护着一对指向关系的映射。到目前位置,我们学到的数据流分析都是流敏感的。

        对于流不敏感的方法,会将程序当作一群无序语句的集合,因此会对整个程序维护一个指向关系的映射。

        ​​​​​

        如上图所示的程序中,如果是流敏感的方法中,在每一条语句之后,都会记录当前程序的指向关系。如果是流不敏感的方法,只会对整个程序维护一组指向关系的映射。例如说c.f 就可能会指向x或者y,如果不考虑顺序,s也会指向x和y,显然,这个s指向y是一个虚假信息,降低了准确性。

        流敏感对于不同语言的效果是不一样的,通常,对于C是非常有效的,但是对于Java,目前还没有证据可以表示,流敏感分析会比流非敏感分析的效率好很多。目前Java的主流都是流不敏感的,因为其更简单。所以本课程所学习的也是流不敏感的,也就是只维护一组指向信息。

6.3.4 Analysis Scope 分析范围

1. 解决问题:Which parts of program should be analyzed? 应该分析程序中的哪些部分?

        可以分为两类:whole-program(整体分析/全程序分析),demand-driven(需求驱动)

  • whole-program(整体分析): 会分析整个程序中的所有指向关系,其结果对所有可能的应用提供信息。
  • demand-driven(需求驱动分析): 针对特定需求计算指向关系,其结果只满足特定的应用。

       

         如上图所示,如果是全程序分析,就会把所有变量的指向关系都计算出来;如果我们感兴趣的点就只有第5行,就可以进行需求驱动分析,只需要分析第四行即可,有这个z 的信息就可以分析第五行的z.bar()了。

        如果需求很明确,可以采用需求驱动分析,这样可以更快地得到结果,但是demand-driven的方式也没有那么美好,因为这个方法虽然只需要部分结果,但是也要求这个结果是safe的,可能还是会对程序绝大部分进行分析后,才能解出正确结果,速度可能并没有快非常多。此外,需求驱动分析只能满足特定的clients,如果有多个clients,然后对每个需求都进行分析,他们之间可能会有重复的部分,可能并没有比全程序分析快。本课程中采用全程序分析。

6.3.5 总结

        如下图所示,便是这四种因素,choice列提供具体的方法,红色为本课程会学习的技术。

        

简单总结如下:

堆抽象:针对对象,采用allocation-site抽象的方法,为每个调用点创建一个抽象对象;

上下文敏感:针对上下文,先学习上下文不敏感,后续会再学习上下文敏感的方法;

流敏感分析:针对控制流,为了减小开销,采用不敏感的;

分析范围:针对分析范围,选择全程序分析。

6.4 指针分析关注的语句

6.4.1 分析什么?

        现在的语言拥有很多类型,例如 if else, switch case, for/while/do while, continue/break…他们不会直接修改某些指针的值,所以我们在做指针分析的时候,很多语句是不需要处理的。

        我们只关注影响指针指向的语句pointer-affecting statements

6.4.2 关注的指针

Local variable 本地变量
Static field 静态字段C.f 有时候会看作global variable,跟处理variable是类似的
Instance field 实例字段x.f 建模成一个由x所指向的object,并加上field f
Array element 数组array[i] 

忽略数组下标、长度,不同位置的数据统一指向一个单独的field

        注意:对于数组而言,因为其每个索引具体指向的对象很难分析出来。所以静态分析的通用做法就是:忽略数组的下标、长度信息,让数据统一指向一个单独的field,例如说arr,将array[i]指向的信息全部抽象映射到array.arr中,取的时候,也直接取array.arr。如下图所示:

        

        在实际的分析中,学会分析 instance filed  也就会 array element了,且static field处理方法与variable类似,所以在后续的学习中,我们将会重点关注第1、3个指针。

6.4.3 关注的语句 ⭐

        接下来,我们将会重点关注影响指针分析的这5种语句:

Newx = new T()创建对象
Assignx = y赋值语句
Storex.f = y

往instance field中存值

Loady = x.f往instance field中取值
Callr = x.k(a, ……)方法调用

注意:

1. 在程序中,这种 x.f 的操作,也可能是很复杂的访问内存的指针表达式,例如 x.f.g.h = y。 我们在做指针分析的时候,对于所有这种memory-accesses的方式,都是一样的,我们会引入临时变量,将其分解成3地址码的形式,进行简化,如下图所示,如果很长就多引入几个中间变量:
        

2. 对于方法调用,上篇文章中提到了三种不同的调用方式,这里我们重点关注最复杂的virtual call的情况

         


🦄写在后边:

本文主要介绍了静态分析领域的重要技术,指针分析,的一些基本概念,以及指针分析的关键要素,并介绍了后续我们会在指针分析中重点关注的变量、指针、语句等。关于指针分析的核心内容将在下篇文章中进行介绍。

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

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

相关文章

AMAT 工业输入输出模块0100-77037

W;① ⑧ 0 ③ 0 ① 7 7 7 ⑤ 9 AMAT 工业输入输出模块0100-77037 0100-76124 0100-71313 0100-71311 0100-71309 0100-71278 0100-71267 0100-71229 0100-71224 0100-20100 IGBT 和 IGCT 是四层器件,乍一看并没有什么不同。但是,当您“ 深入了解…

Spring Boot原理分析(三):IoC容器的继承层次

文章目录 一、Spring Ioc容器的继承层次1.BeanFactory2.ListableBeanFactory3.HierarchicalBeanFactory4.ApplicationContext 二、常用的ApplicationContext的实现类1.ClassPathXmlApplicationContext(基于XML配置)2.AnnotationConfigApplicationContext…

[Android]使用jni实现高斯模糊

1.高斯模糊的原理: 根据周边的像素值来确定自己的像素值,平均值,最大值,最小值,正太分布值 2.均值模糊blur 函数声明: CV_EXPORTS_W void blur( InputArray src, OutputArray dst,Size ksize, Point anc…

python绘制分组条形图

文章目录 数据导入多组条形图堆叠条形图 数据导入 我们经常会遇到对比多个统计量随时间变化的图像,比如想知道中国、美国以及欧盟最近几年GDP变化,如下表所示,单位是万亿美元。 中国美国欧盟201813.8920.5315.98201914.2821.3815.69202014.…

转换或是克隆的虚拟机无法联网,网络服务无法启动

新转换的虚拟机,无法联网,启动网络服务,报错: systemctl start network.service job for network.service failed because the control process exited with error code. 查看网络服务状态,systemctl status network…

SpringMVC 中的控制器如何处理文件上传

SpringMVC 中的控制器如何处理文件上传 Spring MVC 是一个基于 Java 的 Web 框架,它是 Spring 框架的一部分,提供了一系列的组件和工具,帮助开发人员构建 Web 应用程序。其中,控制器是 Spring MVC 中的核心组件之一,它…

SpringMVC 中的控制器如何返回 JSON 数据

SpringMVC 中的控制器如何返回 JSON 数据 SpringMVC 是一个基于 Spring 框架的 Web 框架,它提供了一种方便的方式来处理 HTTP 请求和响应。在 SpringMVC 中,控制器是用来处理请求的组件,它们负责接收请求、处理请求并返回响应。在本文中&…

三大城市分会场精彩呈现—2023架构·可持续未来峰会圆满收官!

2023年6月30日,由The Open Group主办的2023架构可持续未来峰会三大城市分会场成功举办,也代表着本次The Open Group半年度架构峰会圆满收官! 本次大会以“可持续未来”为主题,采用“13”,即北京主会场上海/成都/深圳三…

svg修改图标颜色

对于svg图标,想通过hover或者active 添加颜色,没有办法修改,解决办法: 1. 修改svg图片源 最开始的svg图标: 修改这个fill"currentColor" 要是要修改线条颜色就修改stroke属性: fill属性设置对象…

青岛大学_王卓老师【数据结构与算法】Week05_02_栈的定义和特点_学习笔记

本文是个人学习笔记,素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享, 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权,请留言作删文处理。 课程视频链接: 数据结构与算法基础…

这所985太好考了,专硕06方向仅刷一人,其余过线全收!

一、学校及专业介绍 东北大学(Northeastern University)位于辽宁省沈阳市,是中华人民共和国教育部直属全国重点大学。它是国家“双一流”建设高校、国家“211工程”和“985工程”重点建设高校,全国首批博士、硕士学位授予单位。 …

10.12UEC++/结构体和枚举

1.结构体: 定义: 类中创建对象; UE4中使用: 也可以定义一个结构体类型的变量: 结构体成员想要在细节面板中调整时,也需要每个都加上UPropPerty指令宏才可以: 此时该变量没有break功能&#xff0…

Seal AppManager v0.2 发布:进一步简化应用部署体验

经过近3个月的研发,Seal AppManager v0.2 已正式发布。 Seal AppManager 是一款基于平台工程理念的应用统一部署管理平台,于今年4月首次推出。在上一版本中,我们已经释出集成 ChatGPT 简化服务模板代码生成、云成本可视化、动态环境管理等功…

用html+javascript打造公文一键排版系统2:显示源码/显示预览、清除格式

我们从实现最简单、最基本的功能开始。 一、显示源码/显示预览 我们通过btnShowSrc来实现示源码/显示预览功能&#xff0c;根据btnShowSrc.value来判断<iframe>的显示的内容并切换。 <iframe>默认为显示预览&#xff0c;所以btnShowSrc.value值为“显示源码”&a…

Flink DataStream之Connect合并流

新建类 package test01;import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.datastream.ConnectedStreams; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.datastre…

flutter开发实战-指纹、面容ID验证插件实现

flutter开发实战-指纹、面容ID验证插件实现 在iOS开发中&#xff0c;经常出现需要指纹、面容ID验证的功能。 指纹、面容ID是一种基于用生物识别技术&#xff0c;通过扫描用户的面部特征来验证用户身份。 一、效果图 二、iOS指纹、面容ID验证 在iOS中实现指纹、面容ID验证功能…

一同感受C++模版的所带来的魅力

文章目录 一、泛型编程思想二、函数模版1、函数模板概念2、函数模板格式3、函数模板的原理4、函数模板的实例化5、模板参数的匹配原则 三、类模版1、类模板的定义格式2、类模板的实例化 四、总结与提炼 一、泛型编程思想 首先我们来看一下下面这三个函数&#xff0c;如果学习过…

磁盘与文件系统管理

磁盘结构及分区表示 硬盘 Hard Disk Drive &#xff0c;简称 HDD 是计算机常用的存储设备之一。 1 磁盘基础 1.1 硬盘的结构 1.1.1 数据结构 ①扇区&#xff1a;磁盘上的每个磁道被等分为若干个弧段,这些弧段便是硬盘的扇区(Sector)。硬盘的第一个扇区&#xff0c;叫做引导…

【mysql】-【锁】

文章目录 概述MySQL并发事务访问相同记录读-读情况写-写情况读-写或写-读情况并发问题的解决方案 锁的不同角度分类 概述 事务的隔离性由这章讲述的锁来实现。 MySQL并发事务访问相同记录 并发事务访问相同记录的情况大致可以划分为3种: 读-读情况 读-读情况&#xff0c;…

使用vite创建vue3的Cesium基础项目

使用vite创建vue3的Cesium基础项目 使用vite创建vue3项目&#xff1a;可以参考官方文档Vite官方中文文档 1.1 在指定文件夹路径下使用npm&#xff08;前提是已经安装好了node&#xff09;&#xff1a; bash npm create vitelatest 1.2 cd到创建的项目文件夹&#xff1a; bash c…