C GDB如何确定堆栈的底部?

C GDB如何确定堆栈的底部?,c,gdb,C,Gdb,背景:我正在使用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 i

背景:我正在使用
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 ?? ()
…
(是的,这是建在顶部的。)

此上下文的执行从
taskstart
函数开始,但GDB似乎无法判断是否应该停止尝试读取堆栈,即使它在该帧中的返回地址为NULL

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


编辑:结论:gdb 6.1.1检测堆栈结束的一种方法是检查存储的帧指针是否为空;我通过修改x86和amd64
makecontext(2)
函数,在初始化新上下文时将ebp或rbp重置为零,解决了用例的问题。(在本例中,我不关心其他架构。)GDB7.1解决了这个问题;大概gdb 7.1能够通过一些其他方法检测堆栈的末尾,比如debuginfo。

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

gdb文档说,它停止列出回溯帧的一种方法是在
main()
的返回地址之后


请参见gdb/doc/gdb.textinfo中的
@cindex backtrace beyond@code{main}函数
第6251行。

这听起来像是gdb开发者邮件列表上的一个问题。这是相当古老的FreeBSD(~7.2,我相信)。谢谢查看
taskstart
的反汇编,帧指针保存在条目上。我添加了将创建的上下文的ebp设置为零的代码,GDB6.1.1的堆栈跟踪看起来是正确的。再次感谢!当然,但这在我的情况下并没有特别的帮助,因为这些上下文都不是从
main
@ConradMeyer开始的:如何命名调用
taskstart
的函数,比如
main()
\u main()
\u main()
?不调用
taskstart
。libtask调度程序将用户空间上下文交换到从
taskstart
开始的上下文中。我想
taskstart
可以重命名为
main
\u main
或其他任何名称,但这似乎是一个巨大的难题。将帧指针初始化为零似乎足以让gdb6检测堆栈的结束,并且无论上下文中初始函数的名称如何,它都可以工作。