專利名稱:于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出函數(shù)呼叫堆棧的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及一種可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出函數(shù)呼叫堆棧的方法,特別是涉及一種在不增加任何額外的系統(tǒng)負擔下可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出函數(shù)呼叫堆棧的方法。
背景技術(shù):
在一計算機系統(tǒng)中,動態(tài)配置一內(nèi)存區(qū)塊給一函數(shù)使用是一個基本的系統(tǒng)服務(wù),各個函數(shù)可在需要的時候去要求該計算機系統(tǒng)動態(tài)地配置一內(nèi)存區(qū)塊給它,然后在確定不需要使用該內(nèi)存區(qū)塊后,將該已配置的內(nèi)存區(qū)塊歸還給該計算機系統(tǒng),以實現(xiàn)內(nèi)存資源共享的目的。而在各執(zhí)行線程(thread)或程序(process)由主函數(shù)開始執(zhí)行時,會依據(jù)動態(tài)時期的外界輸入(input)、系統(tǒng)的訊息(message)或硬件的中斷,依需要呼叫其它的子函數(shù)來執(zhí)行其它功能,而子函數(shù)亦可根據(jù)程序邏輯繼續(xù)巢狀地呼叫其它函數(shù),如此反復組合各種函數(shù)則可實現(xiàn)程序執(zhí)行的目的。因為一個函數(shù)被呼叫的時機有各種可能,故當該計算機系統(tǒng)的處理器正在執(zhí)行某一函數(shù)時,若能取得整個函數(shù)呼叫堆棧,方能清楚得知此時函數(shù)被呼叫的原因與時機,即此一信息特別有利于軟件除錯時問題的追蹤與判斷。
請參閱圖1,圖1為現(xiàn)有一計算機系統(tǒng)10的功能方塊圖。計算機系統(tǒng)10包含有一微處理器12、一閃存(flash memory)14、一隨機儲存內(nèi)存(randomaceess memory,RAM)16與一暫存內(nèi)存18。于計算機系統(tǒng)10的運作為微處理器12存取閃存14、隨機儲存內(nèi)存16或暫存內(nèi)存18內(nèi)所儲存的數(shù)據(jù),并執(zhí)行必要的運算。閃存14為一非易失性(non-volatile)內(nèi)存,儲存有一第一函數(shù)F1的原始碼FS1、一第二函數(shù)F2的原始碼FS2以及兩個對應(yīng)第一函數(shù)的假指令(pre-process directive),分別為“__FILE__”以及“__LINE__”,這些假指令的功用會于之后的篇幅解釋。隨機儲存內(nèi)存16為一易失性(volatile)內(nèi)存,其包含有多個內(nèi)存區(qū)塊(memory block)16a、16b、16c,內(nèi)存區(qū)塊16a擁有一文件頭16ah,內(nèi)存區(qū)塊16b擁有一標題16bh,而內(nèi)存區(qū)塊16c擁有一標題16ch。此外,計算機系統(tǒng)10中,暫存內(nèi)存18用來儲存微處理器12對一函數(shù)進行編譯(compile)后所產(chǎn)生的執(zhí)行碼。
請同時參閱圖1與圖2,圖2為圖1所示的第一函數(shù)F1呼叫第二函數(shù)F2的示意圖。當微處理器12編譯一個包含有第一函數(shù)F1與第二函數(shù)F2的程序,于程序編譯(compile time)的過程中,可知第一函數(shù)F1中的第L1行程序代碼的內(nèi)容為呼叫第二函數(shù)F2,此時,依據(jù)現(xiàn)有技術(shù),微處理器12會將第一函數(shù)F1的函數(shù)名稱(例如F1)紀錄于假指令__FILE__內(nèi),而將行號L1紀錄于假指令__LINE__內(nèi)。在程序編譯完成之后,微處理器12便產(chǎn)生一對應(yīng)第一函數(shù)F1的第一函數(shù)執(zhí)行碼FE1以及一對應(yīng)第二函數(shù)F2的第二函數(shù)執(zhí)行碼FE2,此時第一函數(shù)執(zhí)行碼FE1與第二函數(shù)執(zhí)行碼FE2皆儲存于暫存內(nèi)存18內(nèi)。
于本實施例中,第一函數(shù)F1呼叫第二函數(shù)F2的目的為要求計算機系統(tǒng)10將某一內(nèi)存區(qū)塊配置予第一函數(shù)F1,因此,在程序編譯完成后,接下來于程序執(zhí)行(run time)時,當計算機系統(tǒng)10執(zhí)行第一函數(shù)執(zhí)行碼FE1的內(nèi)容到了對應(yīng)行號L1的部分,程序執(zhí)行點會跳躍(branch)到第二函數(shù)執(zhí)行碼FE2所在的地址,亦即從第二函數(shù)F2的起點開始執(zhí)行第二函數(shù)執(zhí)行碼FE2的內(nèi)容,假設(shè)目前計算機系統(tǒng)10應(yīng)第一函數(shù)F1的要求配置給第一函數(shù)F1使用的內(nèi)存區(qū)塊為內(nèi)存區(qū)塊16b,此時,計算機系統(tǒng)10將內(nèi)存配置信息記錄在內(nèi)存區(qū)塊16b的標題(header),也就是將假指令__FILE__與__LINE__所紀錄的內(nèi)容,分別為第一函數(shù)F1的函數(shù)名稱(亦即F1)與行號L1,拷貝至內(nèi)存區(qū)塊16b的標題。如業(yè)界所現(xiàn)有,假指令__FILE__的數(shù)據(jù)儲存型別(data type)是字符(character),因此若需儲存的函數(shù)名稱愈長,即代表假指令__FILE__需占用的儲存空間愈大,而假指令__LINE__內(nèi)所儲存的行號的數(shù)據(jù)儲存型別為一整數(shù)(integer),通常一整數(shù)所占用的空間為四個字節(jié)(4bytes)。在計算機系統(tǒng)10執(zhí)行完第二函數(shù)執(zhí)行碼FE2之后,程序執(zhí)行點會跳躍回第一函數(shù)F1,繼續(xù)執(zhí)行第一函數(shù)F1的第L2行(第L1行的下一行),亦即執(zhí)行第一函數(shù)執(zhí)行碼FE1中對應(yīng)于行號L2的部分。
由上可知,程序設(shè)計師可藉由查看內(nèi)存區(qū)塊16b的文件頭以得知內(nèi)存區(qū)塊16b是由第一函數(shù)F1要求計算機系統(tǒng)10所配置給其使用的內(nèi)存區(qū)塊。因此,利用現(xiàn)有方法可得知所有內(nèi)存區(qū)塊的配置情形,檢視內(nèi)存區(qū)塊為哪一函數(shù)要求計算機系統(tǒng)來配置使用,藉以找出計算機死機或程序錯誤的問題根源。然而現(xiàn)有方法于程序編譯時需要占用非易失性內(nèi)存的空間來紀錄內(nèi)存配置信息,亦即假指令__FILE__與__LINE__的內(nèi)容,且于程序執(zhí)行時亦需要拷貝該內(nèi)存配置信息至隨機儲存內(nèi)存內(nèi),因此提高了計算機系統(tǒng)于時間與內(nèi)存空間的成本而提高計算機系統(tǒng)的系統(tǒng)負擔(system overhand),而并非有效率的分析死機問題或程序除錯的方法。
發(fā)明內(nèi)容
本發(fā)明提供一種在不增加任何額外的系統(tǒng)負擔下可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出函數(shù)呼叫堆棧的方法,以解決上述的問題。
本發(fā)明披露了一種可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出一函數(shù)呼叫堆棧的方法,該方法包含有下列步驟(a)取得執(zhí)行該函數(shù)時所產(chǎn)生的一程序指針;(b)依據(jù)該程序指針取得相對應(yīng)的一指令;(c)檢測步驟(b)所取得的該指令是否與一返回地址指令相符;以及(d)當步驟(b)所取得的該指令與該返回地址指令相符時,儲存該程序指針所指向的一指令地址。
本發(fā)明還披露了一種可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出一函數(shù)呼叫堆棧的方法,該方法包含有下列步驟(a)取得執(zhí)行該函數(shù)時所產(chǎn)生的一程序指針與一堆棧指針;(b)依據(jù)該程序指針取得相對應(yīng)的一指令;(c)檢測步驟(b)所取得的該指令是否與一返回地址指令相符;(d)當步驟(b)所取得的該指令與該返回地址指令不相符時,將該程序指針設(shè)成指向于步驟(b)所取得的該指令的一前一指令;(e)檢測步驟(d)所取得的該前一指令是否與該返回地址指令相符;以及(f)當步驟(d)所取得的該前一指令與該返回地址指令相符時,儲存該程序指針于步驟(d)所指向的一指令地址。
圖1為現(xiàn)有計算機系統(tǒng)的功能方塊圖。
圖2為圖1所示的第一函數(shù)F1呼叫第二函數(shù)F2的示意圖。
圖3為本發(fā)明于計算機系統(tǒng)執(zhí)行函數(shù)時找出函數(shù)呼叫堆棧的流程圖。
附圖符號說明10計算機系統(tǒng)12微處理器
14 閃存16隨機存取內(nèi)存16a、16b、16c 內(nèi)存區(qū)塊16ah、16bh、16ch標題18 暫存內(nèi)存具體實施方式
請參閱圖3,圖3為本發(fā)明于一計算機系統(tǒng)執(zhí)行一函數(shù)(function)時找出函數(shù)呼叫堆棧(function call stack)的流程圖,該方法包含有下列步驟步驟100開始。
步驟102取得執(zhí)行該函數(shù)時所產(chǎn)生的程序指針(program counter)與堆棧指針(stack pointer)。
步驟104依據(jù)該程序指針取得相對應(yīng)的指令(instruction)。
步驟106檢測步驟104所取得的指令是否與一返回地址指令(Push-LR-to-Stack instruction)相符,若相符執(zhí)行步驟108,若不相符則執(zhí)行步驟110。
步驟108儲存該程序指針所指向的指令地址(address),并跳至步驟116。
步驟110檢測于步驟104所取得的指令是否與一堆棧指針操作指令(stack operation instruction)相符,若相符執(zhí)行步驟112,若不相符則執(zhí)行步驟114。
步驟112復原步驟104所取得的指令對該堆棧指針所做的改變,并跳至步驟114。
步驟114將該程序指針設(shè)成指向于步驟104所取得的指令的前一指令,并重新執(zhí)行步驟104。
步驟116比較步驟108所儲存的指令地址是否與該函數(shù)的主函數(shù)名稱的儲存地址相符,若相符執(zhí)行步驟122,若不相符則執(zhí)行步驟118。
步驟118依據(jù)該堆棧指針以取得相對應(yīng)的返回地址。
步驟120將該程序指針設(shè)成指向由步驟118取得的返回地址,并重新執(zhí)行步驟104。
步驟122結(jié)束流程。
于此對上述步驟作一詳細說明,首先執(zhí)行該函數(shù)時所產(chǎn)生的程序指針與堆棧指針可由數(shù)種方式來取得,例如可于該計算機系統(tǒng)死機時由讀取程序指針緩存器與堆棧指針緩存器而得;或于該計算機系統(tǒng)執(zhí)行上下文交換(context switch)時由保留于堆棧(stack)中的程序指針暫存值與堆棧指針暫存值所取得;或如現(xiàn)有技術(shù)的圖2利用第一函數(shù)F1呼叫第二函數(shù)F2時,由第二函數(shù)F2取得呼叫者第一函數(shù)F1的返回位置,也就是說可得出第一函數(shù)F1呼叫第二函數(shù)F2后的當下程序指針值,且第二函數(shù)F2中的區(qū)域變量的地址便是當下的堆棧指針值,可藉由檢查第二函數(shù)F2的組譯文件來得知進入第二函數(shù)F2后,堆棧指針會以多少的平移(offset)成為此區(qū)域變量,而反推出第一函數(shù)F1呼叫后的堆棧指針。
接下來便可依據(jù)該程序指針進行取值操作而得出相對應(yīng)的指令,而再依據(jù)該指令碼來比對檢查此指令是否為將返回緩存器(LR register)所儲存的返回位置存到堆棧的指令。依據(jù)編譯器(compiler)處理巢狀函數(shù)(nestfunction)的原理,此將返回緩存器所儲存的返回位置存到堆棧的指令就是被呼叫函數(shù)(callee)的第一個指令,而可依據(jù)不同編譯器所編譯出的組譯文件對微小差異稍做修正。若步驟104所取得的指令與該返回地址指令相符,則代表目前的程序指針已經(jīng)指到了函數(shù)的起點,此時便儲存該程序指針所指向的指令地址,如此一來便可儲存該函數(shù)所相對應(yīng)的內(nèi)存地址;若步驟104所取得的指令與該返回地址指令不相符,接下來則比對于步驟104所取得的指令是否與一堆棧指針操作指令(stack operation instruction)有關(guān),若為有關(guān),則復原步驟104所取得的指令對該堆棧指針所做的改變。舉例來說,若是該指令對堆棧指針實質(zhì)上平移了+8,則于此便還原該指令對堆棧指針的影響,而對堆棧指針做出實質(zhì)上平移-8的操作。之后再將該程序指針設(shè)成指向于步驟104所取得的指令的前一指令,并利用更新后的程序指針重新執(zhí)行步驟104,也就是說將目前的程序指針根據(jù)該指令的長度,減少一個指令的值。舉例來說,若該指令為32位,則將目前的程序指針實質(zhì)上減去4,若該指令為16位,則將目前的程序指針實質(zhì)上減去2,以此類推。若于步驟104所取得的指令與該堆棧指針操作指令無關(guān),則便可將該程序指針設(shè)成指向于步驟104所取得的指令的前一指令,并利用更新后的程序指針重新執(zhí)行步驟104。
當步驟104所取得的指令與該返回地址指令相符,且已儲存該程序指針所指向的指令地址,則比較步驟108所儲存的指令地址是否與該函數(shù)的主函數(shù)名稱的儲存地址相符,也就是說目前程序指針所指向的指令地址是否符合于主函數(shù)名稱的儲存地址,若相符,則代表主函數(shù)的所有函數(shù)呼叫堆棧的地址均已全部取得,故可結(jié)束整個流程。若步驟108所儲存的指令地址與該函數(shù)的主函數(shù)名稱的儲存地址不相符時,則代表主函數(shù)的所有函數(shù)呼叫堆棧的地址并未全部取得,故此時便必須跳回目前所在函數(shù)的上一層函數(shù)繼續(xù)進行反推出函數(shù)呼叫堆棧的操作,直到跳回一開始的執(zhí)行線程主函數(shù)(threadmain function),以取得主函數(shù)的所有函數(shù)呼叫堆棧的地址。其執(zhí)行程序為根據(jù)該返回地址指令對堆棧指針所做的操作進行還原的操作,然后再由還原后的堆棧指針取出返回緩存器所儲存的返回位置。此還原的操作一般是指當該返回地址指令將返回緩存器所儲存的返回位置存入堆棧之后,通常還是會去存取其它緩存器,故必須于該堆棧中額外還原存取其它緩存器對堆棧指針所造成的改變,如此一來方能正確地從堆棧的內(nèi)存中取出函數(shù)呼叫返回地址的值。此外,若是堆棧為不連續(xù)的堆棧幀(stack frame)所組成,亦需根據(jù)數(shù)據(jù)結(jié)構(gòu)找到下一個堆棧幀。最后再將程序指針設(shè)成指向還原后的堆棧指針所取出的返回位置,此操作亦即代表由目前函數(shù)跳躍回上一層函數(shù)的呼叫處,并重新開始遞歸計算。
于得出主函數(shù)的所有函數(shù)呼叫堆棧的地址后,便可依據(jù)一符號配置表(linker map)判斷出所儲存的程序指針所指向的指令地址所對應(yīng)的函數(shù)指令,也就是說可查出各函數(shù)地址所代表的函數(shù)名稱,如此一來便可在需要的時候找出執(zhí)行線程或程序(process)當下動態(tài)執(zhí)行時期的各函數(shù)呼叫堆棧與函數(shù)歷史路徑。
相較于現(xiàn)有的找出函數(shù)呼叫堆棧的方法,本發(fā)明的方法可在需要的時候以不增加任何額外的系統(tǒng)負擔下于計算機系統(tǒng)執(zhí)行函數(shù)時找出函數(shù)呼叫堆棧與其相對應(yīng)的函數(shù)名稱,而于不需要的時候,則完全沒有任何系統(tǒng)負擔,至于所找出的函數(shù)呼叫堆??捎靡詭椭治鲈撚嬎銠C系統(tǒng)死機時執(zhí)行線程的最后執(zhí)行狀態(tài),意即提供一有效率的分析死機問題或程序除錯的方法。
以上所述僅為本發(fā)明的較佳實施例,凡依本發(fā)明的權(quán)利要求所做的均等變化與修飾,皆應(yīng)屬本發(fā)明專利的涵蓋范圍。
權(quán)利要求
1.一種可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出一函數(shù)呼叫堆棧的方法,該方法包含有下列步驟(a)取得執(zhí)行該函數(shù)時所產(chǎn)生的一程序指針;(b)依據(jù)該程序指針取得相對應(yīng)的一指令;(c)檢測步驟(b)所取得的該指令是否與一返回地址指令相符;以及(d)當步驟(b)所取得的該指令與該返回地址指令相符時,儲存該程序指針所指向的一指令地址。
2.如權(quán)利要求1所述的方法,其還包含下列步驟(e)取得執(zhí)行該函數(shù)時所產(chǎn)生的一堆棧指針;(f)比較步驟(d)所儲存的該指令地址與該函數(shù)的一主函數(shù)名稱的一儲存地址;(g)當步驟(d)所儲存的該指令地址與該主函數(shù)名稱的該儲存地址不相符時,依據(jù)該堆棧指針取得相對應(yīng)的一返回地址;以及(h)將該程序指針設(shè)成由步驟(g)取得的該返回地址。
3.如權(quán)利要求1所述的方法,其于步驟(a)中該程序指針是于該計算機系統(tǒng)死機時由該計算機系統(tǒng)的一程序指針緩存器取得。
4.如權(quán)利要求1所述的方法,其于步驟(a)中該程序指針是于該計算機系統(tǒng)執(zhí)行上下文交換時由保留于一堆棧中的一程序指針暫存值所取得。
5.如權(quán)利要求1所述的方法,其還包含依據(jù)一符號配置表判斷出于步驟(d)中所儲存的該程序指針所指向的該指令地址所對應(yīng)的一函數(shù)指令。
6.一種可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出一函數(shù)呼叫堆棧的方法,該方法包含有下列步驟(a)取得執(zhí)行該函數(shù)時所產(chǎn)生的一程序指針與一堆棧指針;(b)依據(jù)該程序指針取得相對應(yīng)的一指令;(c)檢測步驟(b)所取得的該指令是否與一返回地址指令相符;(d)當步驟(b)所取得的該指令與該返回地址指令不相符時,將該程序指針設(shè)成指向于步驟(b)所取得的該指令的一前一指令;(e)檢測步驟(d)所取得的該前一指令是否與該返回地址指令相符;以及(f)當步驟(d)所取得的該前一指令與該返回地址指令相符時,儲存該程序指針于步驟(d)所指向的一指令地址。
7.如權(quán)利要求6所述的方法,其還包含下列步驟(g)當步驟(b)所取得的該指令與該返回地址指令不相符時,檢測于步驟(b)所取得的該指令是否與一堆棧指針操作指令相符;(h)當步驟(b)所取得的該指令與該堆棧指針操作指令相符時,復原步驟(b)所取得的該指令對該堆棧指針所做的改變。
8.如權(quán)利要求6所述的方法,其還包含下列步驟(i)比較步驟(f)所儲存的該指令地址與該函數(shù)的一主函數(shù)名稱的一儲存地址;(j)當步驟(f)所儲存的該指令地址與該主函數(shù)名稱的該儲存地址不相符時,依據(jù)該堆棧指針取得相對應(yīng)的該返回地址;以及(k)將于步驟(d)中所設(shè)定的該程序指針改設(shè)成由步驟(j)取得的該返回地址。
9.如權(quán)利要求6所述的方法,其于步驟(a)中該程序指針是于該計算機系統(tǒng)死機時由該計算機系統(tǒng)的一程序指針緩存器取得。
10.如權(quán)利要求6所述的方法,其于步驟(a)中該程序指針是于該計算機系統(tǒng)執(zhí)行上下文交換時由保留于一堆棧中的一程序指針暫存值所取得。
全文摘要
一種可于一計算機系統(tǒng)執(zhí)行一函數(shù)時找出一函數(shù)呼叫堆棧的方法,該方法包含有下列步驟(a)取得執(zhí)行該函數(shù)時所產(chǎn)生的一程序指針;(b)依據(jù)該程序指針取得相對應(yīng)的一指令;(c)檢測步驟(b)所取得的該指令是否與一返回地址指令相符;以及(d)當步驟(b)所取得的該指令與該返回地址指令相符時,儲存該程序指針所指向的一指令地址。
文檔編號G06F9/42GK1877518SQ20051007616
公開日2006年12月13日 申請日期2005年6月8日 優(yōu)先權(quán)日2005年6月8日
發(fā)明者林昂賢 申請人:明基電通股份有限公司