遗留 GDB 脚本中堆栈跟踪的停止条件

Rob*_*Rob 5 c c++ python gcc gdb

我有获得基于一个GDB的Python脚本的堆栈跟踪附带的Python 2.6源的传统GDB命令脚本(SO不允许超链接,但这里的网址: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
Run Code Online (Sandbox Code Playgroud)

对于我想要调试的程序,检查Py_MainPy_GetArgcArgv不会很好地工作,所以我正在寻找一个循环条件,当它到达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
Run Code Online (Sandbox Code Playgroud)

我认为这应该可以解决问题,初步检查表明它工作正常。但是,我对编译器可以执行的各种优化并不太熟悉,我担心可能会出现极端情况,它们可能在堆栈中间的某处有效相同。

$fp对于帧指针已被优化掉的调用(例如,通过-g -O3使用 GCC进行编译),它看起来可能为零。我也不确定是否$pc可以依赖于不同,特别是如果发生递归调用。我希望$sp在仍有要处理的有效堆栈时会有所不同,但我有一个模糊的怀疑,即与尾递归相关的优化可能会导致 $sp 相同。

任何建议将不胜感激。

具体问题:

问题 1:在遗留(非 Python)GDB 脚本中是否有更好的方法来确定您是否处于堆栈顶部?

问题2:请问我的假设$sp$pc$fp持有多数或全部优化方案真的吗?

Rob*_*Rob 2

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

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

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

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