------- Comment #11 from jakub at gcc dot gnu dot org  2006-02-21 22:09 -------
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.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208

Reply via email to