1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "thr_uberdata.h" 30 #include <sys/stack.h> 31 32 /* 33 * Initialization of the main stack is performed in libc_init(). 34 * Initialization of thread stacks is performed in _thrp_setup(). 35 */ 36 37 #pragma weak _stack_getbounds = stack_getbounds 38 int 39 stack_getbounds(stack_t *sp) 40 { 41 *sp = curthread->ul_ustack; 42 return (0); 43 } 44 45 #pragma weak _stack_setbounds = stack_setbounds 46 int 47 stack_setbounds(const stack_t *sp) 48 { 49 ulwp_t *self = curthread; 50 51 if (sp == NULL || sp->ss_sp == NULL || 52 (uintptr_t)sp->ss_sp != SA((uintptr_t)sp->ss_sp) || 53 sp->ss_flags != 0 || sp->ss_size < MINSIGSTKSZ || 54 (uintptr_t)sp->ss_size != SA((uintptr_t)sp->ss_size)) { 55 errno = EINVAL; 56 return (-1); 57 } 58 59 sigoff(self); 60 self->ul_ustack = *sp; 61 sigon(self); 62 63 return (0); 64 } 65 66 /* 67 * Returns a boolean value: 68 * 1 addr is within the bounds of the current stack 69 * 0 addr is outside of the bounds of the current stack 70 * Note that addr is an unbiased value. 71 */ 72 #pragma weak _stack_inbounds = stack_inbounds 73 int 74 stack_inbounds(void *addr) 75 { 76 stack_t *ustackp = &curthread->ul_ustack; 77 uintptr_t base = (uintptr_t)ustackp->ss_sp; 78 size_t size = ustackp->ss_size; 79 80 return ((uintptr_t)addr >= base && (uintptr_t)addr < base + size); 81 } 82 83 #pragma weak _stack_violation = stack_violation 84 int 85 stack_violation(int sig, const siginfo_t *sip, const ucontext_t *ucp) 86 { 87 uintptr_t addr; 88 uintptr_t base; 89 size_t size; 90 91 if ((sig != SIGSEGV && sig != SIGBUS) || 92 sip == NULL || ucp == NULL || SI_FROMUSER(sip)) 93 return (0); 94 95 /* 96 * ucp has the correct view of the stack when the signal was raised. 97 */ 98 base = (uintptr_t)ucp->uc_stack.ss_sp; 99 size = ucp->uc_stack.ss_size; 100 #if defined(__sparc) 101 addr = ucp->uc_mcontext.gregs[REG_SP] + STACK_BIAS; 102 #elif defined(__amd64) || defined(__i386) 103 addr = ucp->uc_mcontext.gregs[REG_SP]; 104 /* 105 * If the faulted address is just below the stack pointer we 106 * might be looking at a push instruction that caused the fault 107 * (the largest amount a push instruction can decrement the 108 * stack pointer by is 32). In that case, use the faulted 109 * address in our computation rather than the stack pointer. 110 */ 111 if (addr - (uintptr_t)sip->si_addr < 32) 112 addr = (uintptr_t)sip->si_addr; 113 #else 114 #error "none of __sparc, __amd64, __i386 is defined" 115 #endif 116 return (!(addr >= base && addr < base + size)); 117 } 118