Bug 26208 - Serious problem with unwinding through signal frames
Serious problem with unwinding through signal frames
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: other
4.1.0
: P3 normal
: ---
Assigned To: Jakub Jelinek
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2006-02-10 08:22 UTC by Jakub Jelinek
Modified: 2008-07-07 08:33 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-02-10 08:24:00


Attachments
cleanup-12.c (2.44 KB, text/plain)
2006-02-10 08:23 UTC, Jakub Jelinek
Details
cleanup-12a.S (1.40 KB, text/plain)
2006-02-10 08:23 UTC, Jakub Jelinek
Details
gcc-trunk-pr26208.patch (8.01 KB, patch)
2006-02-21 12:02 UTC, Jakub Jelinek
Details | Diff
binutils-trunk-pr26208.patch (1022 bytes, patch)
2006-02-21 12:02 UTC, Jakub Jelinek
Details | Diff
linux-2.6.15-pr26208.patch (3.16 KB, patch)
2006-02-21 13:12 UTC, Jakub Jelinek
Details | Diff
updated for powerpc and powerpc64 (2.14 KB, text/plain)
2006-02-23 00:41 UTC, Alan Modra
Details
gcc-trunk-pr26208.patch (13.40 KB, patch)
2006-02-24 19:45 UTC, Jakub Jelinek
Details | Diff
binutils-trunk-pr26208.patch (4.31 KB, patch)
2006-02-24 19:45 UTC, Jakub Jelinek
Details | Diff
gcc-trunk-pr26208-2.patch (5.57 KB, patch)
2006-02-26 22:16 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2006-02-10 08:22:27 UTC
The attached testcase usually segfaults on i?86-linux and x86_64-linux
(and likely on most other DWARF2_UNWIND_INFO 1 targets, though the testcase
would need to be tweaked for them).
The problem is that instruction pointer saved in the signal frame is after
last successfully executed instruction and before first non-executed instruction,
while .eh_frame and unwind-dw2.c basically expects context->ra to be after the first non-executed instruction.
To find FDE, unwind-dw2.c uses context->ra - 1, which is good for normal
unwinding, but if e.g. a signal is sent while $pc is at the very beginning
of some function, context->ra - 1 either corresponds to a previous function
or is not covered by any FDE.
Similarly, execute_cfa_program has a loop:
  while (insn_ptr < insn_end && fs->pc < context->ra)
which is good in most cases, but when context->ra is saved IP from sigcontext
in signal frame, this means that the last set of unwind instructions will
not be executed, while it ought to (for signal frame context->ra we'd need
to also execute fs->pc == context->ra instructions).
Comment 1 Jakub Jelinek 2006-02-10 08:23:03 UTC
Created attachment 10814 [details]
cleanup-12.c
Comment 2 Jakub Jelinek 2006-02-10 08:23:26 UTC
Created attachment 10815 [details]
cleanup-12a.S
Comment 3 Ulrich Weigand 2006-02-10 20:00:19 UTC
Yup.  See how this is handled in config/s390/linux-unwind.c:

  /* If we got a SIGSEGV or a SIGBUS, the PSW address points *to*
     the faulting instruction, not after it.  This causes the logic
     in unwind-dw2.c that decrements the RA to determine the correct
     CFI region to get confused.  To fix that, we *increment* the RA
     here in that case.  Note that we cannot modify the RA in place,
     and the frame state wants a *pointer*, not a value; thus we put
     the modified RA value into the unused register 33 slot of FS and
     have the register 32 save address point to that slot.

     Unfortunately, for regular signals on old kernels, we don't know
     the signal number.  We default to not fiddling with the RA;
     that can fail in rare cases.  Upgrade your kernel.  */

  if (signo && (*signo == 11 || *signo == 7))
    {
      fs->regs.reg[33].loc.exp =
        (unsigned char *)regs->psw_addr + 1;
      fs->regs.reg[32].loc.offset =
        (long)&fs->regs.reg[33].loc.exp - new_cfa;
    }
Comment 4 Jakub Jelinek 2006-02-10 20:18:34 UTC
Not all the targets have the luxury of spare register slots.
So the current proposal is to add a new CIE augmentation that will signify
a signal frame.
Comment 5 Ulrich Weigand 2006-02-10 20:34:50 UTC
(In reply to comment #4)
> Not all the targets have the luxury of spare register slots.
I guess we were lucky here ;-)

> So the current proposal is to add a new CIE augmentation that will signify
> a signal frame.
OK, I see.
Comment 6 Jakub Jelinek 2006-02-21 12:02:03 UTC
Created attachment 10884 [details]
gcc-trunk-pr26208.patch
Comment 7 Jakub Jelinek 2006-02-21 12:02:45 UTC
Created attachment 10885 [details]
binutils-trunk-pr26208.patch
Comment 8 Jakub Jelinek 2006-02-21 13:12:39 UTC
Created attachment 10886 [details]
linux-2.6.15-pr26208.patch

This is what I have so far (libjava not done yet), but I'm not sure a simple CIE flag isn't sufficient on all arches.  Consider:
#define _GNU_SOURCE
#include <signal.h>
#include <string.h>
#include <fenv.h>

int *p;
double d = 1.0, e = 0.0;
void sigfpe (int signo) { }
void sigsegv (int signo) { }
void fpe (void) { d /= e; }
void segv (void) { *p = 0; }

int
main (int argc, char **argv)
{
  struct sigaction sa;
  sa.sa_handler = sigfpe;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = 0;
  sigaction (SIGFPE, &sa, 0);
  feenableexcept (FE_ALL_EXCEPT);
  sa.sa_handler = sigsegv;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = 0;
  sigaction (SIGSEGV, &sa, 0);
  if (argc < 2)
    return 1;
  if (strcmp (argv[1], "fpe") == 0)
    fpe ();
  else if (strcmp (argv[1], "segv") == 0)
    segv ();
  else
    return 1;
  return 0;
}

For segv the PC saved in sigcontext is always before the faulting instruction,
at least on i386, x86_64, ppc, ppc64, s390x I tried.
For asynchronously sent signals (that's the reason why I opened this PR), saved
PC will be also before the next instruction to be executed, so for SIGSEGV as well asynchronously sent signals we want the fs->pc <= context->ra in execute_cfa_program and _Unwind_Find_FDE (context->ra, ) behavior.
But, for SIGFPE things are more difficult.
On s390x, PC is in this case after the ddbr instruction rather than before it,
on i386 when using i387 FPU stack PC is after the fdivrp instruction, but at
the following fstpl instruction; adding nops in between shows that it actually
is always before fstpl), on x86_64 or i386 -mfpmath=sse it is before the failing divsd, on ppc similarly.
We should avoid doing hacks, because then say if you inside a SIGFPE handler
call a cancellation point function and a thread is cancelled, we can't rely
on hacks like libjava/include/*-signal.h is doing.  And the instruction that
divides by zero can be e.g. at the very beginning of a function, or the last
instruction in it.
So, my preference would be for the S flag to mean there is a CFA expression
present in the FDE augmentation area.  unwind-dw2.c (uw_frame_state_for) would evaluate that expression (first pushing say context->cfa to the stack) and
set fs->signal_frame to 1 iff it evaluates to non-zero.  MD_FALLBACK_FRAME_STATE_FOR would conditionally define fs->signal_frame
depending on signal number, or si_code and other stuff.
On i386/x86_64 I guess we want to always set fs->signal_frame (so e.g.
the S CFA expression would be DW_OP_lit1), I'd appreciate feedback for other
arches.

Another issue is that this needs coordination between libgcc/binutils/glibc/kernel/libjava.
I did a quick check:
alpha libc cfi
i386 vDSO or libc       libjava private sigaction
x86_64 libc (bogus cfi, in the end MD_FALLBACK_FRAME_STATE_FOR)
ppc vDSO
ppc64 vDSO
sparc32 libc, MD_FALLBACK_FRAME_STATE_FOR
sparc64 libc, MD_FALLBACK_FRAME_STATE_FOR
s390 stack, MD_FALLBACK_FRAME_STATE_FOR         libjava private sigaction
s390x stack, MD_FALLBACK_FRAME_STATE_FOR        libjava private sigaction
ia64 irrelevant, doesn't use Dwarf2 unwind info

This is most important for libjava, as libjava is doing ugly hacks around this problem and thus should know if S flag will be used or not.  In i386 case we are fine, libjava calls sigaction syscall directly and sets SA_RESTORER, so sigreturn pad in libjava is used.  Alpha could use the same trick, MD_FALLBACK_FRAME_STATE_FOR is under GCC's control, but on ppc/ppc64 we are
in trouble when using approx. November 2005 till now kernels (before that
there was no vDSO on ppc{,64}).
Comment 9 Jakub Jelinek 2006-02-21 17:52:25 UTC
This is related to the almost forgotten http://sources.redhat.com/bugzilla/show_bug.cgi?id=300
Comment 10 Richard Henderson 2006-02-21 18:47:01 UTC
(In reply to comment #8)
> This is what I have so far (libjava not done yet)

The patches so far look fine.  

> but I'm not sure a simple CIE flag isn't sufficient on all arches.

You're confounding two different problems: (1) How to unwind from a signal,
at whatever point the signal is delivered, and (2) How to recognize a given
signal within an exception handling region.

Problem 1 is we arrive at the signal handler with the PC set somewhere.  We
assume that the insn at the PC is the next insn to be executed, and that all
previous insns have already been executed.  This is as true of SIGFPE as any
other signal.

Problem 2 is that the SIGFPE may be deliviered much later than the insn that
caused the signal.  This is particularly obvious with 80387, in that it may
not be delivered until the next FP insn.  The only reason we might want to
care about this problem is if we wish to turn the signal into an exception,
and send that to a surrounding catch handler.  This is not the problem we're
trying to solve in this PR.  Frankly, I'm not too concerned about solving it
ever; it requires changes to code generation to solve properly, and I've seen
no one actually request it.  If anyone would have wanted it, I would have 
expected Java, but Java runs with all FP excptions masked.

> This is most important for libjava, as libjava is doing ugly hacks around this
> problem and thus should know if S flag will be used or not.  In i386 case we
> are fine, libjava calls sigaction syscall directly and sets SA_RESTORER, so
> sigreturn pad in libjava is used.  Alpha could use the same trick

Yep.

> MD_FALLBACK_FRAME_STATE_FOR is under GCC's control, but on ppc/ppc64 we are
> in trouble when using approx. November 2005 till now kernels (before that
> there was no vDSO on ppc{,64}).

Will these kernels refuse the sa_restorer field?  I see that ppc does 
have such a field...
Comment 11 Jakub Jelinek 2006-02-21 22:09:16 UTC
Treating all signal frames as _Unwind_Find_FDE (context->ra, ...) and
fs->pc <= context->ra is certainly better than what we are doing now, but
it will only work say on s390 (other arches that raise exception after
the not yet executed insn?) provided:
a) the faulting instructions that raise the exception after the insn don't affect
unwind info in any way
b) they are never the last insn in a FDE
On i386 I understand that even when the SIGFPE shows up on the next FPU insn,
PC in the sigframe will be before that insn, not after it, but on s390 that's
different.
Consider e.g. (ok, agree, convoluted):
#define _GNU_SOURCE
#include <signal.h>
#include <fenv.h>
#include <unistd.h>

void
sigfpe (int signo)
{
  _exit (0);
}

/* This routine is effectively noreturn, it divides by zero.  */
extern void foo (double, double);

asm ("\n"
".text\n"
".balign 16\n"
".globl foo\n"
".type foo, @function\n"
".cfi_startproc\n"
"foo:\n"
"ddbr %f0,%f2\n"
".cfi_endproc\n"
".size foo, .-foo\n"
".skip 64\n"
".previous\n");

int
main (void)
{
  struct sigaction sa;
  sa.sa_handler = sigfpe;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = 0;
  sigaction (SIGFPE, &sa, 0);
  feenableexcept (FE_ALL_EXCEPT);
  foo (1.0, 0.0);
  return 0;
}

on s390x vs.

#define _GNU_SOURCE
#include <signal.h>
#include <fenv.h>
#include <unistd.h>

double d = 1.0, e = 0.0;

void
sigfpe (int signo)
{
  _exit (0);
}

/* This routine is effectively noreturn, it divides by zero.  */
extern void foo (void);

asm ("\n"
".text\n"
".skip 16\n"
".balign 16\n"
".globl foo\n"
".type foo, @function\n"
".cfi_startproc\n"
"foo:\n"
"fldl e\n"
"fdivrl d\n"
"nop;nop;nop;nop;nop\n"
"jmp bar\n"
".cfi_endproc\n"
".size foo, .-foo\n"
".skip 64\n"
".previous\n");

asm ("\n"
".text\n"
".skip 16\n"
".balign 16\n"
".globl bar\n"
".type bar, @function\n"
".cfi_startproc\n"
"bar:\n"
"fstpl d\n"
".cfi_endproc\n"
".size bar, .-bar\n"
".skip 64\n"
".previous\n");

int
main (void)
{
  struct sigaction sa;
  sa.sa_handler = sigfpe;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = 0;
  sigaction (SIGFPE, &sa, 0);
  feenableexcept (FE_ALL_EXCEPT);
  foo ();
  return 0;
}

on i386 (-O0 -fasynchronous-unwind-tables -fexceptions -lm flags in both cases).
If sigfpe decides to call _Unwind_Backtrace, _Unwind_RaiseException etc., with
vanilla GCC it will DTRT on s390{,x} and do the wrong thing on i386 (will not
find FDE when the exception triggers with PC at the start of fstpl insn).
With the patches here, GCC will DTRT on i386, but will fail with the testcase
above on s390{,x}.  In http://sources.redhat.com/bugzilla/show_bug.cgi?id=300
in third option you were proposing having S flag in CIE augmentation string
correspond to .uleb128 len; CFA expression pair in FDE augmentation area
and assuming we are able to write simple rules that for each arch from
struct sigcontext and/or siginfo_t compute "is this signal sent with PC at
first not fully executed insn or after it?", we are fine.

Regarding PPC/PPC64, it seems the kernel does it unconditionally, it apparently
never honored SA_RESTORER and doesn't do it even now :(.
        /* Set up to return from userspace. */
        if (vdso64_rt_sigtramp && current->thread.vdso_base) {
                regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
        } else {
                err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
                if (err)
                        goto badframe;
                regs->link = (unsigned long) &frame->tramp[0];
        }
and similarly for 32-bit.
Comment 12 Richard Henderson 2006-02-21 23:09:47 UTC
Since no one *currently* cares about unwinding from SIGFPE (how could they,
since it doesn't work on the most popular platform), I think we should ignore
this issue entirely.

The Fix is to ensure that, on a platform-by-platform basis, the generated 
code is tailored to meet the assumptions.  In the case of s390, this means
adding a nop, if needed, so that there is a insn after the fp insn still in
the eh region.  In the case of i386, this means adding an fwait before leaving
the eh region.

As for ppc, that's about what I expected.  I guess we'll just have to document
that there's 3 months worth of kernels that shouldn't be used with gcc 
versions after such-and-such.
Comment 13 Jakub Jelinek 2006-02-21 23:15:45 UTC
Ok, let's S be unconditional CIE flag without any CFA expression and if
a real need for CFA expression ever arises, we can always add another flag, right?

If so, I'll work on finishing the libjava bits and start testing (so far
I only tested the cleanup-12 testcase on x86_64).

Also, do you think we should add .cfi_signal_frame assembler directive?
Currently to my knowledge only Alpha uses .cfi_* directives to describe
signal frame unwinding, so if we don't add it, alpha would need that stuff
rewritten into plain old explicit .eh_frame.
Comment 14 Richard Henderson 2006-02-21 23:25:30 UTC
I guess a .cfi_signal_frame directive would be nice, but not strictly required.
Ideally one should never have to write .eh_frame by hand.
Comment 15 Alan Modra 2006-02-22 01:13:54 UTC
ppc vdso caters for pc-1 with the following.

/* The nop here is a hack.  The dwarf2 unwind routines subtract 1 from
   the return address to get an address in the middle of the presumed
   call instruction.  Since we don't have a call here, we artifically
   extend the range covered by the unwind info by padding before the
   real start.  */
	nop
	.balign 8
V_FUNCTION_BEGIN(__kernel_sigtramp_rt64)
.Lsigrt_start = . - 4
	addi	r1, r1, __SIGNAL_FRAMESIZE
	li	r0,__NR_rt_sigreturn
	sc
.Lsigrt_end:
Comment 16 Alan Modra 2006-02-22 05:11:54 UTC
In regard to comment #15, I see that is only half the problem.  The real difficulty is in the last sentence of Jakub's report.  Hmm.  I suppose we could make the ppc vdso eh_frame info adjust the pc as appropriate.  We already do quite a lot of trickery there..
Comment 17 Jakub Jelinek 2006-02-22 08:11:44 UTC
The nop before the signal trampoline is needed for similar reason, but one
signal frame lower.  A normal signal frame lower in the stack will contain
the exact address of the start of the trampoline (or in unusual cases another signal frame will contain some address within the trampoline's range if a thread
has been signalled while executing the few trampoline instructions).  That's
not what is being addressed in this PR, FDE for the trampoline simply
can start 1 (or more) bytes before the trampoline and there is a limited
number of trampolines (the dynamically created ones are always handled by MD_FALLBACK_FRAME_STATE_FOR).  This PR is about PC stored in the signal frame
and used when handling the bottommost frame above the signal frame.

As for PPC vDSO, if you have a spare register slot in the 0 .. DWARF_FRAME_REGISTERS range, you can certainly try to do the same as the S
flag is doing.  In MD_FALLBACK_FRAME_STATE_FOR it is doable (e.g. s390/linux-unwind.h was doing that, although just for 2 selected signals, which wasn't good enough, as e.g. all async signals need to be handled the same).
Doing it in vDSO's .eh_frame might be far more difficult, remember that DW_CFA_expression returns address where a register is stored and there is
no DW_CFA_expression_value that would be able to compute arbitrary register
values and leave it on unwinder implementation to find a memory slot into
which to store the value during unwinding.  I don't think there are any means
to store some value into certain address in .eh_frame either, so you'd need to modify kernel to store both PC and PC+1 into the sigcontext at handle_signal
time and the .eh_frame to use it.  Doable, but it doesn't buy you anything
over just adding S flags.  In both cases were are trouble with libjava
when using kernels since vDSO was added till either S flag is added to the
vDSO .eh_frame, or the above described ugliness is implemented in the kernel.

In libjava/include/*-signal.h we need to know how will signal frame unwinding
work.  On most architectures we know that - MD_FALLBACK_FRAME_STATE_FOR is
used and we control both M_F_F_S_F and *-signal.h in the same tree.  On some
architectures it is under glibc or kernel control (i386, alpha), but *-signal.h
can override it, force use of M_F_F_S_F or provide its own unwind info.
But on ppc it used to be M_F_F_S_F, but since November it is in kernel's hands
and libjava cannot override.  As the S flag doesn't affect older libgcc's,
the only thing that will not work is GCC (libgcc+libgcj particularly) after
(if) these patches make it in with kernel between November and now.
Comment 18 Ulrich Weigand 2006-02-22 09:57:38 UTC
(In reply to comment #17)

> (e.g. s390/linux-unwind.h was doing that, although just for 2 selected
> signals, which  wasn't good enough, as e.g. all async signals need to be
> handled the same).

We've actually taken quite a bit of care to ensure that the position of
the PC on s390 can be understood deterministically in all cases.  The
synchronous signals come in two flavours:
- SIGSEGV and SIGBUS: here the PC points back to the instruction 
that we attempted and failed to execute -- returning from the signal
handler would by default re-execute the failed instruction
- SIGILL, SIGFPE, and SIGTRAP: here the PC points after the instruction
that caused the signal condition to be raised -- returning from the
signal handler would by default simply continue after that instruction

For all asynchronous signals, the PC points to the first instruction we
have not executed yet -- returning from the signal handler thus continues
execution with that instruction.

So you *need* to handle signals differently depending on what signal
it is -- I'm not sure I understand why you want to remove that.  What
we currently have definitely works correctly for all synchronous signals
on s390.

As for asynchronous signals, I guess it depends on what you want to see
happen here -- I'm not sure what it means to throw an exception from 
within an asynchronous signal handler.   For unwinding purposes, I guess
I can see why you would want the next instruction to show up in the
backtrace, so I wouldn't mind changing the 
  if (signal == SIGBUS || signal == SIGSEGV)
to
  if (signal != SIGILL && signal != SIGFPE && signal != SIGTRAP)
Comment 19 Jakub Jelinek 2006-02-22 10:25:05 UTC
Sure, if you want to do that for s390, s390/linux-unwind.h can still do
if (!signo || (*signo != 4 && *signo != 5 && *signo != 8))
  fs->signal_frame = 1;
(I think !signo -> fs->signal_frame = 1; is better default, there are far more
signals that have PC before insn and assuming PC before insn even when PC is
after insn is less severe problem).
The important thing now is only if this needs to be expressible in .eh_frame
or not.  Richard thinks it does not.
Comment 20 Alan Modra 2006-02-23 00:41:30 UTC
Created attachment 10895 [details]
updated for powerpc and powerpc64

Jakub of course is correct that the vdso eh_frame dwarf2 can't increment the pc.  I realized that a few minutes after making comment #16, but figured I'd already made enough useless comments on this bug so didn't bother correcting myself.

I rather like Jakub's solution.  fs->signal_frame would allow us to easily adjust pc in signal frames if necessary, using MD_FROB_UPDATE_CONTEXT.  I suppose we could even use MD_FROB_UPDATE_CONTEXT to *set* fs->signal_frame for ppc kernels with vdso.
Comment 21 Richard Henderson 2006-02-23 01:01:11 UTC
No. MFUC only applies when there is no unwind information available.  When
the vdso is present, unwind information is available.
Comment 22 Alan Modra 2006-02-23 01:08:33 UTC
Richard, aren't you confusing MD_FALLBACK_FRAME_STATE_FOR with MD_FROB_UPDATE_CONTEXT?  The former only happens when we have no unwind, the latter on each uw_update_context.
Comment 23 Jakub Jelinek 2006-02-24 19:45:07 UTC
Created attachment 10909 [details]
gcc-trunk-pr26208.patch
Comment 24 Jakub Jelinek 2006-02-24 19:45:57 UTC
Created attachment 10910 [details]
binutils-trunk-pr26208.patch
Comment 25 Jakub Jelinek 2006-02-24 19:56:28 UTC
Updated patches.  Unfortunately, it seems even this is not enough as Java
(and C++ as well, but there we aren't expecting to throw through signal
frames), the personality routine does the same as uw_frame_state_for was doing,
i.e. subtract one from ra.  That's ok for most frames, unless they are immediately above a signal trampoline.  In that case we shouldn't be subtracting
one.  But returning context->ra - fs->signal_frame in _Unwind_GetIP is a bad idea
IMHO, _Unwind_GetIP should show some instruction pointer, context->ra - 1
may very well not be start of any instruction.  For e.g. _Unwind_Backtrace we
want context->ra as is, not adjusted.  So, I'd say we should export
a new function from libgcc_s, either something like
_Unwind_SignalFrameContext (context) which will return context->signal_frame != 0, or _Unwind_GetIP alternative, _Unwind_GetAdjustedIP (context).
In the first case, C++/Java personality routine would use
_Unwind_GetIP (context) + (_Unwind_SignalFrameContext (context) ? 0 : -1)
instead of the current _Unwind_GetIP (context) - 1, in the latter case it would
use _Unwind_GetAdjustedIP (context) instead of _Unwind_GetIP (context) - 1.
_Unwind_SignalFrameContext sounds more flexible to me.
Richard, what do you think?
Comment 26 Richard Henderson 2006-02-25 01:00:35 UTC
I agree we shouldn't mess with _Unwind_GetIP.  While I kinda like the idea
behind _Unwind_SignalFrameContext, I'm not sure I like the idea of the 
effectively mandatory back-to-back PLT calls.  If you think that _U_SFC
would be useful on its own, then I think we should add both that and the
_U_GetAdjustedIP.
Comment 27 Jakub Jelinek 2006-02-26 22:16:02 UTC
Created attachment 10915 [details]
gcc-trunk-pr26208-2.patch

Incremental patch that introduces _Unwind_GetIPInfo (if anyone knows better
name, suggestions of course welcome) that returns both IP and flag whether
IP is before or after the first non-executed instruction.
So far bootstrapped/regtested on i686-linux and x86_64-linux, no regressions.
Will do more testing on other arches tomorrow.
Comment 28 Jakub Jelinek 2006-02-27 17:26:34 UTC
Subject: Bug 26208

Author: jakub
Date: Mon Feb 27 17:26:26 2006
New Revision: 111488

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=111488
Log:
	PR other/26208
	* unwind-dw2.c (struct _Unwind_Context): Add signal_frame field.
	(extract_cie_info): Handle S flag in augmentation string.
	(execute_cfa_program): If context->signal_frame, execute also
	fs->pc == context->ra instructions.
	(uw_frame_state_for): If context->signal_frame, don't subtract one
	from context->ra to find FDE.
	(uw_update_context_1): Set context->signal_frame to
	fs->signal_frame.
	(_Unwind_GetIPInfo): New function.
	* unwind-dw2.h (_Unwind_FrameState): Add signal_frame field.
	* unwind-c.c (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
	of _Unwind_GetIP.
	* unwind-sjlj.c (_Unwind_GetIPInfo): New function.
	* unwind-generic.h (_Unwind_GetIPInfo): New prototype.
	* unwind-compat.c (_Unwind_GetIPInfo): New function.
	* libgcc-std.ver (_Unwind_GetIPInfo): Export @@GCC_4.2.0.
	* config/ia64/unwind-ia64.c (_Unwind_GetIPInfo): New function.
	* config/arm/unwind-arm.h (_Unwind_GetIPInfo): Define.
	* config/i386/linux-unwind.h (x86_fallback_frame_state,
	x86_64_fallback_frame_state): Set fs->signal_frame.
	* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
	(MD_FROB_UPDATE_CONTEXT): Define unconditionally.
	(frob_update_context): Likewise.  Workaround missing S flag in
	Linux 2.6.12 - 2.6.16 kernel vDSOs.
	* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
	Remove the psw_addr + 1 hack.
libjava/
	* exception.cc (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
	of _Unwind_GetIP.
	* include/i386-signal.h (MAKE_THROW_FRAME): Change into empty macro.
	(HANDLE_DIVIDE_OVERFLOW): Don't adjust _res->eip if falling through
	to throw.
	* include/x86_64-signal.h (MAKE_THROW_FRAME): Change into empty
	macro.
	* include/powerpc-signal.h (MAKE_THROW_FRAME): Change into empty
	macro.
libstdc++-v3/
	* libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Use
	_Unwind_GetIPInfo instead of _Unwind_GetIP.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/arm/unwind-arm.h
    trunk/gcc/config/i386/linux-unwind.h
    trunk/gcc/config/ia64/unwind-ia64.c
    trunk/gcc/config/rs6000/linux-unwind.h
    trunk/gcc/config/s390/linux-unwind.h
    trunk/gcc/libgcc-std.ver
    trunk/gcc/unwind-c.c
    trunk/gcc/unwind-compat.c
    trunk/gcc/unwind-dw2.c
    trunk/gcc/unwind-dw2.h
    trunk/gcc/unwind-generic.h
    trunk/gcc/unwind-sjlj.c
    trunk/libjava/ChangeLog
    trunk/libjava/exception.cc
    trunk/libjava/include/i386-signal.h
    trunk/libjava/include/powerpc-signal.h
    trunk/libjava/include/x86_64-signal.h
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/libsupc++/eh_personality.cc

Comment 29 Jakub Jelinek 2006-02-28 22:20:43 UTC
Subject: Bug 26208

Author: jakub
Date: Tue Feb 28 22:20:34 2006
New Revision: 111581

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=111581
Log:
	PR other/26208
	* unwind-dw2.c (struct _Unwind_Context): Add signal_frame field.
	(extract_cie_info): Handle S flag in augmentation string.
	(execute_cfa_program): If context->signal_frame, execute also
	fs->pc == context->ra instructions.
	(uw_frame_state_for): If context->signal_frame, don't subtract one
	from context->ra to find FDE.
	(uw_update_context_1): Set context->signal_frame to
	fs->signal_frame.
	(_Unwind_GetIPInfo): New function.
	* unwind-dw2.h (_Unwind_FrameState): Add signal_frame field.
	* unwind-c.c (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
	of _Unwind_GetIP.
	* unwind-sjlj.c (_Unwind_GetIPInfo): New function.
	* unwind-generic.h (_Unwind_GetIPInfo): New prototype.
	* unwind-compat.c (_Unwind_GetIPInfo): New function.
	* libgcc-std.ver (_Unwind_GetIPInfo): Export @@GCC_4.2.0.
	* config/ia64/unwind-ia64.c (_Unwind_GetIPInfo): New function.
	* config/arm/unwind-arm.h (_Unwind_GetIPInfo): Define.
	* config/i386/linux-unwind.h (x86_fallback_frame_state,
	x86_64_fallback_frame_state): Set fs->signal_frame.
	* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
	(MD_FROB_UPDATE_CONTEXT): Define unconditionally.
	(frob_update_context): Likewise.  Workaround missing S flag in
	Linux 2.6.12 - 2.6.16 kernel vDSOs.
	* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
	Remove the psw_addr + 1 hack.
libjava/
	* exception.cc (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
	of _Unwind_GetIP.
	* include/i386-signal.h (MAKE_THROW_FRAME): Change into empty macro.
	(HANDLE_DIVIDE_OVERFLOW): Don't adjust _res->eip if falling through
	to throw.
	* include/x86_64-signal.h (MAKE_THROW_FRAME): Change into empty
	macro.
	* include/powerpc-signal.h (MAKE_THROW_FRAME): Change into empty
	macro.
libstdc++-v3/
	* libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Use
	_Unwind_GetIPInfo instead of _Unwind_GetIP.

Modified:
    branches/redhat/gcc-4_1-branch/gcc/ChangeLog
    branches/redhat/gcc-4_1-branch/gcc/config/arm/unwind-arm.h
    branches/redhat/gcc-4_1-branch/gcc/config/i386/linux-unwind.h
    branches/redhat/gcc-4_1-branch/gcc/config/ia64/unwind-ia64.c
    branches/redhat/gcc-4_1-branch/gcc/config/rs6000/linux-unwind.h
    branches/redhat/gcc-4_1-branch/gcc/config/s390/linux-unwind.h
    branches/redhat/gcc-4_1-branch/gcc/libgcc-std.ver
    branches/redhat/gcc-4_1-branch/gcc/unwind-c.c
    branches/redhat/gcc-4_1-branch/gcc/unwind-compat.c
    branches/redhat/gcc-4_1-branch/gcc/unwind-dw2.c
    branches/redhat/gcc-4_1-branch/gcc/unwind-dw2.h
    branches/redhat/gcc-4_1-branch/gcc/unwind-generic.h
    branches/redhat/gcc-4_1-branch/gcc/unwind-sjlj.c
    branches/redhat/gcc-4_1-branch/libjava/ChangeLog
    branches/redhat/gcc-4_1-branch/libjava/exception.cc
    branches/redhat/gcc-4_1-branch/libjava/include/i386-signal.h
    branches/redhat/gcc-4_1-branch/libjava/include/powerpc-signal.h
    branches/redhat/gcc-4_1-branch/libjava/include/x86_64-signal.h
    branches/redhat/gcc-4_1-branch/libstdc++-v3/ChangeLog
    branches/redhat/gcc-4_1-branch/libstdc++-v3/libsupc++/eh_personality.cc

Comment 30 Jakub Jelinek 2006-04-06 13:30:43 UTC
Fixed on the trunk.
Comment 31 Pawel Sikora 2006-09-05 14:31:49 UTC
is it possible to make gcc unwinder work for solaris too?

at this moment unwinding (after throwing the std::exception
from signal handler) on sunos-5.9 looks like this:

       0x10000141c : signalHandler(int)+0x8 
0xffffffff7e8a7b50 : _setuid+0x4c from /usr/lib/sparcv9/libc.so.1
terminate called after throwing an instance of 'std::runtime_error'
  what():  test
Abort (core dumped)
Comment 32 Eric Botcazou 2008-07-07 08:33:27 UTC
Jakub, the patch contains a workaround for the missing S in the CIE augmentation
string for "old" kernels on PPC.  Is this problem really specific to PPC?  It
seems that I'm seeing it on x86 too with 2.6.8 and 2.6.16 kernels.