(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
i386/
sysdep.h
       1  /* Copyright (C) 1992-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifndef _LINUX_I386_SYSDEP_H
      19  #define _LINUX_I386_SYSDEP_H 1
      20  
      21  /* There is some commonality.  */
      22  #include <sysdeps/unix/sysv/linux/sysdep.h>
      23  #include <sysdeps/unix/i386/sysdep.h>
      24  /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
      25  #include <dl-sysdep.h>
      26  #include <tls.h>
      27  
      28  
      29  /* For Linux we can use the system call table in the header file
      30  	/usr/include/asm/unistd.h
      31     of the kernel.  But these symbols do not follow the SYS_* syntax
      32     so we have to redefine the `SYS_ify' macro here.  */
      33  #undef SYS_ify
      34  #define SYS_ify(syscall_name)	__NR_##syscall_name
      35  
      36  #ifndef I386_USE_SYSENTER
      37  # if defined USE_DL_SYSINFO \
      38       && (IS_IN (libc) || IS_IN (libpthread))
      39  #  define I386_USE_SYSENTER	1
      40  # else
      41  #  define I386_USE_SYSENTER	0
      42  # endif
      43  #endif
      44  
      45  #if !I386_USE_SYSENTER && IS_IN (libc) && !defined SHARED
      46  /* Inside static libc, we have two versions.  For compilation units
      47     with !I386_USE_SYSENTER, the vDSO entry mechanism cannot be
      48     used. */
      49  # define I386_DO_SYSCALL_STRING "__libc_do_syscall_int80"
      50  #else
      51  # define I386_DO_SYSCALL_STRING "__libc_do_syscall"
      52  #endif
      53  
      54  #ifdef __ASSEMBLER__
      55  
      56  /* Linux uses a negative return value to indicate syscall errors,
      57     unlike most Unices, which use the condition codes' carry flag.
      58  
      59     Since version 2.1 the return value of a system call might be
      60     negative even if the call succeeded.  E.g., the `lseek' system call
      61     might return a large offset.  Therefore we must not anymore test
      62     for < 0, but test for a real error by making sure the value in %eax
      63     is a real error number.  Linus said he will make sure the no syscall
      64     returns a value in -1 .. -4095 as a valid result so we can safely
      65     test with -4095.  */
      66  
      67  /* We don't want the label for the error handle to be global when we define
      68     it here.  */
      69  #undef SYSCALL_ERROR_LABEL
      70  #define SYSCALL_ERROR_LABEL __syscall_error
      71  
      72  #undef	PSEUDO
      73  #define	PSEUDO(name, syscall_name, args)				      \
      74    .text;								      \
      75    ENTRY (name)								      \
      76      DO_CALL (syscall_name, args);					      \
      77      cmpl $-4095, %eax;							      \
      78      jae SYSCALL_ERROR_LABEL
      79  
      80  #undef	PSEUDO_END
      81  #define	PSEUDO_END(name)						      \
      82    SYSCALL_ERROR_HANDLER							      \
      83    END (name)
      84  
      85  #undef	PSEUDO_NOERRNO
      86  #define	PSEUDO_NOERRNO(name, syscall_name, args)			      \
      87    .text;								      \
      88    ENTRY (name)								      \
      89      DO_CALL (syscall_name, args)
      90  
      91  #undef	PSEUDO_END_NOERRNO
      92  #define	PSEUDO_END_NOERRNO(name)					      \
      93    END (name)
      94  
      95  #define ret_NOERRNO ret
      96  
      97  /* The function has to return the error code.  */
      98  #undef	PSEUDO_ERRVAL
      99  #define	PSEUDO_ERRVAL(name, syscall_name, args) \
     100    .text;								      \
     101    ENTRY (name)								      \
     102      DO_CALL (syscall_name, args);					      \
     103      negl %eax
     104  
     105  #undef	PSEUDO_END_ERRVAL
     106  #define	PSEUDO_END_ERRVAL(name) \
     107    END (name)
     108  
     109  #define ret_ERRVAL ret
     110  
     111  #define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.c is used.  */
     112  
     113  /* The original calling convention for system calls on Linux/i386 is
     114     to use int $0x80.  */
     115  #if I386_USE_SYSENTER
     116  # ifdef PIC
     117  #  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
     118  # else
     119  #  define ENTER_KERNEL call *_dl_sysinfo
     120  # endif
     121  #else
     122  # define ENTER_KERNEL int $0x80
     123  #endif
     124  
     125  /* Linux takes system call arguments in registers:
     126  
     127  	syscall number	%eax	     call-clobbered
     128  	arg 1		%ebx	     call-saved
     129  	arg 2		%ecx	     call-clobbered
     130  	arg 3		%edx	     call-clobbered
     131  	arg 4		%esi	     call-saved
     132  	arg 5		%edi	     call-saved
     133  	arg 6		%ebp	     call-saved
     134  
     135     The stack layout upon entering the function is:
     136  
     137  	24(%esp)	Arg# 6
     138  	20(%esp)	Arg# 5
     139  	16(%esp)	Arg# 4
     140  	12(%esp)	Arg# 3
     141  	 8(%esp)	Arg# 2
     142  	 4(%esp)	Arg# 1
     143  	  (%esp)	Return address
     144  
     145     (Of course a function with say 3 arguments does not have entries for
     146     arguments 4, 5, and 6.)
     147  
     148     The following code tries hard to be optimal.  A general assumption
     149     (which is true according to the data books I have) is that
     150  
     151  	2 * xchg	is more expensive than	pushl + movl + popl
     152  
     153     Beside this a neat trick is used.  The calling conventions for Linux
     154     tell that among the registers used for parameters %ecx and %edx need
     155     not be saved.  Beside this we may clobber this registers even when
     156     they are not used for parameter passing.
     157  
     158     As a result one can see below that we save the content of the %ebx
     159     register in the %edx register when we have less than 3 arguments
     160     (2 * movl is less expensive than pushl + popl).
     161  
     162     Second unlike for the other registers we don't save the content of
     163     %ecx and %edx when we have more than 1 and 2 registers resp.
     164  
     165     The code below might look a bit long but we have to take care for
     166     the pipelined processors (i586).  Here the `pushl' and `popl'
     167     instructions are marked as NP (not pairable) but the exception is
     168     two consecutive of these instruction.  This gives no penalty on
     169     other processors though.  */
     170  
     171  #undef	DO_CALL
     172  #define DO_CALL(syscall_name, args)			      		      \
     173      PUSHARGS_##args							      \
     174      DOARGS_##args							      \
     175      movl $SYS_ify (syscall_name), %eax;					      \
     176      ENTER_KERNEL							      \
     177      POPARGS_##args
     178  
     179  #define PUSHARGS_0	/* No arguments to push.  */
     180  #define	DOARGS_0	/* No arguments to frob.  */
     181  #define	POPARGS_0	/* No arguments to pop.  */
     182  #define	_PUSHARGS_0	/* No arguments to push.  */
     183  #define _DOARGS_0(n)	/* No arguments to frob.  */
     184  #define	_POPARGS_0	/* No arguments to pop.  */
     185  
     186  #define PUSHARGS_1	movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0
     187  #define	DOARGS_1	_DOARGS_1 (4)
     188  #define	POPARGS_1	POPARGS_0; movl %edx, %ebx; L(RESTBX1):
     189  #define	_PUSHARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \
     190  			cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0
     191  #define _DOARGS_1(n)	movl n(%esp), %ebx; _DOARGS_0(n-4)
     192  #define	_POPARGS_1	_POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \
     193  			cfi_restore (ebx); L(POPBX1):
     194  
     195  #define PUSHARGS_2	PUSHARGS_1
     196  #define	DOARGS_2	_DOARGS_2 (8)
     197  #define	POPARGS_2	POPARGS_1
     198  #define _PUSHARGS_2	_PUSHARGS_1
     199  #define	_DOARGS_2(n)	movl n(%esp), %ecx; _DOARGS_1 (n-4)
     200  #define	_POPARGS_2	_POPARGS_1
     201  
     202  #define PUSHARGS_3	_PUSHARGS_2
     203  #define DOARGS_3	_DOARGS_3 (16)
     204  #define POPARGS_3	_POPARGS_3
     205  #define _PUSHARGS_3	_PUSHARGS_2
     206  #define _DOARGS_3(n)	movl n(%esp), %edx; _DOARGS_2 (n-4)
     207  #define _POPARGS_3	_POPARGS_2
     208  
     209  #define PUSHARGS_4	_PUSHARGS_4
     210  #define DOARGS_4	_DOARGS_4 (24)
     211  #define POPARGS_4	_POPARGS_4
     212  #define _PUSHARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \
     213  			cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3
     214  #define _DOARGS_4(n)	movl n(%esp), %esi; _DOARGS_3 (n-4)
     215  #define _POPARGS_4	_POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \
     216  			cfi_restore (esi); L(POPSI1):
     217  
     218  #define PUSHARGS_5	_PUSHARGS_5
     219  #define DOARGS_5	_DOARGS_5 (32)
     220  #define POPARGS_5	_POPARGS_5
     221  #define _PUSHARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \
     222  			cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4
     223  #define _DOARGS_5(n)	movl n(%esp), %edi; _DOARGS_4 (n-4)
     224  #define _POPARGS_5	_POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \
     225  			cfi_restore (edi); L(POPDI1):
     226  
     227  #define PUSHARGS_6	_PUSHARGS_6
     228  #define DOARGS_6	_DOARGS_6 (40)
     229  #define POPARGS_6	_POPARGS_6
     230  #define _PUSHARGS_6	pushl %ebp; cfi_adjust_cfa_offset (4); \
     231  			cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5
     232  #define _DOARGS_6(n)	movl n(%esp), %ebp; _DOARGS_5 (n-4)
     233  #define _POPARGS_6	_POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \
     234  			cfi_restore (ebp); L(POPBP1):
     235  
     236  #else	/* !__ASSEMBLER__ */
     237  
     238  extern int __syscall_error (int)
     239    attribute_hidden __attribute__ ((__regparm__ (1)));
     240  
     241  /* Six-argument syscalls use an out-of-line helper, because an inline
     242     asm using all registers apart from %esp cannot work reliably and
     243     the assembler does not support describing an asm that saves and
     244     restores %ebp itself as a separate stack frame.  This structure
     245     stores the arguments not passed in registers; %edi is passed with a
     246     pointer to this structure.  */
     247  struct libc_do_syscall_args
     248  {
     249    int ebx, edi, ebp;
     250  };
     251  
     252  # define VDSO_NAME  "LINUX_2.6"
     253  # define VDSO_HASH  61765110
     254  
     255  /* List of system calls which are supported as vsyscalls.  */
     256  # define HAVE_CLOCK_GETTIME_VSYSCALL    "__vdso_clock_gettime"
     257  # define HAVE_CLOCK_GETTIME64_VSYSCALL  "__vdso_clock_gettime64"
     258  # define HAVE_GETTIMEOFDAY_VSYSCALL     "__vdso_gettimeofday"
     259  # define HAVE_TIME_VSYSCALL             "__vdso_time"
     260  # define HAVE_CLOCK_GETRES_VSYSCALL     "__vdso_clock_getres"
     261  
     262  # define HAVE_CLONE3_WRAPPER		1
     263  
     264  # undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
     265  # define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
     266  
     267  /* Define a macro which expands inline into the wrapper code for a system
     268     call.  This use is for internal calls that do not need to handle errors
     269     normally.  It will never touch errno.  This returns just what the kernel
     270     gave back.
     271  
     272     The _NCS variant allows non-constant syscall numbers but it is not
     273     possible to use more than four parameters.  */
     274  #undef INTERNAL_SYSCALL
     275  #define INTERNAL_SYSCALL_MAIN_0(name, args...) \
     276      INTERNAL_SYSCALL_MAIN_INLINE(name, 0, args)
     277  #define INTERNAL_SYSCALL_MAIN_1(name, args...) \
     278      INTERNAL_SYSCALL_MAIN_INLINE(name, 1, args)
     279  #define INTERNAL_SYSCALL_MAIN_2(name, args...) \
     280      INTERNAL_SYSCALL_MAIN_INLINE(name, 2, args)
     281  #define INTERNAL_SYSCALL_MAIN_3(name, args...) \
     282      INTERNAL_SYSCALL_MAIN_INLINE(name, 3, args)
     283  #define INTERNAL_SYSCALL_MAIN_4(name, args...) \
     284      INTERNAL_SYSCALL_MAIN_INLINE(name, 4, args)
     285  #define INTERNAL_SYSCALL_MAIN_5(name, args...) \
     286      INTERNAL_SYSCALL_MAIN_INLINE(name, 5, args)
     287  
     288  #define INTERNAL_SYSCALL_MAIN_NCS_0(name, args...) \
     289      INTERNAL_SYSCALL_MAIN_NCS(name, 0, args)
     290  #define INTERNAL_SYSCALL_MAIN_NCS_1(name, args...) \
     291      INTERNAL_SYSCALL_MAIN_NCS(name, 1, args)
     292  #define INTERNAL_SYSCALL_MAIN_NCS_2(name, args...) \
     293      INTERNAL_SYSCALL_MAIN_NCS(name, 2, args)
     294  #define INTERNAL_SYSCALL_MAIN_NCS_3(name, args...) \
     295      INTERNAL_SYSCALL_MAIN_NCS(name, 3, args)
     296  #define INTERNAL_SYSCALL_MAIN_NCS_4(name, args...) \
     297      INTERNAL_SYSCALL_MAIN_NCS(name, 4, args)
     298  #define INTERNAL_SYSCALL_MAIN_NCS_5(name, args...) \
     299      INTERNAL_SYSCALL_MAIN_NCS(name, 5, args)
     300  
     301  /* Each object using 6-argument inline syscalls must include a
     302     definition of __libc_do_syscall.  */
     303  #define INTERNAL_SYSCALL_MAIN_6(name, arg1, arg2, arg3,			\
     304  				arg4, arg5, arg6)			\
     305    struct libc_do_syscall_args _xv =					\
     306      {									\
     307        (int) (arg1),							\
     308        (int) (arg5),							\
     309        (int) (arg6)							\
     310      };									\
     311      asm volatile (							\
     312      "movl %1, %%eax\n\t"						\
     313      "call " I386_DO_SYSCALL_STRING					\
     314      : "=a" (resultvar)							\
     315      : "i" (__NR_##name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \
     316      : "memory", "cc")
     317  #define INTERNAL_SYSCALL_MAIN_NCS_6(name, arg1, arg2, arg3,		\
     318  				    arg4, arg5, arg6)			\
     319    struct libc_do_syscall_args _xv =					\
     320      {									\
     321        (int) (arg1),							\
     322        (int) (arg5),							\
     323        (int) (arg6)							\
     324      };									\
     325      asm volatile (							\
     326      "movl %1, %%eax\n\t"						\
     327      "call " I386_DO_SYSCALL_STRING					\
     328      : "=a" (resultvar)							\
     329      : "a" (name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv)	\
     330      : "memory", "cc")
     331  
     332  #define INTERNAL_SYSCALL(name, nr, args...) \
     333    ({									      \
     334      register unsigned int resultvar;					      \
     335      INTERNAL_SYSCALL_MAIN_##nr (name, args);			      	      \
     336      (int) resultvar; })
     337  #define INTERNAL_SYSCALL_NCS(name, nr, args...) \
     338    ({									      \
     339      register unsigned int resultvar;					      \
     340      INTERNAL_SYSCALL_MAIN_NCS_##nr (name, args);		      	      \
     341      (int) resultvar; })
     342  
     343  #if I386_USE_SYSENTER
     344  # ifdef PIC
     345  #  define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
     346      LOADREGS_##nr(args)							\
     347      asm volatile (							\
     348      "call *%%gs:%P2"							\
     349      : "=a" (resultvar)							\
     350      : "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		\
     351        ASMARGS_##nr(args) : "memory", "cc")
     352  #  define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
     353      LOADREGS_##nr(args)							\
     354      asm volatile (							\
     355      "call *%%gs:%P2"							\
     356      : "=a" (resultvar)							\
     357      : "a" (name), "i" (offsetof (tcbhead_t, sysinfo))			\
     358        ASMARGS_##nr(args) : "memory", "cc")
     359  # else /* I386_USE_SYSENTER && !PIC */
     360  #  define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
     361      LOADREGS_##nr(args)							\
     362      asm volatile (							\
     363      "call *_dl_sysinfo"							\
     364      : "=a" (resultvar)							\
     365      : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
     366  #  define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
     367      LOADREGS_##nr(args)							\
     368      asm volatile (							\
     369      "call *_dl_sysinfo"							\
     370      : "=a" (resultvar)							\
     371      : "a" (name) ASMARGS_##nr(args) : "memory", "cc")
     372  # endif /* I386_USE_SYSENTER && !PIC */
     373  #else /* !I386_USE_SYSENTER */
     374  # define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
     375      LOADREGS_##nr(args)							\
     376      asm volatile (							\
     377      "int $0x80"								\
     378      : "=a" (resultvar)							\
     379      : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
     380  # define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
     381      LOADREGS_##nr(args)							\
     382      asm volatile (							\
     383      "int $0x80"								\
     384      : "=a" (resultvar)							\
     385      : "a" (name) ASMARGS_##nr(args) : "memory", "cc")
     386  #endif /* !I386_USE_SYSENTER */
     387  
     388  #define LOADREGS_0()
     389  #define ASMARGS_0()
     390  #define LOADREGS_1(arg1) \
     391  	LOADREGS_0 ()
     392  #define ASMARGS_1(arg1) \
     393  	ASMARGS_0 (), "b" ((unsigned int) (arg1))
     394  #define LOADREGS_2(arg1, arg2) \
     395  	LOADREGS_1 (arg1)
     396  #define ASMARGS_2(arg1, arg2) \
     397  	ASMARGS_1 (arg1), "c" ((unsigned int) (arg2))
     398  #define LOADREGS_3(arg1, arg2, arg3) \
     399  	LOADREGS_2 (arg1, arg2)
     400  #define ASMARGS_3(arg1, arg2, arg3) \
     401  	ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3))
     402  #define LOADREGS_4(arg1, arg2, arg3, arg4) \
     403  	LOADREGS_3 (arg1, arg2, arg3)
     404  #define ASMARGS_4(arg1, arg2, arg3, arg4) \
     405  	ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4))
     406  #define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
     407  	LOADREGS_4 (arg1, arg2, arg3, arg4)
     408  #define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
     409  	ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5))
     410  
     411  #define ASMFMT_0()
     412  #ifdef __PIC__
     413  # define ASMFMT_1(arg1) \
     414  	, "cd" (arg1)
     415  # define ASMFMT_2(arg1, arg2) \
     416  	, "d" (arg1), "c" (arg2)
     417  # define ASMFMT_3(arg1, arg2, arg3) \
     418  	, "D" (arg1), "c" (arg2), "d" (arg3)
     419  # define ASMFMT_4(arg1, arg2, arg3, arg4) \
     420  	, "D" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
     421  # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
     422  	, "0" (arg1), "m" (_xv), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
     423  #else
     424  # define ASMFMT_1(arg1) \
     425  	, "b" (arg1)
     426  # define ASMFMT_2(arg1, arg2) \
     427  	, "b" (arg1), "c" (arg2)
     428  # define ASMFMT_3(arg1, arg2, arg3) \
     429  	, "b" (arg1), "c" (arg2), "d" (arg3)
     430  # define ASMFMT_4(arg1, arg2, arg3, arg4) \
     431  	, "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
     432  # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
     433  	, "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
     434  #endif
     435  
     436  #define EXTRAVAR_0
     437  #define EXTRAVAR_1
     438  #define EXTRAVAR_2
     439  #define EXTRAVAR_3
     440  #define EXTRAVAR_4
     441  #ifdef __PIC__
     442  # define EXTRAVAR_5 int _xv;
     443  #else
     444  # define EXTRAVAR_5
     445  #endif
     446  
     447  #endif	/* __ASSEMBLER__ */
     448  
     449  /* Each shadow stack slot takes 4 bytes.  Assuming that each stack
     450     frame takes 128 bytes, this is used to compute shadow stack size
     451     from stack size.  */
     452  #define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
     453  
     454  #endif /* linux/i386/sysdep.h */