gdb 6.3 中多个堆栈之间的切换

发布于 2024-08-04 13:44:01 字数 157 浏览 8 评论 0原文

程序中有两个堆栈:一个是由操作系统创建的,第二个是由程序本身创建的,用于运行一些代码。

当程序在第二个堆栈中崩溃时,我想切换到gdb中的主堆栈并查看回溯。是否可以?

我尝试将 rsp 保存到变量并在崩溃后更改它,但生成的回溯不正确。我认为 gdb 无法区分堆栈中的帧。

There are two stacks in the program: one is created by OS and the second is created by program itself to run some code with it.

When the program crashes in the second stack, I want to switch to the main stack in gdb and see the backtrace. Is it possible?

I tried to save the rsp to a variable and change it after the crash, but the resulting backtrace was not right. I think gdb cannot differentiate frames in stack.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

悍妇囚夫 2024-08-11 13:44:01

我认为您的方法是正确的,即恢复一些寄存器值以将 GDB 指向正确的堆栈。很难知道您的应用程序在没有任何源代码的情况下如何工作,但对于下面非常简单的 make/swapcontext 应用程序来说:

#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>

ucontext_t a_ctx, b_ctx;
char b_stack[4096];

void a2() {
    swapcontext(&a_ctx, &b_ctx);
}

void a1() { a2(); }

void b2() {
    printf("pausing");
    pause();  // interrupt here in the debugger
}

void b1() { b2(); }

int main() {
    getcontext(&b_ctx);
    b_ctx.uc_stack.ss_sp = b_stack;
    b_ctx.uc_stack.ss_size = sizeof(b_stack);
    makecontext(&b_ctx, b1, 0);
    a1();
}

set $... 命令可以将寄存器设置为其保存的值GDB 此时 bt 将找到旧堆栈。

(gdb) bt
#0  0x00007ffff7e8cc23 in __libc_pause () at ../sysdeps/unix/sysv/linux/pause.c:29
#1  0x00005555555551c7 in b2 () at src/so.c:16
#2  0x00005555555551d8 in b1 () at src/so.c:19
#3  0x00007ffff7e13a60 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x0000000000000000 in ?? ()
(gdb) set $rbp = a_ctx.uc_mcontext.gregs[REG_RBP]
(gdb) set $rip = a_ctx.uc_mcontext.gregs[REG_RIP]
(gdb) set $rsp = a_ctx.uc_mcontext.gregs[REG_RSP]
(gdb) bt
#0  a2 () at src/so.c:10
#1  0x00005555555551a7 in a1 () at src/so.c:12
#2  0x0000555555555234 in main () at src/so.c:26

I think you were right with the approach of just restoring some register values to point GDB at the right stack. It's difficult to know how your application may have worked without any of its source, but for the very simple make/swapcontext application below:

#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>

ucontext_t a_ctx, b_ctx;
char b_stack[4096];

void a2() {
    swapcontext(&a_ctx, &b_ctx);
}

void a1() { a2(); }

void b2() {
    printf("pausing");
    pause();  // interrupt here in the debugger
}

void b1() { b2(); }

int main() {
    getcontext(&b_ctx);
    b_ctx.uc_stack.ss_sp = b_stack;
    b_ctx.uc_stack.ss_size = sizeof(b_stack);
    makecontext(&b_ctx, b1, 0);
    a1();
}

The set $... command can set registers to their saved values from within GDB at which point bt will find the old stack.

(gdb) bt
#0  0x00007ffff7e8cc23 in __libc_pause () at ../sysdeps/unix/sysv/linux/pause.c:29
#1  0x00005555555551c7 in b2 () at src/so.c:16
#2  0x00005555555551d8 in b1 () at src/so.c:19
#3  0x00007ffff7e13a60 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x0000000000000000 in ?? ()
(gdb) set $rbp = a_ctx.uc_mcontext.gregs[REG_RBP]
(gdb) set $rip = a_ctx.uc_mcontext.gregs[REG_RIP]
(gdb) set $rsp = a_ctx.uc_mcontext.gregs[REG_RSP]
(gdb) bt
#0  a2 () at src/so.c:10
#1  0x00005555555551a7 in a1 () at src/so.c:12
#2  0x0000555555555234 in main () at src/so.c:26
蛮可爱 2024-08-11 13:44:01

如果您有两个线程和两个堆栈,您可以通过“信息线程”查询线程。
在知道要查看哪个线程的堆栈后,使用“thread”命令选择它。将线程号放在命令后面。

那么你只需要通过'bt'查询堆栈即可

If you have two threads with two stacks you can query the thread by 'info threads'.
After you know which thread's stack you want to see select it with the 'thread' command. Put the number of the thread after the command.

Then you only need to query the stack by 'bt'

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文