【軟件分析學習筆記】2:數據流分析及示例,半格和偏序

1 簡述數據流分析

數據流(dataflow)分析將程序看成數據和數據的流動轉移,而將轉移的控制條件忽略掉,只關注數據在轉移過程中的變化。

例如,對於上一節的停機問題的反例程序:

void Evil() {
	if(Halt(Evil)==False)
		return;
	else
		while(True);
} 

其中的if-else就是控制條件,將它忽略掉,抽象成一對非確定選擇(即在這裏程序隨機選擇一條路走)向左走\sqcap向右走:

void Evil() {
	向左走 return;
	向右走 while(True);
} 

即使沒有了if-else,停機問題的反例程序還可以單純用循環給出:

void Evil() {
	while(Halt(Evil))
		;
} 

這裏的循環條件也屬於控制條件,將它也抽象成非確定選擇:

void Evil() {
	AGAIN:
	向左走 goto AGAIN;
	向右走 return;
} 

像這樣將原始程序中的控制條件都抽象成非確定選擇,忽略程序的條件判斷,認爲所有分支都可能到達,就得到了抽象程序。原始程序只有一條執行路徑,抽象程序上有多條執行路徑。原始程序的執行路徑一定包含在抽象程序的執行路徑中,所以對原始程序的問題判定可以轉換成對抽象程序的判定

如對停機問題,原始程序上要求存在自然數n,使程序執行路徑長小於n。而對於抽象程序,是存在自然數n,使程序所有路徑長度都小於n。

注意,抽象程序上的判定問題,得到的是上/下近似的解而不是確定解。如對停機問題而言,實際上就是將抽象程序繪製成流程圖,如果流程圖中沒有環,那麼可以說原始程序一定停機;如果流程圖中有環,那麼要返回[不知道],因爲不存在自然數n使得所有路徑長度都小於n(抽象程序的流程圖中已經沒有條件控制了,環路長度就是無窮)。

2 例:符號分析

符號判定問題的數據流分析。

2.1 簡述

回顧筆記1中第6部分的符號判定問題。對於給定的程序,去掉分支判斷和條件循環之後,得到的抽象程序會有很多分支。使用抽象符號域上作運算的方法,引入[不知道],在nn個不同的分支上分別得到結果v1,v2,...,vn{,,,}v_1,v_2,...,v_n \in \{正,負,零,不知道\},最終判定的輸出就是:
(v1,v2,...,vn)\sqcap(v_1,v_2,...,v_n)

如果viv_ivjv_j一樣,非確定選擇\sqcap合併的結果就是viv_i,否則結果就是[不知道]。

爲了減少計算量,不必在每條路徑結尾做合併,可以在控制流結束匯合的地方提前合併,再將合併結果向下運算,如對於:

xxx
if(xxx)
	xxx
else
	xxx
while(xxx)
	xxx
xxx
xxx
...

那麼只要在while循環結束的地方(即是控制流匯合的地方)提前合併即可。

2.2 算法過程

這裏直接貼老師PPT:
在這裏插入圖片描述

3 例:活躍變量分析

活躍變量判定問題的數據流分析。

3.1 簡述

給出程序中的變量xx和程序點pp,如果xx會在從pp出發的某條路徑上使用,那麼xx對於pp點而言就是活躍變量,否則就不是。活躍變量的分析可以用來做寄存器的換出,對於不活躍的變量沒必要再佔用寄存器資源。

3.2 算法過程

逆向計算路徑上的活躍變量,見這篇文章

PPT上講的沒看懂:
在這裏插入圖片描述

4 半格和偏序

4.1 半格(Semilattice)

半格是二元組(S,)(S,\sqcap),其中SS是一個集合,\sqcap是一個交匯運算(也就是集合中若干元素經過這個運算會聚合成一個)。要求對SS中的任意元素,在運算\sqcap上是冪等、交換、結合的,而且SS中要存在一個最大元(或者叫頂元素TT使得任意xSx\in SxT=xx \sqcap T = x

例如,正整數集合上的"求最小公倍數"的運算就是一個半格,其中最大元T=1T=1

半格的笛卡爾積還是半格:
(S1,1)×(S2,2)=(S1×S2,1×2) (S_1, \sqcap_1) \times (S_2, \sqcap_2) = (S_1 \times S_2, \sqcap_1 \times \sqcap_2)

4.2 偏序(Partial Order)

偏序是二元組(S,)(S,\sqsubseteq),其中SS是一個集合,\sqsubseteq是一個二元關係,要求這個二元關係\sqsubseteq是自反、傳遞、反對稱的。

例如,實數集合上的小於等於關係就是一個偏序關係。

4.3 半格和偏序的關係

每個半格(S,)(S,\sqcap)都定義了同一集合SS上的一個偏序關係(S,)(S,\sqsubseteq),具體是:
xyxy=xx \sqsubseteq y 當且僅當 x \sqcap y = x

例如,正整數集合上的"求最小公倍數運算"是半格,而"整除關係"是對應的偏序。

又如,任意集合和"交集操作"組成了一個半格,頂元素是全集,而"子集關係"是對應的偏序。

又如,任意集合和"並集操作"組成了一個半格,頂元素是空集,而"超集關係"是對應的偏序。

4.4 半格的例子——抽象符號域的交匯操作

對於2的符號分析,在2.2中可以看到擴展的抽象符號域是:
{,,,,T}\{正,負,零,未知,T\}

那麼這個集合上的交匯操作就是一個半格了,其中最大元就是TT,而從:
=T=... 未知 \sqcap 正 = 未知 \\ 正 \sqcap T = 正 \\ ...

這些交匯操作規則可以導出這個半格對應的偏序關係:
T... 未知 \sqsubseteq 正 \\ 正 \sqsubseteq T \\ ...

可以將這些偏序關係整合成偏序圖:

可以看到從下往上畫偏序圖的話,偏序關係對應的半格的頂元素(最大元)就是在最頂上的。

4.5 半格的高度

半格的高度是對應偏序關係的偏序圖中任意兩個結點的最大距離+1,例如4.4抽象符號域的交匯操作的半格,高度就是3。

又如,集合和交集/並集操作組成的半格,高度是集合大小+1。

又如,活躍變量分析中,半格高度爲變量總數+1。

4.6 單調(遞增)函數

單調函數是定義在偏序關係上的。給定偏序關係(S,)(S,\sqsubseteq),稱一個定義在SS上的函數是單調遞增的,當且僅當對任意x,ySx,y \in S有:
xyf(x)f(y) x \sqsubseteq y \Rightarrow f(x) \sqsubseteq f(y)

例如,對2符號分析中的加減乘除操作(固定一個參數)都是單調函數。

3活躍變量分析有關的是, 在集合和交/並操作構成的半格中,給定任意兩個集 合GEN,KILLGEN, KILL,函數f(S)=(SKILL)GENf(S)=(S-KILL) \cup GEN爲單調函數。

5 數據流分析單調框架

對於23是同一類問題,可以用數據流分析通用的框架(數據流分析單調框架)導出不同的算法。對於逆向分析,變換控制流圖方向再應用單調框架即可。
在這裏插入圖片描述
算法僞代碼:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章