On 31.10.17 22:36, Gerald Pfeifer wrote:
On Tue, 31 Oct 2017, Andreas Tobler wrote:
Do we, FreeBSD'ers, want to have gcc unwind support on older than
FreeBSD 9.3 releases? I think the gcc folks do not care, but we are the
ones who might have an need for such a support?
@Gerald, do you have an opinion?
Yes. No. :-)
Those possibly still stuck on obsolete versions of FreeBSD don't
need/want fancy new compilers and GCC 4.9 is still available for
use and does not exhibit this issue, correct? (If it does, nobody
reported any problems.)
It is limited to gcc >=5, gcc-4.9 does not have the
MD_FALLBACK_FRAME_STATE_FOR defined.
I can 'ifdef' the new code and in the 'else' case we fall back to
the already existing path.
If it's "cheap", that might be nice.
Attached, the test is running on gcc trunk and gcc-6. gcc-6 is the last
one with java support and there we have quite extensive test cases which
really test for this MD_FALLBACK_FRAME_STATE_FOR macro. These test
cases, Throw_2 and co do pass. So I think the new bits should be fine.
Also some coming asan test cases do pass with this addition too.
Thanks to the three of you - Tijl, Konstantin, and Andreas!
Gruss,
Andreas
Index: libgcc/config/i386/freebsd-unwind.h
===================================================================
--- libgcc/config/i386/freebsd-unwind.h (revision 254205)
+++ libgcc/config/i386/freebsd-unwind.h (working copy)
@@ -28,7 +28,10 @@
#include <sys/types.h>
#include <signal.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
#include <sys/ucontext.h>
+#include <sys/user.h>
#include <machine/sigframe.h>
#define REG_NAME(reg) sf_uc.uc_mcontext.mc_## reg
@@ -36,6 +39,39 @@
#ifdef __x86_64__
#define MD_FALLBACK_FRAME_STATE_FOR x86_64_freebsd_fallback_frame_state
+#ifdef KERN_PROC_SIGTRAMP
+ /* Newer versions of FreeBSD, > FreeBSD 9.3, provide a
+ kern.proc.sigtramp.<pid> sysctl that returns the location of the
+ signal trampoline. We use this information to find out if we're in
+ a trampoline or not.
+ */
+static int
+x86_64_outside_sigtramp_range (unsigned char *pc)
+{
+ static int sigtramp_range_determined = 0;
+ static unsigned char *sigtramp_start, *sigtramp_end;
+
+ if (sigtramp_range_determined == 0)
+ {
+ struct kinfo_sigtramp kst = {0};
+ size_t len = sizeof (kst);
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid() };
+
+ sigtramp_range_determined = 1;
+ if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0)
+ {
+ sigtramp_range_determined = 2;
+ sigtramp_start = kst.ksigtramp_start;
+ sigtramp_end = kst.ksigtramp_end;
+ }
+ }
+ if (sigtramp_range_determined < 2) /* sysctl failed if < 2 */
+ return 1;
+
+ return (pc < sigtramp_start || pc >= sigtramp_end);
+}
+#endif
+
static _Unwind_Reason_Code
x86_64_freebsd_fallback_frame_state
(struct _Unwind_Context *context, _Unwind_FrameState *fs)
@@ -43,6 +79,7 @@
struct sigframe *sf;
long new_cfa;
+#ifndef KERN_PROC_SIGTRAMP
/* Prior to FreeBSD 9, the signal trampoline was located immediately
before the ps_strings. To support non-executable stacks on AMD64,
the sigtramp was moved to a shared page for FreeBSD 9. Unfortunately
@@ -62,12 +99,15 @@
&& *(unsigned int *)(context->ra + 8) == 0x01a1c0c7
&& *(unsigned int *)(context->ra + 12) == 0x050f0000 ))
return _URC_END_OF_STACK;
+#else
+ if (x86_64_outside_sigtramp_range(context->ra))
+ return _URC_END_OF_STACK;
+#endif
sf = (struct sigframe *) context->cfa;
new_cfa = sf->REG_NAME(rsp);
fs->regs.cfa_how = CFA_REG_OFFSET;
- /* Register 7 is rsp */
- fs->regs.cfa_reg = 7;
+ fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
fs->regs.cfa_offset = new_cfa - (long) context->cfa;
/* The SVR4 register numbering macros aren't usable in libgcc. */
_______________________________________________
freebsd-current@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"