Fix %edx clobbering in lseek64, forkx, and pipe syscalls
authorDavid Bartley <dtbartle@glibc.(none)>
Fri, 30 Jan 2009 10:04:29 +0000 (10:04 +0000)
committerDavid Bartley <dtbartle@glibc.(none)>
Fri, 30 Jan 2009 10:06:49 +0000 (10:06 +0000)
NOTES.opensolaris
nptl/sysdeps/unix/sysv/solaris2/kopensolaris-gnu/fork.c
nptl/sysdeps/unix/sysv/solaris2/kopensolaris-gnu/i386/sysdep-cancel.h
sysdeps/unix/sysv/solaris2/kopensolaris-gnu/fork.c
sysdeps/unix/sysv/solaris2/kopensolaris-gnu/pipe.c
sysdeps/unix/sysv/solaris2/kopensolaris-gnu/syscalls.list

index b650f97..19e80af 100644 (file)
@@ -149,6 +149,31 @@ nsswitch:
     This function is used to parse a file directly, rather than going through
     nsswitch.conf and its databases.
 
     This function is used to parse a file directly, rather than going through
     nsswitch.conf and its databases.
 
+syscalls:
+
+  Dealing with 64-bit returns in 32-bit code is tricky. For 32-bit x86, %eax
+  and %edx are not saved across function calls. Since syscalls always return
+  a 32-bit integer we always have to push/pop %eax across functions. However,
+  since there are very few 64-bit returning syscalls, we don't save %edx unless
+  we have a 64-bit returning syscall. The following is a list of 64-bit
+  returning syscalls:
+
+    getgid, getuid, getpid, forkx, pipe, lseek64
+
+  Currently, the only time we actually call functions is in the case of
+  cancellation points (we call pthread_async_enable/disable). lseek64 is the
+  only syscall listed above that is a cancellation point. To deal with this,
+  we define SYSCALL_64BIT_RETURN in lseek64.S, which triggers inclusion of
+  %edx saving.
+
+  Additionally, 64-bit returning syscalls set both %eax and %edx to -1 on
+  error. Similarily this behaviour is enabled by SYSCALL_64BIT_RETURN. Note
+  that getegid, geteuid, and getppid are special in that their libc
+  equivalents actually return 32-bit integers so we don't need to worry about
+  %edx on error. With forkx and pipe, it suffices to check only the lower
+  32-bits (one of the pid/fd's returned) for -1. For lseek64 we do have to
+  check the full 64-bit return for -1.
+
 sysconf:
 
   Many of the _SC_ sysconf values are obtained via the systemconf syscall. The
 sysconf:
 
   Many of the _SC_ sysconf values are obtained via the systemconf syscall. The
index a9a048f..a0e0394 100644 (file)
@@ -29,7 +29,9 @@ static inline pid_t ARCH_FORK(void)
 {
   rval_t res;
   res.rval64 = INLINE_SYSCALL (forkx, 1, 0);
 {
   rval_t res;
   res.rval64 = INLINE_SYSCALL (forkx, 1, 0);
-  if (res.rval64 == -1)
+
+  /* Only the lower 32-bits are set to -1 on error (see NOTES.opensolaris).  */
+  if (res.rval1 == -1)
     return (pid_t)-1;
   else if (res.rval2 != 0)
     return 0;
     return (pid_t)-1;
   else if (res.rval2 != 0)
     return 0;
index f9d010c..354612b 100644 (file)
 #undef PSEUDO_ERRVAL
 #undef PSEUDO_SUBCALL_NOERRNO
 
 #undef PSEUDO_ERRVAL
 #undef PSEUDO_SUBCALL_NOERRNO
 
+/* This is needed so that we don't clobber %edx in the cancellation calls.  */
+#ifdef SYSCALL_64BIT_RETURN
+# define SYSCALL_64BIT_PUSH_ASM     pushl %edx; cfi_adjust_cfa_offset (4);
+# define SYSCALL_64BIT_POP_ASM      popl %edx; cfi_adjust_cfa_offset (-4);
+#else
+# define SYSCALL_64BIT_PUSH_ASM
+# define SYSCALL_64BIT_POP_ASM
+#endif
+
 #ifdef SYSCALL_RESTARTABLE
 # define DO_RESTART_CANCEL \
     cmpl $ERESTART, %eax; \
 #ifdef SYSCALL_RESTARTABLE
 # define DO_RESTART_CANCEL \
     cmpl $ERESTART, %eax; \
     jnb 3f;                                                                            \
     DO_RESTART_CANCEL                             \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
     jnb 3f;                                                                            \
     DO_RESTART_CANCEL                             \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
+    SYSCALL_64BIT_PUSH_ASM                  \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
+    SYSCALL_64BIT_POP_ASM                     \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
     jmp SYSCALL_ERROR_LABEL;                           \
 3:                                                  \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
     jmp SYSCALL_ERROR_LABEL;                           \
 3:                                                  \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
+    SYSCALL_64BIT_PUSH_ASM                  \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
+    SYSCALL_64BIT_POP_ASM                     \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
   L(pseudo_end):
 
     popl %eax; cfi_adjust_cfa_offset (-4);    \
   L(pseudo_end):
 
     jnb 3f;                                                                            \
     DO_RESTART_CANCEL                             \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
     jnb 3f;                                                                            \
     DO_RESTART_CANCEL                             \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
+    SYSCALL_64BIT_PUSH_ASM                  \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
+    SYSCALL_64BIT_POP_ASM                     \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
     movl 0(%esp), %ecx;                               \
     movl %ecx, 4(%esp);                                                        \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
     movl 0(%esp), %ecx;                               \
     movl %ecx, 4(%esp);                                                        \
     jmp SYSCALL_ERROR_LABEL;                           \
 3:                                                                                     \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
     jmp SYSCALL_ERROR_LABEL;                           \
 3:                                                                                     \
     pushl %eax; cfi_adjust_cfa_offset (4);  \
+    SYSCALL_64BIT_PUSH_ASM                  \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
     movl %ecx, %eax;                        \
     CDISABLE;                           \
+    SYSCALL_64BIT_POP_ASM                     \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
     movl 0(%esp), %ecx;                               \
     movl %ecx, 4(%esp);                                                        \
     popl %eax; cfi_adjust_cfa_offset (-4);    \
     movl 0(%esp), %ecx;                               \
     movl %ecx, 4(%esp);                                                        \
index 59b29d5..6b6b96f 100644 (file)
@@ -30,7 +30,9 @@ __libc_fork (void)
 {
   rval_t res;
   res.rval64 = INLINE_SYSCALL (forkx, 1, 0);
 {
   rval_t res;
   res.rval64 = INLINE_SYSCALL (forkx, 1, 0);
-  if (res.rval64 == -1)
+
+  /* Only the lower 32-bits are set to -1 on error (see NOTES.opensolaris).  */
+  if (res.rval1 == -1)
     return (pid_t)-1;
   else if (res.rval2 != 0)
     return 0;
     return (pid_t)-1;
   else if (res.rval2 != 0)
     return 0;
index 0edb5be..09abf08 100644 (file)
@@ -36,8 +36,11 @@ __pipe (__pipedes)
 
   rval_t result;
   result.rval64 = INLINE_SYSCALL (pipe, 0);
 
   rval_t result;
   result.rval64 = INLINE_SYSCALL (pipe, 0);
-  if (result.rval64 == -1)
+
+  /* Only the lower 32-bits are set to -1 on error (see NOTES.opensolaris).  */
+  if (result.rval1 == -1)
     return -1;
     return -1;
+
   __pipedes[0] = result.rval1;
   __pipedes[1] = result.rval2;
 
   __pipedes[0] = result.rval1;
   __pipedes[1] = result.rval2;
 
index 203f84d..9ae3c21 100644 (file)
@@ -1,5 +1,7 @@
 # File name Caller Syscall name Args Strong name Weak names
 
 # File name Caller Syscall name Args Strong name Weak names
 
+# Important: see NOTES.opensolaris about syscalls that return a 64-bit integer.
+
 #
 # these implement libc functions directly
 #
 #
 # these implement libc functions directly
 #