Fix fork/exec stuff so it works again.  We have to mangle LD_LIBRARY_PATH
as well as LD_PRELOAD, so as to make our libpthread.so go out of scope
when a child which we don't want to trace, is exec'd.  Otherwise the
child can wind up being connected to our libpthread.so but not to
valgrind.so, which is an unworkable combination; you have to be connected
to both or neither.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@291 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/Makefile.am b/Makefile.am
index 257be0b..03cc0da 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/addrcheck/Makefile.am b/addrcheck/Makefile.am
index 257be0b..03cc0da 100644
--- a/addrcheck/Makefile.am
+++ b/addrcheck/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/cachegrind/Makefile.am b/cachegrind/Makefile.am
index 257be0b..03cc0da 100644
--- a/cachegrind/Makefile.am
+++ b/cachegrind/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/corecheck/Makefile.am b/corecheck/Makefile.am
index 257be0b..03cc0da 100644
--- a/corecheck/Makefile.am
+++ b/corecheck/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 257be0b..03cc0da 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/coregrind/valgrind.in b/coregrind/valgrind.in
index 3d12fe1..b316a74 100755
--- a/coregrind/valgrind.in
+++ b/coregrind/valgrind.in
@@ -165,12 +165,17 @@
    exit 1
 fi
 
+# A bit subtle.  The LD_PRELOAD added entry must be absolute
+# and not depend on LD_LIBRARY_PATH.  This is so that we can
+# mess with LD_LIBRARY_PATH for child processes, which makes
+# libpthread.so fall out of visibility, independently of
+# whether valgrind.so is visible.
 
 VG_ARGS="$VALGRIND_OPTS $vgsupp $vgopts"
 export VG_ARGS
 LD_LIBRARY_PATH=$VALGRIND:$LD_LIBRARY_PATH
 export LD_LIBRARY_PATH
-LD_PRELOAD=valgrind.so:$LD_PRELOAD
+LD_PRELOAD=$VALGRIND/valgrind.so:$LD_PRELOAD
 export LD_PRELOAD
 #LD_DEBUG=files
 #LD_DEBUG=symbols
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index 7f44dde..cdcd1ca 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -785,12 +785,12 @@
 extern Bool VG_(stringMatch) ( Char* pat, Char* str );
 
 
-#define __STRING(x)  #x
+#define VG__STRING(__str)  #__str
 
 /* Asserts are permanently enabled.  Hurrah! */
 #define vg_assert(expr)                                               \
   ((void) ((expr) ? 0 :						      \
-	   (VG_(assert_fail) (__STRING(expr),			      \
+	   (VG_(assert_fail) (VG__STRING(expr),			      \
 			      __FILE__, __LINE__,                     \
                               __PRETTY_FUNCTION__), 0)))
 
@@ -1388,8 +1388,10 @@
 extern Char** VG_(client_envp);
 
 /* Remove valgrind.so from a LD_PRELOAD=... string so child processes
-   don't get traced into. */
-extern void   VG_(mash_LD_PRELOAD_string)( Char* ld_preload_str );
+   don't get traced into.  Also mess up $libdir/valgrind so that our
+   libpthread.so disappears from view. */
+void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
+                                                Char* ld_library_path_str );
 
 /* Something of a function looking for a home ... start up GDB.  This
    is called from VG_(swizzle_esp_then_start_GDB) and so runs on the
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index 9047731..ddaf556 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -1100,11 +1100,14 @@
 
    VG_(shutdown_logging)();
 
-   /* In LD_PRELOAD, convert "valgrind.so" into "valgrinq.so", so that
-      child processes don't get traced into.  Also done on simulated
-      execve system call. */
+   /* Remove valgrind.so from a LD_PRELOAD=... string so child
+      processes don't get traced into.  Also mess up $libdir/valgrind
+      so that our libpthread.so disappears from view. */
    if (!VG_(clo_trace_children)) { 
-      VG_(mash_LD_PRELOAD_string)(VG_(getenv)("LD_PRELOAD"));
+      VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
+         VG_(getenv)("LD_PRELOAD"),
+         VG_(getenv)("LD_LIBRARY_PATH") 
+      );
    }
 
    /* Decide how to exit.  This depends on what the scheduler
@@ -1162,17 +1165,39 @@
    tracing into child processes.  To make this work the build system
    also supplies a dummy file, "valgrinq.so". 
 */
-void VG_(mash_LD_PRELOAD_string)( Char* ld_preload_str )
+void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
+                                                Char* ld_library_path_str )
 {
    Char* p;
-   if (ld_preload_str == NULL)
-      return;
+   vg_assert(ld_preload_str != NULL);
+   vg_assert(ld_library_path_str != NULL);
+   /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
+   /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
    p = VG_(strstr)(ld_preload_str, "valgrind.so");
-   if (p == NULL)
+
+   if (p == NULL) {
+      /* perhaps already happened? */
+      vg_assert(VG_(strstr)(ld_preload_str, "valgrinq.so") != NULL);
+      vg_assert(VG_(strstr)(ld_library_path_str, "lib/valgrinq") != NULL);
       return;
+   }
+
+   vg_assert(p[7] == 'd');
    p[7] = 'q';
+
+   /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from 
+      .../lib/valgrind .../lib/valgrinq, which doesn't exist,
+      so that our own libpthread.so goes out of scope. */
+   p = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
+   vg_assert(NULL != p);
+   p += VG_(strlen)(VG_LIBDIR);
+   p += VG_(strlen)("/valgrind");
+   p --;
+   vg_assert(p[0] == 'd');
+   p[0] = 'q';
 }
 
+
 /* RUNS ON THE CLIENT'S STACK, but on the real CPU.  Start GDB and get
    it to attach to this process.  Called if the user requests this
    service after an error has been shown, so she can poke around and
diff --git a/helgrind/Makefile.am b/helgrind/Makefile.am
index 257be0b..03cc0da 100644
--- a/helgrind/Makefile.am
+++ b/helgrind/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/lackey/Makefile.am b/lackey/Makefile.am
index 257be0b..03cc0da 100644
--- a/lackey/Makefile.am
+++ b/lackey/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/memcheck/Makefile.am b/memcheck/Makefile.am
index 257be0b..03cc0da 100644
--- a/memcheck/Makefile.am
+++ b/memcheck/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/none/Makefile.am b/none/Makefile.am
index 257be0b..03cc0da 100644
--- a/none/Makefile.am
+++ b/none/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = demangle . docs tests
 
-CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \
+		-Winline -Wall -Wshadow -O -fomit-frame-pointer -g
 
 valdir = $(libdir)/valgrind
 
diff --git a/valgrind.in b/valgrind.in
index 3d12fe1..b316a74 100755
--- a/valgrind.in
+++ b/valgrind.in
@@ -165,12 +165,17 @@
    exit 1
 fi
 
+# A bit subtle.  The LD_PRELOAD added entry must be absolute
+# and not depend on LD_LIBRARY_PATH.  This is so that we can
+# mess with LD_LIBRARY_PATH for child processes, which makes
+# libpthread.so fall out of visibility, independently of
+# whether valgrind.so is visible.
 
 VG_ARGS="$VALGRIND_OPTS $vgsupp $vgopts"
 export VG_ARGS
 LD_LIBRARY_PATH=$VALGRIND:$LD_LIBRARY_PATH
 export LD_LIBRARY_PATH
-LD_PRELOAD=valgrind.so:$LD_PRELOAD
+LD_PRELOAD=$VALGRIND/valgrind.so:$LD_PRELOAD
 export LD_PRELOAD
 #LD_DEBUG=files
 #LD_DEBUG=symbols
diff --git a/vg_include.h b/vg_include.h
index 7f44dde..cdcd1ca 100644
--- a/vg_include.h
+++ b/vg_include.h
@@ -785,12 +785,12 @@
 extern Bool VG_(stringMatch) ( Char* pat, Char* str );
 
 
-#define __STRING(x)  #x
+#define VG__STRING(__str)  #__str
 
 /* Asserts are permanently enabled.  Hurrah! */
 #define vg_assert(expr)                                               \
   ((void) ((expr) ? 0 :						      \
-	   (VG_(assert_fail) (__STRING(expr),			      \
+	   (VG_(assert_fail) (VG__STRING(expr),			      \
 			      __FILE__, __LINE__,                     \
                               __PRETTY_FUNCTION__), 0)))
 
@@ -1388,8 +1388,10 @@
 extern Char** VG_(client_envp);
 
 /* Remove valgrind.so from a LD_PRELOAD=... string so child processes
-   don't get traced into. */
-extern void   VG_(mash_LD_PRELOAD_string)( Char* ld_preload_str );
+   don't get traced into.  Also mess up $libdir/valgrind so that our
+   libpthread.so disappears from view. */
+void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
+                                                Char* ld_library_path_str );
 
 /* Something of a function looking for a home ... start up GDB.  This
    is called from VG_(swizzle_esp_then_start_GDB) and so runs on the
diff --git a/vg_main.c b/vg_main.c
index 9047731..ddaf556 100644
--- a/vg_main.c
+++ b/vg_main.c
@@ -1100,11 +1100,14 @@
 
    VG_(shutdown_logging)();
 
-   /* In LD_PRELOAD, convert "valgrind.so" into "valgrinq.so", so that
-      child processes don't get traced into.  Also done on simulated
-      execve system call. */
+   /* Remove valgrind.so from a LD_PRELOAD=... string so child
+      processes don't get traced into.  Also mess up $libdir/valgrind
+      so that our libpthread.so disappears from view. */
    if (!VG_(clo_trace_children)) { 
-      VG_(mash_LD_PRELOAD_string)(VG_(getenv)("LD_PRELOAD"));
+      VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
+         VG_(getenv)("LD_PRELOAD"),
+         VG_(getenv)("LD_LIBRARY_PATH") 
+      );
    }
 
    /* Decide how to exit.  This depends on what the scheduler
@@ -1162,17 +1165,39 @@
    tracing into child processes.  To make this work the build system
    also supplies a dummy file, "valgrinq.so". 
 */
-void VG_(mash_LD_PRELOAD_string)( Char* ld_preload_str )
+void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
+                                                Char* ld_library_path_str )
 {
    Char* p;
-   if (ld_preload_str == NULL)
-      return;
+   vg_assert(ld_preload_str != NULL);
+   vg_assert(ld_library_path_str != NULL);
+   /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
+   /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
    p = VG_(strstr)(ld_preload_str, "valgrind.so");
-   if (p == NULL)
+
+   if (p == NULL) {
+      /* perhaps already happened? */
+      vg_assert(VG_(strstr)(ld_preload_str, "valgrinq.so") != NULL);
+      vg_assert(VG_(strstr)(ld_library_path_str, "lib/valgrinq") != NULL);
       return;
+   }
+
+   vg_assert(p[7] == 'd');
    p[7] = 'q';
+
+   /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from 
+      .../lib/valgrind .../lib/valgrinq, which doesn't exist,
+      so that our own libpthread.so goes out of scope. */
+   p = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
+   vg_assert(NULL != p);
+   p += VG_(strlen)(VG_LIBDIR);
+   p += VG_(strlen)("/valgrind");
+   p --;
+   vg_assert(p[0] == 'd');
+   p[0] = 'q';
 }
 
+
 /* RUNS ON THE CLIENT'S STACK, but on the real CPU.  Start GDB and get
    it to attach to this process.  Called if the user requests this
    service after an error has been shown, so she can poke around and
diff --git a/vg_syscall_mem.c b/vg_syscall_mem.c
index 1ffac13..ac681c0 100644
--- a/vg_syscall_mem.c
+++ b/vg_syscall_mem.c
@@ -824,11 +824,16 @@
          if (!VG_(clo_trace_children)) {
             Int i;
             Char** envp = (Char**)arg3;
+            Char*  ld_preload_str = NULL;
+            Char*  ld_library_path_str = NULL;
             for (i = 0; envp[i] != NULL; i++) {
-               if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) {
-                  VG_(mash_LD_PRELOAD_string)(&envp[i][11]);
-               }
+               if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
+                  ld_preload_str = &envp[i][11];
+               if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
+                  ld_library_path_str = &envp[i][16];
             }
+            VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
+	       ld_preload_str, ld_library_path_str );
          }
          KERNEL_DO_SYSCALL(tid,res);
          /* Should we still be alive here?  Don't think so. */