旧版 GDB 脚本中堆栈跟踪的停止条件
Stop condition for stack tracing in legacy GDB script
>我有一个传统的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_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
我认为这应该可以解决问题,初步检查表明它工作正常。但是,我对编译器可以做的优化类型不太熟悉,我担心可能存在一些极端情况,它们可能在堆栈中间的某个地方有效相同。
对于帧指针已优化的调用(例如,通过使用 -g -O3
使用 GCC 进行编译),看起来$fp
可以为零。我也不确定是否可以依靠$pc
来有所不同,尤其是在发生递归调用的情况下。我希望$sp
仍然有有效的堆栈需要处理时会有所不同,但我有一个模糊的怀疑,与尾递归相关的优化可能会导致$sp相同。
任何建议将不胜感激。
具体问题:
问题 1:在遗留(非 Python)GDB 脚本中是否有更好的方法来确定您是否处于堆栈的顶部?
问题 2:我对$sp
、$pc
和$fp
的假设是否适用于大多数或所有优化方案?
对问题 1 没有答案,但我想我可以部分回答问题 2。
尾递归确实会重用现有的堆栈指针和帧指针。这对于堆栈跟踪意味着对同一优化的尾递归函数的多次调用只会在 GDB 中显示一次,因为(显然)堆栈指针正在被重用(并且没有推送新的堆栈或帧指针)。
这似乎意味着您可以根据以前和当前的 $sp 值检查止损条件。遗憾的是,堆栈中间的$sp值可能相同。当某些函数调用被优化掉时,似乎会发生这种情况。
因此,我在问题中提出的停止条件可能相当脆弱,即使它适用于几个现实世界的例子。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 在没有太多条件句的情况下,我如何避免被零除
- 基于多个条件处理地图中的所有元素
- 条件constexpr函数
- 无论条件是否为true,if总是在c++中执行
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 基于模板值的条件变量
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 光线跟踪器灯光反射错误
- 人脸跟踪arduino代码的优化
- 将按位if条件转换为普通if条件
- 条件断点在不应该触发时触发
- 为什么简单的算术减法在"if"条件下不起作用?
- 跟踪滚动条上的鼠标事件
- 如何在for循环中包含两个索引值的测试条件
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 我提出什么条件才能再加5%的折扣
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 即使没有满足他们的条件,我也无法通过一些 do-while 循环
- 旧版 GDB 脚本中堆栈跟踪的停止条件