6

背景:我正在使用getcontext(3)/ makecontext(3)/ setcontext(3)( ucontext.h; SUSv2, POSIX.1-2001) 系列函数分配我自己的机器上下文和堆栈。

当我使用 gdb(版本 6.1.1)检查堆栈时,线程位于我分配的这些上下文之一中,似乎 gdb 不知道堆栈的末端(逻辑底部)在哪里。例如,这是来自 x86 FreeBSD 的堆栈:

#0  0x2872d79f in poll () from /lib/libc.so.7
#1  0x28646e23 in poll () from /lib/libthr.so.3
#2  0x2869b267 in fdtask (task=0x28a3dc40, v=0x0) at fd.c:58
#3  0x2869c8dc in taskstart (y=681827392, x=0) at task.c:58
#4  0x00000000 in ?? ()
#5  0x28a3dc40 in ?? ()
#6  0x00000000 in ?? ()
#7  0x00000000 in ?? ()
…
#65 0x00000000 in ?? ()
…

(是的,这是建立在Russ Cox 的 libtask 库之上的。)

此上下文的执行从taskstart函数开始,但 GDB 似乎无法确定它应该停止尝试读取堆栈,即使它在该帧中遇到了 NULL 的返回地址。

我的问题是:我能做些什么(通过以某种方式格式化堆栈,或设置寄存器等)来帮助 GDB 了解堆栈的顶部在哪里?谢谢。

编辑:结论:gdb 6.1.1 检测堆栈末尾的一种方法似乎是检查存储的帧指针是否为 NULL;我通过修改 x86 和 amd64makecontext(2)函数以在初始化新上下文时将 ebp 或 rbp 重置为零来解决我的用例问题。(在这种情况下,我不关心其他架构。)这个问题在 gdb 7.1 中消失了;据推测,gdb 7.1 能够通过其他方式(例如 debuginfo)检测堆栈结束。

4

2 回答 2

2

如果 GDB 使用帧指针来展开堆栈(DWARF2 之前的方法),它会在到达空帧指针时停止,我相信。对于 DWARF2,事情要复杂得多,因为“帧指针”是由堆栈指针与指令指针和当前指令的 DWARF2 帧偏移信息相结合隐式确定的,但基本上效果是相同的。不确定这些天使用的是哪个 FreeBSD。

于 2012-04-05T16:32:56.630 回答
0

gdb文档说,它停止列出回溯帧的一种方法是在main().

请参阅第 6251 行gdb/doc/gdb.textinfo 中的ftp://sourceware.org/pub/gdb/snapshots/current/gdb-7.4.50.20120405.tar.bz2@cindex backtrace beyond @code{main} function

于 2012-04-05T19:05:51.020 回答