Backward Slicing 到底是什么?
引言
经过一华学长的确认,真正的 backward slicing 是一种程序切片技术,用于追踪特定程序位置或变量的影响源,涵盖 数据依赖 和 控制依赖。它的目标是识别对一个给定变量、表达式或程序位置产生影响的所有代码部分。简单来说,它通过逆向追踪程序的依赖关系,将所有与目标相关的指令集合为一个切片,方便分析与调试。
Backward Slicing 的具体步骤
-
选择目标:首先确定要分析的变量或位置,比如某个关键变量的最终值或者特定的执行点。
-
数据依赖追踪:从目标变量或位置出发,追踪所有影响其值的指令(赋值、操作)。这一步的核心是找出目标变量的定义和使用情况,比如该变量依赖于哪些输入数据或计算操作。
-
控制依赖追踪:在数据追踪之外,还要考虑目标变量的生成是否受控制流影响。比如,某个
if语句或while循环控制了目标变量的赋值操作,则需要将这些控制条件和分支结构也纳入切片。 -
构建切片:将数据依赖和控制依赖的指令集合成一个完整的代码切片,代表着目标变量或位置在程序中的所有影响源。
SSA 中的 Backward Slicing
在 SSA (Static Single Assignment) 形式中,每个变量都有唯一的定义(赋值)点,因此 backward slicing 的流程稍有不同:
- 确定感兴趣的 SSA 变量(如
%1504),并从该变量出发向后追溯影响源。 - 追踪数据依赖:直接找到目标变量的定义点,逐级追溯其操作数的定义,将所有定义指令加入切片中。
- 追踪控制依赖:在 SSA 中,控制依赖一般涉及条件跳转或
phi函数。需要确定变量定义的路径是否依赖于特定条件:- 若某条指令的执行受条件跳转控制,则将控制条件纳入切片。
- 若使用
phi函数合并多个控制流分支,则追踪phi函数的输入变量及其控制路径。
- 递归追溯依赖:对每一个依赖变量,继续进行数据依赖和控制依赖的追踪,直到找到初始输入变量或无需进一步追踪为止。
例子
以下代码:
x = 0
if y > 5:
x = z + 1
print(x)
转换为 SSA 形式如下:
y0 = y
z0 = z
x0 = 0 # 初始赋值
if y0 > 5:
x1 = z0 + 1 # 条件成立时赋值
x2 = phi(x0, x1) # 使用 phi 函数选择 x 的最终值
print(x2)
在 SSA 形式中,x2 是 print 函数中使用的变量,而 x1 和 x0 是 x 在不同路径中的不同版本。phi(x0, x1) 表示 x2 的值取决于 y0 > 5 的结果,即选择 x0 或 x1。
假设我们对 print(x2) 中的 x2 进行 backward slicing,追踪所有对 x2 产生影响的指令,包括数据依赖和控制依赖:
-
数据依赖追踪:
x2由phi(x0, x1)生成,因此我们追踪x0和x1。x0的值直接为0。x1的值由z0 + 1生成,因此我们追踪z0,即z0 = z。
-
控制依赖追踪:
x1的生成依赖于条件y0 > 5,该条件需要纳入切片,因为它决定了x1 = z0 + 1的执行。
最终得到的切片包含以下所有指令:
y0 = y
z0 = z
x0 = 0
if y0 > 5:
x1 = z0 + 1
x2 = phi(x0, x1)
print(x2)
这个切片包含了所有对 x2 的定义和控制条件的依赖,形成了完整的 backward slice,用于分析 print(x2) 的值及其所有潜在来源。
Backward Slicing 与 Control Flow 和 Data Flow 的关系
1. Backward Slicing on Control Flow
- 仅关注控制依赖,找到目标指令的执行受哪些控制条件的影响。
- 通过追溯控制流图 (CFG),收集所有决定目标指令是否执行的条件语句和控制结构。
- 应用场景:适用于分析目标指令是否受特定条件、分支或循环的控制。例如,分析
CALL指令的执行路径,可以找到所有影响它是否执行的控制条件和分支。
2. Backward Slicing on Data Flow
- 仅关注数据依赖,找到目标变量或指令的所有数据来源。
- 通过追溯数据依赖图或使用-定义链,从目标变量开始逆向追踪其所有数据来源,直到初始赋值。
- 应用场景:适用于分析某个变量的最终值受哪些指令影响。例如,追踪变量
x的值,收集所有影响x赋值和计算的语句。
3. 完整的 Backward Slicing(真正的 Backward Slicing)
- 综合数据流和控制流:既追踪目标变量或指令的所有数据依赖,又追踪其执行路径上的控制依赖。
- 应用场景:完整的 backward slicing 提供了对程序中特定位置或变量的全局分析,适合用于更复杂的场景,特别是在需要追踪控制条件的影响时。
总结
完整的 backward slicing 是在 数据依赖 和 控制依赖 的基础上进行的全面分析。相比单独的数据流追踪或控制流追踪,它能够提供程序中特定位置或变量的完整依赖路径,使其成为一种强大且全面的分析手段。