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