Re: Using frame to switch stacks

Simon Marchi <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
On 2018-02-28 13:05, Niklas Reiners wrote:
> Hello everyone,
> 
> I'm debugging a library which uses multiple stacks. The documentation
> states that frame / select-frame can be used for this. However I can
> only seem to get it to work with stack and pc address of frames that
> are with in the current stack. Parameter pairs outside the stack
> (composing another stack) yield an invalid frame.
> 
> To show this behavior and how I invoke frame I prepared a minimal
> example, containing a program with two stacks and a python script for
> gdb. It can be found here:
> https://github.com/NotAC0W/gdb-switch-stacks
> 
> The repository also contains a more detailed description of the
> program and the output of an example run.
> 
> Am I using frame correctly or should I be using different commands?
> 
> Thank you very much for your help,
> 
> Niklas

Hi Niklas,

This is a late response, but I guess it's better late than never.  I 
only took a quick look so excuse me if I a missing some obvious things.

When switching from stack 1 to stack 2 in your application, you save the 
registers of the current frame of stack 1 to an application-defined 
area, much like an OS would do (it would store them in a task 
structure).  When the crash happens, the values in the "physical" 
registers are those of the current frame of stack 2.

When you instruct GDB to manually switch to a stack frame with a given 
sp and pc, it can create a frame with those values.  But GDB probably 
still reads the register values of the current Linux thread (those of 
stack 2, which was the current one at the time of the crash), because 
that's the level of awareness it has.  To get to the upper frames, it 
would need to read the registers associated to stack 1, which are 
currently stashed away.

For example, according to the DWARF info, finding the value of rsp for 
the frame of "main" (also the return address) is "rsp of setup's frame + 
48".  But if GDB does that computation using the rsp from the other 
stack, it will certainly give something that doesn't make sense.

If you try to set the registers directly, you can probably make GDB do 
what you want:

(gdb) bt
#0  asmfoo2 () at functions.S:14
#1  0x000055555555476c in asmfoo () at functions.S:31
#2  0x00005555555546b4 in new_world () at main.c:14
#3  0x0000000000000000 in ?? ()
(gdb) set $rip = 0x555555554727
(gdb) set $rsp = 0x7fffffffd8e0
(gdb) bt
#0  setup () at main.c:28
#1  0x0000555555554743 in main (argc=1, argv=0x7fffffffda08) at 
main.c:31

You would need to restore all the registers like this to be sure to have 
coherent variable values.

I'm not sure in what situations the "frame <stack-addr> <code-addr>" 
command is useful, maybe someone else can tell.

Simon
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.