[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #24 from ktietz at gcc dot gnu dot org 2009-01-31 17:21 --- (In reply to comment #21) Hi Joey, thanks for helping look at this bug. If you catch up with all the comments, you'll see that it's not just Cygwin, SjLj was broken on Linux too; the mechanism works the same way on both, but only Cygwin uses it as the default EH mechanism, so it doesn't get as much testing! I tested it for w64, too. And it solved most EH/SjLj issue we had for this target. Btw w64 has it as default mechanism, too. The regression runs are complete and shown no new bug. So for me this patch is ok. Cheers, Kai -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #25 from hjl at gcc dot gnu dot org 2009-01-31 17:34 --- Subject: Bug 38952 Author: hjl Date: Sat Jan 31 17:34:03 2009 New Revision: 143823 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=143823 Log: 2009-01-31 Dave Korn dave.korn.cyg...@gmail.com PR target/38952 * config/i386/i386.c (ix86_builtin_setjmp_frame_value): New. (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Override default to point at it. Modified: trunk/gcc/ChangeLog trunk/gcc/config/i386/i386.c -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #26 from hjl dot tools at gmail dot com 2009-01-31 17:34 --- Fixed. -- hjl dot tools at gmail dot com changed: What|Removed |Added Status|NEW |RESOLVED Resolution||FIXED http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #20 from Joey dot ye at intel dot com 2009-01-26 11:49 --- (In reply to comment #10) This is caused by stack alignment change, revision 138335. Joey and Xuepeng will look into it after holiday, Feb. 1. This must be stack alignment change. Looks we didn't handle stack unwinding on Cygwin correctly. Dave, comparing the the EH mechanism in Linux, what's the difference of SjLj EH in Cygwin? Answer to this question might help solving the problem sooner. Thanks - Joey -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #21 from dave dot korn dot cygwin at gmail dot com 2009-01-26 19:03 --- Hi Joey, thanks for helping look at this bug. If you catch up with all the comments, you'll see that it's not just Cygwin, SjLj was broken on Linux too; the mechanism works the same way on both, but only Cygwin uses it as the default EH mechanism, so it doesn't get as much testing! I'm fairly confident I've analyzed the problem correctly and that the patch I'm testing (attached, and submitted to gcc-patches at http://gcc.gnu.org/ml/gcc-patches/2009-01/msg01258.html) is the right solution to the problem, and my PC is running through all the regression tests now, so what would help most is if you could just look over my analysis and tell me if you think I've got the right understanding of your code and the loophole that caused the bug. cheers, DaveK -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #22 from hjl dot tools at gmail dot com 2009-01-26 22:29 --- (In reply to comment #18) Created an attachment (id=17183) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17183action=view) [edit] Implement TARGET_BUILTIN_SETJMP_FRAME_VALUE. Now testing this patch which should fix setjmp calculations of the frame base pointer without affecting the way ordinary stack local variable slots are computed. I investigated C++ failures with --enable-sjlj-exceptions on Linux/Intel64 http://gcc.gnu.org/ml/gcc-testresults/2009-01/msg02626.html All of them are expected. This looks good to me. -- hjl dot tools at gmail dot com changed: What|Removed |Added CC||ubizjak at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #23 from hjl at gcc dot gnu dot org 2009-01-26 23:39 --- Subject: Bug 38952 Author: hjl Date: Mon Jan 26 23:39:02 2009 New Revision: 143689 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=143689 Log: 2009-01-26 H.J. Lu hongjiu...@intel.com PR target/38952 * g++.dg/torture/stackalign/test-unwind.h (main): Also return 0 if __USING_SJLJ_EXCEPTIONS__ is defined. * g++.dg/torture/stackalign/unwind-0.C (foo): Don't define if __USING_SJLJ_EXCEPTIONS__ is defined. * g++.dg/torture/stackalign/unwind-1.C (foo): Likewise. * g++.dg/torture/stackalign/unwind-2.C (foo): Likewise. * g++.dg/torture/stackalign/unwind-3.C (foo): Likewise. * g++.dg/torture/stackalign/unwind-4.C (foo): Likewise. * g++.dg/torture/stackalign/unwind-5.C (foo): Likewise. * g++.dg/torture/stackalign/unwind-6.C (foo): Likewise. Modified: trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/torture/stackalign/test-unwind.h trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-0.C trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-1.C trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-2.C trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-3.C trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-4.C trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-5.C trunk/gcc/testsuite/g++.dg/torture/stackalign/unwind-6.C -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #18 from dave dot korn dot cygwin at gmail dot com 2009-01-25 21:36 --- Created an attachment (id=17183) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17183action=view) Implement TARGET_BUILTIN_SETJMP_FRAME_VALUE. Now testing this patch which should fix setjmp calculations of the frame base pointer without affecting the way ordinary stack local variable slots are computed. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #19 from dave dot korn dot cygwin at gmail dot com 2009-01-25 23:07 --- Created an attachment (id=17184) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17184action=view) Implement TARGET_BUILTIN_SETJMP_FRAME_VALUE *correctly*. Dur. Corrected patch for return type thinko. -- dave dot korn dot cygwin at gmail dot com changed: What|Removed |Added Attachment #17183|0 |1 is obsolete|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
-- rguenth at gcc dot gnu dot org changed: What|Removed |Added Keywords||wrong-code Target Milestone|--- |4.4.0 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #8 from ubizjak at gmail dot com 2009-01-24 17:06 --- There are numerous g++ EH failures even for x86-pc-linux-gnu, when gcc is configured with --enable-sjlj-exceptions, so something is serious FUBAR w.r.t to SJLJ exceptions. === g++ tests === Running target unix FAIL: g++.dg/abi/forced.C execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O2 execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -Os execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O2 execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -Os execution test FAIL: g++.dg/torture/stackalign/eh-inline-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-inline-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-inline-1.C -O2 execution test FAIL: g++.dg/torture/stackalign/eh-inline-1.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/eh-inline-1.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/eh-inline-1.C -Os execution test FAIL: g++.dg/torture/stackalign/eh-vararg-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-vararg-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-vararg-1.C -O2 execution test FAIL: g++.dg/torture/stackalign/eh-vararg-1.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/eh-vararg-1.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/eh-vararg-1.C -Os execution test FAIL: g++.dg/torture/stackalign/eh-vararg-2.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-vararg-2.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-vararg-2.C -O2 execution test FAIL: g++.dg/torture/stackalign/eh-vararg-2.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/eh-vararg-2.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/eh-vararg-2.C -Os execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O2 execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O3 -fomit-frame-pointer -funroll-loops execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions execution test FAIL: g++.dg/torture/stackalign/throw-1.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/throw-1.C -Os execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O0 execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O1 execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O2 execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O3 -fomit-frame-pointer -funroll-loops execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions execution test FAIL: g++.dg/torture/stackalign/throw-2.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/throw-2.C -Os execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O0 execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O1 execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O2 execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O3 -fomit-frame-pointer -funroll-loops execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions execution test FAIL: g++.dg/torture/stackalign/throw-3.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/throw-3.C -Os execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O2 execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O3 -fomit-frame-pointer execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -O3 -g execution test FAIL: g++.dg/torture/stackalign/eh-alloca-1.C -Os execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O0 execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O1 execution test FAIL: g++.dg/torture/stackalign/eh-global-1.C -O2 execution test FAIL:
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #9 from dave dot korn dot cygwin at gmail dot com 2009-01-24 18:12 --- Thanks for the test results and confirmation, Uros. It looks like more or less exactly the same list of FAILs as I see on Cygwin, so I think this confirms a generic issue with frame pointer elimination in the i386 backend. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #10 from hjl dot tools at gmail dot com 2009-01-24 21:41 --- This is caused by stack alignment change, revision 138335. Joey and Xuepeng will look into it after holiday, Feb. 1. -- hjl dot tools at gmail dot com changed: What|Removed |Added CC||Joey dot ye at intel dot ||com, xuepeng dot guo at ||intel dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #11 from dave dot korn dot cygwin at gmail dot com 2009-01-25 05:33 --- Thanks for your help HJ. I'll do some more debugging and add notes while you're away. Happy New Year! -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #12 from dave dot korn dot cygwin at gmail dot com 2009-01-25 05:56 --- Created an attachment (id=17177) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17177action=view) Correct code compiled with -mpreferred-stack-boundary=2 Adding -mpreferred-stack-boundary=2 to the compile line generates a correct, functioning executable. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #13 from dave dot korn dot cygwin at gmail dot com 2009-01-25 05:58 --- Created an attachment (id=17178) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17178action=view) Diffs between good and bad versions This shows a diff between the testcase compiled with -mpreferred-stack-boundary=2 and with -mpreferred-stack-boundary=4 (the default). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #14 from dave dot korn dot cygwin at gmail dot com 2009-01-25 06:05 --- Adding -mpreferred-stack-boundary=2 to the command line generates correct code. Here are the diffs between code generated by that setting and the default (-mpreferred-stack-boundary=4) for the start of the function: --- eh-sb2.s2009-01-25 05:24:46.71875 + +++ eh-sb4.s2009-01-25 05:26:19.18750 + @@ -10,19 +10,20 @@ _main: pushl %ebp movl%esp, %ebp + andl$-16, %esp pushl %edi pushl %esi pushl %ebx - subl$68, %esp - movl$___gxx_personality_sj0, -40(%ebp) - movl$LLSDA0, -36(%ebp) - leal-32(%ebp), %eax - leal-12(%ebp), %edx + subl$84, %esp + movl$___gxx_personality_sj0, 52(%esp) + movl$LLSDA0, 56(%esp) + leal60(%esp), %eax + leal80(%esp), %edx movl%edx, (%eax) movl$L5, %edx movl%edx, 4(%eax) movl%esp, 8(%eax) - leal-64(%ebp), %eax + leal28(%esp), %eax movl%eax, (%esp) call__Unwind_SjLj_Register So I think I'm starting to grok what's happening here. Because of the larger stack alignment required, and because the incoming stack alignment is only 8, not 16, we have to use an AND to mask and align the incoming esp. Now that means then that we have a hole of unknown size in our stack frame, just below the frame pointer at the top end. So because this gap is unkown, we can't index down from the frame pointer %ebp to the rest of the stack frame any more, which is why we have to turn the elimination basis upside down and calculate all the eliminations upward from esp instead. (The gap is in fact composed of two components. The dynamic adjustment needed to align the incoming stack, which cannot be known at compile time, and then the extra space allocated to the stack frame to ensure its size is a multiple of the alignment so that the lower end of the frame is also aligned. Although this second part is known at compile-time, as long as the first part is unpredictable we have to do the eliminations from the stack base, not frame pointer). This is all fine for most stack frame contents, but it goes wrong in exactly the same-but-opposite way if we're trying to access items of the stack frame *above* the gap - and that's what's happening in my test case, because we're trying to get the address of HARD_FRAME_POINTER, aka the value in $ebp, aka 4 or 8 bytes below the ARG_POINTER (compile-time known constant offset). So the one or two items above the gap - the frame pointer and the return pc value (Does this bug affect __builtin_return_address(0) as well, by any chance? I haven't checked) - would have to still be eliminated against HARD_FRAME_POINTER and denied elimination against STACK_POINTER in the case where there is going to be stack realignment in the prologue. And that is presumably the intention of this if clause in ix86_can_eliminate: if (stack_realign_fp) return ((from == ARG_POINTER_REGNUM to == HARD_FRAME_POINTER_REGNUM) || (from == FRAME_POINTER_REGNUM to == STACK_POINTER_REGNUM)); else [ ... ] I'll look at why it's not doing what it's supposed to. One possibility is that stack_realign_fp isn't becoming true until after the elimination has already taken place. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #15 from dave dot korn dot cygwin at gmail dot com 2009-01-25 06:33 --- (In reply to comment #14) And that is presumably the intention of this if clause in ix86_can_eliminate: if (stack_realign_fp) return ((from == ARG_POINTER_REGNUM to == HARD_FRAME_POINTER_REGNUM) || (from == FRAME_POINTER_REGNUM to == STACK_POINTER_REGNUM)); else [ ... ] I just looked twice at that and it seemed odd to me. Testing this: if (stack_realign_fp) return ((from == ARG_POINTER_REGNUM to == HARD_FRAME_POINTER_REGNUM) || (from == FRAME_POINTER_REGNUM - to == STACK_POINTER_REGNUM)); + to == HARD_FRAME_POINTER_REGNUM)); gives me this: (gdb) disass main Dump of assembler code for function main: 0x00401070 main+0:push %ebp 0x00401071 main+1:mov%esp,%ebp 0x00401073 main+3:and$0xfff0,%esp 0x00401076 main+6:push %edi 0x00401077 main+7:push %esi 0x00401078 main+8:push %ebx 0x00401079 main+9:sub$0x54,%esp 0x0040107c main+12: movl $0x4075f0,-0x34(%ebp) 0x00401083 main+19: movl $0x407bc4,-0x30(%ebp) 0x0040108a main+26: lea-0x2c(%ebp),%eax 0x0040108d main+29: lea-0x18(%ebp),%edx 0x00401090 main+32: mov%edx,(%eax) 0x00401092 main+34: mov$0x4010e2,%edx 0x00401097 main+39: mov%edx,0x4(%eax) 0x0040109a main+42: mov%esp,0x8(%eax) 0x0040109d main+45: lea-0x4c(%ebp),%eax 0x004010a0 main+48: mov%eax,(%esp) 0x004010a3 main+51: call 0x405058 _Unwind_SjLj_Register Which works, but now I suspect the address calculations accessing the jmp_buf are going to be wrong. Argh. It looks like we have to know whether there's an offset in the mem rtx relating to FRAME_POINTER_REGNUM and if it's negative we have to allow elimination against STACK_POINTER but if its zero or positive we'd have to only allow elimination against HARD_FRAME_POINTER ... ouch. Guess the next thing I'll try is simply not allowing elimination against FRAME_POINTER at all in this context. That'll mean we can't -fomit-frame-pointer in functions which have stack_realign_fp true, but it beats wrong code and maybe there's a way of avoiding it that I haven't thought of. Now testing: if (stack_realign_fp) return ((from == ARG_POINTER_REGNUM to == HARD_FRAME_POINTER_REGNUM) || (from == FRAME_POINTER_REGNUM - to == STACK_POINTER_REGNUM)); + 0)); -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #16 from dave dot korn dot cygwin at gmail dot com 2009-01-25 06:40 --- ./eh.C: In function 'int main()': ./eh.C:11: internal compiler error: in print_reg, at config/i386/i386.c:10466 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html for instructions. LOL, no, that didn't help. Will try again tomorrow. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #17 from dave dot korn dot cygwin at gmail dot com 2009-01-25 07:47 --- And this is what I'll try: -- Target Hook: bool TARGET_BUILTIN_SETJMP_FRAME_VALUE () This target hook should return an rtx that is used to store the address of the current frame into the built in `setjmp' buffer. The default value, `virtual_stack_vars_rtx', is correct for most machines. One reason you may need to define this target hook is if `hard_frame_pointer_rtx' is the appropriate value on your machine. (The first patch fixed all the failing eh testcases, but accessing the local variables downward through %ebp would mean they'd be misaligned, not starting down at the bottom of the frame, and differently aligned according to the dynamic component of the gap, so it would be bound to go wrong in situations involving vectors or other higher-alignment datatypes.) If I leave the can_eliminate test alone but define this target hook, I figure we should still get local vars indexed upward from $esp but will get the frame pointer indexed down from $ebp, or at least that's how I read the above. So hopefully a target hook that overrides the default return value with hard_frame_pointer_rtx if stack_realign_fp is true and otherwise returns virtual_stack_vars_rtx like the default might be what we're looking for. AFAICT it's not currently defined for i386. Need sleep nowzzZZZ... -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #1 from dave dot korn dot cygwin at gmail dot com 2009-01-23 23:31 --- Created an attachment (id=17169) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17169action=view) Simple throw-catch testcase Test cases don't come much simpler than this. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #2 from dave dot korn dot cygwin at gmail dot com 2009-01-23 23:31 --- Created an attachment (id=17170) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17170action=view) Pre-processed source of testcase. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #3 from dave dot korn dot cygwin at gmail dot com 2009-01-23 23:32 --- Created an attachment (id=17171) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17171action=view) Generated assembler for testcase -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #4 from dave dot korn dot cygwin at gmail dot com 2009-01-23 23:44 --- The bug manifests itself as a crash on exit from main(); $eip is set to zero and we get a SEGV. On entry to main(), the registers show: esp0x22cc40 0x22cc40 ebp0x22cca8 0x22cca8 Just before the epilogue at the end of main, we see: esp0x22cc40 0x22cc40 ebp0x22cc90 0x22cc90 (gdb) x/32xw 0x22cc40 0x22cc40: 0x0022cc5c 0x0040e7e0 0x 0x004f0584 0x22cc50: 0x005005c2 0x32200060 0x0022cc78 0x 0x22cc60: 0x 0x100325b8 0x0001 0x61010173 0x22cc70: 0x0001 0x00407600 0x00407bd4 0x0022cc90 0x22cc80: 0x004010ec 0x0022cc40 0x 0x610df2c7 0x22cc90: 0x100324fa 0x 0x611021a0 0x0040546c 0x22cca0: 0x611021a0 0x0040546c 0x0022cd98 0x610060e8 0x22ccb0: 0x0001 0x100324a0 0x10030090 0x6003 (gdb) and so when we come to the ret instruction, ... (gdb) Breakpoint 2, 0x00401125 in main () at ./eh.C:11 11 } (gdb) info reg eax0x0 0 ecx0x22cb30 2280240 edx0x0 0 ebx0x0 0 esp0x22cc94 0x22cc94 ebp0x100324fa 0x100324fa esi0x611021a0 1628447136 edi0x40546c 4215916 eip0x401125 0x401125 main+181 eflags 0x202[ IF ] cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x38 56 gs 0x0 0 (gdb) stepi 0x in ?? () Next comment will analyze how $ebp comes to have the wrong value. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #5 from dave dot korn dot cygwin at gmail dot com 2009-01-24 00:10 --- Here is a disassembly of the start of the main function: (gdb) disass main Dump of assembler code for function main: 0x00401070 main+0:push %ebp 0x00401071 main+1:mov%esp,%ebp 0x00401073 main+3:and$0xfff0,%esp 0x00401076 main+6:sub$0x60,%esp 0x00401079 main+9:mov%ebx,0x54(%esp) 0x0040107d main+13: mov%esi,0x58(%esp) 0x00401081 main+17: mov%edi,0x5c(%esp) 0x00401085 main+21: movl $0x407600,0x34(%esp) 0x0040108d main+29: movl $0x407bd4,0x38(%esp) 0x00401095 main+37: lea0x3c(%esp),%eax 0x00401099 main+41: lea0x50(%esp),%edx 0x0040109d main+45: mov%edx,(%eax) 0x0040109f main+47: movl $0x4010ec,0x4(%eax) 0x004010a6 main+54: mov%esp,0x8(%eax) 0x004010a9 main+57: lea0x1c(%esp),%eax 0x004010ad main+61: mov%eax,(%esp) 0x004010b0 main+64: call 0x405068 _Unwind_SjLj_Register 0x004010b5 main+69: call 0x40515c __main 0x004010ba main+74: movl $0x4,(%esp) 0x004010c1 main+81: call 0x406b00 __cxa_allocate_exception 0x004010c6 main+86: movl $0x1,(%eax) 0x004010cc main+92: movl $0x0,0x8(%esp) 0x004010d4 main+100: movl $0x40e7e0,0x4(%esp) 0x004010dc main+108: mov%eax,(%esp) 0x004010df main+111: movl $0x1,0x20(%esp) 0x004010e7 main+119: call 0x4075a0 __cxa_throw 0x004010ec main+124: mov0x24(%esp),%eax 0x004010f0 main+128: mov%eax,(%esp) 0x004010f3 main+131: call 0x406da0 __cxa_begin_catch If we set a breakpoint on every function call, and run through it: (gdb) r Starting program: /win/i/FSF-Gcc/obj-sjlj/gcc/testsuite/g++/eh.exe [New thread 648.0x754] [New thread 648.0x31c] Breakpoint 1, main () at ./eh.C:4 4 { (gdb) print $esp $2 = (void *) 0x22ccac (gdb) c Continuing. Breakpoint 3, 0x004010b0 in main () at ./eh.C:4 4 { (gdb) print $esp $3 = (void *) 0x22cc40 (gdb) print $ebp $14 = (void *) 0x22cca8 (gdb) c Continuing. Breakpoint 4, main () at ./eh.C:4 4 { (gdb) print $ebp $4 = (void *) 0x22cca8 (gdb) c Continuing. Breakpoint 5, 0x004010c1 in main () at ./eh.C:6 6 throw 1; (gdb) print $ebp $5 = (void *) 0x22cca8 (gdb) c Continuing. Breakpoint 6, 0x004010e7 in main () at ./eh.C:6 6 throw 1; (gdb) print $ebp $6 = (void *) 0x22cca8 (gdb) c Continuing. Breakpoint 10, _Unwind_SjLj_RaiseException (exc=0x100325b8) at /gnu/gcc/gcc/libgcc/../gcc/unwind-sjlj.c:148 148 if (use_fc_key 0) Current language: auto; currently c (gdb) print $ebp $7 = (void *) 0x22cc18 (gdb) c Continuing. Breakpoint 7, 0x004010f3 in main () at ./eh.C:8 8 catch (...) { Current language: auto; currently c++ (gdb) print $ebp $8 = (void *) 0x22cc90 (gdb) c Continuing. Breakpoint 8, 0x00401100 in main () at ./eh.C:8 8 catch (...) { (gdb) print $ebp $9 = (void *) 0x22cc90 (gdb) c Continuing. Breakpoint 9, 0x0040110c in main () at ./eh.C:8 8 catch (...) { (gdb) print $ebp $10 = (void *) 0x22cc90 (gdb) c Continuing. Breakpoint 11, 0x00401122 in main () at ./eh.C:11 11 } (gdb) print $ebp $11 = (void *) 0x22cc90 (gdb) c Continuing. Breakpoint 2, 0x00401125 in main () at ./eh.C:11 11 } (gdb) print $ebp $12 = (void *) 0x100324fa (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x in ?? () (gdb) ... we can see that $ebp is correct right up until the call to __cxa_throw at 0x004010e7, but when we return to the catch landing site at 0x004010f3, $ebp is incorrect. This incorrect value is calculated in the code at the start of main(), where the code generated by sjlj_emit_function_enter calls expand_builtin_setjmp_setup to initialise the jbuf[] member of the struct SjLj_Function_Context that it then passes to _Unwind_SjLj_Register. From that call: 0x004010a9 main+57: lea0x1c(%esp),%eax 0x004010ad main+61: mov%eax,(%esp) 0x004010b0 main+64: call 0x405068 _Unwind_SjLj_Register the struct is at an offset of 0x1c on the stack. Looking at the memory dump, just before the call: 0x22cc40: 0x0022cc5c 0xbdbdbdbd 0xbdbdbdbd 0xbdbdbdbd 0x22cc50: 0xbdbdbdbd 0xbdbdbdbd 0xbdbdbdbd 0xbdbdbdbd 0x22cc60: 0xbdbdbdbd 0xbdbdbdbd 0xbdbdbdbd 0xbdbdbdbd 0x22cc70: 0xbdbdbdbd 0x00407600 0x00407bd4 0x0022cc90 0x22cc80: 0x004010ec 0x0022cc40 0xbdbdbdbd 0xbdbdbdbd 0x22cc90: 0xbdbdbdbd 0x 0x611021a0 0x0040546c 0x22cca0: 0xbdbdbdbd 0xbdbdbdbd 0x0022cd98 0x610060e8 0x22ccb0: 0x0001 0x100324a0 0x10030090 0x6003 .. shows that the struct has been initialised like so: OFFS:0x001c: prev = 0xbdbdbdbd, call_Site 0xbdbdbdbd OFFS:0x0024: data[4] = { 0xbdbdbdbd, 0xbdbdbdbd, 0xbdbdbdbd, 0xbdbdbdbd } OFFS:0x0034: personality = 0x00407600 = __gxx_personality_sj0 OFFS:0x0038: lsda = 0x00407bd4 = __DTOR_LIST__+16:0x010d00ff
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #6 from dave dot korn dot cygwin at gmail dot com 2009-01-24 01:08 --- Here is the RTL that is created by the .130r.eh pass: everything between note 2 and call_insn 3, was added after expand. try_optimize_cfg iteration 2 (note 1 0 4 NOTE_INSN_DELETED) (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) (note 2 4 46 2 NOTE_INSN_FUNCTION_BEG) (insn 46 2 47 2 (set (mem/c:SI (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -28 [0xffe4])) [0 S4 A32]) (symbol_ref:SI (__gxx_personality_sj0) [flags 0x43])) -1 (nil)) (insn 47 46 48 2 (set (mem/c:SI (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -24 [0xffe8])) [0 S4 A32]) (symbol_ref:SI (*LLSDA0) [flags 0x2])) -1 (nil)) (insn 48 47 49 2 (parallel [ (set (reg:SI 63) (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -20 [0xffec]))) (clobber (reg:CC 17 flags)) ]) -1 (nil)) (insn 49 48 50 2 (set (mem:SI (reg:SI 63) [0 S4 A8]) (reg/f:SI 54 virtual-stack-vars)) -1 (nil)) (insn 50 49 51 2 (set (reg/f:SI 64) (label_ref:SI 56)) -1 (insn_list:REG_LABEL_OPERAND 56 (nil))) (insn 51 50 52 2 (set (mem:SI (plus:SI (reg:SI 63) (const_int 4 [0x4])) [0 S4 A8]) (reg/f:SI 64)) -1 (nil)) (insn 52 51 53 2 (set (mem:SI (plus:SI (reg:SI 63) (const_int 8 [0x8])) [0 S4 A8]) (reg/f:SI 7 sp)) -1 (nil)) (insn 53 52 54 2 (parallel [ (set (reg:SI 65) (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -52 [0xffcc]))) (clobber (reg:CC 17 flags)) ]) -1 (nil)) (insn 54 53 55 2 (set (mem:SI (reg/f:SI 56 virtual-outgoing-args) [0 S4 A32]) (reg:SI 65)) -1 (nil)) (call_insn 55 54 3 2 (call (mem:QI (symbol_ref:SI (_Unwind_SjLj_Register) [flags 0x43]) [0 S1 A8]) (const_int 16 [0x10])) -1 (expr_list:REG_EH_REGION (const_int 0 [0x0]) (nil)) (nil)) (call_insn 3 55 6 2 ./eh.C:4 (call (mem:QI (symbol_ref:SI (__main) [flags 0x43]) [0 S1 A8]) (const_int 0 [0x0])) -1 (expr_list:REG_EH_REGION (const_int 0 [0x0]) (nil)) (nil)) Pass 133r.vregs turns this into: (insn 46 2 47 2 (set (mem/c:SI (plus:SI (reg/f:SI 20 frame) (const_int -28 [0xffe4])) [0 S4 A32]) (symbol_ref:SI (__gxx_personality_sj0) [flags 0x43])) 41 {*movsi_1} (nil)) (insn 47 46 48 2 (set (mem/c:SI (plus:SI (reg/f:SI 20 frame) (const_int -24 [0xffe8])) [0 S4 A32]) (symbol_ref:SI (*LLSDA0) [flags 0x2])) 41 {*movsi_1} (nil)) (insn 48 47 49 2 (parallel [ (set (reg:SI 63) (plus:SI (reg/f:SI 20 frame) (const_int -20 [0xffec]))) (clobber (reg:CC 17 flags)) ]) 213 {*addsi_1} (nil)) (insn 49 48 50 2 (set (mem:SI (reg:SI 63) [0 S4 A8]) (reg/f:SI 20 frame)) 41 {*movsi_1} (nil)) (insn 50 49 51 2 (set (reg/f:SI 64) (label_ref:SI 56)) 41 {*movsi_1} (insn_list:REG_LABEL_OPERAND 56 (nil))) (insn 51 50 52 2 (set (mem:SI (plus:SI (reg:SI 63) (const_int 4 [0x4])) [0 S4 A8]) (reg/f:SI 64)) 41 {*movsi_1} (nil)) (insn 52 51 53 2 (set (mem:SI (plus:SI (reg:SI 63) (const_int 8 [0x8])) [0 S4 A8]) (reg/f:SI 7 sp)) 41 {*movsi_1} (nil)) (insn 53 52 54 2 (parallel [ (set (reg:SI 65) (plus:SI (reg/f:SI 20 frame) (const_int -52 [0xffcc]))) (clobber (reg:CC 17 flags)) ]) 213 {*addsi_1} (nil)) (insn 54 53 55 2 (set (mem:SI (reg/f:SI 7 sp) [0 S4 A32]) (reg:SI 65)) 41 {*movsi_1} (nil)) (call_insn 55 54 3 2 (call (mem:QI (symbol_ref:SI (_Unwind_SjLj_Register) [flags 0x43]) [0 S1 A8]) (const_int 16 [0x10])) 466 {*call_0} (expr_list:REG_EH_REGION (const_int 0 [0x0]) (nil)) (nil)) Note that insn 49 is the crucial one here that stores the (later miscalculated) value of the frame pointer (i.e., $ebp - before elimination) into the jmp_buf. At pass 174r.ira, this becomes: (insn 48 47 73 2 (parallel [ (set (reg/f:SI 0 ax [63]) (plus:SI (reg/f:SI 7 sp) (const_int 60 [0x3c]))) (clobber (reg:CC 17 flags)) ]) 213 {*addsi_1} (expr_list:REG_EQUIV (plus:SI (reg/f:SI 7 sp) (const_int 60 [0x3c])) (nil))) (insn 73 48 49 2 (set (reg:SI 1 dx) (plus:SI (reg/f:SI 7 sp) (const_int 80 [0x50]))) 209 {*lea_1} (nil)) (insn 49 73 51 2 (set (mem:SI (reg/f:SI 0 ax [63]) [0 S4 A8]) (reg:SI 1 dx)) 41 {*movsi_1} (nil)) And this is the point at which the incorrect offset first appears. Ouch. I hope this isn't an IRA bug, I know nothing about that. Is it valid to do frame pointer elimination before reload like that? Because the other possibility is that the x86 backend is suddenly growing the frame size during some later pass. (Well, I guess we
[Bug target/38952] [4.4 Regression] EH does not work.
--- Comment #7 from dave dot korn dot cygwin at gmail dot com 2009-01-24 06:23 --- Not IRA-related, it seems, but reload-backend interaction. -fno-ira doesn't make any difference to the generated code to calculate the frame pointer for the jmp_buf. In a non-IRA build, pass 172r.lreg has: (insn 49 48 51 2 (set (mem:SI (reg/f:SI 63) [0 S4 A8]) (reg/f:SI 20 frame)) 41 {*movsi_1} (nil)) and pass 173r.greg has (insn 73 48 49 2 (set (reg:SI 1 dx) (plus:SI (reg/f:SI 7 sp) (const_int 80 [0x50]))) 209 {*lea_1} (nil)) (insn 49 73 51 2 (set (mem:SI (reg/f:SI 0 ax [63]) [0 S4 A8]) (reg:SI 1 dx)) 41 {*movsi_1} (nil)) and here we can see that it's reload doing the FP elimination: Reloads for insn # 49 Reload 0: reload_out (SI) = (mem:SI (reg/f:SI 0 ax [63]) [0 S4 A8]) NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional reload_out_reg: (mem:SI (reg/f:SI 0 ax [63]) [0 S4 A8]) Reload 1: reload_in (SI) = (plus:SI (reg/f:SI 7 sp) (const_int 80 [0x50])) GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1) reload_in_reg: (plus:SI (reg/f:SI 7 sp) (const_int 80 [0x50])) reload_reg_rtx: (reg:SI 1 dx) -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952