summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc
diff options
context:
space:
mode:
authorVitaliy Gusev <gusev.vitaliy@gmail.com>2020-07-20 13:58:21 -0700
committerJoshua M. Clulow <josh@sysmgr.org>2020-07-21 10:44:14 -0700
commit6a8fa7ea16d9870b21c82af67a2053cb47ed1fb4 (patch)
tree96408da85939e462d75f0600ddc5e88db0d33c21 /usr/src/lib/libc
parent9b65801e8bd9a9007efed89ac479e99b9dab83d1 (diff)
downloadillumos-gate-6a8fa7ea16d9870b21c82af67a2053cb47ed1fb4.tar.gz
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>
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r--usr/src/lib/libc/amd64/gen/siglongjmp.c4
-rw-r--r--usr/src/lib/libc/amd64/threads/asm_subr.s8
-rw-r--r--usr/src/lib/libc/amd64/threads/machdep.c6
-rw-r--r--usr/src/lib/libc/inc/sigjmp_struct.h15
4 files changed, 26 insertions, 7 deletions
diff --git a/usr/src/lib/libc/amd64/gen/siglongjmp.c b/usr/src/lib/libc/amd64/gen/siglongjmp.c
index d71f40a034..dda4c945d6 100644
--- a/usr/src/lib/libc/amd64/gen/siglongjmp.c
+++ b/usr/src/lib/libc/amd64/gen/siglongjmp.c
@@ -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;
diff --git a/usr/src/lib/libc/amd64/threads/asm_subr.s b/usr/src/lib/libc/amd64/threads/asm_subr.s
index 9feef4a2e2..3898e9c6e6 100644
--- a/usr/src/lib/libc/amd64/threads/asm_subr.s
+++ b/usr/src/lib/libc/amd64/threads/asm_subr.s
@@ -104,7 +104,11 @@ __sighndlrend:
#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 @@ __sighndlrend:
SET_SIZE(sigsetjmp)
SET_SIZE(_sigsetjmp)
-#endif /* SIZEOF_SIGJMP_BUF < SIZEOF_UCONTEXT_T */
+#endif /* SIZEOF_SIGJMP_BUF - _LONG_ALIGNMENT < SIZEOF_UCONTEXT_T */
diff --git a/usr/src/lib/libc/amd64/threads/machdep.c b/usr/src/lib/libc/amd64/threads/machdep.c
index b1638e0b31..81b8ee37ec 100644
--- a/usr/src/lib/libc/amd64/threads/machdep.c
+++ b/usr/src/lib/libc/amd64/threads/machdep.c
@@ -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 @@ setup_top_frame(void *stk, size_t stksize, ulwp_t *ulwp)
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 @@ setgregs(ulwp_t *ulwp, gregset_t rs)
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;
diff --git a/usr/src/lib/libc/inc/sigjmp_struct.h b/usr/src/lib/libc/inc/sigjmp_struct.h
index 988e6ca14c..7d347c2d3c 100644
--- a/usr/src/lib/libc/inc/sigjmp_struct.h
+++ b/usr/src/lib/libc/inc/sigjmp_struct.h
@@ -32,6 +32,7 @@ extern "C" {
#include <sys/types.h>
#include <sys/stack.h>
+#include <sys/sysmacros.h>
#include <ucontext.h>
#include <setjmp.h>
@@ -73,6 +74,20 @@ typedef struct {
#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