软件分析10 - 上下文敏感指针分析(1)
Introduction
motivation
上下文不敏感的指针分析将同一个方法调用所有可能的返回值传播给所有左值Var.这会降低精度.
上下文敏感则会将不同实参对应的返回值区分开分别传播.
建模与区分
要进行上下文敏感分析,最核心的任务就是对不同的调用上下文进行建模。一个可行的建模方法是区分不同上下文的数据流.
一个最古老且最广为人知的区分不同上下文的办法是call-site sensitivity.(还有很多其它变式)
-
一个method的每个上下文被表示为一个调用点链(a chain of call sites)
a call site of the method,
a call site of the caller,
a call site of caller of caller, etc.
上述两种对上下文实现的表述实际上说了两件事:
1. 不同上下文怎么区分?(即回答了上下文"A"为什么不是"B")
2. 不同上下文怎么建模?(在区分完"A"与"B"之后抽象出两者最核心的区别, 并利用这种区别得出与上下文不敏感分析不同的分析)
实现
在上下文不敏感分析中,对同一个方法(dispatch()结果相同)的分析不区分参数、调用点等上下文信息. 完全被当作是同一个个体. 而在上下文敏感分析中就需要将不同上下文的同一个方法区别开. 上面已经提过了如何区别及建模的办法, 这些办法对应的具体实现就是cloning-Based Context Sensitivity
简单来讲就是将之前作为同一个个体的方法以上下文为标识分开,分别作为一个cloning entity. 与此同时,方法涉及的变量(方法体内变量、返回到的变量)都要区分开(分开的办法继承自方法分开的办法)
然而,仅仅分开方法和变量是不够的(详见slides p32). 还需要实现堆的上下文敏感.
在之前的分析中,堆抽象为allocation-site abstraction. 现在则新增Context-sensitive
与变量类似,堆的上下文同样继承自所在方法的上下文.
Rules
Notation
根据上文Cloning-Based Context Sentivity的定义, 图中的记号仅仅是在之前分析的基础上加了所在clone的上下文记号.
Rule

在上述记号体系下,分别说明这些推理规则的合理性:
-
New
变量和对象的上下文都继承自所在方法,都为\(c\)
-
Assign
赋值语句在上下文\(c\)中, 故变量\(x,y\)的上下文都为\(c\), 对象\(o_i\)allocate时的上下文为\(c'\), 故传播给\(x\)后上下文不变也为\(c'\)
变量的作用域和生命期都与所在的函数栈帧相同(暂不考虑全局变量), 而堆对象并非如此. 因此对象的上下文与所在栈帧无直接关系(非allocation)
-
Store & Load
根据上面两条分析很自然可以得到.
-
Call
Select()会根据调用点信息生成callee的上下文
其它规则同上
上面介绍了上下文敏感分析的大致思路和数学形式,之后会补充算法实现部分以及其它不同的上下文建模方式