diff options
Diffstat (limited to 'usr/src/lib/libc/port/gen/stack.c')
-rw-r--r-- | usr/src/lib/libc/port/gen/stack.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/usr/src/lib/libc/port/gen/stack.c b/usr/src/lib/libc/port/gen/stack.c new file mode 100644 index 0000000000..6b1e314e8a --- /dev/null +++ b/usr/src/lib/libc/port/gen/stack.c @@ -0,0 +1,117 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "thr_uberdata.h" +#include <sys/stack.h> + +/* + * Initialization of the main stack is performed in libc_init(). + * Initialization of thread stacks is performed in _thr_setup(). + */ + +#pragma weak stack_getbounds = _stack_getbounds +int +_stack_getbounds(stack_t *sp) +{ + *sp = curthread->ul_ustack; + return (0); +} + +#pragma weak stack_setbounds = _stack_setbounds +int +_stack_setbounds(const stack_t *sp) +{ + ulwp_t *self = curthread; + + if (sp == NULL || sp->ss_sp == NULL || + (uintptr_t)sp->ss_sp != SA((uintptr_t)sp->ss_sp) || + sp->ss_flags != 0 || sp->ss_size < MINSIGSTKSZ || + (uintptr_t)sp->ss_size != SA((uintptr_t)sp->ss_size)) { + errno = EINVAL; + return (-1); + } + + sigoff(self); + self->ul_ustack = *sp; + sigon(self); + + return (0); +} + +/* + * Returns a boolean value: + * 1 addr is within the bounds of the current stack + * 0 addr is outside of the bounds of the current stack + * Note that addr is an unbiased value. + */ +#pragma weak stack_inbounds = _stack_inbounds +int +_stack_inbounds(void *addr) +{ + stack_t *ustackp = &curthread->ul_ustack; + uintptr_t base = (uintptr_t)ustackp->ss_sp; + size_t size = ustackp->ss_size; + + return ((uintptr_t)addr >= base && (uintptr_t)addr < base + size); +} + +#pragma weak stack_violation = _stack_violation +int +_stack_violation(int sig, const siginfo_t *sip, const ucontext_t *ucp) +{ + uintptr_t addr; + uintptr_t base; + size_t size; + + if ((sig != SIGSEGV && sig != SIGBUS) || + sip == NULL || ucp == NULL || SI_FROMUSER(sip)) + return (0); + + /* + * ucp has the correct view of the stack when the signal was raised. + */ + base = (uintptr_t)ucp->uc_stack.ss_sp; + size = ucp->uc_stack.ss_size; +#if defined(__sparc) + addr = ucp->uc_mcontext.gregs[REG_SP] + STACK_BIAS; +#elif defined(__amd64) || defined(__i386) + addr = ucp->uc_mcontext.gregs[REG_SP]; + /* + * If the faulted address is just below the stack pointer we + * might be looking at a push instruction that caused the fault + * (the largest amount a push instruction can decrement the + * stack pointer by is 32). In that case, use the faulted + * address in our computation rather than the stack pointer. + */ + if (addr - (uintptr_t)sip->si_addr < 32) + addr = (uintptr_t)sip->si_addr; +#else +#error "none of __sparc, __amd64, __i386 is defined" +#endif + return (!(addr >= base && addr < base + size)); +} |