11debfc3dSmrg /* Library support for -fsplit-stack. */
2*8feb0f0bSmrg /* Copyright (C) 2009-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Ian Lance Taylor <iant@google.com>.
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg
171debfc3dSmrg Under Section 7 of GPL version 3, you are granted additional
181debfc3dSmrg permissions described in the GCC Runtime Library Exception, version
191debfc3dSmrg 3.1, as published by the Free Software Foundation.
201debfc3dSmrg
211debfc3dSmrg You should have received a copy of the GNU General Public License and
221debfc3dSmrg a copy of the GCC Runtime Library Exception along with this program;
231debfc3dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
241debfc3dSmrg <http://www.gnu.org/licenses/>. */
251debfc3dSmrg
26*8feb0f0bSmrg #pragma GCC optimize ("no-isolate-erroneous-paths-dereference")
27*8feb0f0bSmrg
281debfc3dSmrg /* powerpc 32-bit not supported. */
291debfc3dSmrg #if !defined __powerpc__ || defined __powerpc64__
301debfc3dSmrg
311debfc3dSmrg #include "tconfig.h"
321debfc3dSmrg #include "tsystem.h"
331debfc3dSmrg #include "coretypes.h"
341debfc3dSmrg #include "tm.h"
351debfc3dSmrg #include "libgcc_tm.h"
361debfc3dSmrg
371debfc3dSmrg /* If inhibit_libc is defined, we cannot compile this file. The
381debfc3dSmrg effect is that people will not be able to use -fsplit-stack. That
391debfc3dSmrg is much better than failing the build particularly since people
401debfc3dSmrg will want to define inhibit_libc while building a compiler which
411debfc3dSmrg can build glibc. */
421debfc3dSmrg
431debfc3dSmrg #ifndef inhibit_libc
441debfc3dSmrg
451debfc3dSmrg #include <assert.h>
461debfc3dSmrg #include <errno.h>
471debfc3dSmrg #include <signal.h>
481debfc3dSmrg #include <stdlib.h>
491debfc3dSmrg #include <string.h>
501debfc3dSmrg #include <unistd.h>
511debfc3dSmrg #include <sys/mman.h>
521debfc3dSmrg #include <sys/uio.h>
531debfc3dSmrg
541debfc3dSmrg #include "generic-morestack.h"
551debfc3dSmrg
56*8feb0f0bSmrg /* Some systems use LD_PRELOAD or similar tricks to add hooks to
57*8feb0f0bSmrg mmap/munmap. That breaks this code, because when we call mmap
58*8feb0f0bSmrg there is enough stack space for the system call but there is not,
59*8feb0f0bSmrg in general, enough stack space to run a hook. Try to avoid the
60*8feb0f0bSmrg problem by calling syscall directly. We only do this on GNU/Linux
61*8feb0f0bSmrg for now, but it should be easy to add support for more systems with
62*8feb0f0bSmrg testing. */
63*8feb0f0bSmrg
64*8feb0f0bSmrg #if defined(__gnu_linux__)
65*8feb0f0bSmrg
66*8feb0f0bSmrg #include <sys/syscall.h>
67*8feb0f0bSmrg
68*8feb0f0bSmrg #if defined(SYS_mmap) || defined(SYS_mmap2)
69*8feb0f0bSmrg
70*8feb0f0bSmrg #ifdef SYS_mmap2
71*8feb0f0bSmrg #define MORESTACK_MMAP SYS_mmap2
72*8feb0f0bSmrg #define MORESTACK_ADJUST_OFFSET(x) ((x) / 4096ULL)
73*8feb0f0bSmrg #else
74*8feb0f0bSmrg #define MORESTACK_MMAP SYS_mmap
75*8feb0f0bSmrg #define MORESTACK_ADJUST_OFFSET(x) (x)
76*8feb0f0bSmrg #endif
77*8feb0f0bSmrg
78*8feb0f0bSmrg static void *
morestack_mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)79*8feb0f0bSmrg morestack_mmap (void *addr, size_t length, int prot, int flags, int fd,
80*8feb0f0bSmrg off_t offset)
81*8feb0f0bSmrg {
82*8feb0f0bSmrg offset = MORESTACK_ADJUST_OFFSET (offset);
83*8feb0f0bSmrg
84*8feb0f0bSmrg #ifdef __s390__
85*8feb0f0bSmrg long args[6] = { (long) addr, (long) length, (long) prot, (long) flags,
86*8feb0f0bSmrg (long) fd, (long) offset };
87*8feb0f0bSmrg return (void *) syscall (MORESTACK_MMAP, args);
88*8feb0f0bSmrg #else
89*8feb0f0bSmrg return (void *) syscall (MORESTACK_MMAP, addr, length, prot, flags, fd,
90*8feb0f0bSmrg offset);
91*8feb0f0bSmrg #endif
92*8feb0f0bSmrg }
93*8feb0f0bSmrg
94*8feb0f0bSmrg #define mmap morestack_mmap
95*8feb0f0bSmrg
96*8feb0f0bSmrg #endif /* defined(SYS_MMAP) || defined(SYS_mmap2) */
97*8feb0f0bSmrg
98*8feb0f0bSmrg #if defined(SYS_munmap)
99*8feb0f0bSmrg
100*8feb0f0bSmrg static int
morestack_munmap(void * addr,size_t length)101*8feb0f0bSmrg morestack_munmap (void * addr, size_t length)
102*8feb0f0bSmrg {
103*8feb0f0bSmrg return (int) syscall (SYS_munmap, addr, length);
104*8feb0f0bSmrg }
105*8feb0f0bSmrg
106*8feb0f0bSmrg #define munmap morestack_munmap
107*8feb0f0bSmrg
108*8feb0f0bSmrg #endif /* defined(SYS_munmap) */
109*8feb0f0bSmrg
110*8feb0f0bSmrg #endif /* defined(__gnu_linux__) */
111*8feb0f0bSmrg
1121debfc3dSmrg typedef unsigned uintptr_type __attribute__ ((mode (pointer)));
1131debfc3dSmrg
1141debfc3dSmrg /* This file contains subroutines that are used by code compiled with
1151debfc3dSmrg -fsplit-stack. */
1161debfc3dSmrg
1171debfc3dSmrg /* Declare functions to avoid warnings--there is no header file for
1181debfc3dSmrg these internal functions. We give most of these functions the
1191debfc3dSmrg flatten attribute in order to minimize their stack usage--here we
1201debfc3dSmrg must minimize stack usage even at the cost of code size, and in
1211debfc3dSmrg general inlining everything will do that. */
1221debfc3dSmrg
1231debfc3dSmrg extern void
1241debfc3dSmrg __generic_morestack_set_initial_sp (void *sp, size_t len)
1251debfc3dSmrg __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
1261debfc3dSmrg
1271debfc3dSmrg extern void *
1281debfc3dSmrg __generic_morestack (size_t *frame_size, void *old_stack, size_t param_size)
1291debfc3dSmrg __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
1301debfc3dSmrg
1311debfc3dSmrg extern void *
1321debfc3dSmrg __generic_releasestack (size_t *pavailable)
1331debfc3dSmrg __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
1341debfc3dSmrg
1351debfc3dSmrg extern void
1361debfc3dSmrg __morestack_block_signals (void)
1371debfc3dSmrg __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
1381debfc3dSmrg
1391debfc3dSmrg extern void
1401debfc3dSmrg __morestack_unblock_signals (void)
1411debfc3dSmrg __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
1421debfc3dSmrg
1431debfc3dSmrg extern size_t
1441debfc3dSmrg __generic_findstack (void *stack)
1451debfc3dSmrg __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
1461debfc3dSmrg
1471debfc3dSmrg extern void
1481debfc3dSmrg __morestack_load_mmap (void)
1491debfc3dSmrg __attribute__ ((no_split_stack, visibility ("hidden")));
1501debfc3dSmrg
1511debfc3dSmrg extern void *
1521debfc3dSmrg __morestack_allocate_stack_space (size_t size)
1531debfc3dSmrg __attribute__ ((visibility ("hidden")));
1541debfc3dSmrg
1551debfc3dSmrg /* These are functions which -fsplit-stack code can call. These are
1561debfc3dSmrg not called by the compiler, and are not hidden. FIXME: These
1571debfc3dSmrg should be in some header file somewhere, somehow. */
1581debfc3dSmrg
1591debfc3dSmrg extern void *
1601debfc3dSmrg __splitstack_find (void *, void *, size_t *, void **, void **, void **)
1611debfc3dSmrg __attribute__ ((visibility ("default")));
1621debfc3dSmrg
1631debfc3dSmrg extern void
1641debfc3dSmrg __splitstack_block_signals (int *, int *)
1651debfc3dSmrg __attribute__ ((visibility ("default")));
1661debfc3dSmrg
1671debfc3dSmrg extern void
1681debfc3dSmrg __splitstack_getcontext (void *context[10])
1691debfc3dSmrg __attribute__ ((no_split_stack, visibility ("default")));
1701debfc3dSmrg
1711debfc3dSmrg extern void
1721debfc3dSmrg __splitstack_setcontext (void *context[10])
1731debfc3dSmrg __attribute__ ((no_split_stack, visibility ("default")));
1741debfc3dSmrg
1751debfc3dSmrg extern void *
1761debfc3dSmrg __splitstack_makecontext (size_t, void *context[10], size_t *)
1771debfc3dSmrg __attribute__ ((visibility ("default")));
1781debfc3dSmrg
1791debfc3dSmrg extern void *
1801debfc3dSmrg __splitstack_resetcontext (void *context[10], size_t *)
1811debfc3dSmrg __attribute__ ((visibility ("default")));
1821debfc3dSmrg
1831debfc3dSmrg extern void
1841debfc3dSmrg __splitstack_releasecontext (void *context[10])
1851debfc3dSmrg __attribute__ ((visibility ("default")));
1861debfc3dSmrg
1871debfc3dSmrg extern void
1881debfc3dSmrg __splitstack_block_signals_context (void *context[10], int *, int *)
1891debfc3dSmrg __attribute__ ((visibility ("default")));
1901debfc3dSmrg
1911debfc3dSmrg extern void *
1921debfc3dSmrg __splitstack_find_context (void *context[10], size_t *, void **, void **,
1931debfc3dSmrg void **)
1941debfc3dSmrg __attribute__ ((visibility ("default")));
1951debfc3dSmrg
1961debfc3dSmrg /* These functions must be defined by the processor specific code. */
1971debfc3dSmrg
1981debfc3dSmrg extern void *__morestack_get_guard (void)
1991debfc3dSmrg __attribute__ ((no_split_stack, visibility ("hidden")));
2001debfc3dSmrg
2011debfc3dSmrg extern void __morestack_set_guard (void *)
2021debfc3dSmrg __attribute__ ((no_split_stack, visibility ("hidden")));
2031debfc3dSmrg
2041debfc3dSmrg extern void *__morestack_make_guard (void *, size_t)
2051debfc3dSmrg __attribute__ ((no_split_stack, visibility ("hidden")));
2061debfc3dSmrg
2071debfc3dSmrg /* When we allocate a stack segment we put this header at the
2081debfc3dSmrg start. */
2091debfc3dSmrg
2101debfc3dSmrg struct stack_segment
2111debfc3dSmrg {
2121debfc3dSmrg /* The previous stack segment--when a function running on this stack
2131debfc3dSmrg segment returns, it will run on the previous one. */
2141debfc3dSmrg struct stack_segment *prev;
2151debfc3dSmrg /* The next stack segment, if it has been allocated--when a function
2161debfc3dSmrg is running on this stack segment, the next one is not being
2171debfc3dSmrg used. */
2181debfc3dSmrg struct stack_segment *next;
2191debfc3dSmrg /* The total size of this stack segment. */
2201debfc3dSmrg size_t size;
2211debfc3dSmrg /* The stack address when this stack was created. This is used when
2221debfc3dSmrg popping the stack. */
2231debfc3dSmrg void *old_stack;
2241debfc3dSmrg /* A list of memory blocks allocated by dynamic stack
2251debfc3dSmrg allocation. */
2261debfc3dSmrg struct dynamic_allocation_blocks *dynamic_allocation;
2271debfc3dSmrg /* A list of dynamic memory blocks no longer needed. */
2281debfc3dSmrg struct dynamic_allocation_blocks *free_dynamic_allocation;
2291debfc3dSmrg /* An extra pointer in case we need some more information some
2301debfc3dSmrg day. */
2311debfc3dSmrg void *extra;
2321debfc3dSmrg };
2331debfc3dSmrg
2341debfc3dSmrg /* This structure holds the (approximate) initial stack pointer and
2351debfc3dSmrg size for the system supplied stack for a thread. This is set when
2361debfc3dSmrg the thread is created. We also store a sigset_t here to hold the
2371debfc3dSmrg signal mask while splitting the stack, since we don't want to store
2381debfc3dSmrg that on the stack. */
2391debfc3dSmrg
2401debfc3dSmrg struct initial_sp
2411debfc3dSmrg {
2421debfc3dSmrg /* The initial stack pointer. */
2431debfc3dSmrg void *sp;
2441debfc3dSmrg /* The stack length. */
2451debfc3dSmrg size_t len;
2461debfc3dSmrg /* A signal mask, put here so that the thread can use it without
2471debfc3dSmrg needing stack space. */
2481debfc3dSmrg sigset_t mask;
2491debfc3dSmrg /* Non-zero if we should not block signals. This is a reversed flag
2501debfc3dSmrg so that the default zero value is the safe value. The type is
2511debfc3dSmrg uintptr_type because it replaced one of the void * pointers in
2521debfc3dSmrg extra. */
2531debfc3dSmrg uintptr_type dont_block_signals;
2541debfc3dSmrg /* Some extra space for later extensibility. */
2551debfc3dSmrg void *extra[4];
2561debfc3dSmrg };
2571debfc3dSmrg
2581debfc3dSmrg /* A list of memory blocks allocated by dynamic stack allocation.
2591debfc3dSmrg This is used for code that calls alloca or uses variably sized
2601debfc3dSmrg arrays. */
2611debfc3dSmrg
2621debfc3dSmrg struct dynamic_allocation_blocks
2631debfc3dSmrg {
2641debfc3dSmrg /* The next block in the list. */
2651debfc3dSmrg struct dynamic_allocation_blocks *next;
2661debfc3dSmrg /* The size of the allocated memory. */
2671debfc3dSmrg size_t size;
2681debfc3dSmrg /* The allocated memory. */
2691debfc3dSmrg void *block;
2701debfc3dSmrg };
2711debfc3dSmrg
2721debfc3dSmrg /* These thread local global variables must be shared by all split
2731debfc3dSmrg stack code across shared library boundaries. Therefore, they have
2741debfc3dSmrg default visibility. They have extensibility fields if needed for
2751debfc3dSmrg new versions. If more radical changes are needed, new code can be
2761debfc3dSmrg written using new variable names, while still using the existing
2771debfc3dSmrg variables in a backward compatible manner. Symbol versioning is
2781debfc3dSmrg also used, although, since these variables are only referenced by
2791debfc3dSmrg code in this file and generic-morestack-thread.c, it is likely that
2801debfc3dSmrg simply using new names will suffice. */
2811debfc3dSmrg
2821debfc3dSmrg /* The first stack segment allocated for this thread. */
2831debfc3dSmrg
2841debfc3dSmrg __thread struct stack_segment *__morestack_segments
2851debfc3dSmrg __attribute__ ((visibility ("default")));
2861debfc3dSmrg
2871debfc3dSmrg /* The stack segment that we think we are currently using. This will
2881debfc3dSmrg be correct in normal usage, but will be incorrect if an exception
2891debfc3dSmrg unwinds into a different stack segment or if longjmp jumps to a
2901debfc3dSmrg different stack segment. */
2911debfc3dSmrg
2921debfc3dSmrg __thread struct stack_segment *__morestack_current_segment
2931debfc3dSmrg __attribute__ ((visibility ("default")));
2941debfc3dSmrg
2951debfc3dSmrg /* The initial stack pointer and size for this thread. */
2961debfc3dSmrg
2971debfc3dSmrg __thread struct initial_sp __morestack_initial_sp
2981debfc3dSmrg __attribute__ ((visibility ("default")));
2991debfc3dSmrg
3001debfc3dSmrg /* A static signal mask, to avoid taking up stack space. */
3011debfc3dSmrg
3021debfc3dSmrg static sigset_t __morestack_fullmask;
3031debfc3dSmrg
304a2dc1f3fSmrg /* Page size, as returned from getpagesize(). Set on startup. */
305a2dc1f3fSmrg static unsigned int static_pagesize;
306a2dc1f3fSmrg
307a2dc1f3fSmrg /* Set on startup to non-zero value if SPLIT_STACK_GUARD env var is set. */
308a2dc1f3fSmrg static int use_guard_page;
309a2dc1f3fSmrg
3101debfc3dSmrg /* Convert an integer to a decimal string without using much stack
3111debfc3dSmrg space. Return a pointer to the part of the buffer to use. We this
3121debfc3dSmrg instead of sprintf because sprintf will require too much stack
3131debfc3dSmrg space. */
3141debfc3dSmrg
3151debfc3dSmrg static char *
print_int(int val,char * buf,int buflen,size_t * print_len)3161debfc3dSmrg print_int (int val, char *buf, int buflen, size_t *print_len)
3171debfc3dSmrg {
3181debfc3dSmrg int is_negative;
3191debfc3dSmrg int i;
3201debfc3dSmrg unsigned int uval;
3211debfc3dSmrg
3221debfc3dSmrg uval = (unsigned int) val;
3231debfc3dSmrg if (val >= 0)
3241debfc3dSmrg is_negative = 0;
3251debfc3dSmrg else
3261debfc3dSmrg {
3271debfc3dSmrg is_negative = 1;
3281debfc3dSmrg uval = - uval;
3291debfc3dSmrg }
3301debfc3dSmrg
3311debfc3dSmrg i = buflen;
3321debfc3dSmrg do
3331debfc3dSmrg {
3341debfc3dSmrg --i;
3351debfc3dSmrg buf[i] = '0' + (uval % 10);
3361debfc3dSmrg uval /= 10;
3371debfc3dSmrg }
3381debfc3dSmrg while (uval != 0 && i > 0);
3391debfc3dSmrg
3401debfc3dSmrg if (is_negative)
3411debfc3dSmrg {
3421debfc3dSmrg if (i > 0)
3431debfc3dSmrg --i;
3441debfc3dSmrg buf[i] = '-';
3451debfc3dSmrg }
3461debfc3dSmrg
3471debfc3dSmrg *print_len = buflen - i;
3481debfc3dSmrg return buf + i;
3491debfc3dSmrg }
3501debfc3dSmrg
3511debfc3dSmrg /* Print the string MSG/LEN, the errno number ERR, and a newline on
3521debfc3dSmrg stderr. Then crash. */
3531debfc3dSmrg
3541debfc3dSmrg void
3551debfc3dSmrg __morestack_fail (const char *, size_t, int) __attribute__ ((noreturn));
3561debfc3dSmrg
3571debfc3dSmrg void
__morestack_fail(const char * msg,size_t len,int err)3581debfc3dSmrg __morestack_fail (const char *msg, size_t len, int err)
3591debfc3dSmrg {
3601debfc3dSmrg char buf[24];
3611debfc3dSmrg static const char nl[] = "\n";
3621debfc3dSmrg struct iovec iov[3];
3631debfc3dSmrg union { char *p; const char *cp; } const_cast;
3641debfc3dSmrg
3651debfc3dSmrg const_cast.cp = msg;
3661debfc3dSmrg iov[0].iov_base = const_cast.p;
3671debfc3dSmrg iov[0].iov_len = len;
3681debfc3dSmrg /* We can't call strerror, because it may try to translate the error
3691debfc3dSmrg message, and that would use too much stack space. */
3701debfc3dSmrg iov[1].iov_base = print_int (err, buf, sizeof buf, &iov[1].iov_len);
3711debfc3dSmrg const_cast.cp = &nl[0];
3721debfc3dSmrg iov[2].iov_base = const_cast.p;
3731debfc3dSmrg iov[2].iov_len = sizeof nl - 1;
3741debfc3dSmrg /* FIXME: On systems without writev we need to issue three write
3751debfc3dSmrg calls, or punt on printing errno. For now this is irrelevant
3761debfc3dSmrg since stack splitting only works on GNU/Linux anyhow. */
3771debfc3dSmrg writev (2, iov, 3);
3781debfc3dSmrg abort ();
3791debfc3dSmrg }
3801debfc3dSmrg
3811debfc3dSmrg /* Allocate a new stack segment. FRAME_SIZE is the required frame
3821debfc3dSmrg size. */
3831debfc3dSmrg
3841debfc3dSmrg static struct stack_segment *
allocate_segment(size_t frame_size)3851debfc3dSmrg allocate_segment (size_t frame_size)
3861debfc3dSmrg {
3871debfc3dSmrg unsigned int pagesize;
3881debfc3dSmrg unsigned int overhead;
3891debfc3dSmrg unsigned int allocate;
3901debfc3dSmrg void *space;
3911debfc3dSmrg struct stack_segment *pss;
3921debfc3dSmrg
3931debfc3dSmrg pagesize = static_pagesize;
3941debfc3dSmrg overhead = sizeof (struct stack_segment);
3951debfc3dSmrg
3961debfc3dSmrg allocate = pagesize;
3971debfc3dSmrg if (allocate < MINSIGSTKSZ)
3981debfc3dSmrg allocate = ((MINSIGSTKSZ + overhead + pagesize - 1)
3991debfc3dSmrg & ~ (pagesize - 1));
4001debfc3dSmrg if (allocate < frame_size)
4011debfc3dSmrg allocate = ((frame_size + overhead + pagesize - 1)
4021debfc3dSmrg & ~ (pagesize - 1));
4031debfc3dSmrg
4041debfc3dSmrg if (use_guard_page)
4051debfc3dSmrg allocate += pagesize;
4061debfc3dSmrg
4071debfc3dSmrg /* FIXME: If this binary requires an executable stack, then we need
4081debfc3dSmrg to set PROT_EXEC. Unfortunately figuring that out is complicated
4091debfc3dSmrg and target dependent. We would need to use dl_iterate_phdr to
4101debfc3dSmrg see if there is any object which does not have a PT_GNU_STACK
4111debfc3dSmrg phdr, though only for architectures which use that mechanism. */
4121debfc3dSmrg space = mmap (NULL, allocate, PROT_READ | PROT_WRITE,
4131debfc3dSmrg MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
4141debfc3dSmrg if (space == MAP_FAILED)
4151debfc3dSmrg {
4161debfc3dSmrg static const char msg[] =
4171debfc3dSmrg "unable to allocate additional stack space: errno ";
4181debfc3dSmrg __morestack_fail (msg, sizeof msg - 1, errno);
4191debfc3dSmrg }
4201debfc3dSmrg
4211debfc3dSmrg if (use_guard_page)
4221debfc3dSmrg {
4231debfc3dSmrg void *guard;
4241debfc3dSmrg
4251debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
4261debfc3dSmrg guard = space;
4271debfc3dSmrg space = (char *) space + pagesize;
4281debfc3dSmrg #else
4291debfc3dSmrg guard = space + allocate - pagesize;
4301debfc3dSmrg #endif
4311debfc3dSmrg
4321debfc3dSmrg mprotect (guard, pagesize, PROT_NONE);
4331debfc3dSmrg allocate -= pagesize;
4341debfc3dSmrg }
4351debfc3dSmrg
4361debfc3dSmrg pss = (struct stack_segment *) space;
4371debfc3dSmrg
4381debfc3dSmrg pss->prev = NULL;
4391debfc3dSmrg pss->next = NULL;
4401debfc3dSmrg pss->size = allocate - overhead;
4411debfc3dSmrg pss->dynamic_allocation = NULL;
4421debfc3dSmrg pss->free_dynamic_allocation = NULL;
4431debfc3dSmrg pss->extra = NULL;
4441debfc3dSmrg
4451debfc3dSmrg return pss;
4461debfc3dSmrg }
4471debfc3dSmrg
4481debfc3dSmrg /* Free a list of dynamic blocks. */
4491debfc3dSmrg
4501debfc3dSmrg static void
free_dynamic_blocks(struct dynamic_allocation_blocks * p)4511debfc3dSmrg free_dynamic_blocks (struct dynamic_allocation_blocks *p)
4521debfc3dSmrg {
4531debfc3dSmrg while (p != NULL)
4541debfc3dSmrg {
4551debfc3dSmrg struct dynamic_allocation_blocks *next;
4561debfc3dSmrg
4571debfc3dSmrg next = p->next;
4581debfc3dSmrg free (p->block);
4591debfc3dSmrg free (p);
4601debfc3dSmrg p = next;
4611debfc3dSmrg }
4621debfc3dSmrg }
4631debfc3dSmrg
4641debfc3dSmrg /* Merge two lists of dynamic blocks. */
4651debfc3dSmrg
4661debfc3dSmrg static struct dynamic_allocation_blocks *
merge_dynamic_blocks(struct dynamic_allocation_blocks * a,struct dynamic_allocation_blocks * b)4671debfc3dSmrg merge_dynamic_blocks (struct dynamic_allocation_blocks *a,
4681debfc3dSmrg struct dynamic_allocation_blocks *b)
4691debfc3dSmrg {
4701debfc3dSmrg struct dynamic_allocation_blocks **pp;
4711debfc3dSmrg
4721debfc3dSmrg if (a == NULL)
4731debfc3dSmrg return b;
4741debfc3dSmrg if (b == NULL)
4751debfc3dSmrg return a;
4761debfc3dSmrg for (pp = &a->next; *pp != NULL; pp = &(*pp)->next)
4771debfc3dSmrg ;
4781debfc3dSmrg *pp = b;
4791debfc3dSmrg return a;
4801debfc3dSmrg }
4811debfc3dSmrg
4821debfc3dSmrg /* Release stack segments. If FREE_DYNAMIC is non-zero, we also free
4831debfc3dSmrg any dynamic blocks. Otherwise we return them. */
4841debfc3dSmrg
4851debfc3dSmrg struct dynamic_allocation_blocks *
__morestack_release_segments(struct stack_segment ** pp,int free_dynamic)4861debfc3dSmrg __morestack_release_segments (struct stack_segment **pp, int free_dynamic)
4871debfc3dSmrg {
4881debfc3dSmrg struct dynamic_allocation_blocks *ret;
4891debfc3dSmrg struct stack_segment *pss;
4901debfc3dSmrg
4911debfc3dSmrg ret = NULL;
4921debfc3dSmrg pss = *pp;
4931debfc3dSmrg while (pss != NULL)
4941debfc3dSmrg {
4951debfc3dSmrg struct stack_segment *next;
4961debfc3dSmrg unsigned int allocate;
4971debfc3dSmrg
4981debfc3dSmrg next = pss->next;
4991debfc3dSmrg
5001debfc3dSmrg if (pss->dynamic_allocation != NULL
5011debfc3dSmrg || pss->free_dynamic_allocation != NULL)
5021debfc3dSmrg {
5031debfc3dSmrg if (free_dynamic)
5041debfc3dSmrg {
5051debfc3dSmrg free_dynamic_blocks (pss->dynamic_allocation);
5061debfc3dSmrg free_dynamic_blocks (pss->free_dynamic_allocation);
5071debfc3dSmrg }
5081debfc3dSmrg else
5091debfc3dSmrg {
5101debfc3dSmrg ret = merge_dynamic_blocks (pss->dynamic_allocation, ret);
5111debfc3dSmrg ret = merge_dynamic_blocks (pss->free_dynamic_allocation, ret);
5121debfc3dSmrg }
5131debfc3dSmrg }
5141debfc3dSmrg
5151debfc3dSmrg allocate = pss->size + sizeof (struct stack_segment);
5161debfc3dSmrg if (munmap (pss, allocate) < 0)
5171debfc3dSmrg {
5181debfc3dSmrg static const char msg[] = "munmap of stack space failed: errno ";
5191debfc3dSmrg __morestack_fail (msg, sizeof msg - 1, errno);
5201debfc3dSmrg }
5211debfc3dSmrg
5221debfc3dSmrg pss = next;
5231debfc3dSmrg }
5241debfc3dSmrg *pp = NULL;
5251debfc3dSmrg
5261debfc3dSmrg return ret;
5271debfc3dSmrg }
5281debfc3dSmrg
5291debfc3dSmrg /* This function is called by a processor specific function to set the
5301debfc3dSmrg initial stack pointer for a thread. The operating system will
5311debfc3dSmrg always create a stack for a thread. Here we record a stack pointer
5321debfc3dSmrg near the base of that stack. The size argument lets the processor
5331debfc3dSmrg specific code estimate how much stack space is available on this
5341debfc3dSmrg initial stack. */
5351debfc3dSmrg
5361debfc3dSmrg void
__generic_morestack_set_initial_sp(void * sp,size_t len)5371debfc3dSmrg __generic_morestack_set_initial_sp (void *sp, size_t len)
5381debfc3dSmrg {
5391debfc3dSmrg /* The stack pointer most likely starts on a page boundary. Adjust
5401debfc3dSmrg to the nearest 512 byte boundary. It's not essential that we be
5411debfc3dSmrg precise here; getting it wrong will just leave some stack space
5421debfc3dSmrg unused. */
5431debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
5441debfc3dSmrg sp = (void *) ((((__UINTPTR_TYPE__) sp + 511U) / 512U) * 512U);
5451debfc3dSmrg #else
5461debfc3dSmrg sp = (void *) ((((__UINTPTR_TYPE__) sp - 511U) / 512U) * 512U);
5471debfc3dSmrg #endif
5481debfc3dSmrg
5491debfc3dSmrg __morestack_initial_sp.sp = sp;
5501debfc3dSmrg __morestack_initial_sp.len = len;
5511debfc3dSmrg sigemptyset (&__morestack_initial_sp.mask);
5521debfc3dSmrg
5531debfc3dSmrg sigfillset (&__morestack_fullmask);
5541debfc3dSmrg #if defined(__GLIBC__) && defined(__linux__)
5551debfc3dSmrg /* In glibc, the first two real time signals are used by the NPTL
5561debfc3dSmrg threading library. By taking them out of the set of signals, we
5571debfc3dSmrg avoiding copying the signal mask in pthread_sigmask. More
5581debfc3dSmrg importantly, pthread_sigmask uses less stack space on x86_64. */
5591debfc3dSmrg sigdelset (&__morestack_fullmask, __SIGRTMIN);
5601debfc3dSmrg sigdelset (&__morestack_fullmask, __SIGRTMIN + 1);
5611debfc3dSmrg #endif
5621debfc3dSmrg }
5631debfc3dSmrg
5641debfc3dSmrg /* This function is called by a processor specific function which is
5651debfc3dSmrg run in the prologue when more stack is needed. The processor
5661debfc3dSmrg specific function handles the details of saving registers and
5671debfc3dSmrg frobbing the actual stack pointer. This function is responsible
5681debfc3dSmrg for allocating a new stack segment and for copying a parameter
5691debfc3dSmrg block from the old stack to the new one. On function entry
5701debfc3dSmrg *PFRAME_SIZE is the size of the required stack frame--the returned
5711debfc3dSmrg stack must be at least this large. On function exit *PFRAME_SIZE
5721debfc3dSmrg is the amount of space remaining on the allocated stack. OLD_STACK
5731debfc3dSmrg points at the parameters the old stack (really the current one
5741debfc3dSmrg while this function is running). OLD_STACK is saved so that it can
5751debfc3dSmrg be returned by a later call to __generic_releasestack. PARAM_SIZE
5761debfc3dSmrg is the size in bytes of parameters to copy to the new stack. This
5771debfc3dSmrg function returns a pointer to the new stack segment, pointing to
5781debfc3dSmrg the memory after the parameters have been copied. The returned
5791debfc3dSmrg value minus the returned *PFRAME_SIZE (or plus if the stack grows
5801debfc3dSmrg upward) is the first address on the stack which should not be used.
5811debfc3dSmrg
5821debfc3dSmrg This function is running on the old stack and has only a limited
5831debfc3dSmrg amount of stack space available. */
5841debfc3dSmrg
5851debfc3dSmrg void *
__generic_morestack(size_t * pframe_size,void * old_stack,size_t param_size)5861debfc3dSmrg __generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size)
5871debfc3dSmrg {
5881debfc3dSmrg size_t frame_size = *pframe_size;
5891debfc3dSmrg struct stack_segment *current;
5901debfc3dSmrg struct stack_segment **pp;
5911debfc3dSmrg struct dynamic_allocation_blocks *dynamic;
5921debfc3dSmrg char *from;
5931debfc3dSmrg char *to;
5941debfc3dSmrg void *ret;
5951debfc3dSmrg size_t i;
5961debfc3dSmrg size_t aligned;
5971debfc3dSmrg
5981debfc3dSmrg current = __morestack_current_segment;
5991debfc3dSmrg
6001debfc3dSmrg pp = current != NULL ? ¤t->next : &__morestack_segments;
6011debfc3dSmrg if (*pp != NULL && (*pp)->size < frame_size)
6021debfc3dSmrg dynamic = __morestack_release_segments (pp, 0);
6031debfc3dSmrg else
6041debfc3dSmrg dynamic = NULL;
6051debfc3dSmrg current = *pp;
6061debfc3dSmrg
6071debfc3dSmrg if (current == NULL)
6081debfc3dSmrg {
6091debfc3dSmrg current = allocate_segment (frame_size + param_size);
6101debfc3dSmrg current->prev = __morestack_current_segment;
6111debfc3dSmrg *pp = current;
6121debfc3dSmrg }
6131debfc3dSmrg
6141debfc3dSmrg current->old_stack = old_stack;
6151debfc3dSmrg
6161debfc3dSmrg __morestack_current_segment = current;
6171debfc3dSmrg
6181debfc3dSmrg if (dynamic != NULL)
6191debfc3dSmrg {
6201debfc3dSmrg /* Move the free blocks onto our list. We don't want to call
6211debfc3dSmrg free here, as we are short on stack space. */
6221debfc3dSmrg current->free_dynamic_allocation =
6231debfc3dSmrg merge_dynamic_blocks (dynamic, current->free_dynamic_allocation);
6241debfc3dSmrg }
6251debfc3dSmrg
6261debfc3dSmrg *pframe_size = current->size - param_size;
6271debfc3dSmrg
6281debfc3dSmrg /* Align the returned stack to a 32-byte boundary. */
6291debfc3dSmrg aligned = (param_size + 31) & ~ (size_t) 31;
6301debfc3dSmrg
6311debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
6321debfc3dSmrg {
6331debfc3dSmrg char *bottom = (char *) (current + 1) + current->size;
6341debfc3dSmrg to = bottom - aligned;
6351debfc3dSmrg ret = bottom - aligned;
6361debfc3dSmrg }
6371debfc3dSmrg #else
6381debfc3dSmrg to = current + 1;
6391debfc3dSmrg to += aligned - param_size;
6401debfc3dSmrg ret = (char *) (current + 1) + aligned;
6411debfc3dSmrg #endif
6421debfc3dSmrg
6431debfc3dSmrg /* We don't call memcpy to avoid worrying about the dynamic linker
6441debfc3dSmrg trying to resolve it. */
6451debfc3dSmrg from = (char *) old_stack;
6461debfc3dSmrg for (i = 0; i < param_size; i++)
6471debfc3dSmrg *to++ = *from++;
6481debfc3dSmrg
6491debfc3dSmrg return ret;
6501debfc3dSmrg }
6511debfc3dSmrg
6521debfc3dSmrg /* This function is called by a processor specific function when it is
6531debfc3dSmrg ready to release a stack segment. We don't actually release the
6541debfc3dSmrg stack segment, we just move back to the previous one. The current
6551debfc3dSmrg stack segment will still be available if we need it in
6561debfc3dSmrg __generic_morestack. This returns a pointer to the new stack
6571debfc3dSmrg segment to use, which is the one saved by a previous call to
6581debfc3dSmrg __generic_morestack. The processor specific function is then
6591debfc3dSmrg responsible for actually updating the stack pointer. This sets
6601debfc3dSmrg *PAVAILABLE to the amount of stack space now available. */
6611debfc3dSmrg
6621debfc3dSmrg void *
__generic_releasestack(size_t * pavailable)6631debfc3dSmrg __generic_releasestack (size_t *pavailable)
6641debfc3dSmrg {
6651debfc3dSmrg struct stack_segment *current;
6661debfc3dSmrg void *old_stack;
6671debfc3dSmrg
6681debfc3dSmrg current = __morestack_current_segment;
6691debfc3dSmrg old_stack = current->old_stack;
6701debfc3dSmrg current = current->prev;
6711debfc3dSmrg __morestack_current_segment = current;
6721debfc3dSmrg
6731debfc3dSmrg if (current != NULL)
6741debfc3dSmrg {
6751debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
6761debfc3dSmrg *pavailable = (char *) old_stack - (char *) (current + 1);
6771debfc3dSmrg #else
6781debfc3dSmrg *pavailable = (char *) (current + 1) + current->size - (char *) old_stack;
6791debfc3dSmrg #endif
6801debfc3dSmrg }
6811debfc3dSmrg else
6821debfc3dSmrg {
6831debfc3dSmrg size_t used;
6841debfc3dSmrg
6851debfc3dSmrg /* We have popped back to the original stack. */
6861debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
6871debfc3dSmrg if ((char *) old_stack >= (char *) __morestack_initial_sp.sp)
6881debfc3dSmrg used = 0;
6891debfc3dSmrg else
6901debfc3dSmrg used = (char *) __morestack_initial_sp.sp - (char *) old_stack;
6911debfc3dSmrg #else
6921debfc3dSmrg if ((char *) old_stack <= (char *) __morestack_initial_sp.sp)
6931debfc3dSmrg used = 0;
6941debfc3dSmrg else
6951debfc3dSmrg used = (char *) old_stack - (char *) __morestack_initial_sp.sp;
6961debfc3dSmrg #endif
6971debfc3dSmrg
6981debfc3dSmrg if (used > __morestack_initial_sp.len)
6991debfc3dSmrg *pavailable = 0;
7001debfc3dSmrg else
7011debfc3dSmrg *pavailable = __morestack_initial_sp.len - used;
7021debfc3dSmrg }
7031debfc3dSmrg
7041debfc3dSmrg return old_stack;
7051debfc3dSmrg }
7061debfc3dSmrg
7071debfc3dSmrg /* Block signals while splitting the stack. This avoids trouble if we
7081debfc3dSmrg try to invoke a signal handler which itself wants to split the
7091debfc3dSmrg stack. */
7101debfc3dSmrg
7111debfc3dSmrg extern int pthread_sigmask (int, const sigset_t *, sigset_t *)
7121debfc3dSmrg __attribute__ ((weak));
7131debfc3dSmrg
7141debfc3dSmrg void
__morestack_block_signals(void)7151debfc3dSmrg __morestack_block_signals (void)
7161debfc3dSmrg {
7171debfc3dSmrg if (__morestack_initial_sp.dont_block_signals)
7181debfc3dSmrg ;
7191debfc3dSmrg else if (pthread_sigmask)
7201debfc3dSmrg pthread_sigmask (SIG_BLOCK, &__morestack_fullmask,
7211debfc3dSmrg &__morestack_initial_sp.mask);
7221debfc3dSmrg else
7231debfc3dSmrg sigprocmask (SIG_BLOCK, &__morestack_fullmask,
7241debfc3dSmrg &__morestack_initial_sp.mask);
7251debfc3dSmrg }
7261debfc3dSmrg
7271debfc3dSmrg /* Unblock signals while splitting the stack. */
7281debfc3dSmrg
7291debfc3dSmrg void
__morestack_unblock_signals(void)7301debfc3dSmrg __morestack_unblock_signals (void)
7311debfc3dSmrg {
7321debfc3dSmrg if (__morestack_initial_sp.dont_block_signals)
7331debfc3dSmrg ;
7341debfc3dSmrg else if (pthread_sigmask)
7351debfc3dSmrg pthread_sigmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL);
7361debfc3dSmrg else
7371debfc3dSmrg sigprocmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL);
7381debfc3dSmrg }
7391debfc3dSmrg
7401debfc3dSmrg /* This function is called to allocate dynamic stack space, for alloca
7411debfc3dSmrg or a variably sized array. This is a regular function with
7421debfc3dSmrg sufficient stack space, so we just use malloc to allocate the
7431debfc3dSmrg space. We attach the allocated blocks to the current stack
7441debfc3dSmrg segment, so that they will eventually be reused or freed. */
7451debfc3dSmrg
7461debfc3dSmrg void *
__morestack_allocate_stack_space(size_t size)7471debfc3dSmrg __morestack_allocate_stack_space (size_t size)
7481debfc3dSmrg {
7491debfc3dSmrg struct stack_segment *seg, *current;
7501debfc3dSmrg struct dynamic_allocation_blocks *p;
7511debfc3dSmrg
7521debfc3dSmrg /* We have to block signals to avoid getting confused if we get
7531debfc3dSmrg interrupted by a signal whose handler itself uses alloca or a
7541debfc3dSmrg variably sized array. */
7551debfc3dSmrg __morestack_block_signals ();
7561debfc3dSmrg
7571debfc3dSmrg /* Since we don't want to call free while we are low on stack space,
7581debfc3dSmrg we may have a list of already allocated blocks waiting to be
7591debfc3dSmrg freed. Release them all, unless we find one that is large
7601debfc3dSmrg enough. We don't look at every block to see if one is large
7611debfc3dSmrg enough, just the first one, because we aren't trying to build a
7621debfc3dSmrg memory allocator here, we're just trying to speed up common
7631debfc3dSmrg cases. */
7641debfc3dSmrg
7651debfc3dSmrg current = __morestack_current_segment;
7661debfc3dSmrg p = NULL;
7671debfc3dSmrg for (seg = __morestack_segments; seg != NULL; seg = seg->next)
7681debfc3dSmrg {
7691debfc3dSmrg p = seg->free_dynamic_allocation;
7701debfc3dSmrg if (p != NULL)
7711debfc3dSmrg {
7721debfc3dSmrg if (p->size >= size)
7731debfc3dSmrg {
7741debfc3dSmrg seg->free_dynamic_allocation = p->next;
7751debfc3dSmrg break;
7761debfc3dSmrg }
7771debfc3dSmrg
7781debfc3dSmrg free_dynamic_blocks (p);
7791debfc3dSmrg seg->free_dynamic_allocation = NULL;
7801debfc3dSmrg p = NULL;
7811debfc3dSmrg }
7821debfc3dSmrg }
7831debfc3dSmrg
7841debfc3dSmrg if (p == NULL)
7851debfc3dSmrg {
7861debfc3dSmrg /* We need to allocate additional memory. */
7871debfc3dSmrg p = malloc (sizeof (*p));
7881debfc3dSmrg if (p == NULL)
7891debfc3dSmrg abort ();
7901debfc3dSmrg p->size = size;
7911debfc3dSmrg p->block = malloc (size);
7921debfc3dSmrg if (p->block == NULL)
7931debfc3dSmrg abort ();
7941debfc3dSmrg }
7951debfc3dSmrg
7961debfc3dSmrg /* If we are still on the initial stack, then we have a space leak.
7971debfc3dSmrg FIXME. */
7981debfc3dSmrg if (current != NULL)
7991debfc3dSmrg {
8001debfc3dSmrg p->next = current->dynamic_allocation;
8011debfc3dSmrg current->dynamic_allocation = p;
8021debfc3dSmrg }
8031debfc3dSmrg
8041debfc3dSmrg __morestack_unblock_signals ();
8051debfc3dSmrg
8061debfc3dSmrg return p->block;
8071debfc3dSmrg }
8081debfc3dSmrg
8091debfc3dSmrg /* Find the stack segment for STACK and return the amount of space
8101debfc3dSmrg available. This is used when unwinding the stack because of an
8111debfc3dSmrg exception, in order to reset the stack guard correctly. */
8121debfc3dSmrg
8131debfc3dSmrg size_t
__generic_findstack(void * stack)8141debfc3dSmrg __generic_findstack (void *stack)
8151debfc3dSmrg {
8161debfc3dSmrg struct stack_segment *pss;
8171debfc3dSmrg size_t used;
8181debfc3dSmrg
8191debfc3dSmrg for (pss = __morestack_current_segment; pss != NULL; pss = pss->prev)
8201debfc3dSmrg {
8211debfc3dSmrg if ((char *) pss < (char *) stack
8221debfc3dSmrg && (char *) pss + pss->size > (char *) stack)
8231debfc3dSmrg {
8241debfc3dSmrg __morestack_current_segment = pss;
8251debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
8261debfc3dSmrg return (char *) stack - (char *) (pss + 1);
8271debfc3dSmrg #else
8281debfc3dSmrg return (char *) (pss + 1) + pss->size - (char *) stack;
8291debfc3dSmrg #endif
8301debfc3dSmrg }
8311debfc3dSmrg }
8321debfc3dSmrg
8331debfc3dSmrg /* We have popped back to the original stack. */
8341debfc3dSmrg
8351debfc3dSmrg if (__morestack_initial_sp.sp == NULL)
8361debfc3dSmrg return 0;
8371debfc3dSmrg
8381debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
8391debfc3dSmrg if ((char *) stack >= (char *) __morestack_initial_sp.sp)
8401debfc3dSmrg used = 0;
8411debfc3dSmrg else
8421debfc3dSmrg used = (char *) __morestack_initial_sp.sp - (char *) stack;
8431debfc3dSmrg #else
8441debfc3dSmrg if ((char *) stack <= (char *) __morestack_initial_sp.sp)
8451debfc3dSmrg used = 0;
8461debfc3dSmrg else
8471debfc3dSmrg used = (char *) stack - (char *) __morestack_initial_sp.sp;
8481debfc3dSmrg #endif
8491debfc3dSmrg
8501debfc3dSmrg if (used > __morestack_initial_sp.len)
8511debfc3dSmrg return 0;
8521debfc3dSmrg else
8531debfc3dSmrg return __morestack_initial_sp.len - used;
8541debfc3dSmrg }
8551debfc3dSmrg
8561debfc3dSmrg /* This function is called at program startup time to make sure that
8571debfc3dSmrg mmap, munmap, and getpagesize are resolved if linking dynamically.
8581debfc3dSmrg We want to resolve them while we have enough stack for them, rather
859a2dc1f3fSmrg than calling into the dynamic linker while low on stack space.
860a2dc1f3fSmrg Similarly, invoke getenv here to check for split-stack related control
861a2dc1f3fSmrg variables, since doing do as part of the __morestack path can result
862a2dc1f3fSmrg in unwanted use of SSE/AVX registers (see GCC PR 86213). */
8631debfc3dSmrg
8641debfc3dSmrg void
__morestack_load_mmap(void)8651debfc3dSmrg __morestack_load_mmap (void)
8661debfc3dSmrg {
8671debfc3dSmrg /* Call with bogus values to run faster. We don't care if the call
8681debfc3dSmrg fails. Pass __MORESTACK_CURRENT_SEGMENT to make sure that any
8691debfc3dSmrg TLS accessor function is resolved. */
8701debfc3dSmrg mmap (__morestack_current_segment, 0, PROT_READ, MAP_ANONYMOUS, -1, 0);
8711debfc3dSmrg mprotect (NULL, 0, 0);
872a2dc1f3fSmrg munmap (0, static_pagesize);
873a2dc1f3fSmrg
874a2dc1f3fSmrg /* Initialize these values here, so as to avoid dynamic linker
875a2dc1f3fSmrg activity as part of a __morestack call. */
876a2dc1f3fSmrg static_pagesize = getpagesize();
877a2dc1f3fSmrg use_guard_page = getenv ("SPLIT_STACK_GUARD") != 0;
8781debfc3dSmrg }
8791debfc3dSmrg
8801debfc3dSmrg /* This function may be used to iterate over the stack segments.
8811debfc3dSmrg This can be called like this.
8821debfc3dSmrg void *next_segment = NULL;
8831debfc3dSmrg void *next_sp = NULL;
8841debfc3dSmrg void *initial_sp = NULL;
8851debfc3dSmrg void *stack;
8861debfc3dSmrg size_t stack_size;
8871debfc3dSmrg while ((stack = __splitstack_find (next_segment, next_sp, &stack_size,
8881debfc3dSmrg &next_segment, &next_sp,
8891debfc3dSmrg &initial_sp)) != NULL)
8901debfc3dSmrg {
8911debfc3dSmrg // Stack segment starts at stack and is stack_size bytes long.
8921debfc3dSmrg }
8931debfc3dSmrg
8941debfc3dSmrg There is no way to iterate over the stack segments of a different
8951debfc3dSmrg thread. However, what is permitted is for one thread to call this
8961debfc3dSmrg with the first two values NULL, to pass next_segment, next_sp, and
8971debfc3dSmrg initial_sp to a different thread, and then to suspend one way or
8981debfc3dSmrg another. A different thread may run the subsequent
8991debfc3dSmrg __morestack_find iterations. Of course, this will only work if the
9001debfc3dSmrg first thread is suspended during the __morestack_find iterations.
9011debfc3dSmrg If not, the second thread will be looking at the stack while it is
9021debfc3dSmrg changing, and anything could happen.
9031debfc3dSmrg
9041debfc3dSmrg FIXME: This should be declared in some header file, but where? */
9051debfc3dSmrg
9061debfc3dSmrg void *
__splitstack_find(void * segment_arg,void * sp,size_t * len,void ** next_segment,void ** next_sp,void ** initial_sp)9071debfc3dSmrg __splitstack_find (void *segment_arg, void *sp, size_t *len,
9081debfc3dSmrg void **next_segment, void **next_sp,
9091debfc3dSmrg void **initial_sp)
9101debfc3dSmrg {
9111debfc3dSmrg struct stack_segment *segment;
9121debfc3dSmrg void *ret;
9131debfc3dSmrg char *nsp;
9141debfc3dSmrg
9151debfc3dSmrg if (segment_arg == (void *) (uintptr_type) 1)
9161debfc3dSmrg {
9171debfc3dSmrg char *isp = (char *) *initial_sp;
9181debfc3dSmrg
9191debfc3dSmrg if (isp == NULL)
9201debfc3dSmrg return NULL;
9211debfc3dSmrg
9221debfc3dSmrg *next_segment = (void *) (uintptr_type) 2;
9231debfc3dSmrg *next_sp = NULL;
9241debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
9251debfc3dSmrg if ((char *) sp >= isp)
9261debfc3dSmrg return NULL;
9271debfc3dSmrg *len = (char *) isp - (char *) sp;
9281debfc3dSmrg return sp;
9291debfc3dSmrg #else
9301debfc3dSmrg if ((char *) sp <= (char *) isp)
9311debfc3dSmrg return NULL;
9321debfc3dSmrg *len = (char *) sp - (char *) isp;
9331debfc3dSmrg return (void *) isp;
9341debfc3dSmrg #endif
9351debfc3dSmrg }
9361debfc3dSmrg else if (segment_arg == (void *) (uintptr_type) 2)
9371debfc3dSmrg return NULL;
9381debfc3dSmrg else if (segment_arg != NULL)
9391debfc3dSmrg segment = (struct stack_segment *) segment_arg;
9401debfc3dSmrg else
9411debfc3dSmrg {
9421debfc3dSmrg *initial_sp = __morestack_initial_sp.sp;
9431debfc3dSmrg segment = __morestack_current_segment;
9441debfc3dSmrg sp = (void *) &segment;
9451debfc3dSmrg while (1)
9461debfc3dSmrg {
9471debfc3dSmrg if (segment == NULL)
9481debfc3dSmrg return __splitstack_find ((void *) (uintptr_type) 1, sp, len,
9491debfc3dSmrg next_segment, next_sp, initial_sp);
9501debfc3dSmrg if ((char *) sp >= (char *) (segment + 1)
9511debfc3dSmrg && (char *) sp <= (char *) (segment + 1) + segment->size)
9521debfc3dSmrg break;
9531debfc3dSmrg segment = segment->prev;
9541debfc3dSmrg }
9551debfc3dSmrg }
9561debfc3dSmrg
9571debfc3dSmrg if (segment->prev == NULL)
9581debfc3dSmrg *next_segment = (void *) (uintptr_type) 1;
9591debfc3dSmrg else
9601debfc3dSmrg *next_segment = segment->prev;
9611debfc3dSmrg
9621debfc3dSmrg /* The old_stack value is the address of the function parameters of
9631debfc3dSmrg the function which called __morestack. So if f1 called f2 which
9641debfc3dSmrg called __morestack, the stack looks like this:
9651debfc3dSmrg
9661debfc3dSmrg parameters <- old_stack
9671debfc3dSmrg return in f1
9681debfc3dSmrg return in f2
9691debfc3dSmrg registers pushed by __morestack
9701debfc3dSmrg
9711debfc3dSmrg The registers pushed by __morestack may not be visible on any
9721debfc3dSmrg other stack, if we are being called by a signal handler
9731debfc3dSmrg immediately after the call to __morestack_unblock_signals. We
9741debfc3dSmrg want to adjust our return value to include those registers. This
9751debfc3dSmrg is target dependent. */
9761debfc3dSmrg
9771debfc3dSmrg nsp = (char *) segment->old_stack;
9781debfc3dSmrg
9791debfc3dSmrg if (nsp == NULL)
9801debfc3dSmrg {
9811debfc3dSmrg /* We've reached the top of the stack. */
9821debfc3dSmrg *next_segment = (void *) (uintptr_type) 2;
9831debfc3dSmrg }
9841debfc3dSmrg else
9851debfc3dSmrg {
9861debfc3dSmrg #if defined (__x86_64__)
9871debfc3dSmrg nsp -= 12 * sizeof (void *);
9881debfc3dSmrg #elif defined (__i386__)
9891debfc3dSmrg nsp -= 6 * sizeof (void *);
9901debfc3dSmrg #elif defined __powerpc64__
9911debfc3dSmrg #elif defined __s390x__
9921debfc3dSmrg nsp -= 2 * 160;
9931debfc3dSmrg #elif defined __s390__
9941debfc3dSmrg nsp -= 2 * 96;
9951debfc3dSmrg #else
9961debfc3dSmrg #error "unrecognized target"
9971debfc3dSmrg #endif
9981debfc3dSmrg
9991debfc3dSmrg *next_sp = (void *) nsp;
10001debfc3dSmrg }
10011debfc3dSmrg
10021debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
10031debfc3dSmrg *len = (char *) (segment + 1) + segment->size - (char *) sp;
10041debfc3dSmrg ret = (void *) sp;
10051debfc3dSmrg #else
10061debfc3dSmrg *len = (char *) sp - (char *) (segment + 1);
10071debfc3dSmrg ret = (void *) (segment + 1);
10081debfc3dSmrg #endif
10091debfc3dSmrg
10101debfc3dSmrg return ret;
10111debfc3dSmrg }
10121debfc3dSmrg
10131debfc3dSmrg /* Tell the split stack code whether it has to block signals while
10141debfc3dSmrg manipulating the stack. This is for programs in which some threads
10151debfc3dSmrg block all signals. If a thread already blocks signals, there is no
10161debfc3dSmrg need for the split stack code to block them as well. If NEW is not
10171debfc3dSmrg NULL, then if *NEW is non-zero signals will be blocked while
10181debfc3dSmrg splitting the stack, otherwise they will not. If OLD is not NULL,
10191debfc3dSmrg *OLD will be set to the old value. */
10201debfc3dSmrg
10211debfc3dSmrg void
__splitstack_block_signals(int * new,int * old)10221debfc3dSmrg __splitstack_block_signals (int *new, int *old)
10231debfc3dSmrg {
10241debfc3dSmrg if (old != NULL)
10251debfc3dSmrg *old = __morestack_initial_sp.dont_block_signals ? 0 : 1;
10261debfc3dSmrg if (new != NULL)
10271debfc3dSmrg __morestack_initial_sp.dont_block_signals = *new ? 0 : 1;
10281debfc3dSmrg }
10291debfc3dSmrg
10301debfc3dSmrg /* The offsets into the arrays used by __splitstack_getcontext and
10311debfc3dSmrg __splitstack_setcontext. */
10321debfc3dSmrg
10331debfc3dSmrg enum __splitstack_context_offsets
10341debfc3dSmrg {
10351debfc3dSmrg MORESTACK_SEGMENTS = 0,
10361debfc3dSmrg CURRENT_SEGMENT = 1,
10371debfc3dSmrg CURRENT_STACK = 2,
10381debfc3dSmrg STACK_GUARD = 3,
10391debfc3dSmrg INITIAL_SP = 4,
10401debfc3dSmrg INITIAL_SP_LEN = 5,
10411debfc3dSmrg BLOCK_SIGNALS = 6,
10421debfc3dSmrg
10431debfc3dSmrg NUMBER_OFFSETS = 10
10441debfc3dSmrg };
10451debfc3dSmrg
10461debfc3dSmrg /* Get the current split stack context. This may be used for
10471debfc3dSmrg coroutine switching, similar to getcontext. The argument should
10481debfc3dSmrg have at least 10 void *pointers for extensibility, although we
10491debfc3dSmrg don't currently use all of them. This would normally be called
10501debfc3dSmrg immediately before a call to getcontext or swapcontext or
10511debfc3dSmrg setjmp. */
10521debfc3dSmrg
10531debfc3dSmrg void
__splitstack_getcontext(void * context[NUMBER_OFFSETS])10541debfc3dSmrg __splitstack_getcontext (void *context[NUMBER_OFFSETS])
10551debfc3dSmrg {
10561debfc3dSmrg memset (context, 0, NUMBER_OFFSETS * sizeof (void *));
10571debfc3dSmrg context[MORESTACK_SEGMENTS] = (void *) __morestack_segments;
10581debfc3dSmrg context[CURRENT_SEGMENT] = (void *) __morestack_current_segment;
10591debfc3dSmrg context[CURRENT_STACK] = (void *) &context;
10601debfc3dSmrg context[STACK_GUARD] = __morestack_get_guard ();
10611debfc3dSmrg context[INITIAL_SP] = (void *) __morestack_initial_sp.sp;
10621debfc3dSmrg context[INITIAL_SP_LEN] = (void *) (uintptr_type) __morestack_initial_sp.len;
10631debfc3dSmrg context[BLOCK_SIGNALS] = (void *) __morestack_initial_sp.dont_block_signals;
10641debfc3dSmrg }
10651debfc3dSmrg
10661debfc3dSmrg /* Set the current split stack context. The argument should be a
10671debfc3dSmrg context previously passed to __splitstack_getcontext. This would
10681debfc3dSmrg normally be called immediately after a call to getcontext or
10691debfc3dSmrg swapcontext or setjmp if something jumped to it. */
10701debfc3dSmrg
10711debfc3dSmrg void
__splitstack_setcontext(void * context[NUMBER_OFFSETS])10721debfc3dSmrg __splitstack_setcontext (void *context[NUMBER_OFFSETS])
10731debfc3dSmrg {
10741debfc3dSmrg __morestack_segments = (struct stack_segment *) context[MORESTACK_SEGMENTS];
10751debfc3dSmrg __morestack_current_segment =
10761debfc3dSmrg (struct stack_segment *) context[CURRENT_SEGMENT];
10771debfc3dSmrg __morestack_set_guard (context[STACK_GUARD]);
10781debfc3dSmrg __morestack_initial_sp.sp = context[INITIAL_SP];
10791debfc3dSmrg __morestack_initial_sp.len = (size_t) context[INITIAL_SP_LEN];
10801debfc3dSmrg __morestack_initial_sp.dont_block_signals =
10811debfc3dSmrg (uintptr_type) context[BLOCK_SIGNALS];
10821debfc3dSmrg }
10831debfc3dSmrg
10841debfc3dSmrg /* Create a new split stack context. This will allocate a new stack
10851debfc3dSmrg segment which may be used by a coroutine. STACK_SIZE is the
10861debfc3dSmrg minimum size of the new stack. The caller is responsible for
10871debfc3dSmrg actually setting the stack pointer. This would normally be called
10881debfc3dSmrg before a call to makecontext, and the returned stack pointer and
10891debfc3dSmrg size would be used to set the uc_stack field. A function called
10901debfc3dSmrg via makecontext on a stack created by __splitstack_makecontext may
10911debfc3dSmrg not return. Note that the returned pointer points to the lowest
10921debfc3dSmrg address in the stack space, and thus may not be the value to which
10931debfc3dSmrg to set the stack pointer. */
10941debfc3dSmrg
10951debfc3dSmrg void *
__splitstack_makecontext(size_t stack_size,void * context[NUMBER_OFFSETS],size_t * size)10961debfc3dSmrg __splitstack_makecontext (size_t stack_size, void *context[NUMBER_OFFSETS],
10971debfc3dSmrg size_t *size)
10981debfc3dSmrg {
10991debfc3dSmrg struct stack_segment *segment;
11001debfc3dSmrg void *initial_sp;
11011debfc3dSmrg
11021debfc3dSmrg memset (context, 0, NUMBER_OFFSETS * sizeof (void *));
11031debfc3dSmrg segment = allocate_segment (stack_size);
11041debfc3dSmrg context[MORESTACK_SEGMENTS] = segment;
11051debfc3dSmrg context[CURRENT_SEGMENT] = segment;
11061debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
11071debfc3dSmrg initial_sp = (void *) ((char *) (segment + 1) + segment->size);
11081debfc3dSmrg #else
11091debfc3dSmrg initial_sp = (void *) (segment + 1);
11101debfc3dSmrg #endif
11111debfc3dSmrg context[STACK_GUARD] = __morestack_make_guard (initial_sp, segment->size);
11121debfc3dSmrg context[INITIAL_SP] = NULL;
11131debfc3dSmrg context[INITIAL_SP_LEN] = 0;
11141debfc3dSmrg *size = segment->size;
11151debfc3dSmrg return (void *) (segment + 1);
11161debfc3dSmrg }
11171debfc3dSmrg
11181debfc3dSmrg /* Given an existing split stack context, reset it back to the start
11191debfc3dSmrg of the stack. Return the stack pointer and size, appropriate for
11201debfc3dSmrg use with makecontext. This may be used if a coroutine exits, in
11211debfc3dSmrg order to reuse the stack segments for a new coroutine. */
11221debfc3dSmrg
11231debfc3dSmrg void *
__splitstack_resetcontext(void * context[10],size_t * size)11241debfc3dSmrg __splitstack_resetcontext (void *context[10], size_t *size)
11251debfc3dSmrg {
11261debfc3dSmrg struct stack_segment *segment;
11271debfc3dSmrg void *initial_sp;
11281debfc3dSmrg size_t initial_size;
11291debfc3dSmrg void *ret;
11301debfc3dSmrg
11311debfc3dSmrg /* Reset the context assuming that MORESTACK_SEGMENTS, INITIAL_SP
11321debfc3dSmrg and INITIAL_SP_LEN are correct. */
11331debfc3dSmrg
11341debfc3dSmrg segment = context[MORESTACK_SEGMENTS];
11351debfc3dSmrg context[CURRENT_SEGMENT] = segment;
11361debfc3dSmrg context[CURRENT_STACK] = NULL;
11371debfc3dSmrg if (segment == NULL)
11381debfc3dSmrg {
11391debfc3dSmrg initial_sp = context[INITIAL_SP];
11401debfc3dSmrg initial_size = (uintptr_type) context[INITIAL_SP_LEN];
11411debfc3dSmrg ret = initial_sp;
11421debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
11431debfc3dSmrg ret = (void *) ((char *) ret - initial_size);
11441debfc3dSmrg #endif
11451debfc3dSmrg }
11461debfc3dSmrg else
11471debfc3dSmrg {
11481debfc3dSmrg #ifdef __LIBGCC_STACK_GROWS_DOWNWARD__
11491debfc3dSmrg initial_sp = (void *) ((char *) (segment + 1) + segment->size);
11501debfc3dSmrg #else
11511debfc3dSmrg initial_sp = (void *) (segment + 1);
11521debfc3dSmrg #endif
11531debfc3dSmrg initial_size = segment->size;
11541debfc3dSmrg ret = (void *) (segment + 1);
11551debfc3dSmrg }
11561debfc3dSmrg context[STACK_GUARD] = __morestack_make_guard (initial_sp, initial_size);
11571debfc3dSmrg context[BLOCK_SIGNALS] = NULL;
11581debfc3dSmrg *size = initial_size;
11591debfc3dSmrg return ret;
11601debfc3dSmrg }
11611debfc3dSmrg
11621debfc3dSmrg /* Release all the memory associated with a splitstack context. This
11631debfc3dSmrg may be used if a coroutine exits and the associated stack should be
11641debfc3dSmrg freed. */
11651debfc3dSmrg
11661debfc3dSmrg void
__splitstack_releasecontext(void * context[10])11671debfc3dSmrg __splitstack_releasecontext (void *context[10])
11681debfc3dSmrg {
11691debfc3dSmrg __morestack_release_segments (((struct stack_segment **)
11701debfc3dSmrg &context[MORESTACK_SEGMENTS]),
11711debfc3dSmrg 1);
11721debfc3dSmrg }
11731debfc3dSmrg
11741debfc3dSmrg /* Like __splitstack_block_signals, but operating on CONTEXT, rather
11751debfc3dSmrg than on the current state. */
11761debfc3dSmrg
11771debfc3dSmrg void
__splitstack_block_signals_context(void * context[NUMBER_OFFSETS],int * new,int * old)11781debfc3dSmrg __splitstack_block_signals_context (void *context[NUMBER_OFFSETS], int *new,
11791debfc3dSmrg int *old)
11801debfc3dSmrg {
11811debfc3dSmrg if (old != NULL)
11821debfc3dSmrg *old = ((uintptr_type) context[BLOCK_SIGNALS]) != 0 ? 0 : 1;
11831debfc3dSmrg if (new != NULL)
11841debfc3dSmrg context[BLOCK_SIGNALS] = (void *) (uintptr_type) (*new ? 0 : 1);
11851debfc3dSmrg }
11861debfc3dSmrg
11871debfc3dSmrg /* Find the stack segments associated with a split stack context.
11881debfc3dSmrg This will return the address of the first stack segment and set
11891debfc3dSmrg *STACK_SIZE to its size. It will set next_segment, next_sp, and
11901debfc3dSmrg initial_sp which may be passed to __splitstack_find to find the
11911debfc3dSmrg remaining segments. */
11921debfc3dSmrg
11931debfc3dSmrg void *
__splitstack_find_context(void * context[NUMBER_OFFSETS],size_t * stack_size,void ** next_segment,void ** next_sp,void ** initial_sp)11941debfc3dSmrg __splitstack_find_context (void *context[NUMBER_OFFSETS], size_t *stack_size,
11951debfc3dSmrg void **next_segment, void **next_sp,
11961debfc3dSmrg void **initial_sp)
11971debfc3dSmrg {
11981debfc3dSmrg void *sp;
11991debfc3dSmrg struct stack_segment *segment;
12001debfc3dSmrg
12011debfc3dSmrg *initial_sp = context[INITIAL_SP];
12021debfc3dSmrg
12031debfc3dSmrg sp = context[CURRENT_STACK];
12041debfc3dSmrg if (sp == NULL)
12051debfc3dSmrg {
12061debfc3dSmrg /* Most likely this context was created but was never used. The
12071debfc3dSmrg value 2 is a code used by __splitstack_find to mean that we
12081debfc3dSmrg have reached the end of the list of stacks. */
12091debfc3dSmrg *next_segment = (void *) (uintptr_type) 2;
12101debfc3dSmrg *next_sp = NULL;
12111debfc3dSmrg *initial_sp = NULL;
12121debfc3dSmrg return NULL;
12131debfc3dSmrg }
12141debfc3dSmrg
12151debfc3dSmrg segment = context[CURRENT_SEGMENT];
12161debfc3dSmrg if (segment == NULL)
12171debfc3dSmrg {
12181debfc3dSmrg /* Most likely this context was saved by a thread which was not
12191debfc3dSmrg created using __splistack_makecontext and which has never
12201debfc3dSmrg split the stack. The value 1 is a code used by
12211debfc3dSmrg __splitstack_find to look at the initial stack. */
12221debfc3dSmrg segment = (struct stack_segment *) (uintptr_type) 1;
12231debfc3dSmrg }
12241debfc3dSmrg
12251debfc3dSmrg return __splitstack_find (segment, sp, stack_size, next_segment, next_sp,
12261debfc3dSmrg initial_sp);
12271debfc3dSmrg }
12281debfc3dSmrg
12291debfc3dSmrg #endif /* !defined (inhibit_libc) */
12301debfc3dSmrg #endif /* not powerpc 32-bit */
1231