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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/acconfig.h b/acconfig.h
index aa5ffc3..5e98213 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 d8ea557..a74c985 100644
--- a/configure.in
+++ b/configure.in
@@ -132,6 +132,16 @@
],
glibc="2.2")
+AC_EGREP_CPP([GLIBC_23], [
+#include <features.h>
+#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 @@
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 692e5d8..70abb17 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -76,11 +76,29 @@
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 @@
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 @@
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 @@
{
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 @@
{
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 @@
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 @@
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 86a46c1..f6f7833 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 __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 692e5d8..70abb17 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -76,11 +76,29 @@
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 @@
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 @@
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 @@
{
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 @@
{
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 @@
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 @@
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 86a46c1..f6f7833 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 __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"); }