x86ManualBacktrace

This tutorial will show you how to manually rebuild a backtrace with GDB on x86 using the stack frame pointer and current instruction pointer.

Consider the following gdb backtrace: (gdb) bt
 * 1) 0 0x0041d402 in ??
 * 2) 1 0x00aa930e in ??  at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/lowlevellock.S:57 from /lib/tls/libc.so.6
 * 3) 2 0x00afd820 in ??  from /lib/tls/libc.so.6
 * 4) 3 0x00afbff4 in ??  from /lib/tls/libc.so.6
 * 5) 4 0x00000028 in ??
 * 6) 5 0x00a3b9bf in ??  from /lib/tls/libc.so.6
 * 7) 6 0x00020460 in ??
 * 8) 7 0xb7801ba0 in ??
 * 9) 8 0xb78004e8 in ??
 * 10) 9 0x001a312b in _tr_init  from /usr/lib/libz.so.1
 * 11) 10 0x001a1aa9 in deflateReset from /usr/lib/libz.so.1
 * 12) 11 0x00000000 in ??

It's pretty clear that this is corrupted, evidence the following field:
 * 1) 4 0x00000028 in ??

Get the register information for the process: (gdb) info reg eax           0xfffffffc       -4 ecx           0x0      0 edx           0x2      2 ebx           0xafd820 11524128 esp           0xbf9ef304       0xbf9ef304 ebp           0xbf9ef358       0xbf9ef358 esi           0x0      0 edi           0xa85e980        176548224 eip           0x41d402 0x41d402 eflags        0x202    514 cs            0x73     115 ss            0x7b     123 ds            0x7b     123 es            0x7b     123 fs            0x0      0 gs            0x33     51

On x86: %esp : top of the stack %ebp : current stack frame %eip : Instruction pointer

Stack Frame Layout for x86: --- Low addresses --- 0(%esp) | top of the stack frame (this is the same as -n(%ebp)) -|- -n(%ebp) | variable sized stack frame -4(%ebp) | varied 0(%ebp) | previous stack frame address 4(%ebp) | return address --- High addresses

Color Key: blue : Current Stack frame address (%ebp) green : Higher stack frame addresses purple : Previous %ebp pointers held at by each stack frame (back chain pointer) red : Return address, i.e. calling function

Using the current stack frame address from %ebp dump the stack above it:

(gdb) info reg ebp ebp           0xbf9ef358        0xbf9ef358

(gdb) x/2048h * 0xbf9ef358 0xbf9ef358 : 0xbf9ef388 0x00d94cf7  0x0a85e988  0x00000024 0xbf9ef368: 0xbf9ef388 0x00d94d8a  0x00000000  0x05000000 0xbf9ef378: 0x00000000 0x0a85e994  0x00000000  0x0a86dacc 0xbf9ef388 : 0xbf9ef418 0x00c331ab  0x0a85e994  0x00000015 0xbf9ef398: 0x00000000 0xb7800000  0x0992f188  0xbf9ef40c ... 0xbf9ef408: 0xbf9ef428 0x097150e0  0x0992f26c  0xbf9ef6e0 0xbf9ef418 : 0xbf9ef488 0x00dc7cb9  0x00000002  0x0a86dacc 0xbf9ef428: 0x00000000 0x00000000  0x00000001  0x00000016 0xbf9ef438: 0xbf9ef488 0x00dd7888  0x0a9f8e74  0xbf9ef6e0 0xbf9ef448: 0xce1cf0f4 0xbf9ef6e0  0x0992f26c  0x00000009 0xbf9ef458: 0xbf9ef488 0x00dcc28b  0x09718000  0x00004540 0xbf9ef468: 0x00000001 0xbf9ef6e8  0x0a8bb624  0x00000000 0xbf9ef478: 0x0992f26c 0xbf9ef6e4  0x09932570  0xbf9ef6e0 0xbf9ef488 : 0xbf9ef728 0x00dc76cd  0xbf9ef6e0  0xffffffff 0xbf9ef498: 0x0a1e8bf8 0x00000000  0x0a86e060  0x0a8b8428 ... 0xbf9ef718: 0xbf9ef8f0 0x00000000  0xbf9ef7c0  0xbf9ef8f0 0xbf9ef728 : 0xbf9ef788 0x00dc78ba  0x09932570  0x00000000 0xbf9ef738: 0xbf9ef758 0x00da3a25  0xb780047c  0x0a7f1408 0xbf9ef748: 0x4373f45a 0x0a7f13fc  0x0aa2be2c  0xbf9ef8f0 0xbf9ef758: 0xbf9ef788 0x00dfbc5b  0x0a7f13fc  0x017f13fc 0xbf9ef768: 0x00000001 0x00000000  0x00000000  0xbf9efac0 0xbf9ef778: 0x09931fbc 0xbf9ef8f4  0x00000000  0xbf9ef8f0 0xbf9ef788 : 0xbf9ef938 0x00dc76cd  0xbf9ef8f0  0x00000000 0xbf9ef798: 0x00000000 0x00000000  0x0aa2bf10  0x0aaf9800 ... 0xbf9ef928: 0xbf9ef9b0 0x00000000  0x00000000  0xbf9e6ad0 0xbf9ef938 : 0xbf9efa08 0x00da08f3  0x0a181c68  0x0aa47ef4 0xbf9ef948: 0x00000010 0xbf9ef9b8  0x00000000  0x00000000 ... 0xbf9ef9f8: 0xbf9f0470 0xbf9efac8  0xbf9efac4  0x00000005 0xbf9efa08 : 0xbf9efa58 0x00da14ec  0xbf9efa20  0x00000000 0xbf9efa18: 0x00000000 0x00000000  0x00000024  0x09718000 0xbf9efa28: 0x09ebc944 0x00000000  0xbf9efac0  0x00000002 0xbf9efa38: 0xbf9efac8 0x00000000  0x00000001  0x00000000 0xbf9efa48: 0x00000000 0x00000000  0x00000000  0x00000000 0xbf9efa58 : 0xbf9efb28 0x00d7d5e0  0x09718000  0x00000000 0xbf9efa68: 0x09ebc944 0xbf9efac0  0x00000002  0xbf9efac8 ... 0xbf9efb18: 0x00000000 0x00000001  0xbf9f0110  0xbf9effd0 0xbf9efb28 : 0xbf9efb48 0x00d7d713  0x00000001  0x00000000 0xbf9efb38: 0x00000000 0x00000000  0x00d6f7bc  0xbf9f0070 0xbf9efb48 : 0xbf9f01c8 0x00d6fb20  0x00000001  0x01031c20 0xbf9efb58: 0x0000009c 0xbf9f0110  0x00afbff4  0x0a117a64 ... 0xbf9f01c8 : 0x00000000 0x00dfab20 NOTE: The previous memory dump has been converted to 'big endian' for the point of clarification. For brevity's sake unnecessary parts of the stack frames have been left out and replaced with "..."

Using this stack dump we know that the stack frame address in the %ebp register is the stack frame for the current instruction in the %eip register (unless this was a leaf function which didn't stack a frame but that's irrelevant for this discussion). Using the %ebp and %eip registers as a starting point we can build the first line in our backtrace rebuild:

StackFrame | Instruction Pointer   | Pointer 0xbf9ef358 | 0x0041d402

When program control branches to a new function a stack frame is stacked and the callee function's last address is stored at the new frame's address %ebp + 4 (i.e. the last memory address in the callee's stack frame which is +4 from the current stack frame at %ebp). In order to get the caller's stack frame and instruction pointer just look at %ebp and %ebp+4:

In the stack find the memory at the stack frame in %ebp and the one at %ebp+4 (which will hold the callee's instruction pointer).

0xbf9ef358 : 0xbf9ef388 0x00d94cf7

So using the address at 0xbf9ef358 and 0xbf9ef35c which is 0xbf9ef388 and 0x00d94cf7 continue to build our list: StackFrame | Instruction Pointer   | Pointer

0xbf9ef358 | 0x0041d402 0xbf9ef388 | 0x00d94cf7 Continue by looking at the next stack frame address 0xbf9ef388:

0xbf9ef388 : 0xbf9ef418 0x00c331ab

Keep doing this until we have a full back trace. You'll know you've reached the bottom of the stack when the previous stack frame pointer is 0x00000000.

0xbf9f01c8 : 0x00000000 0x00dfab20

Here's a complete manually rebuilt stack frame: StackFrame | Instruction Pointer   | Pointer

0xbf9ef358 | 0x0041d402 0xbf9ef388 | 0x00d94cf7 0xbf9ef418 | 0x00c331ab 0xbf9ef488 | 0x00dc7cb9 0xbf9ef728 | 0x00dc76cd 0xbf9ef788 | 0x00dc78ba 0xbf9ef938 | 0x00dc76cd 0xbf9efa08 | 0x00da08f3 0xbf9efa58 | 0x00da14ec 0xbf9efb28 | 0x00d7d5e0 0xbf9efb48 | 0x00d7d713 0xbf9f01c8 | 0x00d6fb20 0x00000000 | 0x00dfab20