背景:我分配我自己的机器环境和堆栈与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 ?? ()
…
Run Code Online (Sandbox Code Playgroud)
(是的,这是建立在Russ Cox的libtask库之上的.)
这个上下文的执行从taskstart函数开始,但似乎GDB无法弄清楚它应该停止尝试读取堆栈,即使它在该帧中遇到NULL的返回地址.
我的问题是:我能做些什么(通过以某种方式格式化堆栈,或设置寄存器,任何东西)来帮助GDB了解堆栈顶部的位置?谢谢.
编辑:结论:似乎gdb 6.1.1检测到堆栈结束的一种方法是检查存储的帧指针是否为NULL; 我通过修改x86和amd64 makecontext(2)函数来修复我的用例问题,以便在初始化新上下文时将ebp或rbp重置为零.(在这种情况下,我不关心其他架构.)这个问题随着gdb 7.1而消失; 据推测,gdb 7.1能够通过其他方式检测堆栈的结束,例如debuginfo.
我相信,如果 GDB 使用帧指针展开堆栈(DWARF2 之前的方法),它会在到达空帧指针时停止。对于 DWARF2,事情要复杂得多,因为“帧指针”是由堆栈指针与指令指针和当前指令的 DWARF2 帧偏移信息相结合隐式确定的,但本质上效果是相同的。现在不知道使用哪个 FreeBSD。