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检测堆栈的结束,并且无论上下文中初始函数的名称如何,它都可以工作。