[PATCH] Store errno value before using __set_errno()

Ingo van Lil inguin at gmx.de
Thu Jun 4 12:33:34 UTC 2009


The __syscall_error() function stores the errno value in the edx
register before invoking the __set_errno() macro. When using the
pthread library this macro calls thread_self() to determine the errno
location, which might clobber the edx register. The errno value must
be stored in a "real" variable so the compiler can take care of
saving/restoring it if necessary.

Signed-off-by: Ingo van Lil <inguin at gmx.de>
---

The problem can be easily reproduced using the following test program:

#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>

int main(void)
{
    void *map = mmap(NULL, 0, 0, 0, -1, 0);
    printf("map = %p, errno = %d\n", map, errno);
    return 0;
}

The results differ depending on whether -lpthread is linked or not:

* Without libpthread:
# syscall_test
map = 0xffffffff, errno = 9

* With libpthread:
# syscall_test
map = 0xffffffff, errno = -1073867372

Regards,
Ingo


 libc/sysdeps/linux/i386/__syscall_error.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/libc/sysdeps/linux/i386/__syscall_error.c b/libc/sysdeps/linux/i386/__syscall_error.c
index 7509d44..36946bc 100644
--- a/libc/sysdeps/linux/i386/__syscall_error.c
+++ b/libc/sysdeps/linux/i386/__syscall_error.c
@@ -28,9 +28,8 @@
 int __syscall_error(void) attribute_hidden;
 int __syscall_error(void)
 {
-	register int edx __asm__ ("%edx");
-	__asm__ ("mov %eax, %edx\n\t"
-		 "negl %edx");
-	__set_errno (edx);
+	register int eax __asm__ ("%eax");
+	int _errno = -eax;
+	__set_errno (_errno);
 	return -1;
 }
-- 
1.6.0.6



More information about the uClibc mailing list