* Exception handling problem on x86-64
@ 2002-04-25 2:55 ` Bo Thorsen
2002-04-25 10:08 ` David Edelsohn
0 siblings, 1 reply; 4+ messages in thread
From: Bo Thorsen @ 2002-04-25 2:55 UTC (permalink / raw)
To: bugs, gcc; +Cc: Jan Hubicka
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 <uw_update_context_1>:
^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
<uw_update_context_1+0xee>
447f18: 83 f8 02 cmp $0x2,%eax
447f1b: 0f 85 e0 00 00 00 jne 448001
<uw_update_context_1+0x121
>
{
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 <read_uleb128>
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 <execute_stack_op>
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
<uw_update_context_1+0xe3>
447f63: 83 fa 01 cmp $0x1,%edx
447f66: 72 0a jb 447f72
<uw_update_context_1+0x92>
447f68: 83 fa 02 cmp $0x2,%edx
447f6b: 74 4a je 447fb7
<uw_update_context_1+0xd7>
447f6d: 83 fa 03 cmp $0x3,%edx
447f70: 74 19 je 447f8b
<uw_update_context_1+0xab>
447f72: 48 ff c3 inc %rbx
447f75: 48 83 fb 11 cmp $0x11,%rbx
447f79: 7e d8 jle 447f53
<uw_update_context_1+0x73>
{
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 <read_uleb128>
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 <execute_stack_op>
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
<uw_update_context_1+0x92>
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
<uw_update_context_1+0xd0>
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
<uw_update_context_1+0xd0>
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
<uw_update_context_1+0x110
>
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
<uw_update_context_1+0x6a>
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
<uw_update_context_1+0x104
>
448001: e8 3a 75 00 00 callq 44f540 <abort>
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 <uw_update_context>:
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 <uw_update_context_1>
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 <uw_init_context_1>:
^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 <memset>
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 <uw_frame_state_for>
4480a8: 85 c0 test %eax,%eax
4480aa: 75 64 jne 448110 <uw_init_context_1+0xc0>
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 <uw_update_context_1>
/* 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 <abort>
Bo.
--
Bo Thorsen | Praestevejen 4
Free software developer | 5290 Marslev
SuSE Labs | Denmark
^ permalink raw reply [flat|nested] 4+ messages in thread