public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: John Marino <gnugcc@marino.st>
To: gcc-patches <gcc-patches@gcc.gnu.org>
Subject: [patch] Fix Unwind support on DragonFly BSD after sigtramp move
Date: Fri, 07 Jul 2017 23:17:00 -0000	[thread overview]
Message-ID: <fac907b9-e5f1-8251-ff3c-cf89cd9e511d@marino.st> (raw)

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

Right after DragonFly 4.8 was released (27 Mar 2017), the signal 
trampoline was moved (twice) in response to a Ryzen bug.  This broke 
GCC's unwind support for DragonFly.

To avoid hardcoding the sigtramp location to avoid issues like this in 
the future, a new sysctl was added to DragonFly to return the signal 
trampoline address range (FreeBSD has a similar sysctl for similar 
reasons).  The attached patch fixes DragonFly unwind support for current 
DragonFly, and maintains support for Release 4.8 and earlier.

This patch has been in use for a few months and works fine.  It is 
similar in function to the FreeBSD Aarch64 unwind support I submitted 
through Andreas T. a few months ago.

I believe the patch can be applied to trunk and release 7 branch.
I am the closest thing to a maintainer for DragonFly, so I don't know if 
additional approval is needed.  This patch is purely DragonFly-specific 
and cannot affect other platforms in any way.

If agreed, it would be great if somebody could commit this for me 
against the trunk and GCC-7-branch.

Thanks!
John

P.S.  Yes, my copyright assignment is on file (I've contributed a few 
patches already).

suggested log entry of libgcc/ChangeLog:

2017-07-XX  John Marino  <gnugcc@marino.st>
        * config/i386/dragonfly-unwind.h: Handle sigtramp relocation.

[-- Attachment #2: patch-libgcc_config_i386_dragonfly-unwind.h --]
[-- Type: text/x-chdr, Size: 2657 bytes --]

--- libgcc/config/i386/dragonfly-unwind.h.orig	2017-02-06 16:26:52 UTC
+++ libgcc/config/i386/dragonfly-unwind.h
@@ -28,9 +28,13 @@ see the files COPYING3 and COPYING.RUNTI
 
 #include <sys/types.h>
 #include <sys/sysctl.h>
+#include <sys/param.h>
 #include <signal.h>
 #include <sys/ucontext.h>
 #include <machine/sigframe.h>
+#if __DragonFly_version > 400800
+#include <sys/kinfo.h>
+#endif
 
 
 #define REG_NAME(reg)	sf_uc.uc_mcontext.mc_## reg
@@ -39,20 +43,44 @@ see the files COPYING3 and COPYING.RUNTI
 #define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
 
 
-static void
-x86_64_sigtramp_range (unsigned char **start, unsigned char **end)
+static int
+x86_64_outside_sigtramp_range (unsigned char *pc)
 {
-  unsigned long ps_strings;
-  int mib[2];
-  size_t len;
-
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PS_STRINGS;
-  len = sizeof (ps_strings);
-  sysctl (mib, 2, &ps_strings, &len, NULL, 0);
+  static int sigtramp_range_determined = 0;
+  static unsigned char *sigtramp_start, *sigtramp_end;
 
-  *start = (unsigned char *)ps_strings - 32;
-  *end   = (unsigned char *)ps_strings;
+  if (sigtramp_range_determined == 0)
+    {
+#if __DragonFly_version > 400800
+      struct kinfo_sigtramp kst = {0};
+      size_t len = sizeof (kst);
+      int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP };
+
+      sigtramp_range_determined = 1;
+      if (sysctl (mib, 3, &kst, &len, NULL, 0) == 0)
+      {
+        sigtramp_range_determined = 2;
+        sigtramp_start = kst.ksigtramp_start;
+        sigtramp_end   = kst.ksigtramp_end;
+      }
+#else
+      unsigned long ps_strings;
+      size_t len = sizeof (ps_strings);
+      int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
+  
+      sigtramp_range_determined = 1;
+      if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
+      {
+        sigtramp_range_determined = 2;
+        sigtramp_start = (unsigned char *)ps_strings - 32;
+        sigtramp_end   = (unsigned char *)ps_strings;
+      }
+#endif
+    }
+  if (sigtramp_range_determined < 2)  /* sysctl failed if < 2 */
+    return 1;
+
+  return (pc < sigtramp_start || pc >= sigtramp_end );
 }
 
 
@@ -60,13 +88,10 @@ static _Unwind_Reason_Code
 x86_64_dragonfly_fallback_frame_state
 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 {
-  unsigned char *pc = context->ra;
-  unsigned char *sigtramp_start, *sigtramp_end;
   struct sigframe *sf;
   long new_cfa;
 
-  x86_64_sigtramp_range(&sigtramp_start, &sigtramp_end);
-  if (pc >= sigtramp_end || pc < sigtramp_start)
+  if (x86_64_outside_sigtramp_range(context->ra))
     return _URC_END_OF_STACK;
 
   sf = (struct sigframe *) context->cfa;

             reply	other threads:[~2017-07-07 23:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-07 23:17 John Marino [this message]
2017-07-19  5:50 ` Jeff Law
2017-07-19 15:56   ` Jonathan Wakely

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=fac907b9-e5f1-8251-ff3c-cf89cd9e511d@marino.st \
    --to=gnugcc@marino.st \
    --cc=gcc-patches@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).