Examining copied stack contents

Martin Schröder gschroeder@onlinehome.de
Sat Jul 3 10:48:00 GMT 2010


Hello everyone.

I'm currently implementing a high-level debugger based on GDB for a 
coroutine-based simulation framework. The platform is GNU/Linux on x86.

That framework implements coroutines by using the C/C++ setjmp/longjmp 
instructions and by copying the call stack that is used by each 
coroutine to dynamically allocated memory on the heap. It's this latter 
aspect that gives me terrible headaches in GDB.

My question is simply: Is it possible to point GDB to the copied 
contents of the call stack and tell it to print out the information 
contained therein?

The documentation [1] does contain the following note:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
frame addr
f addr
Select the frame at address addr. This is useful mainly if the chaining 
of stack frames has been damaged by a bug, making it impossible for gdb 
to assign numbers properly to all frames. In addition, this can be 
useful when your program has multiple stacks and switches between them.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Additionally, the docs about the "info frame" command also say that it 
accepts memory addresses as arguments.


Unfortunately, this does not seem to work as well as I anticipated. I 
tried several versions of the GDB, from 6.8 to the newest 7.1, but they 
all exhibit the same issues.

When I stop the program directly after the call stack was saved, the 
situation presents itself as follows:

The stack pointer register is at 0xbfffeec0. The first two stack frames 
return the following data:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(gdb) info frame 0
Stack frame at 0xbfffeef0:
 eip = 0x805a972 in [CODE LINE]; saved eip 0x805a588
 called by frame at 0xbfffef30
 source language c++.
 Arglist at 0xbfffeee8, args: this=0x80b3238
 Locals at 0xbfffeee8, Previous frame's sp is 0xbfffeef0
 Saved registers:
  ebp at 0xbfffeee8, eip at 0xbfffeeec

(gdb) info frame 1
Stack frame at 0xbfffef30:
 eip = 0x805a588 in [CODE LINE]; saved eip 0x806b2a6
 called by frame at 0xbfffef70, caller of frame at 0xbfffeef0
 source language c++.
 Arglist at 0xbfffef28, args: this=0x80b2bd8
 Locals at 0xbfffef28, Previous frame's sp is 0xbfffef30
 Saved registers:
  ebx at 0xbfffef20, ebp at 0xbfffef28, esi at 0xbfffef24, eip at 
0xbfffef2c
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The program copied the whole stack (including a bit of safety margin) 
beginning with the address 0xbfffeedf to the address 0x80b39c8.

Now, if I tell GDB to print information about the stack frame located at 
0xbfffeef0, it does so correctly:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(gdb) info frame 0xbfffeef0
Stack frame at 0xbfffeef0:
 eip = 0x805a972 in [CODE LINE]; saved eip 0x805a588
 called by frame at 0xbfffef30
 source language c++.
 Arglist at 0xbfffeee8, args: this=0x80b3238
 Locals at 0xbfffeee8, Previous frame's sp is 0xbfffeef0
 Saved registers:
  ebp at 0xbfffeee8, eip at 0xbfffeeec

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

But if I point it to the exact copy of that frame, beginning with 
0x80b39d9, I get the following "fail safe" information that the GDB also 
prints when I point it to *any* arbitrary address:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(gdb) info frame 0x80b39d9
Stack frame at 0x80b39d9:
 eip = 0x0; saved eip 0x80b39c8
 called by frame at 0xbfffeef0
 Arglist at 0xbfffeebc, args:
 Locals at 0xbfffeebc, Previous frame's sp is 0xbfffeec4
 Saved registers:
  eip at 0xbfffeec0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

But if I examine the memory ranges, they are absolutely identical:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(gdb) x/8x 0x80b39d9
0x80b39d9: 0x080b3238 0x080b2bd8 0x080b2ca4 0x080b2ca4
0x80b39e9: 0x0021a73c 0x080b2bc8 0x080b3238 0x00000000
(gdb) x/8x 0xbfffeef0
0xbfffeef0: 0x080b3238 0x080b2bd8 0x080b2ca4 0x080b2ca4
0xbfffef00: 0x0021a73c 0x080b2bc8 0x080b3238 0x00000000
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Obviously, the GDB doesn't even attempt to interpret the given address 
as a stack frame. I am aware that the GDB needs debugging symbols to 
make any sense out of the stack (after all, the frame size depends on 
the actual call they represent); and also that the addresses inside the 
copied stack can't be followed, because they still point to the original 
memory addresses.

But I'm also aware that the GDB *should be* able to do what I want it to 
do. For one, the documentation explicitly mentions that the feature 
works with programs that utilize multiple stacks. Furthermore, the GDB 
is also able to debug Multi-Threaded programs, which also need to save 
the call stack to dynamic heap memory.



So, my question is: Is it possible to examine the copied stack? And if 
yes, what do I need to give to the GDB to allow it?



Thanks in advance,
    Martin Schröder.


[1] - http://sourceware.org/gdb/current/onlinedocs/gdb/Selection.html 



More information about the Gdb mailing list