1 /* Internal header file for <setjmp.h>.  Linux/x86 version.
2    Copyright (C) 2017-2022 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