| 1 | /* Internal header file for <setjmp.h>.  Linux/x86 version. | 
|---|
| 2 | Copyright (C) 2017-2020 Free Software Foundation, Inc. | 
|---|
| 3 | This file is part of the GNU C Library. | 
|---|
| 4 |  | 
|---|
| 5 | The GNU C Library is free software; you can redistribute it and/or | 
|---|
| 6 | modify it under the terms of the GNU Lesser General Public | 
|---|
| 7 | License as published by the Free Software Foundation; either | 
|---|
| 8 | version 2.1 of the License, or (at your option) any later version. | 
|---|
| 9 |  | 
|---|
| 10 | The GNU C Library is distributed in the hope that it will be useful, | 
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 13 | Lesser General Public License for more details. | 
|---|
| 14 |  | 
|---|
| 15 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 16 | License along with the GNU C Library; if not, see | 
|---|
| 17 | <https://www.gnu.org/licenses/>.  */ | 
|---|
| 18 |  | 
|---|
| 19 | #ifndef	_SETJMPP_H | 
|---|
| 20 | #define	_SETJMPP_H	1 | 
|---|
| 21 |  | 
|---|
| 22 | #include <bits/types/__sigset_t.h> | 
|---|
| 23 | #include <libc-pointer-arith.h> | 
|---|
| 24 | #include <sigsetops.h> | 
|---|
| 25 |  | 
|---|
| 26 | /* <setjmp/setjmp.h> has | 
|---|
| 27 |  | 
|---|
| 28 | struct __jmp_buf_tag | 
|---|
| 29 | { | 
|---|
| 30 | __jmp_buf __jmpbuf; | 
|---|
| 31 | int __mask_was_saved; | 
|---|
| 32 | __sigset_t __saved_mask; | 
|---|
| 33 | }; | 
|---|
| 34 |  | 
|---|
| 35 | struct __jmp_buf_tag is 32 bits aligned on i386 and is 64 bits | 
|---|
| 36 | aligned on x32 and x86-64.  __saved_mask is aligned to 32 bits | 
|---|
| 37 | on i386/x32 without padding and is aligned to 64 bits on x86-64 | 
|---|
| 38 | with 32 bit padding. | 
|---|
| 39 |  | 
|---|
| 40 | and <nptl/descr.h> has | 
|---|
| 41 |  | 
|---|
| 42 | struct pthread_unwind_buf | 
|---|
| 43 | { | 
|---|
| 44 | struct | 
|---|
| 45 | { | 
|---|
| 46 | __jmp_buf jmp_buf; | 
|---|
| 47 | int mask_was_saved; | 
|---|
| 48 | } cancel_jmp_buf[1]; | 
|---|
| 49 |  | 
|---|
| 50 | union | 
|---|
| 51 | { | 
|---|
| 52 | void *pad[4]; | 
|---|
| 53 | struct | 
|---|
| 54 | { | 
|---|
| 55 | struct pthread_unwind_buf *prev; | 
|---|
| 56 | struct _pthread_cleanup_buffer *cleanup; | 
|---|
| 57 | int canceltype; | 
|---|
| 58 | } data; | 
|---|
| 59 | } priv; | 
|---|
| 60 | }; | 
|---|
| 61 |  | 
|---|
| 62 | struct pthread_unwind_buf is 32 bits aligned on i386 and 64 bits | 
|---|
| 63 | aligned on x32/x86-64.  cancel_jmp_buf is aligned to 32 bits on | 
|---|
| 64 | i386 and is aligned to 64 bits on x32/x86-64. | 
|---|
| 65 |  | 
|---|
| 66 | The pad array in struct pthread_unwind_buf is used by setjmp to save | 
|---|
| 67 | shadow stack register.  The usable space in __saved_mask for sigset | 
|---|
| 68 | and shadow stack pointer: | 
|---|
| 69 | 1. i386: The 4x4 byte pad array which can be used for 4 byte shadow | 
|---|
| 70 | stack pointer and maximum 12 byte sigset. | 
|---|
| 71 | 2. x32: 4 byte padding + the 4x4 byte pad array which can be used | 
|---|
| 72 | for 8 byte shadow stack pointer and maximum 12 byte sigset. | 
|---|
| 73 | 3. x86-64: The 4x8 byte pad array which can be used for 8 byte | 
|---|
| 74 | shadow stack pointer and maximum 24 byte sigset. | 
|---|
| 75 |  | 
|---|
| 76 | NB: We use setjmp in thread cancellation and this saves the shadow | 
|---|
| 77 | stack register, but __libc_unwind_longjmp doesn't restore the shadow | 
|---|
| 78 | stack register since cancellation never returns after longjmp.  */ | 
|---|
| 79 |  | 
|---|
| 80 | /* Number of bits per long.  */ | 
|---|
| 81 | #define _JUMP_BUF_SIGSET_BITS_PER_WORD (8 * sizeof (unsigned long int)) | 
|---|
| 82 | /* The biggest signal number.  As of kernel 4.14, x86 _NSIG is 64. The | 
|---|
| 83 | common maximum sigset for i386, x32 and x86-64 is 12 bytes (96 bits). | 
|---|
| 84 | Define it to 96 to leave some rooms for future use.  */ | 
|---|
| 85 | #define _JUMP_BUF_SIGSET_NSIG	96 | 
|---|
| 86 | /* Number of longs to hold all signals.  */ | 
|---|
| 87 | #define _JUMP_BUF_SIGSET_NWORDS \ | 
|---|
| 88 | (ALIGN_UP (_JUMP_BUF_SIGSET_NSIG, _JUMP_BUF_SIGSET_BITS_PER_WORD) \ | 
|---|
| 89 | / _JUMP_BUF_SIGSET_BITS_PER_WORD) | 
|---|
| 90 |  | 
|---|
| 91 | typedef struct | 
|---|
| 92 | { | 
|---|
| 93 | unsigned long int __val[_JUMP_BUF_SIGSET_NWORDS]; | 
|---|
| 94 | } __jmp_buf_sigset_t; | 
|---|
| 95 |  | 
|---|
| 96 | typedef union | 
|---|
| 97 | { | 
|---|
| 98 | __sigset_t __saved_mask_compat; | 
|---|
| 99 | struct | 
|---|
| 100 | { | 
|---|
| 101 | __jmp_buf_sigset_t __saved_mask; | 
|---|
| 102 | /* Used for shadow stack pointer.  NB: Shadow stack pointer | 
|---|
| 103 | must have the same alignment as __saved_mask.  Otherwise | 
|---|
| 104 | offset of __saved_mask will be changed.  */ | 
|---|
| 105 | unsigned long int __shadow_stack_pointer; | 
|---|
| 106 | } __saved; | 
|---|
| 107 | } __jmpbuf_arch_t; | 
|---|
| 108 |  | 
|---|
| 109 | #undef __sigset_t | 
|---|
| 110 | #define __sigset_t __jmpbuf_arch_t | 
|---|
| 111 | #include <setjmp.h> | 
|---|
| 112 | #undef __saved_mask | 
|---|
| 113 | #define __saved_mask __saved_mask.__saved.__saved_mask | 
|---|
| 114 |  | 
|---|
| 115 | #include <signal.h> | 
|---|
| 116 |  | 
|---|
| 117 | typedef struct | 
|---|
| 118 | { | 
|---|
| 119 | unsigned long int __val[__NSIG_WORDS]; | 
|---|
| 120 | } __sigprocmask_sigset_t; | 
|---|
| 121 |  | 
|---|
| 122 | extern jmp_buf ___buf; | 
|---|
| 123 | extern  __typeof (___buf[0].__saved_mask) ___saved_mask; | 
|---|
| 124 | _Static_assert (sizeof (___saved_mask) >= sizeof (__sigprocmask_sigset_t), | 
|---|
| 125 | "size of ___saved_mask < size of __sigprocmask_sigset_t"); | 
|---|
| 126 |  | 
|---|
| 127 | #endif /* setjmpP.h  */ | 
|---|
| 128 |  | 
|---|