xref: /onnv-gate/usr/src/lib/libc/port/gen/stack.c (revision 6812:febeba71273d)
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