This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ppc64 unwinding problem


Hi!

Although ppc64-linux defines MD_FALLBACK_FRAME_STATE_FOR, it cannot unwind
through signal handlers.

The problem is rs6000_emit_eh_toc_restore, which during __builtin_eh_return
emits a loop to restore r2 register (which is never noted in FDEs,
as it is a register under linker's control, not compiler).
This loop has the AIX ABI assumptions, ie. that word at $r1 contains
saved $r1, 16($r1) is saved lr and 40($r1) is saved $r2.
Unfortunately this cannot work with MD_FALLBACK_FRAME_STATE_FOR, as
signal handler frame does not follow AIX calling convention and thus
the loop generated by __builtin_eh_return segfaults.
This is very bad, not only because some libgcj stuff does not work
(there are other bugs on ppc64 in gcj), but because NPTL relies on this.

I think adding code to __builtin_eh_return to recognize and handle
linux signal frames would be way too ugly (and would mean basically
duplicating MD_FALLBACK_FRAME_STATE_FOR functionality, though in RTL),
so as a different alternative I see adding some MD_CFA_PROGRAM macro
which would do an implicit CFA operation (I don't think
if (*($r1 + 16) == 0xE8410028) DW_CFA_offset (2, -40); else do nothing
is expressible in Dwarf2) either before or after executing CIE CFA program.
What do you think about that?

/* { dg-do run { target i?86-*-linux* x86_64-*-linux* ia64-*-linux* alpha*-*-linux* powerpc*-*-linux* s390*-*-linux* sparc*-*-linux* } } */
/* { dg-options "-fasynchronous-unwind-tables -fexceptions -O2" } */
/* Verify that cleanups work with exception handling through signal
   frames.  */

#include <unwind.h>
#include <stdlib.h>
#include <signal.h>

static _Unwind_Reason_Code
force_unwind_stop (int version, _Unwind_Action actions,
                   _Unwind_Exception_Class exc_class,
                   struct _Unwind_Exception *exc_obj,
                   struct _Unwind_Context *context,
                   void *stop_parameter)
{
  if (actions & _UA_END_OF_STACK)
    abort ();
  return _URC_NO_REASON;
}

static void force_unwind ()
{
  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
  exc->exception_class = 0;
  exc->exception_cleanup = 0;
                   
#ifndef __USING_SJLJ_EXCEPTIONS__
  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
#else
  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
#endif
                   
  abort ();
}

int count;
char *null;

static void counter (void *p __attribute__((unused)))
{
  ++count;
}

static void handler (void *p __attribute__((unused)))
{
  if (count != 2)
    abort ();
  exit (0);
}

static int __attribute__((noinline)) fn5 ()
{
  char dummy __attribute__((cleanup (counter)));
  force_unwind ();
  return 0;
}

static void fn4 (int sig)
{
  char dummy __attribute__((cleanup (counter)));
  fn5 ();
  null = NULL;
}

static void fn3 ()
{
  abort ();
}

static int __attribute__((noinline)) fn2 ()
{
  *null = 0;
  fn3 ();
  return 0;
}

static int __attribute__((noinline)) fn1 ()
{
  signal (SIGSEGV, fn4);
  fn2 ();
  return 0;
}

static int __attribute__((noinline)) fn0 ()
{
  char dummy __attribute__((cleanup (handler)));
  fn1 ();
  null = 0;
  return 0;
}

int main()
{ 
  fn0 ();
  abort ();
}


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]