[rfc] Teach i386 prologue reader about _alloca and __main
Pedro Alves
pedro_alves@portugalmail.pt
Sat Oct 13 20:26:00 GMT 2007
Hi guys,
This is a new take on solving the issue described here:
http://www.sourceware.org/ml/gdb/2006-11/msg00140.html
On a nutshell, breaking on main is broken on Cygwin, and
all targets where gcc emits a call to __main in main,
right after the prologue. __main is responsible for calling
the c++ constructors of global objects, and registering the
destructors of the same objects to run at exit. This call
is inserted on targets that don't have an .init section.
http://sources.redhat.com/ml/gdb-patches/2006-12/msg00140.html
My first aproach tackled it by making i386 skip the prologue
using the debug info, and teaching gcc to put the line marker
that marks the end of the prologue after the __main call.
http://sources.redhat.com/ml/gdb-patches/2006-12/msg00140.html
http://gcc.gnu.org/ml/gcc-patches/2006-12/msg00633.html
Mark didn't like it, because:
"The last time I tried using sals on i386, I simply encountered too
many cases where the line number information couldn't be trusted and
putting a breakpoint on a function that was defenitely called never
hit."
http://sources.redhat.com/ml/gdb-patches/2006-12/msg00375.html
To which Daniel responded:
"Yeah. That's definitely the biggest risk.
I think the first step, for Pedro's specific problem, should be
to recognize the call to __main as special and skippable. We can
play with sals later."
The attached patch does that - make __main skippable. This version
doesn't need any gcc changes.
There are a few complications, though. On NT, the stack must be grown
page wise, by touching a guard page. Because of that we often see calls
to _alloca AKA __chkstk (gcc/config/i386/cygwin.asm) in the prologue:
http://cygwin.com/ml/cygwin-developers/2001-10/msg00108.html
http://cygwin.com/ml/cygwin-developers/2001-10/msg00118.html
There is another problem with the prologue analysing, which is visible
on i386 targets using stabs debug info on gcc >= 4.1.0.
eg:
int main (int argc, char **argv)
{
On stabs, the debugger only knows that argc is the first parameter to
the function and that its type is int. It is up to the debugger
to know how to extract it from the frame.
Gcc >= 4.1 can put code in the prologue to realign the stack pointer.
In that case, the frame base will not be the same as the incoming args
address, so gdb prints garbage for the arguments:
main (argc=2280856, argv=0x61006198) at main.c:8
The prologue analyser already knows about a saved_sp, and that it
can be extracted from %ecx, but on cygwin, %ecx will be clobbered
by the __main call, before we get to user code:
int
main (int argc, char ** argv)
{
401050: 8d 4c 24 04 lea 0x4(%esp),%ecx
401054: 83 e4 f0 and $0xfffffff0,%esp
401057: ff 71 fc pushl 0xfffffffc(%ecx)
40105a: 55 push %ebp
40105b: 89 e5 mov %esp,%ebp
40105d: 53 push %ebx
40105e: 51 push %ecx
40105f: b8 20 40 00 00 mov $0x4020,%eax
401064: e8 d7 00 00 00 call 401140 <___chkstk>
401069: 89 cb mov %ecx,%ebx
40106b: e8 60 01 00 00 call 4011d0 <___main>
char asdf[0x4001];
printf ("argc %d\n", argc);
401070: 8b 03 mov (%ebx),%eax
Luckilly, %ecx is pushed on the stack, and we already know how to
get at it thanks to i386_analyze_register_saves.
Follows a listing of prologue patterns I see here on i386 Cygwin.
---
#include <stdio.h>
int
main (int argc, char ** argv)
{
char asdf[0x4001];
printf ("argc %d\n", argc);
...
}
gcc3.4.4 (cygming special) -O0
_main:
.stabn 68,0,8,LM1-_main
LM1:
pushl %ebp ;frame setup
movl %esp, %ebp ;
movl $16440, %eax ;local space
call __alloca ;
andl $-16, %esp ;alignment
movl $0, %eax ;local space
addl $15, %eax ;
addl $15, %eax ;
shrl $4, %eax ;
sall $4, %eax ;
movl %eax, -16412(%ebp) ;
movl -16412(%ebp), %eax ;
call __alloca ;
.stabn 68,0,8,LM2-_main
LM2:
call ___main ;__main call
.stabn 68,0,11,LM3-_main
LM3:
---
gcc3.4.4 (cygming special) -O1
_main:
.stabn 68,0,8,LM1-_main
LM1:
pushl %ebp ;frame setup
movl %esp, %ebp ;
pushl %ebx
movl $16420, %eax ;local space
call __alloca ;
movl 8(%ebp), %ebx
andl $-16, %esp ;alignment
movl $16, %eax ;local space
call __alloca
.stabn 68,0,8,LM2-_main
LM2:
call ___main ;__main call
.stabn 68,0,11,LM3-_main
LM3:
---
gcc3.4.4 (cygming special) -O2
_main:
.stabn 68,0,8,LM1-_main
LM1:
pushl %ebp ;frame setup
movl $16420, %eax ;parameter to __alloca migrated here.
movl %esp, %ebp ;frame setup
pushl %ebx
call __alloca
.stabn 68,0,8,LM2-_main
LM2:
movl 8(%ebp), %ebx
andl $-16, %esp
movl $16, %eax
call __alloca
call ___main
.stabn 68,0,11,LM3-_main
LM3:
---
gcc 4.3.0 20070824 -O0
_main:
.stabd 46,0,0
.stabn 68,0,8,LM0-LFBB1
LM0:
LFBB1:
leal 4(%esp), %ecx ;stack alignment
andl $-16, %esp ;
pushl -4(%ecx) ;
pushl %ebp ;frame setup
movl %esp, %ebp ;
pushl %ebx ;register saves
pushl %ecx ;
movl $16416, %eax ;local space
call __alloca ;
movl %ecx, %ebx
.stabn 68,0,8,LM1-LFBB1
LM1:
call ___main ;__main call
.stabn 68,0,11,LM2-LFBB1
LM2:
gcc 4.3.0 20070824 -O1
_main:
.stabd 46,0,0
.stabn 68,0,8,LM0-LFBB1
LM0:
LFBB1:
leal 4(%esp), %ecx ;stack alignment
andl $-16, %esp ;
pushl -4(%ecx) ;
pushl %ebp ;frame setup
movl %esp, %ebp ;
pushl %esi ;register saves
pushl %ebx ;register saves
pushl %ecx ;register saves
subl $12, %esp ;local space
movl (%ecx), %esi
movl 4(%ecx), %ebx
.stabn 68,0,8,LM1-LFBB1
LM1:
call ___main ;main call
.stabn 68,0,11,LM2-LFBB1
gcc 4.3.0 20070824 -O2
_main:
.stabd 46,0,0
.stabn 68,0,8,LM0-LFBB1
LM0:
LFBB1:
leal 4(%esp), %ecx ;stack alignment
andl $-16, %esp ;
pushl -4(%ecx) ;
pushl %ebp ;frame setup
movl %esp, %ebp ;
pushl %esi ;register saves
pushl %ebx ;register saves
pushl %ecx ;register saves
subl $12, %esp ;local space
.stabn 68,0,8,LM1-LFBB1
LM1:
movl (%ecx), %esi
movl 4(%ecx), %ebx
call ___main ;main call
.stabn 68,0,11,LM2-LFBB1
LM2:
Note that the standard compiler on Cygwin is still gcc3 based, and it
is unknown when it will switch to a newer one.
The patch teaches gdb about the -O0 level good behaved prologues,
and where easy makes it understand optimized ones.
The __main call is only expected on targets that gdb knows it should
be there. A new gdbarch callback is introduced for it, and cygwin
registers it.
The patch intruduces a few minsyms lookups, which I'm not sure we
can do without. It looks like the risk is high to get it wrong
otherwise.
If left a few things to clean up, as it would make the patch harder
to read.
With this patch, all the run_to_main related failures and
timeouts are gone, both with stock cygwin gcc, and with 4.3 trunk (*),
and we start to see the real failures that are masked currently.
(*) - In the mean time, cygming switched to dwarf debug info by default
in 4.3. MinGW land has a gcc 4.2 based compiler in testing
with the prospect of becoming the officially supported compiler.
With nosignals on the board file, I get the FAIL rate down to
< 150, and no new problems. Much better.
It will need a lot more testing and tweaking, but I'd like to get
comments before I spend more time in this.
If this looks too much, the gcc3 patterns support could be
dropped, as if the reader stops mid-line, the rest of the line is
skipped, and that at -O0 lands us in the __main call. For gcc4, we
need to read the prologue, due to the need to know where the args
are on the stack - but gcc4 prologues are much more consistent.
So...
Comments?
Cheers,
Pedro Alves
-------------- next part --------------
A non-text attachment was scrubbed...
Name: skip_main.diff
Type: text/x-diff
Size: 19401 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20071013/cd486dcb/attachment.bin>
More information about the Gdb-patches
mailing list