1、引言
前面我们介绍过,指针分析是提高现有程序分析技术精度的一个重要技术。在这篇文章之前,流敏感指针分析还没有收到非常多的关注。然而,流敏感的指针分析在分析多线程时时非常有用的。而且流敏感技术也能非常大的提高程序分析的精度。
有些同学可能还不清楚流敏感是什么意思。这里简单介绍下。
补充知识:流敏感分析
流敏感分析是考虑了每个程序点的独有状态值,即在某条语句之前和之后,可能状态值是不一样的。比如:
// int *p, *q, a, b, c
1: p = &a;
2: q = &b;
3: p = &c;
4: p = q;
如果是非流敏感分析,那么分析结果将是 pts_set [p] = {a, b, c} 对所有位置均成立,显然这是错误的。因为在语句1之后,p只是指向了a。
如果是流敏感分析,那么结果是,对于语句1执行后,pts_set [p] = {a,b}, 在语句3执行后,pts_set [p] = {a ,c}, 在语句4执行后,pts_set [p] = {a, b, c}。
可以看到,流敏感分析对于程序分析精度的提高是非常有用的。
总结: 流敏感和非流敏感的区别在于:流敏感为每个程序点都计算了该点独有的程序状态
接着继续讲,流敏感之前不受待见的另一个原因是,当时传统的流敏感是在IDFA(即迭代式数据流分析框架)上做的,这个框架对流敏感式非常低效的,因为它保守地沿着CFG传递所有的数据流信息。导致一些根本不会在当前语句成立的数据流信息也传递到了。而对于大型项目程序来说,CFG是非常庞大的,CFG的节点也是非常多的,所以以IDFA为框架的流敏感分析就显得非常低效了。
本文主要利用稀疏分析来优化流敏感信息流的传递过程,作者认为,我们只需要将某个变量的定义和使用连一条边,然后在这条边上传递信息既可,这就是稀疏分析。我们只在必须的边上进行传递,跳过了非常多的无用节点,这样就能大幅提高流敏感的执行效率。
2、正文解读
在正文解读之前,我们有必要给大家概括一下这篇论文的总体解决思路,这样可以帮助大家在继续阅读下面内容的时候,有个整体概念,避免不知道在讲什么。
这篇论文的主要解决方案是,分阶段的求解流敏感指针分析,论文把这个叫做SFA (Staged Flow Sensitive Analysis)。首先,用一个不太精确的流非敏感,但计算速度快的辅助指针分析算法来保守地求解def-usei信息,然后,使用得到的def-usr信息来稀疏求解流敏感分析。
介绍完整体流程之后,我们进入正文。要继续读懂本文,需要3个前提知识,分别是LLVM IR、SSA、def-use求解框架,如果对这三部分还不太明白的,可以自行百度。
2.1 AUX辅助指针分析选择
AUX,即辅助指针分析,为了简化,后面就直接写AUX了。我们选择指针分析,可以从精度和可扩展性来看,一个更精确的指针分析会产生更稀疏的分析结果。如果AUX的扩展性低,那么这也会限制后面的分析。本文使用了基于包含的指针分析,即Andersen类型的分析,这类分析也是非敏感分析中最精确的分析技术,并且可以适用于数百万行代码的项目。
这里有一个问题,就是我用staged的指针分析,其结果会不会比AUX的精度低呢?换句话说,阶段性的指针分析结果精度会不会比单步指针分许结果精度更低呢?文中解释到,只要AUX是非敏感的分析,加上了后阶段的敏感性分析,那么其最终的结果一定不会比AUX精度低,至少也是平齐的效果。
2.2 稀疏流敏感指针分析
SFS(Sparse Flow-Sensitive Pointer Analysis) 的主要数据结构是def-use graph (DUG),这个图包含了一些表示程序语句的节点,以及表示def和use的边,如果一个变量在节点x处定义,在节点y处使用,则连一条有向边,x -> y。
下面我们来看下,这个图的边是如何计算得到的。
首先,我们使用AUX的结果,来将取址变量转化成SSA形式。一旦LOAD和STORE语句被标记为 χ \chi χ和miu函数之后,就可以使用标准的SSA算法来转化成SSA形式。
这里我们看一个例子,Fig 2 是一个简单的控制流图,以及AUX计算出来的points-to sets。
我们利用points-to sets,以及 χ \chi χ函数和μ函数来将上面这个图转化为SSA形式,如Fig 3所示。
具体的解释在图中已经很清晰了,并且 χ \chi χ函数和μ函数的作用也在图注中写明了。这里不再赘述。
这里需要说明一个问题,我们前面提到过,AUX是一个流不敏感的分析,所以其精确程度不如后续的流敏感指针分析。
所以这会带来三个问题,对于 ∗ x = y *x=y ∗x=y, 其标注为 v m v_m vm = χ \chi χ( v m v_m vm),
- 如果在流敏感分析中, x x x 不指向 v v v,这种情况下, v v v是不会发生任何变化的,即 v v v不会指向y,且 v m v_m vm 是 v n v_n v