我有一個傳統GDB命令腳本,用於根據Python 2.6源代碼附帶的GDB腳本獲取Python堆棧跟蹤(SO不允許超鏈接,但這裏是網址:http://#%20http://svn.python.org/view/*checkout*/python/branches/release26-maint/Misc/
)傳統GDB腳本中堆棧跟蹤的停止條件
該腳本有一個while循環,基於退出的程序計數器有一個相當脆弱的檢查,這可能僅適用於直接運行Python的情況(如註釋中的原始代碼所述)如果解釋器是從C/C++應用程序啓動的話,則不行。
現有while循環是這樣的:
while $pc < Py_Main || $pc > Py_GetArgcArgv
# ...
# code for extracting Python stack from local vars in relevant frames
# of C stack
# ...
up-silently 1
因爲我要調試的程序,對Py_Main
和Py_GetArgcArgv
支票都不會很好地工作,所以我在尋找一個循環條件當它達到main
時,它將評估爲false。
所以我一直在玩弄使用程序計數器,幀指針和堆棧指針的想法,因爲如果up-silently
失敗,它們將具有與先前相同的值,這意味着我在堆棧頂部,像這樣:
set $oldpc = -1
set $oldfp = -1
set $oldsp = -1
while !($oldpc == $pc && $oldfp == $fp && $oldsp == $sp)
# ...
# code for extracting Python stack from local vars in relevant frames
# of C stack
# ...
set $oldpc = $pc
set $oldsp = $sp
set $oldfp = $fp
up-silently 1
我認爲這應該做的伎倆,初步檢查表明它工作正常。不過,我並不太熟悉編譯器可以做的各種優化,我擔心可能存在某些角落的情況,他們可能有效地在堆棧中的某處處於相同位置。
看起來$fp
對於幀指針已被優化掉的呼叫可以爲零(例如,通過使用GCC編譯使用-g -O3
)。我也不確定$pc
是否可以依賴於不同,特別是如果遞歸調用正在發生。我希望$sp
會有所不同,雖然仍然有待處理的堆棧,但是我有一個模糊的懷疑,即與tail recursion相關的優化可能導致$ sp相同。
任何意見將不勝感激。
具體的問題:
問題1:是否有遺留(非Python)的GDB腳本更好的方式來弄清楚,如果你在堆棧的頂部?
問題2:將我的$sp
,$pc
和$fp
假設持有多數或全部優化方案真的嗎?