about summary refs log tree commit diff
path: root/sysdeps/unix
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/i386/sysdep.S10
-rw-r--r--sysdeps/unix/i386/sysdep.h14
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h4
3 files changed, 19 insertions, 9 deletions
diff --git a/sysdeps/unix/i386/sysdep.S b/sysdeps/unix/i386/sysdep.S
index efe4f56e95..95e2fd5c7a 100644
--- a/sysdeps/unix/i386/sysdep.S
+++ b/sysdeps/unix/i386/sysdep.S
@@ -41,11 +41,11 @@ notb:
 #ifndef	PIC
 	movl %eax, C_SYMBOL_NAME(errno)
 #else
-	/* Standard PIC nonsense to store into `errno' through the GOT.  */
-	call here
-here:	popl %ecx
-	addl $_GLOBAL_OFFSET_TABLE_+[.-here], %ecx
-	movl C_SYMBOL_NAME(errno@GOT)(%ecx), %ecx
+	/* The caller has pushed %ebx and then set it up to
+	   point to the GOT before calling us through the PLT.  */
+	movl C_SYMBOL_NAME(errno@GOT)(%ebx), %ecx
+	/* Pop %ebx value saved before jumping here.  */
+	popl %ebx
 	movl %eax, (%ecx)
 #endif
 	movl $-1, %eax
diff --git a/sysdeps/unix/i386/sysdep.h b/sysdeps/unix/i386/sysdep.h
index 7fd77dd936..fb1781b156 100644
--- a/sysdeps/unix/i386/sysdep.h
+++ b/sysdeps/unix/i386/sysdep.h
@@ -42,15 +42,23 @@ Cambridge, MA 02139, USA.  */
 #endif
 
 #define	PSEUDO(name, syscall_name, args)				      \
+lose: SYSCALL_PIC_SETUP							      \
+  jmp JUMPTARGET(syscall_error)						      \
   .globl syscall_error;							      \
   ENTRY (name)								      \
   DO_CALL (syscall_name, args);						      \
-  jb JUMPTARGET(syscall_error)
+  jb lose
 
 #ifdef PIC
-#define JUMPTARGET(name) name##@PLT
+#define JUMPTARGET(name)	name##@PLT
+#define SYSCALL_PIC_SETUP \
+    pushl %ebx;								      \
+    call 0f;								      \
+0:  popl %ebx;								      \
+    addl $_GLOBAL_OFFSET_TABLE+[.-0b], %ebx;
 #else
-#define JUMPTARGET(name) name
+#define JUMPTARGET(name)	name
+#define SYSCALL_PIC_SETUP	/* Nothing.  */
 #endif
 
 /* This is defined as a separate macro so that other sysdep.h files
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index a40ca86e40..ccb484664f 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -42,12 +42,14 @@ Cambridge, MA 02139, USA.  */
 #undef	PSEUDO
 #define	PSEUDO(name, syscall_name, args)				      \
   .text;								      \
+ lose: SYSCALL_PIC_SETUP						      \
+    jmp JUMPTARGET (syscall_error)					      \
   .globl syscall_error;							      \
   ENTRY (name)								      \
     movl $SYS_ify (syscall_name), %eax;					      \
     DO_CALL (args);							      \
     testl %eax, %eax;							      \
-    jl JUMPTARGET (syscall_error)
+    jl lose
 
 /* We define our own ENTRY macro because the alignment should be 16 for ELF.  */
 #undef ENTRY