停止旧版GDB脚本中的堆栈跟踪条件

时间:2014-04-04 07:55:37

标签: python c++ c gcc gdb

我有一个遗留的GDB命令脚本,用于根据Python 2.6源代码附带的GDB脚本获取Python堆栈跟踪(SO不允许使用超链接,但这里是URL:http://#%20http://svn.python.org/view/*checkout*/python/branches/release26-maint/Misc/

该脚本有一个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的检查不会很好地工作,所以我正在寻找一个循环条件,当它获得时将评估为false到main

所以我一直在考虑使用程序计数器,帧指针和堆栈指针的想法,因为如果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 个答案:

答案 0 :(得分:2)

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

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

这似乎暗示您可以检查停止条件的$ sp的先前值和当前值。不幸的是,$ sp值在堆栈中间可以是相同的。当一些函数调用被优化掉时,似乎会发生这种情况。

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