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
stack_getbounds(stack_t * sp)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
stack_setbounds(const stack_t * sp)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
stack_inbounds(void * addr)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
stack_violation(int sig,const siginfo_t * sip,const ucontext_t * ucp)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