2014-04-04 33 views
3

我有一个传统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_MainPy_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假设持有多数或全部优化方案真的吗?

回答

1

所以我没有回答问题1,但我想我可以部分回答问题2

Tail recursion确实会重用现有的堆栈指针和帧指针。这意味着堆栈跟踪的意思是多次调用相同优化的尾递归函数只会在一次出现,因为(显然)堆栈指针正在被重用(并且没有新的堆栈或帧指针被推送)。

这似乎意味着您可以检查$ sp的以前和当前值停止条件。不幸的是,$ sp值在堆栈中间可能是相同的。这似乎发生在某些函数调用已被优化掉的情况下。

因此,我在我的问题中提出的停止条件可能相当脆弱,即使它适用于几个现实世界的例子。