public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Andrew Haley <aph@redhat.com>
To: "gcc@gcc.gnu.org" <gcc@gcc.gnu.org>
Subject: ARM Linux EABI: unwinding through a segfault handler
Date: Thu, 25 Aug 2011 12:26:00 -0000	[thread overview]
Message-ID: <4E563F58.2060006@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 3455 bytes --]

Throwing an exception through a segfault handler doesn't always work
on ARM: the attached example fails on current gcc trunk.

panda-9:~ $ g++ segv.cc -fnon-call-exceptions -g
panda-9:~ $ ./a.out
terminate called after throwing an instance of 'FoobarException*'
Aborted

The bug is that _Unwind_GetIPInfo doesn't correctly set ip_before_insn.
Instead, it always sets it to zero; it should be set to 1 if this
is a frame created by a signal handler:


#define _Unwind_GetIPInfo(context, ip_before_insn) \
  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)


Fixing this on ARM is hard because signal frames aren't specially
marked as they are on systems that use DWARF unwinder data.  I have
a patch that works on systems where the signal restorer is exactly

        mov     r7, $SYS_rt_sigreturn
        swi     0x0

It works as a proof of concept, but it's fugly.

So, suggestions welcome.  Is there a nice way to detect a signal frame?

Andrew.


2011-08-25  Andrew Haley  <aph@redhat.com>

	* config/arm/unwind-arm.h (_Unwind_IsSignalFrame): New.
	(_Unwind_GetIPInfo): Use _Unwind_IsSignalFrame.
	* config/arm/unwind-arm.c (UCB_SIGNAL_FRAME): New def.
	(get_eit_entry): Update UCB_SIGNAL_FRAME.
	(_Unwind_IsSignalFrame): New function.

Index: config/arm/unwind-arm.c
===================================================================
--- config/arm/unwind-arm.c     (revision 178028)
+++ config/arm/unwind-arm.c     (working copy)
@@ -61,6 +61,7 @@
 #define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
 #define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
 #define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4)
+#define UCB_SIGNAL_FRAME(ucbp) ((ucbp)->unwinder_cache.reserved5)

 struct core_regs
 {
@@ -595,7 +596,14 @@
 {
   const __EIT_entry * eitp;
   int nrec;
-
+
+  {
+    _uw *pc = (_uw *)(return_address & ~3);
+     UCB_SIGNAL_FRAME(ucbp) <<= 1;
+     UCB_SIGNAL_FRAME(ucbp)
+       |= pc[0] == 0xe3a070ad && pc[1] == 0xef000000;
+  }
+
   /* The return address is the address of the instruction following the
      call instruction (plus one in thumb mode).  If this was the last
      instruction in the function the address will lie in the following
@@ -941,6 +949,15 @@
 }


+_Unwind_Word
+_Unwind_IsSignalFrame (_Unwind_Context *context)
+{
+  _Unwind_Control_Block *ucbp
+    = (_Unwind_Control_Block *)_Unwind_GetGR (context, 12);
+  return (UCB_SIGNAL_FRAME (ucbp) & 2) != 0;
+}
+
+
 /* Free an exception.  */

 void
Index: config/arm/unwind-arm.h
===================================================================
--- config/arm/unwind-arm.h     (revision 178028)
+++ config/arm/unwind-arm.h     (working copy)
@@ -217,6 +217,8 @@
   _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
                                            __gnu_unwind_state *);

+  _Unwind_Word _Unwind_IsSignalFrame (_Unwind_Context *context);
+
   /* Decode an R_ARM_TARGET2 relocation.  */
   static inline _Unwind_Word
   _Unwind_decode_target2 (_Unwind_Word ptr)
@@ -254,7 +256,8 @@
   (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)

 #define _Unwind_GetIPInfo(context, ip_before_insn) \
-  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+    (*ip_before_insn = _Unwind_IsSignalFrame (context), \
+      _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)

   static inline void
   _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)




[-- Attachment #2: segv.cc --]
[-- Type: text/plain, Size: 509 bytes --]

#define _POSIX_SOURCE

#include <signal.h>
#include <stdio.h>

int *a;

class FoobarException
{
  int thingy;
};

void signal_handler(int signum, siginfo_t *info, void *)
{
  FoobarException *f = new FoobarException;
  throw f;
}

int main()
{
  struct sigaction act;

  act.sa_sigaction = signal_handler;
  sigemptyset (&act.sa_mask);
  act.sa_flags = SA_SIGINFO;
  sigaction (11, &act, NULL);

  try
    {
      printf("%d\n", *a);
    }
  catch (FoobarException *f)
    {
      printf("Hello!\n");
    }
}

             reply	other threads:[~2011-08-25 12:26 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-25 12:26 Andrew Haley [this message]
2011-08-25 16:57 ` David Daney
2011-08-25 17:01   ` Andrew Haley
2011-08-29 15:19 ` Ken Werner
2011-08-29 17:14   ` Daniel Jacobowitz
2011-08-30  9:11     ` Andrew Haley
2011-08-30 15:28     ` Joseph S. Myers
2011-10-27  8:33     ` Paul Brook
2011-10-27  9:06       ` Andrew Haley
2011-10-27 12:54         ` Paul Brook
2011-10-27 12:55           ` Andrew Haley
2011-10-27 13:25             ` Paul Brook
2015-02-03 22:41               ` mads_bn
2015-09-18 15:37                 ` Matthijs van Duin
2015-10-03 20:41                   ` Matthijs van Duin
2015-10-04  8:05                     ` Andrew Haley
2015-10-04 12:09                       ` Matthijs van Duin
2015-10-05 15:24                         ` Ian Lance Taylor
2015-02-03 22:42               ` mads_bn
2014-08-01 12:25 ` prafullakota
2015-10-04  8:50 SV: " mads_bn
2015-10-04 13:09 ` Matthijs van Duin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4E563F58.2060006@redhat.com \
    --to=aph@redhat.com \
    --cc=gcc@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).