diff options
author | John Marino <gnugcc@marino.st> | 2017-07-19 15:55:11 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2017-07-19 16:55:11 +0100 |
commit | de7422048ee2e388cedbeb328077948ae8f06c2a (patch) | |
tree | bd6989b07b46ec381f344b4b3cc82b35b3ef56b7 /libgcc | |
parent | e020783cd60ae60a361cd18f1a3763f65f30b0b8 (diff) | |
download | gcc-de7422048ee2e388cedbeb328077948ae8f06c2a.zip gcc-de7422048ee2e388cedbeb328077948ae8f06c2a.tar.gz gcc-de7422048ee2e388cedbeb328077948ae8f06c2a.tar.bz2 |
Fix Unwind support on DragonFly BSD after sigtramp move
2017-07-19 John Marino <gnugcc@marino.st>
* config/i386/dragonfly-unwind.h: Handle sigtramp relocation.
From-SVN: r250354
Diffstat (limited to 'libgcc')
-rw-r--r-- | libgcc/ChangeLog | 4 | ||||
-rw-r--r-- | libgcc/config/i386/dragonfly-unwind.h | 59 |
2 files changed, 46 insertions, 17 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 36e0847..db33eea 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,7 @@ +2017-07-19 John Marino <gnugcc@marino.st> + + * config/i386/dragonfly-unwind.h: Handle sigtramp relocation. + 2017-07-12 Michael Meissner <meissner@linux.vnet.ibm.com> PR target/81193 diff --git a/libgcc/config/i386/dragonfly-unwind.h b/libgcc/config/i386/dragonfly-unwind.h index 18b90fc..ca1f46e 100644 --- a/libgcc/config/i386/dragonfly-unwind.h +++ b/libgcc/config/i386/dragonfly-unwind.h @@ -28,9 +28,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #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.RUNTIME respectively. If not, see #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); - - *start = (unsigned char *)ps_strings - 32; - *end = (unsigned char *)ps_strings; + static int sigtramp_range_determined = 0; + static unsigned char *sigtramp_start, *sigtramp_end; + + 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; |