From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17160 invoked by alias); 25 Apr 2002 09:54:04 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 17135 invoked from network); 25 Apr 2002 09:54:01 -0000 Received: from unknown (HELO pluto.sonofthor.dk) (80.196.18.231) by sources.redhat.com with SMTP; 25 Apr 2002 09:54:01 -0000 Received: from pluto (localhost [127.0.0.1]) by pluto.sonofthor.dk (Postfix on SuSE Linux 8.0 (i386)) with ESMTP id 9F1AA24112; Thu, 25 Apr 2002 12:01:17 +0200 (CEST) Content-Type: text/plain; charset="us-ascii" From: Bo Thorsen To: bugs@x86-64.org, gcc@gcc.gnu.org Subject: Exception handling problem on x86-64 Date: Thu, 25 Apr 2002 02:55:00 -0000 Cc: Jan Hubicka MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-Id: <200204251201.17404.bo@sonofthor.dk> X-SW-Source: 2002-04/txt/msg01308.txt.bz2 I'm currently trying to debug why any throw expression in c++ fails. The reason is that the stackpointer rbp is set to 0xfffffffffffffff8 at some point which is wrong, but I can't find the place where this happens. Present leader for the bug is this line (macro expanded): context->ra = __builtin_extract_return_addr ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column)); at the end of uw_init_context_1 in unwind-dw2.c. It's being called from _Unwind_RaiseException(struct _Unwind_Exception *exc) in unwind.inc. These are the first lines in that file: _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) { struct _Unwind_Context this_context, cur_context; _Unwind_Reason_Code code; uw_init_context (&this_context); cur_context = this_context; Before the uw_init_context() call, the stack is fine. When it returns, the stack is corrupted. Here are the rsp and rbp before and after the calls: rbp 0x7fbffff420 0x7fbffff420 rsp 0x7fbffff400 0x7fbffff400 ... rbp 0xfffffffffffffff8 0xfffffffffffffff8 rsp 0x7fbffff090 0x7fbffff090 Something sets rbp to a stack offset (at least that's my guess). It seems to me that the __builtin_extract_return_addr does something quite wrong here. Unfortunately gdb is quite crippled atm so it's not a great help, but if there is anything else I can provide to give a further idea of what's going wrong here, please ask. This bug is driving me nuts. Here are objdump -drS of the functions: 0000000000447ee0 : ^L static void uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) { 447ee0: 41 56 push %r14 struct _Unwind_Context orig_context = *context; 447ee2: b9 19 00 00 00 mov $0x19,%ecx 447ee7: 41 55 push %r13 447ee9: 49 89 fd mov %rdi,%r13 447eec: 41 54 push %r12 447eee: 55 push %rbp 447eef: 48 89 f5 mov %rsi,%rbp 447ef2: 4c 89 ee mov %r13,%rsi 447ef5: 53 push %rbx 447ef6: 48 81 ec e0 00 00 00 sub $0xe0,%rsp void *cfa; long i; /* Compute this frame's CFA. */ switch (fs->cfa_how) 447efd: 8b 85 40 01 00 00 mov 0x140(%rbp),%eax 447f03: 4c 8d 74 24 10 lea 0x10(%rsp,1),%r14 447f08: fc cld 447f09: 83 f8 01 cmp $0x1,%eax 447f0c: 4c 89 f7 mov %r14,%rdi 447f0f: f3 48 a5 repz movsq %ds:(%rsi),%es:(%rdi) 447f12: 0f 84 b6 00 00 00 je 447fce 447f18: 83 f8 02 cmp $0x2,%eax 447f1b: 0f 85 e0 00 00 00 jne 448001 { case CFA_REG_OFFSET: /* Special handling here: Many machines do not use a frame pointer, and track the CFA only through offsets from the stack pointer from one frame to the next. In this case, the stack pointer is never stored, so it has no saved address in the context. What we do have is the CFA from the previous stack frame. */ if (context->reg[fs->cfa_reg] == NULL) cfa = context->cfa; else cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->cfa_reg); cfa += fs->cfa_offset; break; case CFA_EXP: /* ??? No way of knowing what register number is the stack pointer to do the same sort of handling as above. Assume that if the CFA calculation is so complicated as to require a stack program that this will not be a problem. */ { const unsigned char *exp = fs->cfa_exp; 447f21: 48 8b bd 38 01 00 00 mov 0x138(%rbp),%rdi _Unwind_Word len; exp = read_uleb128 (exp, &len); 447f28: 48 8d 74 24 08 lea 0x8(%rsp,1),%rsi 447f2d: e8 0e f1 ff ff callq 447040 cfa = (void *) (_Unwind_Ptr) 447f32: 31 c9 xor %ecx,%ecx 447f34: 4c 89 ea mov %r13,%rdx 447f37: 48 89 c6 mov %rax,%rsi 447f3a: 48 89 c7 mov %rax,%rdi 447f3d: 48 03 74 24 08 add 0x8(%rsp,1),%rsi 447f42: e8 e9 f3 ff ff callq 447330 447f47: 49 89 c4 mov %rax,%r12 execute_stack_op (exp, exp + len, context, 0); break; } default: abort (); } context->cfa = cfa; 447f4a: 4d 89 a5 90 00 00 00 mov %r12,0x90(%r13) /* Compute the addresses of all registers saved in this frame. */ for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i) 447f51: 31 db xor %ebx,%ebx switch (fs->regs.reg[i].how) 447f53: 48 89 d8 mov %rbx,%rax 447f56: 48 c1 e0 04 shl $0x4,%rax 447f5a: 8b 54 05 08 mov 0x8(%rbp,%rax,1),%edx 447f5e: 83 fa 01 cmp $0x1,%edx 447f61: 74 60 je 447fc3 447f63: 83 fa 01 cmp $0x1,%edx 447f66: 72 0a jb 447f72 447f68: 83 fa 02 cmp $0x2,%edx 447f6b: 74 4a je 447fb7 447f6d: 83 fa 03 cmp $0x3,%edx 447f70: 74 19 je 447f8b 447f72: 48 ff c3 inc %rbx 447f75: 48 83 fb 11 cmp $0x11,%rbx 447f79: 7e d8 jle 447f53 { case REG_UNSAVED: break; case REG_SAVED_OFFSET: context->reg[i] = cfa + fs->regs.reg[i].loc.offset; break; case REG_SAVED_REG: context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg]; break; case REG_SAVED_EXP: { const unsigned char *exp = fs->regs.reg[i].loc.exp; _Unwind_Word len; _Unwind_Ptr val; exp = read_uleb128 (exp, &len); val = execute_stack_op (exp, exp + len, &orig_context, (_Unwind_Ptr) cfa); context->reg[i] = (void *) val; } break; } } 447f7b: 48 81 c4 e0 00 00 00 add $0xe0,%rsp 447f82: 5b pop %rbx 447f83: 5d pop %rbp 447f84: 41 5c pop %r12 447f86: 41 5d pop %r13 447f88: 41 5e pop %r14 447f8a: c3 retq 447f8b: 48 8b 7c 05 00 mov 0x0(%rbp,%rax,1),%rdi 447f90: 48 89 e6 mov %rsp,%rsi 447f93: e8 a8 f0 ff ff callq 447040 447f98: 4c 89 e1 mov %r12,%rcx 447f9b: 4c 89 f2 mov %r14,%rdx 447f9e: 48 89 c6 mov %rax,%rsi 447fa1: 48 89 c7 mov %rax,%rdi 447fa4: 48 03 34 24 add (%rsp,1),%rsi 447fa8: e8 83 f3 ff ff callq 447330 447fad: 90 nop 447fae: 90 nop 447faf: 90 nop 447fb0: 49 89 44 dd 00 mov %rax,0x0(%r13,%rbx,8) 447fb5: eb bb jmp 447f72 447fb7: 48 8b 44 05 00 mov 0x0(%rbp,%rax,1),%rax 447fbc: 48 8b 44 c4 10 mov 0x10(%rsp,%rax,8),%rax 447fc1: eb ed jmp 447fb0 447fc3: 48 8b 54 05 00 mov 0x0(%rbp,%rax,1),%rdx 447fc8: 4a 8d 04 22 lea (%rdx,%r12,1),%rax 447fcc: eb e2 jmp 447fb0 447fce: 48 8b 85 30 01 00 00 mov 0x130(%rbp),%rax 447fd5: 49 83 7c c5 00 00 cmpq $0x0,0x0(%r13,%rax,8) 447fdb: 75 13 jne 447ff0 447fdd: 4d 8b a5 90 00 00 00 mov 0x90(%r13),%r12 447fe4: 4c 03 a5 28 01 00 00 add 0x128(%rbp),%r12 447feb: e9 5a ff ff ff jmpq 447f4a 447ff0: 48 63 85 30 01 00 00 movslq 0x130(%rbp),%rax 447ff7: 49 8b 44 c5 00 mov 0x0(%r13,%rax,8),%rax 447ffc: 4c 8b 20 mov (%rax),%r12 447fff: eb e3 jmp 447fe4 448001: e8 3a 75 00 00 callq 44f540 448006: 90 nop 448007: 90 nop 448008: 90 nop 448009: 90 nop 44800a: 90 nop 44800b: 90 nop 44800c: 90 nop 44800d: 90 nop 44800e: 90 nop 44800f: 90 nop 0000000000448010 : static void uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) { 448010: 48 83 ec 18 sub $0x18,%rsp 448014: 4c 89 64 24 10 mov %r12,0x10(%rsp,1) 448019: 48 89 5c 24 08 mov %rbx,0x8(%rsp,1) 44801e: 49 89 f4 mov %rsi,%r12 448021: 48 89 fb mov %rdi,%rbx uw_update_context_1 (context, fs); 448024: e8 b7 fe ff ff callq 447ee0 448029: 49 0f b6 84 24 68 01 movzbq 0x168(%r12,1),%rax 448030: 00 00 /* Compute the return address now, since the return address column can change from frame to frame. */ context->ra = __builtin_extract_return_addr ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column)); } 448032: 4c 8b 64 24 10 mov 0x10(%rsp,1),%r12 448037: 48 8b 04 c3 mov (%rbx,%rax,8),%rax 44803b: 48 8b 00 mov (%rax),%rax 44803e: 48 89 83 98 00 00 00 mov %rax,0x98(%rbx) 448045: 48 8b 5c 24 08 mov 0x8(%rsp,1),%rbx 44804a: 48 83 c4 18 add $0x18,%rsp 44804e: c3 retq 44804f: 90 nop 44804f: 90 nop 0000000000448050 : ^L /* Fill in CONTEXT for top-of-stack. The only valid registers at this level will be the return address and the CFA. */ #define uw_init_context(CONTEXT) \ do \ { \ /* Do any necessary initialization to access arbitrary stack frames. \ On the SPARC, this means flushing the register windows. */ \ __builtin_unwind_init (); \ uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ __builtin_return_address (0)); \ } \ while (0) static void uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa, void *outer_ra) { 448050: 48 81 ec a8 01 00 00 sub $0x1a8,%rsp void *ra = __builtin_extract_return_addr (__builtin_return_address (0)); _Unwind_FrameState fs; memset (context, 0, sizeof (struct _Unwind_Context)); 448057: 31 c0 xor %eax,%eax 448059: 48 89 9c 24 88 01 00 mov %rbx,0x188(%rsp,1) 448060: 00 448061: 48 89 ac 24 90 01 00 mov %rbp,0x190(%rsp,1) 448068: 00 448069: 4c 89 a4 24 98 01 00 mov %r12,0x198(%rsp,1) 448070: 00 448071: 48 8b 9c 24 a8 01 00 mov 0x1a8(%rsp,1),%rbx 448078: 00 448079: 48 89 fd mov %rdi,%rbp 44807c: 4c 89 ac 24 a0 01 00 mov %r13,0x1a0(%rsp,1) 448083: 00 448084: 49 89 f4 mov %rsi,%r12 448087: 49 89 d5 mov %rdx,%r13 44808a: 31 f6 xor %esi,%esi 44808c: ba c8 00 00 00 mov $0xc8,%edx 448091: e8 6a ae 01 00 callq 462f00 context->ra = ra; if (uw_frame_state_for (context, &fs) != _URC_NO_REASON) 448096: 48 89 e6 mov %rsp,%rsi 448099: 48 89 ef mov %rbp,%rdi 44809c: 48 89 9d 98 00 00 00 mov %rbx,0x98(%rbp) 4480a3: e8 68 fa ff ff callq 447b10 4480a8: 85 c0 test %eax,%eax 4480aa: 75 64 jne 448110 abort (); /* Force the frame state to use the known cfa value. */ context->cfa = outer_cfa; 4480ac: 4c 89 a5 90 00 00 00 mov %r12,0x90(%rbp) fs.cfa_how = CFA_REG_OFFSET; fs.cfa_reg = 0; fs.cfa_offset = 0; uw_update_context_1 (context, &fs); 4480b3: 48 89 ef mov %rbp,%rdi 4480b6: 48 89 e6 mov %rsp,%rsi 4480b9: c7 84 24 40 01 00 00 movl $0x1,0x140(%rsp,1) 4480c0: 01 00 00 00 4480c4: 48 c7 84 24 30 01 00 movq $0x0,0x130(%rsp,1) 4480cb: 00 00 00 00 00 4480d0: 48 c7 84 24 28 01 00 movq $0x0,0x128(%rsp,1) 4480d7: 00 00 00 00 00 4480dc: e8 ff fd ff ff callq 447ee0 /* If the return address column was saved in a register in the initialization context, then we can't see it in the given call frame data. So have the initialization context tell us. */ context->ra = __builtin_extract_return_addr (outer_ra); 4480e1: 4c 89 ad 98 00 00 00 mov %r13,0x98(%rbp) } 4480e8: 4c 8b ac 24 a0 01 00 mov 0x1a0(%rsp,1),%r13 4480ef: 00 4480f0: 4c 8b a4 24 98 01 00 mov 0x198(%rsp,1),%r12 4480f7: 00 4480f8: 48 8b 9c 24 88 01 00 mov 0x188(%rsp,1),%rbx 4480ff: 00 448100: 48 8b ac 24 90 01 00 mov 0x190(%rsp,1),%rbp 448107: 00 448108: 48 81 c4 a8 01 00 00 add $0x1a8,%rsp 44810f: c3 retq 448110: e8 2b 74 00 00 callq 44f540 Bo. -- Bo Thorsen | Praestevejen 4 Free software developer | 5290 Marslev SuSE Labs | Denmark