From: Julian Seward Date: Mon, 7 Oct 2002 23:56:55 +0000 (+0000) Subject: Initial stuff to make it work on Red Hat 8: X-Git-Tag: svn/VALGRIND_1_9_4~220 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a3d18038518f727074de178d40df06ccf8fa47af;p=thirdparty%2Fvalgrind.git Initial stuff to make it work on Red Hat 8: - autoconf stuff for detecting glibc-2.3 - vg_libpthread_unimp.c: hack for __pthread_clock_[gs]ettime - vg_libpthread.c: initialise thread's default locale by calling __uselocale(LC_GLOBAL_LOCALE) at the right time. Gruesome. Also need to do this for new other threads - not yet done. - cleanups -- don't use write() to write messages when bombing out, instead go direct to the syscalls. Avoids nasty circularities with glibc initialisations. MERGE TO STABLE git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1207 --- diff --git a/acconfig.h b/acconfig.h index aa5ffc3d3f..5e9821355d 100644 --- a/acconfig.h +++ b/acconfig.h @@ -6,6 +6,7 @@ #undef GLIBC_2_1 #undef GLIBC_2_2 +#undef GLIBC_2_3 #undef XFREE_3 #undef XFREE_4 diff --git a/configure.in b/configure.in index d8ea557052..a74c9852bd 100644 --- a/configure.in +++ b/configure.in @@ -132,6 +132,16 @@ AC_EGREP_CPP([GLIBC_22], [ ], glibc="2.2") +AC_EGREP_CPP([GLIBC_23], [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ == 3) + GLIBC_23 + #endif +#endif +], +glibc="2.3") + case "${glibc}" in 2.1) AC_MSG_RESULT(2.1 family) @@ -145,9 +155,18 @@ case "${glibc}" in DEFAULT_SUPP="${DEFAULT_SUPP} glibc-2.2.supp" ;; + 2.3) + AC_MSG_RESULT(2.3 family) + AC_DEFINE(GLIBC_2_3) + ## Use the same suppression for as for 2.2. + ## This is a horrible hack that should be gotten + ## rid of. JRS, 20021007. + DEFAULT_SUPP="${DEFAULT_SUPP} glibc-2.2.supp" + ;; + *) AC_MSG_RESULT(unsupported version) - AC_MSG_ERROR([Valgrind requires the glibc version 2.1 or 2.2]) + AC_MSG_ERROR([Valgrind requires the glibc version 2.1, 2.2 or 2.3]) ;; esac diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c index 692e5d89ab..70abb179df 100644 --- a/coregrind/arch/x86-linux/vg_libpthread.c +++ b/coregrind/arch/x86-linux/vg_libpthread.c @@ -75,12 +75,30 @@ static void wait_for_fd_to_be_readable_or_erring ( int fd ); +static +int my_do_syscall1 ( int syscallno, int arg1 ); + static int my_do_syscall2 ( int syscallno, int arg1, int arg2 ); -__attribute__((weak)) -ssize_t write(int fd, const void *buf, size_t count); +static +int my_do_syscall3 ( int syscallno, + int arg1, int arg2, int arg3 ); + + +#ifdef GLIBC_2_3 + /* kludge by JRS (not from glibc) ... */ + typedef void* __locale_t; + + /* Copied from locale/locale.h in glibc-2.2.93 sources */ + /* This value can be passed to `uselocale' and may be returned by + it. Passing this value to any other function has undefined + behavior. */ +# define LC_GLOBAL_LOCALE ((__locale_t) -1L) + extern __locale_t __uselocale ( __locale_t ); +#endif + /* --------------------------------------------------------------------- Helpers. We have to be pretty self-sufficient. @@ -101,20 +119,18 @@ int get_pt_trace_level ( void ) return res; } - static void my_exit ( int arg ) { - int __res; - __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80" - : "=a" (__res) - : "0" (__NR_exit), - "c" (arg) ); - /* We don't bother to mention the fact that this asm trashes %ebx, - since it won't return. If you ever do let it return ... fix - this! */ + my_do_syscall1(__NR_exit, arg); + /*NOTREACHED*/ } +static +void my_write ( int fd, const void *buf, int count ) +{ + my_do_syscall3(__NR_write, fd, (int)buf, count ); +} /* We need this guy -- it's in valgrind.so. */ extern void VG_(startup) ( void ); @@ -145,7 +161,7 @@ void barf ( char* str ) strcat(buf, "\nvalgrind's libpthread.so: "); strcat(buf, str); strcat(buf, "\n\n"); - write(2, buf, strlen(buf)); + my_write(2, buf, strlen(buf)); my_exit(1); /* We have to persuade gcc into believing this doesn't return. */ while (1) { }; @@ -156,10 +172,10 @@ static void ignored ( char* msg ) { if (get_pt_trace_level() >= 0) { char* ig = "valgrind's libpthread.so: IGNORED call to: "; - write(2, ig, strlen(ig)); - write(2, msg, strlen(msg)); + my_write(2, ig, strlen(ig)); + my_write(2, msg, strlen(msg)); ig = "\n"; - write(2, ig, strlen(ig)); + my_write(2, ig, strlen(ig)); } } @@ -167,10 +183,10 @@ static void kludged ( char* msg ) { if (get_pt_trace_level() >= 0) { char* ig = "valgrind's libpthread.so: KLUDGED call to: "; - write(2, ig, strlen(ig)); - write(2, msg, strlen(msg)); + my_write(2, ig, strlen(ig)); + my_write(2, msg, strlen(msg)); ig = "\n"; - write(2, ig, strlen(ig)); + my_write(2, ig, strlen(ig)); } } @@ -183,10 +199,10 @@ __attribute__((noreturn)) void vgPlain_unimp ( char* what ) { char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: "; - write(2, ig, strlen(ig)); - write(2, what, strlen(what)); + my_write(2, ig, strlen(ig)); + my_write(2, what, strlen(what)); ig = "\n"; - write(2, ig, strlen(ig)); + my_write(2, ig, strlen(ig)); barf("Please report this bug to me at: jseward@acm.org"); } @@ -1418,19 +1434,40 @@ void init_libc_tsd_keys ( void ) int res, i; pthread_key_t k; + /* Don't fall into deadlock if we get called again whilst we still + hold the lock, via the __uselocale() call herein. */ + if (libc_specifics_inited != 0) + return; + + /* Take the lock. */ res = pthread_mutex_lock(&libc_specifics_inited_mx); if (res != 0) barf("init_libc_tsd_keys: lock"); - if (libc_specifics_inited == 0) { - /* printf("INIT libc specifics\n"); */ - libc_specifics_inited = 1; - for (i = 0; i < _LIBC_TSD_KEY_N; i++) { - res = pthread_key_create(&k, NULL); - if (res != 0) barf("init_libc_tsd_keys: create"); - libc_specifics_keys[i] = k; - } + /* Now test again, to be sure there is no mistake. */ + if (libc_specifics_inited != 0) { + res = pthread_mutex_unlock(&libc_specifics_inited_mx); + if (res != 0) barf("init_libc_tsd_keys: unlock(1)"); + return; + } + + /* Actually do the initialisation. */ + /* printf("INIT libc specifics\n"); */ + for (i = 0; i < _LIBC_TSD_KEY_N; i++) { + res = pthread_key_create(&k, NULL); + if (res != 0) barf("init_libc_tsd_keys: create"); + libc_specifics_keys[i] = k; } + /* Signify init done. */ + libc_specifics_inited = 1; + +# ifdef GLIBC_2_3 + /* Set the initialising thread's locale to the global (default) + locale. A hack in support of glibc-2.3. */ + __uselocale(LC_GLOBAL_LOCALE); +# endif + + /* Unlock and return. */ res = pthread_mutex_unlock(&libc_specifics_inited_mx); if (res != 0) barf("init_libc_tsd_keys: unlock"); } diff --git a/coregrind/arch/x86-linux/vg_libpthread_unimp.c b/coregrind/arch/x86-linux/vg_libpthread_unimp.c index 86a46c1c56..f6f7833a59 100644 --- a/coregrind/arch/x86-linux/vg_libpthread_unimp.c +++ b/coregrind/arch/x86-linux/vg_libpthread_unimp.c @@ -34,6 +34,8 @@ Give a binding for everything the real libpthread.so binds. ------------------------------------------------------------------ */ +#include "vg_include.h" /* For GLIBC_2_3, or not, as the case may be */ + extern void vgPlain_unimp ( char* ); #define unimp(str) vgPlain_unimp(str) @@ -163,6 +165,14 @@ void sem_unlink ( void ) { unimp("sem_unlink"); } void __pthread_clock_gettime ( void ) { unimp("__pthread_clock_gettime"); } void __pthread_clock_settime ( void ) { unimp("__pthread_clock_settime"); } +#ifdef GLIBC_2_3 +/* Needed for Red Hat 8.0 */ +__asm__(".symver __pthread_clock_gettime," + "__pthread_clock_gettime@GLIBC_PRIVATE"); +__asm__(".symver __pthread_clock_settime," + "__pthread_clock_settime@GLIBC_PRIVATE"); +#endif + #if 0 void pthread_create@@GLIBC_2.1 ( void ) { unimp("pthread_create@@GLIBC_2.1"); } diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c index 692e5d89ab..70abb179df 100644 --- a/coregrind/vg_libpthread.c +++ b/coregrind/vg_libpthread.c @@ -75,12 +75,30 @@ static void wait_for_fd_to_be_readable_or_erring ( int fd ); +static +int my_do_syscall1 ( int syscallno, int arg1 ); + static int my_do_syscall2 ( int syscallno, int arg1, int arg2 ); -__attribute__((weak)) -ssize_t write(int fd, const void *buf, size_t count); +static +int my_do_syscall3 ( int syscallno, + int arg1, int arg2, int arg3 ); + + +#ifdef GLIBC_2_3 + /* kludge by JRS (not from glibc) ... */ + typedef void* __locale_t; + + /* Copied from locale/locale.h in glibc-2.2.93 sources */ + /* This value can be passed to `uselocale' and may be returned by + it. Passing this value to any other function has undefined + behavior. */ +# define LC_GLOBAL_LOCALE ((__locale_t) -1L) + extern __locale_t __uselocale ( __locale_t ); +#endif + /* --------------------------------------------------------------------- Helpers. We have to be pretty self-sufficient. @@ -101,20 +119,18 @@ int get_pt_trace_level ( void ) return res; } - static void my_exit ( int arg ) { - int __res; - __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80" - : "=a" (__res) - : "0" (__NR_exit), - "c" (arg) ); - /* We don't bother to mention the fact that this asm trashes %ebx, - since it won't return. If you ever do let it return ... fix - this! */ + my_do_syscall1(__NR_exit, arg); + /*NOTREACHED*/ } +static +void my_write ( int fd, const void *buf, int count ) +{ + my_do_syscall3(__NR_write, fd, (int)buf, count ); +} /* We need this guy -- it's in valgrind.so. */ extern void VG_(startup) ( void ); @@ -145,7 +161,7 @@ void barf ( char* str ) strcat(buf, "\nvalgrind's libpthread.so: "); strcat(buf, str); strcat(buf, "\n\n"); - write(2, buf, strlen(buf)); + my_write(2, buf, strlen(buf)); my_exit(1); /* We have to persuade gcc into believing this doesn't return. */ while (1) { }; @@ -156,10 +172,10 @@ static void ignored ( char* msg ) { if (get_pt_trace_level() >= 0) { char* ig = "valgrind's libpthread.so: IGNORED call to: "; - write(2, ig, strlen(ig)); - write(2, msg, strlen(msg)); + my_write(2, ig, strlen(ig)); + my_write(2, msg, strlen(msg)); ig = "\n"; - write(2, ig, strlen(ig)); + my_write(2, ig, strlen(ig)); } } @@ -167,10 +183,10 @@ static void kludged ( char* msg ) { if (get_pt_trace_level() >= 0) { char* ig = "valgrind's libpthread.so: KLUDGED call to: "; - write(2, ig, strlen(ig)); - write(2, msg, strlen(msg)); + my_write(2, ig, strlen(ig)); + my_write(2, msg, strlen(msg)); ig = "\n"; - write(2, ig, strlen(ig)); + my_write(2, ig, strlen(ig)); } } @@ -183,10 +199,10 @@ __attribute__((noreturn)) void vgPlain_unimp ( char* what ) { char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: "; - write(2, ig, strlen(ig)); - write(2, what, strlen(what)); + my_write(2, ig, strlen(ig)); + my_write(2, what, strlen(what)); ig = "\n"; - write(2, ig, strlen(ig)); + my_write(2, ig, strlen(ig)); barf("Please report this bug to me at: jseward@acm.org"); } @@ -1418,19 +1434,40 @@ void init_libc_tsd_keys ( void ) int res, i; pthread_key_t k; + /* Don't fall into deadlock if we get called again whilst we still + hold the lock, via the __uselocale() call herein. */ + if (libc_specifics_inited != 0) + return; + + /* Take the lock. */ res = pthread_mutex_lock(&libc_specifics_inited_mx); if (res != 0) barf("init_libc_tsd_keys: lock"); - if (libc_specifics_inited == 0) { - /* printf("INIT libc specifics\n"); */ - libc_specifics_inited = 1; - for (i = 0; i < _LIBC_TSD_KEY_N; i++) { - res = pthread_key_create(&k, NULL); - if (res != 0) barf("init_libc_tsd_keys: create"); - libc_specifics_keys[i] = k; - } + /* Now test again, to be sure there is no mistake. */ + if (libc_specifics_inited != 0) { + res = pthread_mutex_unlock(&libc_specifics_inited_mx); + if (res != 0) barf("init_libc_tsd_keys: unlock(1)"); + return; + } + + /* Actually do the initialisation. */ + /* printf("INIT libc specifics\n"); */ + for (i = 0; i < _LIBC_TSD_KEY_N; i++) { + res = pthread_key_create(&k, NULL); + if (res != 0) barf("init_libc_tsd_keys: create"); + libc_specifics_keys[i] = k; } + /* Signify init done. */ + libc_specifics_inited = 1; + +# ifdef GLIBC_2_3 + /* Set the initialising thread's locale to the global (default) + locale. A hack in support of glibc-2.3. */ + __uselocale(LC_GLOBAL_LOCALE); +# endif + + /* Unlock and return. */ res = pthread_mutex_unlock(&libc_specifics_inited_mx); if (res != 0) barf("init_libc_tsd_keys: unlock"); } diff --git a/coregrind/vg_libpthread_unimp.c b/coregrind/vg_libpthread_unimp.c index 86a46c1c56..f6f7833a59 100644 --- a/coregrind/vg_libpthread_unimp.c +++ b/coregrind/vg_libpthread_unimp.c @@ -34,6 +34,8 @@ Give a binding for everything the real libpthread.so binds. ------------------------------------------------------------------ */ +#include "vg_include.h" /* For GLIBC_2_3, or not, as the case may be */ + extern void vgPlain_unimp ( char* ); #define unimp(str) vgPlain_unimp(str) @@ -163,6 +165,14 @@ void sem_unlink ( void ) { unimp("sem_unlink"); } void __pthread_clock_gettime ( void ) { unimp("__pthread_clock_gettime"); } void __pthread_clock_settime ( void ) { unimp("__pthread_clock_settime"); } +#ifdef GLIBC_2_3 +/* Needed for Red Hat 8.0 */ +__asm__(".symver __pthread_clock_gettime," + "__pthread_clock_gettime@GLIBC_PRIVATE"); +__asm__(".symver __pthread_clock_settime," + "__pthread_clock_settime@GLIBC_PRIVATE"); +#endif + #if 0 void pthread_create@@GLIBC_2.1 ( void ) { unimp("pthread_create@@GLIBC_2.1"); }