------- 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 $0xfffffff0,%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>: lea 0x3c(%esp),%eax 0x00401099 <main+41>: lea 0x50(%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>: lea 0x1c(%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>: mov 0x24(%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. 0x00000000 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>: lea 0x1c(%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 0x00000000 0x611021a0 0x0040546c 0x22cca0: 0xbdbdbdbd 0xbdbdbdbd 0x0022cd98 0x610060e8 0x22ccb0: 0x00000001 0x100324a0 0x10030090 0x60030000 .. 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 OFFS:0x003c: jbuf = void*[5] at 0x22cc7c: 0x0022cc90 0x22cc80: 0x004010ec 0x0022cc40 0xbdbdbdbd 0xbdbdbdbd (note that I manually filled the empty stack frame with 0xbd bytes immediately after it was allocated in this run). A comment in expand_builtin_setjmp_setup says /* We store the frame pointer and the address of receiver_label in the buffer and use the rest of it for the stack save area, which is machine-dependent. */ and 0x004010ec is indeed the receiver_label, but 0x0022cc90 is not the frame pointer. The code that initialises this struct is 0x00401085 <main+21>: movl $0x407600,0x34(%esp) 0x0040108d <main+29>: movl $0x407bd4,0x38(%esp) 0x00401095 <main+37>: lea 0x3c(%esp),%eax 0x00401099 <main+41>: lea 0x50(%esp),%edx 0x0040109d <main+45>: mov %edx,(%eax) 0x0040109f <main+47>: movl $0x4010ec,0x4(%eax) 0x004010a6 <main+54>: mov %esp,0x8(%eax) and so it is clear that the "lea 0x50(%esp),%edx" is the source of the incorrect value 0x0022cc90, that is stored into jbuf[0]. As this is an offset relative to the stack pointer, yet it originates in the line emit_move_insn (mem, targetm.builtin_setjmp_frame_value ()); I am working on the hypothesis that something has gone wrong with frame pointer elimination. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952