changeset 25231:d8949b8d8933

12747 sigsetjmp should allow for 8 byte aligned buffer on amd64 Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Joshua M. Clulow <josh@sysmgr.org> Approved by: Joshua M. Clulow <josh@sysmgr.org>
author Vitaliy Gusev <gusev.vitaliy@gmail.com>
date Mon, 20 Jul 2020 13:58:21 -0700
parents 8f171bd0ccda
children 1e97e55a86d8
files usr/src/lib/libc/amd64/gen/siglongjmp.c usr/src/lib/libc/amd64/threads/asm_subr.s usr/src/lib/libc/amd64/threads/machdep.c usr/src/lib/libc/inc/sigjmp_struct.h
diffstat 4 files changed, 26 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libc/amd64/gen/siglongjmp.c	Mon Apr 13 10:15:27 2020 +0300
+++ b/usr/src/lib/libc/amd64/gen/siglongjmp.c	Mon Jul 20 13:58:21 2020 -0700
@@ -29,6 +29,7 @@
 #include <sys/ucontext.h>
 #include <setjmp.h>
 #include <ucontext.h>
+#include "sigjmp_struct.h"
 #include "libc.h"
 
 #pragma weak _siglongjmp = siglongjmp
@@ -36,8 +37,7 @@
 void
 siglongjmp(sigjmp_buf env, int val)
 {
-	/* LINTED alignment */
-	ucontext_t *ucp = (ucontext_t *)env;
+	ucontext_t *ucp = SIGJMP2UCONTEXT(env);
 
 	if (val)
 		ucp->uc_mcontext.gregs[REG_R0] = val;
--- a/usr/src/lib/libc/amd64/threads/asm_subr.s	Mon Apr 13 10:15:27 2020 +0300
+++ b/usr/src/lib/libc/amd64/threads/asm_subr.s	Mon Jul 20 13:58:21 2020 -0700
@@ -104,7 +104,11 @@
 
 #undef	sigsetjmp
 
-#if SIZEOF_SIGJMP_BUF < SIZEOF_UCONTEXT_T
+/*
+ * Ensure that a "ucontext_t" will fit within a "sigjmp_buf", including the
+ * extra 8 bytes we may need for correct alignment on AMD64.
+ */
+#if SIZEOF_SIGJMP_BUF - _LONG_ALIGNMENT < SIZEOF_UCONTEXT_T
 
 #error "sigjmp_buf is too small to contain a ucontext_t"
 
@@ -171,4 +175,4 @@
 	SET_SIZE(sigsetjmp)
 	SET_SIZE(_sigsetjmp)
 
-#endif	/* SIZEOF_SIGJMP_BUF < SIZEOF_UCONTEXT_T */
+#endif	/* SIZEOF_SIGJMP_BUF - _LONG_ALIGNMENT < SIZEOF_UCONTEXT_T */
--- a/usr/src/lib/libc/amd64/threads/machdep.c	Mon Apr 13 10:15:27 2020 +0300
+++ b/usr/src/lib/libc/amd64/threads/machdep.c	Mon Jul 20 13:58:21 2020 -0700
@@ -28,6 +28,7 @@
 #include <procfs.h>
 #include <ucontext.h>
 #include <setjmp.h>
+#include "sigjmp_struct.h"
 
 extern int getlwpstatus(thread_t, lwpstatus_t *);
 extern int putlwpregs(thread_t, prgregset_t);
@@ -66,7 +67,7 @@
 
 int
 setup_context(ucontext_t *ucp, void *(*func)(ulwp_t *),
-	ulwp_t *ulwp, caddr_t stk, size_t stksize)
+    ulwp_t *ulwp, caddr_t stk, size_t stksize)
 {
 	uint64_t *stack;
 
@@ -172,8 +173,7 @@
 int
 __csigsetjmp(sigjmp_buf env, int savemask, gregset_t rs)
 {
-	/* LINTED alignment */
-	ucontext_t *ucp = (ucontext_t *)env;
+	ucontext_t *ucp = SIGJMP2UCONTEXT(env);
 	ulwp_t *self = curthread;
 
 	ucp->uc_link = self->ul_siglink;
--- a/usr/src/lib/libc/inc/sigjmp_struct.h	Mon Apr 13 10:15:27 2020 +0300
+++ b/usr/src/lib/libc/inc/sigjmp_struct.h	Mon Jul 20 13:58:21 2020 -0700
@@ -32,6 +32,7 @@
 
 #include <sys/types.h>
 #include <sys/stack.h>
+#include <sys/sysmacros.h>
 #include <ucontext.h>
 #include <setjmp.h>
 
@@ -73,6 +74,20 @@
 
 #endif	/* __sparc */
 
+#if defined(__amd64)
+/*
+ * The "sigjmp_buf" type is an array of long and thus can have 8-byte alignment
+ * on AMD64 systems.  The "ucontext_t" type has a stricter 16-byte alignment
+ * requirement, so we must round the pointer up when casting.
+ *
+ * This is not required on other architectures:
+ *  - SPARC does not store the ucontext_t in the sigjmp_buf
+ *  - i386 only requires 4-byte alignment for ucontext_t
+ */
+#define	SIGJMP2UCONTEXT(x)	\
+	((ucontext_t *)P2ROUNDUP((uintptr_t)(x),  sizeof (upad128_t)))
+#endif
+
 #ifdef	__cplusplus
 }
 #endif