1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-01 10:06:57 +03:00

Add SYSCALL_ULONG_ARG_[12] to pass long to syscall [BZ #25810]

X32 has 32-bit long and pointer with 64-bit off_t.  Since x32 psABI
requires that pointers passed in registers must be zero-extended to
64bit, x32 can share many syscall interfaces with LP64.  When a LP64
syscall with long and unsigned long int arguments is used for x32, these
arguments must be properly extended to 64-bit.  Otherwise if the upper
32 bits of the register have undefined value, such a syscall will be
rejected by kernel.

For syscalls implemented in assembly codes, 'U' is added to syscall
signature key letters for unsigned long, which is zero-extended to
64-bit types.  SYSCALL_ULONG_ARG_1 and SYSCALL_ULONG_ARG_2 are passed
to syscall-template.S for the first and the second unsigned long int
arguments if PSEUDOS_HAVE_ULONG_INDICES is defined.  They are used by
x32 to zero-extend 32-bit arguments to 64 bits.

Tested on i386, x86-64 and x32 as well as with build-many-glibcs.py.
This commit is contained in:
H.J. Lu
2020-04-29 05:35:34 -07:00
parent 9207e30d3f
commit 2ad5d0845d
6 changed files with 159 additions and 30 deletions

View File

@ -25,6 +25,12 @@
defining a few macros:
SYSCALL_NAME syscall name
SYSCALL_NARGS number of arguments this call takes
SYSCALL_ULONG_ARG_1 the first unsigned long int argument this
call takes. 0 means that there are no
unsigned long int arguments.
SYSCALL_ULONG_ARG_2 the second unsigned long int argument this
call takes. 0 means that there is at most
one unsigned long int argument.
SYSCALL_SYMBOL primary symbol name
SYSCALL_NOERRNO 1 to define a no-errno version (see below)
SYSCALL_ERRVAL 1 to define an error-value version (see below)
@ -44,9 +50,31 @@
/* This indirection is needed so that SYMBOL gets macro-expanded. */
#define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL)
#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N)
#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N)
#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N)
/* If PSEUDOS_HAVE_ULONG_INDICES is defined, PSEUDO and T_PSEUDO macros
have 2 extra arguments for unsigned long int arguments:
Extra argument 1: Position of the first unsigned long int argument.
Extra argument 2: Position of the second unsigned long int argument.
*/
#ifndef PSEUDOS_HAVE_ULONG_INDICES
# undef SYSCALL_ULONG_ARG_1
# define SYSCALL_ULONG_ARG_1 0
#endif
#if SYSCALL_ULONG_ARG_1
# define T_PSEUDO(SYMBOL, NAME, N, U1, U2) \
PSEUDO (SYMBOL, NAME, N, U1, U2)
# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N, U1, U2) \
PSEUDO_NOERRNO (SYMBOL, NAME, N, U1, U2)
# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N, U1, U2) \
PSEUDO_ERRVAL (SYMBOL, NAME, N, U1, U2)
#else
# define T_PSEUDO(SYMBOL, NAME, N) \
PSEUDO (SYMBOL, NAME, N)
# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) \
PSEUDO_NOERRNO (SYMBOL, NAME, N)
# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) \
PSEUDO_ERRVAL (SYMBOL, NAME, N)
#endif
#define T_PSEUDO_END(SYMBOL) PSEUDO_END (SYMBOL)
#define T_PSEUDO_END_NOERRNO(SYMBOL) PSEUDO_END_NOERRNO (SYMBOL)
#define T_PSEUDO_END_ERRVAL(SYMBOL) PSEUDO_END_ERRVAL (SYMBOL)
@ -56,7 +84,12 @@
/* This kind of system call stub never returns an error.
We return the return value register to the caller unexamined. */
# if SYSCALL_ULONG_ARG_1
T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
# else
T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
# endif
ret_NOERRNO
T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL)
@ -66,7 +99,12 @@ T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL)
value, or zero for success. We may massage the kernel's return value
to meet that ABI, but we never set errno here. */
# if SYSCALL_ULONG_ARG_1
T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
# else
T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
# endif
ret_ERRVAL
T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL)
@ -75,7 +113,12 @@ T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL)
/* This is a "normal" system call stub: if there is an error,
it returns -1 and sets errno. */
# if SYSCALL_ULONG_ARG_1
T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
# else
T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
# endif
ret
T_PSEUDO_END (SYSCALL_SYMBOL)