背景:我正在使用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)检测堆栈结束。