Josh Carter Workbench
Books

Investigating The Stack With the Debugger

This post was an early draft of material for my book The New Programmer’s Survival Manual, now published by Pragmatic Programmers.

This section assumes I already covered some basics of GDB earlier in the book, which I plan to do.

Once you have some concept of registers and the stack, it’s time to play. Take our original example and save this as stack.c:

int main()
{
    int i = 0x11223344;
    char s[4];
    s[0] = 'f';
    s[1] = 'o';
    s[2] = 'o';
    s[3] = '\\0';
    return 0;
}

Compile this with GCC:

gcc -m32 -S stack.c

The -m32 option tells it to generate 32-bit code (you can investigate 64 bit on your own) and the -S option tells GCC to compile to assembly rather than machine code. This generates stack.s which you can look at in a text editor.

Now assemble the code:

gcc -m32 -gstabs -o stack stack.s

Again we need to specify 32 bit, and the -gstabs option tells GCC to include debugging info for GDB. This generates stack, which you can now run in GDB:

gdb stack

Try list main (or simply l main) first, and you’ll see the beginning of main():

(gdb) l main
1		.text
2	.globl _main
3	_main:
4		pushl	%ebp
5		movl	%esp, %ebp
6		subl	$24, %esp
[...]

Looks familiar, right? Set a breakpoint at main (break main or b main) then run the program (run or r). Now you can single-step (step or s) and follow along with the program putting stuff on the stack. Once you’ve stepped past the subl ..., %esp instruction, investigate the stack and base pointers:

(gdb) p $esp
$1 = (void *) 0xbffff7a0
(gdb) p $ebp
$2 = (void *) 0xbffff7b8

Note that registers are displayed with a percent sign in front (like %esp) but GDB makes you put a dollar sign in front (like $esp).

On my computer, GCC makes a stack frame of 24 bytes (subl $24, %esp), and I can verify this with GDB:

(gdb) p $ebp - $esp
$3 = 24

Now let’s investigate some items on the stack. Keep stepping until you see the MOV instruction:

7		movl	$287454020, -12(%ebp)

Step one more time to execute the instruction. Since GCC decided to move 0x11223344 to the base pointer minus 12, I can look at that using the x command:

(gdb) x/w $ebp - 12
0xbffff7ac:	0x11223344

Remember, x is used to eXamine the contents of memory. Where p $ebp just prints the value of EBP, x $ebp prints the memory that EBP points to. In this case, I specify x/w to explicitly tell GDB that I want to examine a “word” of memory. I say “word” in quotes because “word” means different things depending on who you ask; in the Intel 8086 universe it means 2 bytes. In GDB universe it means 4 bytes.

Go ahead and step through the program and investigate the other stuff on the stack. We’ll get to a beefier example in just a moment. Before executing the LEAVE instruction, however, examine that integer one more time using ‘x/4b’ just for grins:

(gdb) x/4b $ebp - 12
0xbffff7ac:	0x44	0x33	0x22	0x11

Notice the four bytes appear to be backwards? Mull over that one for a while. We’ll revisit it later.

Filed under: Books Pragprowrimo 2009