This is documented behaviour of gdb
, and it is (supposed to be) configurable.
When I compile your code with gcc 4.7.2
(-O3
), I get the following assembly:
_main:
LFB1:
movl _i.2134(%rip), %eax
cmpl $10, %eax
jle L6
xorl %eax, %eax
ret
L6:
addl $1, %eax
pushq %rdx
LCFI0:
movl %eax, _i.2134(%rip)
xorl %eax, %eax
call _main ; <=== recursive call
popq %rcx
LCFI1:
movl $101, %esi
xorl %eax, %eax
leaq LC0(%rip), %rdi
jmp _printf
LFE1:
This refutes the hypothesis that the recursive call is optimized away.
Now, if I load the binary into gdb
and set a breakpoint on main()
, it gets hit repeatedly. When I examine the registers, %rsp
is getting decremented with each call, so there are clearly stack frames associated with each main()
.
Nonetheless, bt
only shows a single frame:
(gdb) bt
#0 0x0000000100000f50 in main ()
(In this case, I know there are three main()
frames and not just one.)
I therefore conclude that this has something to do with gdb
itself.
Upon further investigation, it turns out that this behaviour is documented:
Most programs have a standard user entry point—a place where system libraries and startup code transition into user code. For C this is main
. When gdb
finds the entry function in a backtrace it will terminate the backtrace, to avoid tracing into highly system-specific (and generally uninteresting) code.
When I set the following in gdb
:
set backtrace past-main on
set backtrace past-entry on
it starts showing two main()
frames. For some reason, it's still not going any deeper.