summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/i386')
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.S32
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h31
2 files changed, 53 insertions, 10 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.S b/sysdeps/unix/sysv/linux/i386/sysdep.S
index 0130ad02a9..7d5444d6a6 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.S
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,26 +27,46 @@ Cambridge, MA 02139, USA. */
.globl errno
.type errno,@object
.size errno,4
-errno: .space 4
+errno: .zero 4
.globl _errno
.type _errno,@object
_errno = errno /* This name is expected by hj libc.so.5 startup code. */
.text
-/* The following code is not used at all in the shared library.
- The PIC system call stubs set errno themselves. */
+/* The following code is only used in the shared library when we
+ compile the reentrant version. Otherwise each system call defines
+ each own version. */
-#ifndef PIC
+#ifndef PIC
/* The syscall stubs jump here when they detect an error.
The code for Linux is almost identical to the canonical Unix/i386
code, except that the error number in %eax is negated. */
-.globl __syscall_error
+ .globl __syscall_error
+ .type __syscall_error,@function
__syscall_error:
negl %eax
#define __syscall_error __syscall_error_1
#include <sysdeps/unix/i386/sysdep.S>
+#endif /* !PIC */
+
+
+#ifdef _LIBC_REENTRANT
+ .globl __errno_location
+ .type __errno_location,@function
+__errno_location:
+#ifdef PIC
+ call .L2
+.L2: popl %ecx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-.L2], %ecx
+ movl errno@GOT(%ecx), %eax
+#else
+ movl $errno, %eax
+#endif
+ ret
+.Lfe1:
+ .size __errno_location, .Lfe1-__errno_location
#endif
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index c77bbbbf86..96470a19b9 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -45,21 +45,44 @@ Cambridge, MA 02139, USA. */
testl %eax, %eax; \
jl syscall_error;
-#ifndef PIC
+#ifndef PIC
#define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
#else
/* Store (- %eax) into errno through the GOT. */
+#ifdef _LIBC_REENTRANT
#define SYSCALL_ERROR_HANDLER \
+ .type syscall_error,@function; \
+syscall_error: \
+ pushl %ebx; \
+ call 0f; \
+0:popl %ebx; \
+ xorl %edx, %edx; \
+ addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx; \
+ subl %eax, %edx; \
+ movl errno@GOT(%ebx), %ecx; \
+ movl %edx, (%ecx); \
+ pushl %edx; \
+ call __errno_location@PLT; \
+ popl %ecx; \
+ popl %ebx; \
+ movl %ecx, (%eax); \
+ movl $-1, %eax; \
+ ret;
+#else
+#define SYSCALL_ERROR_HANDLER \
+ .type syscall_error,@function; \
syscall_error: \
call 0f; \
0:popl %ecx; \
- negl %eax; \
+ xorl %edx, %edx; \
addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ecx; \
+ subl %eax, %edx; \
movl errno@GOT(%ecx), %ecx; \
- movl %eax, (%ecx); \
+ movl %edx, (%ecx); \
movl $-1, %eax; \
ret;
-#endif
+#endif /* _LIBC_REENTRANT */
+#endif /* PIC */
/* Linux takes system call arguments in registers: