專利名稱:基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法
技術(shù)領(lǐng)域:
本發(fā)明涉及一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,屬于編譯器應(yīng)用 技術(shù)領(lǐng)域。
背景技術(shù):
C語言使用堆棧來存儲局部變量和傳遞函數(shù)的參數(shù),所以,如果函數(shù)的調(diào)用層 數(shù)過多或者出現(xiàn)了遞歸調(diào)用,就非常容易使得堆棧上的內(nèi)存需求超過了最大能夠使用的 空間限制,產(chǎn)生堆棧溢出。在普通的PC系統(tǒng)中,堆棧溢出并不是一個(gè)很明顯的問題,一 是因?yàn)楹芏嘞到y(tǒng)中含有存儲器管理單元(MMU),可以提供對堆棧內(nèi)存空間的保護(hù)。二 是因?yàn)槠胀≒C系統(tǒng)存儲器容量較大,可以分配給堆棧足夠的內(nèi)存空間,但是在內(nèi)存容量 受限制且大多不具備內(nèi)存保護(hù)機(jī)制的嵌入式設(shè)備上,堆棧溢出經(jīng)常會(huì)出現(xiàn),而且一旦出 現(xiàn),往往意味著整個(gè)系統(tǒng)崩潰。所以在對嵌入式的C代碼進(jìn)行檢查的時(shí)候,堆棧溢出檢 查是一個(gè)很重要的方面。目前,在堆棧分析方面,還沒有太多成熟的工具可用,唯一可以使用的是商用 分析工具stackAnalyzer。這款軟件可以自動(dòng)分析出應(yīng)用程序中最差情況下的堆棧使用情 況;分析結(jié)果以標(biāo)注的形式在調(diào)用關(guān)系圖和控制流圖中顯示。它可以計(jì)算出任何一個(gè)函 數(shù)的堆棧使用情況,并且起始點(diǎn)可以任意選取,也可以預(yù)報(bào)可能出現(xiàn)的堆棧溢出,以及 優(yōu)化對堆棧的使用。但是,這款軟件是一個(gè)需要付費(fèi)的商用產(chǎn)品,且價(jià)格較高。同時(shí), 由于沒有源代碼,無法對其本身的安全性進(jìn)行評估,因此不能在航天軟件開發(fā)上進(jìn)行應(yīng) 用。為了檢測到是否有堆棧溢出錯(cuò)誤發(fā)生,實(shí)際上是要監(jiān)測在每個(gè)函數(shù)被調(diào)用時(shí)堆 棧上存在的棧幀數(shù)目以及每個(gè)棧幀的內(nèi)存需求。但由于棧幀的增減變化是在運(yùn)行時(shí)動(dòng)態(tài) 地表現(xiàn)出來的,所以,靜態(tài)的堆棧溢出檢查有很大的困難。主要體現(xiàn)在以下兩個(gè)方面第一,如何獲得每個(gè)函數(shù)的棧幀的大小,也就是棧幀的內(nèi)存需求。每個(gè)函數(shù)都 可以定義任意數(shù)目和類型的臨時(shí)變量以及輸入?yún)?shù),如何能夠比較準(zhǔn)確地計(jì)算所有這些 變量和參數(shù)使用的內(nèi)存大小。第二,如何統(tǒng)計(jì)整個(gè)程序的函數(shù)調(diào)用情況。堆棧上棧幀的數(shù)目和順序是隨著函 數(shù)調(diào)用序列而動(dòng)態(tài)變化的,如何能夠精確地跟蹤程序中所有從main函數(shù)開始的調(diào)用序列 對于溢出檢測有著決定性的影響。用C語言寫的源程序分布在不同的文件中,每個(gè)文件 都包含了若干個(gè)函數(shù),如何從這些代碼中分析出每條函數(shù)調(diào)用序列
發(fā)明內(nèi)容
為了解決上述問題,為了保證堆棧的安全性,在分析了國內(nèi)外堆棧檢查技術(shù)的 基礎(chǔ)上,采用了 John Regehr提出的通過對通用寄存器和中斷控制寄存器的狀態(tài)進(jìn)行建模 來檢測堆棧溢出方法的思想。該方法將程序的運(yùn)行過程表示為一個(gè)狀態(tài)遷移流程圖,通 過對這個(gè)圖的分析來判斷是否存在堆棧溢出的情況。借鑒這樣的思想,本發(fā)明提出了一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,該方法對建立圖和分析的方法進(jìn)行了較 大的改進(jìn)。本發(fā)明采用的技術(shù)方案如下一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于包括以下步驟1)獲得每個(gè)函數(shù)的棧幀的大小;2)獲得每個(gè)函數(shù)的調(diào)用路徑;3)對所有的函數(shù)調(diào)用關(guān)系建立函數(shù)調(diào)用圖;
4)遍歷整個(gè)函數(shù)調(diào)用圖,得到所有以main函數(shù)為起點(diǎn)、以底層的子函數(shù)為終點(diǎn) 的路徑。進(jìn)一步地在所述步驟1)中,通過分析編譯器為每個(gè)函數(shù)生成的匯編代碼段,從每個(gè)函數(shù) 的代碼段的調(diào)整棧頂指針語句中獲得每個(gè)函數(shù)的棧幀的大小。在所述步驟2)中,分析編譯器為每個(gè)函數(shù)產(chǎn)生的RTL代碼,尋找其中的調(diào)用指 令,從而找到所有函數(shù)的調(diào)用關(guān)系。在所述步驟3)中,函數(shù)調(diào)用關(guān)系圖的定義如下函數(shù)調(diào)用關(guān)系圖中的節(jié)點(diǎn)是程序中所有函數(shù)的集合,圖中的邊表示函數(shù)之間的 調(diào)用關(guān)系,如果函數(shù)間存在調(diào)用關(guān)系,那么節(jié)點(diǎn)間通過有向弧相連接,這個(gè)有向弧從調(diào) 用節(jié)點(diǎn)指向被調(diào)用節(jié)點(diǎn),如果調(diào)用關(guān)系圖中存在環(huán),說明程序中存在遞歸調(diào)用。所述步驟4)進(jìn)一步包括以下步驟將圖中所有的節(jié)點(diǎn)標(biāo)記為未被訪問的;將圖中所有的邊標(biāo)記為空;堆棧大小初始化為零;遍歷函數(shù)調(diào)用關(guān)系圖;如果節(jié)點(diǎn)u正在被訪問,則計(jì)算函數(shù)U使用的堆棧大小并加到總的堆棧大小 中;如果總的堆棧大小大于預(yù)設(shè)的堆棧最大值,則堆棧溢出;如果節(jié)點(diǎn)u的鄰居節(jié)點(diǎn)ν被訪問過了且ν不是u的祖先節(jié)點(diǎn)則表明存在環(huán);如果節(jié)點(diǎn)ν未被訪問,則將U標(biāo)記為ν的祖先節(jié)點(diǎn),然后以ν為參數(shù)繼續(xù)調(diào)用遍 歷函數(shù);通過該遍歷算法并結(jié)合堆棧計(jì)算方法計(jì)算出堆棧使用的大小。本發(fā)明的優(yōu)點(diǎn)是本發(fā)明提供的堆棧檢測方法,利用了編譯器的中間結(jié)果,大 大的降低了開發(fā)的難度,且功能專一,運(yùn)行效率高。源代碼完全自主開發(fā),對于提高敏 感領(lǐng)域中嵌入式軟件的質(zhì)量,是一種很好的嘗試。
具體實(shí)施例方式本發(fā)明提供了一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法。該方法包括以 下步驟一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于包括以下步驟1)獲得每個(gè)函數(shù)的棧幀的大??;
2)獲得每個(gè)函數(shù)的調(diào)用路徑;3)對所有的函數(shù)調(diào)用關(guān)系建立函數(shù)調(diào)用圖;4)遍歷整個(gè)函數(shù)調(diào)用圖,得到所有以main函數(shù)為起點(diǎn)、以底層的子函數(shù)為終點(diǎn) 的路徑。下面詳細(xì)說明1.獲得函數(shù)堆棧大小的方法是分析編譯過程生成的匯編代碼。為了能夠調(diào)整棧 頂指針和棧幀指針,編譯器會(huì)為每個(gè)函數(shù)都生成如下一段特殊的匯編代碼,稱為函數(shù)的
“序言”。
權(quán)利要求
1.一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于包括以下步驟1)獲得每個(gè)函數(shù)的棧幀的大??;2)獲得每個(gè)函數(shù)的調(diào)用路徑;3)對所有的函數(shù)調(diào)用關(guān)系建立函數(shù)調(diào)用圖;4)遍歷整個(gè)函數(shù)調(diào)用圖,得到所有以main函數(shù)為起點(diǎn)、以底層的子函數(shù)為終點(diǎn)的路徑。
2.如權(quán)利要求1所述的基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于 在所述步驟1)中,通過分析編譯器為每個(gè)函數(shù)生成的匯編代碼段,從每個(gè)函數(shù)的代碼段的調(diào)整棧頂指針語句中獲得每個(gè)函數(shù)的棧幀的大小。
3.如權(quán)利要求1所述的基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于 在所述步驟2)中,分析編譯器為每個(gè)函數(shù)產(chǎn)生的RTL代碼,尋找其中的調(diào)用指令,從而找到所有函數(shù)的調(diào)用關(guān)系。
4.如權(quán)利要求1所述的基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于 在所述步驟3)中,函數(shù)調(diào)用關(guān)系圖的定義如下函數(shù)調(diào)用關(guān)系圖中的節(jié)點(diǎn)是程序中所有函數(shù)的集合,圖中的邊表示函數(shù)之間的調(diào)用 關(guān)系,如果函數(shù)間存在調(diào)用關(guān)系,那么節(jié)點(diǎn)間通過有向弧相連接,這個(gè)有向弧從調(diào)用節(jié) 點(diǎn)指向被調(diào)用節(jié)點(diǎn),如果調(diào)用關(guān)系圖中存在環(huán),說明程序中存在遞歸調(diào)用。
5.如權(quán)利要求1所述的基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,其特征在于所述 步驟4)進(jìn)一步包括以下步驟將圖中所有的節(jié)點(diǎn)標(biāo)記為未被訪問的; 將圖中所有的邊標(biāo)記為空; 堆棧大小初始化為零; 遍歷函數(shù)調(diào)用關(guān)系圖;如果節(jié)點(diǎn)u正在被訪問,則計(jì)算函數(shù)u使用的堆棧大小并加到總的堆棧大小中; 如果總的堆棧大小大于預(yù)設(shè)的堆棧最大值,則堆棧溢出; 如果節(jié)點(diǎn)u的鄰居節(jié)點(diǎn)ν被訪問過了且ν不是u的祖先節(jié)點(diǎn)則表明存在環(huán); 如果節(jié)點(diǎn)ν未被訪問,則將u標(biāo)記為ν的祖先節(jié)點(diǎn),然后以ν為參數(shù)繼續(xù)調(diào)用遍歷函數(shù);通過該遍歷算法并結(jié)合堆棧計(jì)算方法計(jì)算出堆棧使用的大小。
全文摘要
本發(fā)明涉及一種基于編譯過程中間結(jié)果的靜態(tài)堆棧檢測方法,包括以下步驟1)獲得每個(gè)函數(shù)的棧幀的大?。?)獲得每個(gè)函數(shù)的調(diào)用路徑;3)對所有的函數(shù)調(diào)用關(guān)系建立函數(shù)調(diào)用圖;4)遍歷整個(gè)函數(shù)調(diào)用圖,得到所有以main函數(shù)為起點(diǎn)、以底層的子函數(shù)為終點(diǎn)的路徑。本發(fā)明提供的堆棧檢測方法,利用了編譯器的中間結(jié)果,大大的降低了開發(fā)的難度,且功能專一,運(yùn)行效率高。源代碼完全自主開發(fā),對于提高敏感領(lǐng)域中嵌入式軟件的質(zhì)量,是一種很好的嘗試。
文檔編號G06F9/45GK102012833SQ201010539860
公開日2011年4月13日 申請日期2010年11月9日 優(yōu)先權(quán)日2010年11月9日
發(fā)明者孫磊, 張惠臻, 石文臣, 程勝 申請人:北京神舟航天軟件技術(shù)有限公司