public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* ARM Linux EABI: unwinding through a segfault handler
@ 2011-08-25 12:26 Andrew Haley
  2011-08-25 16:57 ` David Daney
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Andrew Haley @ 2011-08-25 12:26 UTC (permalink / raw)
  To: gcc

[-- 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");
    }
}

^ permalink raw reply	[flat|nested] 21+ messages in thread
* SV: ARM Linux EABI: unwinding through a segfault handler
@ 2015-10-04  8:50 mads_bn
  2015-10-04 13:09 ` Matthijs van Duin
  0 siblings, 1 reply; 21+ messages in thread
From: mads_bn @ 2015-10-04  8:50 UTC (permalink / raw)
  To: gcc

Nice work !

 

Some time ago I was in a project, where we would like to get more context in
syslog when e.g. SIGSEGV occurred (embedded Linux).

On x86 this was working fine, and I hope a change like this for ARM will
allow it to work here as well (as long as stack is still valid).

 

I don't have access to such an ARM setup currently.

Can somebody try if e.g. backtrace_symbols () will show where the offending
code was called from?

http://linux.die.net/man/3/backtrace_symbols 

 

Also I really like the idea to get this back into the mainstream version, so
we all will benefit from it in future ;-)

 

/Mads

 

Fra: Matthijs van Duin [via gcc]
[mailto:ml-node+s1065356n1191196h83@n5.nabble.com] 
Sendt: 3. oktober 2015 22:42
Til: mads_bn <madsbn@mail.dk>
Emne: Re: ARM Linux EABI: unwinding through a segfault handler

 

A shiny revised version of my unwind-through-signal code for ARM EABI: 

https://github.com/mvduin/arm-signal-unwind/

For actual unwinding it now uses sigreturn as a cleanup handler (after 
diddling the ucontext to make it land right onto a call to 
_Unwind_Resume), which means that all state should get properly 
restored by the kernel. 

Virtual unwinding still only restores core registers, but hopefully 
that isn't too big a problem in practice. 

A small test is included that confirms throwing exceptions out of 
SEGV, checks VFP is restored properly, and that returning normally 
from an async signal handler still works (my original patch accidently 
broke that). 

I'd finally like to take a moment to say this was hell to figure 
out.... this shit is really documented nowhere properly since it 
appears to be a magic blend of ARM EABI and IA64 C++ ABI (meaning 
neither documentation quite applies) and I had to plow through the 
innards of libgcc and libsupc++ to figure out how things *actually* 
work. Argh. 

Anyhow, it only took four years, but you can now throw 
NullPointerExceptions on ARM. Enjoy. ;-) 

Matthijs van Duin 



  _____  

If you reply to this email, your message will be added to the discussion
below:

http://gcc.1065356.n5.nabble.com/ARM-Linux-EABI-unwinding-through-a-segfault
-handler-tp692287p1191196.html 

To unsubscribe from ARM Linux EABI: unwinding through a segfault handler,
click here
<http://gcc.1065356.n5.nabble.com/template/NamlServlet.jtp?macro=unsubscribe
_by_code&node=692287&code=bWFkc2JuQG1haWwuZGt8NjkyMjg3fDIwNDQ1NTEzNzU=> .
 
<http://gcc.1065356.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewe
r&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNam
espace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.Nod
eNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emai
ls%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml> NAML 





--
View this message in context: http://gcc.1065356.n5.nabble.com/SV-ARM-Linux-EABI-unwinding-through-a-segfault-handler-tp1191260.html
Sent from the gcc - Dev mailing list archive at Nabble.com.

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2015-10-05 15:24 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-25 12:26 ARM Linux EABI: unwinding through a segfault handler Andrew Haley
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

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).