diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-04-29 05:35:34 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-04-29 05:35:34 -0700 |
commit | 2ad5d0845d80589d0adf86593bd36a7c71a521f8 (patch) | |
tree | 81bc0b7de7e0b93604944ed70e4125866547eb39 /sysdeps/unix/make-syscalls.sh | |
parent | 9207e30d3f070712df6c4175547094be112454d2 (diff) | |
download | glibc-2ad5d0845d80589d0adf86593bd36a7c71a521f8.tar.gz glibc-2ad5d0845d80589d0adf86593bd36a7c71a521f8.tar.xz glibc-2ad5d0845d80589d0adf86593bd36a7c71a521f8.zip |
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.
Diffstat (limited to 'sysdeps/unix/make-syscalls.sh')
-rw-r--r-- | sysdeps/unix/make-syscalls.sh | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh index c07626677f..4f6c3490a2 100644 --- a/sysdeps/unix/make-syscalls.sh +++ b/sysdeps/unix/make-syscalls.sh @@ -30,6 +30,7 @@ # P: optionally-NULL pointer to typed object (e.g., 3rd argument to sigaction) # s: non-NULL string (e.g., 1st arg to open) # S: optionally-NULL string (e.g., 1st arg to acct) +# U: unsigned long int (32-bit types are zero-extended to 64-bit types) # v: vararg scalar (e.g., optional 3rd arg to open) # V: byte-per-page vector (3rd arg to mincore) # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4) @@ -184,6 +185,27 @@ while read file srcfile caller syscall args strong weak; do ?:?????????) nargs=9;; esac + # Derive the unsigned long int arguments from the argument signature + ulong_arg_1=0 + ulong_arg_2=0 + ulong_count=0 + for U in $(echo $args | sed -e "s/.*:/:/" | grep -ob U) + do + ulong_count=$(expr $ulong_count + 1) + ulong_arg=$(echo $U | sed -e "s/:U//") + case $ulong_count in + 1) + ulong_arg_1=$ulong_arg + ;; + 2) + ulong_arg_2=$ulong_arg + ;; + *) + echo >&2 "$0: Too many unsigned long int arguments for syscall ($strong $weak)" + exit 2 + esac + done + # Make sure only the first syscall rule is used, if multiple dirs # define the same syscall. echo '' @@ -245,6 +267,8 @@ while read file srcfile caller syscall args strong weak; do \$(make-target-directory) (echo '#define SYSCALL_NAME $syscall'; \\ echo '#define SYSCALL_NARGS $nargs'; \\ + echo '#define SYSCALL_ULONG_ARG_1 $ulong_arg_1'; \\ + echo '#define SYSCALL_ULONG_ARG_2 $ulong_arg_2'; \\ echo '#define SYSCALL_SYMBOL $strong'; \\ echo '#define SYSCALL_NOERRNO $noerrno'; \\ echo '#define SYSCALL_ERRVAL $errval'; \\ |