'Switching between multiple stacks in gdb 6.3

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.



Solution 1:[1]

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

Solution 2:[2]

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'

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 GKFX
Solution 2 Vereb