Merge patch from Jeremy Fitzhardinge:

16-function-intercept
  Implement a more reliable for vg_libpthread to intercept libc
  calls. Since the only reliable way of making sure that our code
  defines the symbol is by making sure that valgrind.so itself does it,
  this patch adds a new file, vg_intercept.so, which defines those
  symbols. They are then passed off to a weak local function if
  libpthread isn't present, or to the libpthread version if it is.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1265 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 225033f..8fb589e 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -45,6 +45,7 @@
 	vg_from_ucode.c \
 	vg_helpers.S \
 	vg_instrument.c \
+	vg_intercept.c \
 	vg_main.c \
 	vg_malloc2.c \
 	vg_memory.c \
diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c
index 771ed74..ed22be6 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -1826,8 +1826,8 @@
 
 extern
 int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
-__attribute__((weak))
-int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+
+int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
 {
    __my_pthread_testcancel();
    wait_for_fd_to_be_readable_or_erring(s);
@@ -3067,7 +3067,7 @@
 
 /* Turn a blocking msgsnd() into a polling non-blocking one, so that
    other threads make progress */
-int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
+int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
 {
    struct vki_timespec nanosleep_interval;
    int err;
@@ -3102,7 +3102,7 @@
 
 /* Turn a blocking msgrcv() into a polling non-blocking one, so that
    other threads make progress */
-int msgrcv( int msqid, void  *msgp,  size_t msgsz, long msgtyp, int msgflg )
+int VGL_(msgrcv)( int msqid, void  *msgp,  size_t msgsz, long msgtyp, int msgflg )
 {
    struct vki_timespec nanosleep_interval;
    int err;
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index d657850..5de1d30 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -1453,6 +1453,7 @@
 extern Addr VG_(noncompact_helper_addrs)  [];
 extern Int  VG_(noncompact_helper_offsets)[];
 
+#define VGL_(x)		vgIntercept_##x
 
 #endif /* ndef __VG_INCLUDE_H */
 
diff --git a/coregrind/vg_intercept.c b/coregrind/vg_intercept.c
new file mode 100644
index 0000000..7b984c9
--- /dev/null
+++ b/coregrind/vg_intercept.c
@@ -0,0 +1,111 @@
+/*
+ * Intercepts for various libc functions we want to capture (mostly for threading purposes)
+ *
+ * This has some nasty duplication of stuff from vg_libpthread.c
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+
+#include "valgrind.h"
+#include "vg_include.h"
+
+# define strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
+# define weak_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
+
+#define WEAK	__attribute__((weak))
+
+#include "vg_kerneliface.h"
+
+static
+__inline__
+int is_kerror ( int res )
+{
+   if (res >= -4095 && res <= -1)
+      return 1;
+   else
+      return 0;
+}
+
+
+static inline
+int my_do_syscall5 ( int syscallno, 
+                     int arg1, int arg2, int arg3, int arg4, int arg5 )
+{ 
+   int __res;
+   __asm__ volatile ("int $0x80"
+                     : "=a" (__res)
+                     : "0" (syscallno),
+                       "b" (arg1),
+                       "c" (arg2),
+                       "d" (arg3),
+                       "S" (arg4),
+                       "D" (arg5));
+   return __res;
+}
+
+/* -------------------------------- msgsnd -------------------------------- */
+#include <asm/ipc.h>		/* for ipc_kludge */
+
+static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
+{
+   return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
+}
+
+WEAK int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
+{
+   int err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
+   if (is_kerror(err)) {
+      *(__errno_location()) = -err;
+      return -1;
+   }
+   return 0;
+}
+
+int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
+{
+   return VGL_(msgsnd)(msgid, msgp, msgsz, msgflg);
+}
+
+/* -------------------------------- msgrcv -------------------------------- */
+
+WEAK int VGL_(msgrcv)( int msqid, void  *msgp,  size_t msgsz, long msgtyp, int msgflg )
+{
+   struct ipc_kludge tmp;
+   int err;
+
+   tmp.msgp = msgp;
+   tmp.msgtyp = msgtyp;
+
+   err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
+
+   if (is_kerror(err)) {
+      *(__errno_location()) = -err;
+      return -1;
+   }
+   return 0;
+}
+
+int msgrcv( int msqid, void  *msgp,  size_t msgsz, long msgtyp, int msgflg )
+{
+   return VGL_(msgrcv)( msqid, msgp,  msgsz, msgtyp, msgflg );
+}
+
+/* -------------------------------- accept -------------------------------- */
+
+#include <sys/socket.h>
+
+extern
+int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+WEAK int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+   return __libc_accept(s, addr, addrlen);
+}
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+   return VGL_(accept)(s, addr, addrlen);
+}
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index 771ed74..ed22be6 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -1826,8 +1826,8 @@
 
 extern
 int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
-__attribute__((weak))
-int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+
+int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
 {
    __my_pthread_testcancel();
    wait_for_fd_to_be_readable_or_erring(s);
@@ -3067,7 +3067,7 @@
 
 /* Turn a blocking msgsnd() into a polling non-blocking one, so that
    other threads make progress */
-int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
+int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
 {
    struct vki_timespec nanosleep_interval;
    int err;
@@ -3102,7 +3102,7 @@
 
 /* Turn a blocking msgrcv() into a polling non-blocking one, so that
    other threads make progress */
-int msgrcv( int msqid, void  *msgp,  size_t msgsz, long msgtyp, int msgflg )
+int VGL_(msgrcv)( int msqid, void  *msgp,  size_t msgsz, long msgtyp, int msgflg )
 {
    struct vki_timespec nanosleep_interval;
    int err;