10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*6812Sraf * Common Development and Distribution License (the "License").
6*6812Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*6812Sraf
220Sstevel@tonic-gate /*
23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include "thr_uberdata.h"
300Sstevel@tonic-gate #include <sys/stack.h>
310Sstevel@tonic-gate
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate * Initialization of the main stack is performed in libc_init().
34*6812Sraf * Initialization of thread stacks is performed in _thrp_setup().
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
37*6812Sraf #pragma weak _stack_getbounds = stack_getbounds
380Sstevel@tonic-gate int
stack_getbounds(stack_t * sp)39*6812Sraf stack_getbounds(stack_t *sp)
400Sstevel@tonic-gate {
410Sstevel@tonic-gate *sp = curthread->ul_ustack;
420Sstevel@tonic-gate return (0);
430Sstevel@tonic-gate }
440Sstevel@tonic-gate
45*6812Sraf #pragma weak _stack_setbounds = stack_setbounds
460Sstevel@tonic-gate int
stack_setbounds(const stack_t * sp)47*6812Sraf stack_setbounds(const stack_t *sp)
480Sstevel@tonic-gate {
490Sstevel@tonic-gate ulwp_t *self = curthread;
500Sstevel@tonic-gate
510Sstevel@tonic-gate if (sp == NULL || sp->ss_sp == NULL ||
520Sstevel@tonic-gate (uintptr_t)sp->ss_sp != SA((uintptr_t)sp->ss_sp) ||
530Sstevel@tonic-gate sp->ss_flags != 0 || sp->ss_size < MINSIGSTKSZ ||
540Sstevel@tonic-gate (uintptr_t)sp->ss_size != SA((uintptr_t)sp->ss_size)) {
550Sstevel@tonic-gate errno = EINVAL;
560Sstevel@tonic-gate return (-1);
570Sstevel@tonic-gate }
580Sstevel@tonic-gate
590Sstevel@tonic-gate sigoff(self);
600Sstevel@tonic-gate self->ul_ustack = *sp;
610Sstevel@tonic-gate sigon(self);
620Sstevel@tonic-gate
630Sstevel@tonic-gate return (0);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate * Returns a boolean value:
680Sstevel@tonic-gate * 1 addr is within the bounds of the current stack
690Sstevel@tonic-gate * 0 addr is outside of the bounds of the current stack
700Sstevel@tonic-gate * Note that addr is an unbiased value.
710Sstevel@tonic-gate */
72*6812Sraf #pragma weak _stack_inbounds = stack_inbounds
730Sstevel@tonic-gate int
stack_inbounds(void * addr)74*6812Sraf stack_inbounds(void *addr)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate stack_t *ustackp = &curthread->ul_ustack;
770Sstevel@tonic-gate uintptr_t base = (uintptr_t)ustackp->ss_sp;
780Sstevel@tonic-gate size_t size = ustackp->ss_size;
790Sstevel@tonic-gate
800Sstevel@tonic-gate return ((uintptr_t)addr >= base && (uintptr_t)addr < base + size);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
83*6812Sraf #pragma weak _stack_violation = stack_violation
840Sstevel@tonic-gate int
stack_violation(int sig,const siginfo_t * sip,const ucontext_t * ucp)85*6812Sraf stack_violation(int sig, const siginfo_t *sip, const ucontext_t *ucp)
860Sstevel@tonic-gate {
870Sstevel@tonic-gate uintptr_t addr;
880Sstevel@tonic-gate uintptr_t base;
890Sstevel@tonic-gate size_t size;
900Sstevel@tonic-gate
910Sstevel@tonic-gate if ((sig != SIGSEGV && sig != SIGBUS) ||
920Sstevel@tonic-gate sip == NULL || ucp == NULL || SI_FROMUSER(sip))
930Sstevel@tonic-gate return (0);
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * ucp has the correct view of the stack when the signal was raised.
970Sstevel@tonic-gate */
980Sstevel@tonic-gate base = (uintptr_t)ucp->uc_stack.ss_sp;
990Sstevel@tonic-gate size = ucp->uc_stack.ss_size;
1000Sstevel@tonic-gate #if defined(__sparc)
1010Sstevel@tonic-gate addr = ucp->uc_mcontext.gregs[REG_SP] + STACK_BIAS;
1020Sstevel@tonic-gate #elif defined(__amd64) || defined(__i386)
1030Sstevel@tonic-gate addr = ucp->uc_mcontext.gregs[REG_SP];
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate * If the faulted address is just below the stack pointer we
1060Sstevel@tonic-gate * might be looking at a push instruction that caused the fault
1070Sstevel@tonic-gate * (the largest amount a push instruction can decrement the
1080Sstevel@tonic-gate * stack pointer by is 32). In that case, use the faulted
1090Sstevel@tonic-gate * address in our computation rather than the stack pointer.
1100Sstevel@tonic-gate */
1110Sstevel@tonic-gate if (addr - (uintptr_t)sip->si_addr < 32)
1120Sstevel@tonic-gate addr = (uintptr_t)sip->si_addr;
1130Sstevel@tonic-gate #else
1140Sstevel@tonic-gate #error "none of __sparc, __amd64, __i386 is defined"
1150Sstevel@tonic-gate #endif
1160Sstevel@tonic-gate return (!(addr >= base && addr < base + size));
1170Sstevel@tonic-gate }
118