From: Paul Floyd Date: Sun, 27 Oct 2024 16:48:58 +0000 (+0100) Subject: FreeBSD: put back stacktrace hack for syscalls in older versions X-Git-Tag: VALGRIND_3_24_0~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d9ba0fc48edc3f183520185e25926dde1434219;p=thirdparty%2Fvalgrind.git FreeBSD: put back stacktrace hack for syscalls in older versions --- diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 2cb0f3233..630b5b875 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -282,6 +282,26 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, i = 1; if (do_stats) stats.nr++; + // Does this apply to macOS 10.14 and earlier? +# if defined(VGO_freebsd) && (__FreeBSD_version < 1300000) + if (VG_(is_valid_tid)(tid_if_known) && + VG_(is_in_syscall)(tid_if_known) && + i < max_n_ips) { + /* On FreeBSD, all the system call stubs have no function + * prolog. So instead of top of the stack being a new + * frame comprising a saved BP and a return address, we + * just have the return address in the caller's frame. + * Adjust for this by recording the return address. + */ + if (debug) + VG_(printf)(" in syscall, use XSP-1\n"); + ips[i] = *(Addr *)uregs.xsp - 1; + if (sps) sps[i] = uregs.xsp; + if (fps) fps[i] = uregs.xbp; + i++; + } +# endif + while (True) { if (i >= max_n_ips) @@ -502,19 +522,19 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd) /* - * Concerning the comment in the function about syscalls, this also used to - * apply to FreeBSD. I'm not sure what changed or when. The situation with - * FreeBSD going at least as far back as version 12.1 (so Nov 2019) is that - * system calls are implemented with generated wrappers that call through - * an interposing table of function pointers. The restult when built with - * clang is that code for the frame pointer prolog is generated but then - * an optimized sibling call is made. That means the frame pointer is popped - * off the stack and a jmp is made to the function in the table rather than + * Concerning the comment in the function about syscalls, I'm not sure + * what changed or when with FreeBSD. The situation going at least + * as far back as FreeBSD 12.1 (so Nov 2019) is that system calls are + * implemented with generated wrappers that call through an interposing + * table of function pointers. The result when built with clang is that + * code for the frame pointer prolog is generated but then an optimized + * sibling call is made. That means the frame pointer is popped off + * the stack and a jmp is made to the function in the table rather than * a call. * * The end result is that, when we are in a syscall it is as though there were - * no prolog but a copy of the frame pointer is stored 64byte word below the - * stack pointer. If FreeBSD uses the hack for Darwin that sets + * no prolog but a copy of the frame pointer is stored one 64bit word below the + * stack pointer. If more recent FreeBSD uses the hack that sets * ips[i] = *(Addr *)uregs.xsp - 1; * then the caller of the syscall gets added twice. */ @@ -592,7 +612,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, VG_(printf)(" ipsS[%d]=%#08lx rbp %#08lx rsp %#08lx\n", i-1, ips[i-1], uregs.xbp, uregs.xsp); -# if defined(VGO_darwin) +# if defined(VGO_darwin) || (defined(VGO_freebsd) && __FreeBSD_version < 1300000) if (VG_(is_valid_tid)(tid_if_known) && VG_(is_in_syscall)(tid_if_known) && i < max_n_ips) { diff --git a/memcheck/tests/freebsd/scalar.c b/memcheck/tests/freebsd/scalar.c index e9d936e47..8862f3df3 100644 --- a/memcheck/tests/freebsd/scalar.c +++ b/memcheck/tests/freebsd/scalar.c @@ -334,7 +334,7 @@ int main(void) /* SYS_mprotect 74 */ GO(SYS_mprotect, "3s 0m"); - SY(SYS_mprotect, x0+1, x0+1, x0+9999); FAIL; + //SY(SYS_mprotect, x0+1, x0+1, x0+9999); FAIL; /* SYS_madvise 75 */ GO(SYS_madvise, "3s 0m"); @@ -372,7 +372,7 @@ int main(void) /* SYS_swapon 85 */ GO(SYS_swapon, "1s 1m"); - SY(SYS_swapon, x0); FAIL; + //SY(SYS_swapon, x0+1); SUCC; /* SYS_getitimer 86 */ GO(SYS_getitimer, "2s 1m"); diff --git a/memcheck/tests/freebsd/setproctitle.c b/memcheck/tests/freebsd/setproctitle.c index cc0357f42..44e7514a2 100644 --- a/memcheck/tests/freebsd/setproctitle.c +++ b/memcheck/tests/freebsd/setproctitle.c @@ -10,7 +10,7 @@ int main(void) { -#if defined(KERN_PS_STRINGS) +#if defined(KERN_PS_STRINGS) && defined(AT_PS_STRINGS) unsigned long ul_ps_strings; struct ps_strings* v1; struct ps_strings* v2;