Added regression tests that verify the following behavior:
- On Linux, whether Valgrind properly intercepts the system calls that access
  /proc/self/cmdline, /proc/<pid>/cmdline, /proc/self/exe and /proc/<pid>/exe.
- On Darwin, whether Valgrind does not modify the behavior of the system calls
  that access the aforementioned files.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10871 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/configure.in b/configure.in
index bd3df63..fd5a4b5 100644
--- a/configure.in
+++ b/configure.in
@@ -1526,6 +1526,7 @@
         pthread_rwlock_timedrdlock \
         pthread_rwlock_timedwrlock \
         pthread_spin_lock          \
+        readlinkat   \
         semtimedop   \
         signalfd     \
         sigwaitinfo  \
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index 154d4e1..4b8cd27 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -88,6 +88,8 @@
 	munmap_exe.stderr.exp munmap_exe.vgtest \
 	nestedfns.stderr.exp nestedfns.stdout.exp nestedfns.vgtest \
 	pending.stdout.exp pending.stderr.exp pending.vgtest \
+	procfs-linux.stderr.exp procfs-linux.vgtest \
+	procfs-non-linux.stderr.exp procfs-non-linux.vgtest \
 	pth_atfork1.stderr.exp pth_atfork1.stdout.exp pth_atfork1.vgtest \
 	pth_blockedsig.stderr.exp \
 	pth_blockedsig.stdout.exp pth_blockedsig.vgtest \
@@ -155,6 +157,7 @@
 	munmap_exe map_unaligned map_unmap mq \
 	nestedfns \
 	pending \
+	procfs-cmdline-exe \
 	pth_atfork1 pth_blockedsig pth_cancel1 pth_cancel2 pth_cvsimple \
 	pth_empty pth_exit pth_exit2 pth_mutexspeed pth_once pth_rwlock \
 	pth_stackalign \
diff --git a/none/tests/procfs-cmdline-exe.c b/none/tests/procfs-cmdline-exe.c
new file mode 100644
index 0000000..9f550e5
--- /dev/null
+++ b/none/tests/procfs-cmdline-exe.c
@@ -0,0 +1,115 @@
+/*
+ * Read /proc/self/cmdline and /proc/self/exe such that it can be tested
+ * whether Valgrind intercepts the system calls that access these pseudo-files
+ * properly on Linux and whether Valgrind does not modify the behavior of
+ * accessing these files on other operating systems.
+ */
+
+#define _ATFILE_SOURCE
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include "../../config.h"
+
+static void test_cmdline(const char* const cwd, const char* const label,
+                         const char* const path)
+{
+  int fd, n;
+  char ch;
+      
+  fprintf(stderr, "%s:\n", label);
+  fd = open(path, 0); 
+  if (fd >= 0)
+  {
+    while ((n = read(fd, &ch, 1)) > 0)
+    {
+      if (ch == '\\')
+        fprintf(stderr, "\\\\");
+      else if (ch == 0)
+        fprintf(stderr, "\\0");
+      else if (isprint((unsigned)ch))
+        fprintf(stderr, "%c", ch);
+      else
+        fprintf(stderr, "\\0%o", ch);
+    }
+    fprintf(stderr, "\n");
+    close(fd);
+  }
+  else
+    perror("open()");
+}
+
+static void test_readlink(const char* const cwd, const char* const label,
+                          const char* const path)
+{
+  char buf[512];
+  const char* p;
+  int n;
+
+  if ((n = readlink(path, buf, sizeof(buf) - 1)) >= 0)
+  {
+    buf[n] = 0;
+    p = buf;
+    if (strncmp(buf, cwd, strlen(cwd)) == 0)
+      p += strlen(cwd);
+    fprintf(stderr, "Result of readlink(\"%s\"): %s\n", label, p);
+  }
+  else
+    perror("readlink");
+}
+
+static void test_readlinkat(const char* const cwd, const char* const label,
+                            const char* const path)
+{
+#if HAVE_READLINKAT
+  char buf[512];
+  const char* p;
+  int n;
+
+  if ((n = readlinkat(AT_FDCWD, path, buf, sizeof(buf) - 1)) >= 0)
+  {
+    buf[n] = 0;
+    p = buf;
+    if (strncmp(buf, cwd, strlen(cwd)) == 0)
+      p += strlen(cwd);
+    fprintf(stderr, "Result of readlinkat(\"%s\"): %s\n", label, p);
+  }
+  else
+    perror("readlinkat");
+#else
+  errno = ENOSYS;
+  perror("readlinkat");
+#endif
+}
+
+int main(int argc, char** argv)
+{
+  char cwd[512];
+  char path[512];
+
+  cwd[0] = 0;
+  if (! getcwd(cwd, sizeof(cwd)))
+    perror("getcwd");
+  strcat(cwd, "/");
+
+  snprintf(path, sizeof(path), "/proc/%d/cmdline", getpid());
+
+  test_cmdline(cwd, "/proc/self/cmdline", "/proc/self/cmdline");
+  test_cmdline(cwd, "/proc/<pid>/cmdline", path);
+
+  snprintf(path, sizeof(path), "/proc/%d/exe", getpid());
+
+  test_readlink(cwd, "/proc/self/exe", "/proc/self/exe");
+  test_readlink(cwd, "/proc/<pid>/exe", path);
+
+  test_readlinkat(cwd, "/proc/self/exe", "/proc/self/exe");
+  test_readlinkat(cwd, "/proc/<pid>/exe", path);
+
+  return 0;
+}
diff --git a/none/tests/procfs-linux.stderr.exp b/none/tests/procfs-linux.stderr.exp
new file mode 100644
index 0000000..6314262
--- /dev/null
+++ b/none/tests/procfs-linux.stderr.exp
@@ -0,0 +1,10 @@
+
+/proc/self/cmdline:
+./procfs-cmdline-exe\0arg1\0arg 2\0arg3\0
+/proc/<pid>/cmdline:
+./procfs-cmdline-exe\0arg1\0arg 2\0arg3\0
+Result of readlink("/proc/self/exe"): procfs-cmdline-exe
+Result of readlink("/proc/<pid>/exe"): procfs-cmdline-exe
+Result of readlinkat("/proc/self/exe"): procfs-cmdline-exe
+Result of readlinkat("/proc/<pid>/exe"): procfs-cmdline-exe
+
diff --git a/none/tests/procfs-linux.vgtest b/none/tests/procfs-linux.vgtest
new file mode 100644
index 0000000..ea8a8e9
--- /dev/null
+++ b/none/tests/procfs-linux.vgtest
@@ -0,0 +1,4 @@
+prereq: [ $(uname) = Linux ]
+prog: procfs-cmdline-exe
+args: arg1 "arg 2" arg3
+stderr_filter: filter_stderr
diff --git a/none/tests/procfs-non-linux.stderr.exp b/none/tests/procfs-non-linux.stderr.exp
new file mode 100644
index 0000000..ec92dfa
--- /dev/null
+++ b/none/tests/procfs-non-linux.stderr.exp
@@ -0,0 +1,10 @@
+
+/proc/self/cmdline:
+open(): No such file or directory
+/proc/<pid>/cmdline:
+open(): No such file or directory
+readlink: No such file or directory
+readlink: No such file or directory
+readlinkat: Function not implemented
+readlinkat: Function not implemented
+
diff --git a/none/tests/procfs-non-linux.vgtest b/none/tests/procfs-non-linux.vgtest
new file mode 100644
index 0000000..61bf349
--- /dev/null
+++ b/none/tests/procfs-non-linux.vgtest
@@ -0,0 +1,3 @@
+prereq: [ $(uname) != Linux ]
+prog: procfs-cmdline-exe
+stderr_filter: filter_stderr