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