Allow readlink to handle /proc/self/exe and /proc/<pid>/exe properly.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3048 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c
index 0ad289c..4b47203 100644
--- a/coregrind/vg_syscalls.c
+++ b/coregrind/vg_syscalls.c
@@ -4401,18 +4401,33 @@
}
}
-PRE(sys_readlink, 0)
+PRE(sys_readlink, Special)
{
+ char name[25];
+
PRINT("sys_readlink ( %p, %p, %llu )", arg1,arg2,(ULong)arg3);
PRE_REG_READ3(long, "readlink",
const char *, path, char *, buf, int, bufsiz);
PRE_MEM_RASCIIZ( "readlink(path)", arg1 );
PRE_MEM_WRITE( "readlink(buf)", arg2,arg3 );
-}
-POST(sys_readlink)
-{
- POST_MEM_WRITE( arg2, res );
+ /*
+ * Handle the single case where readlink failed reading /proc/self/exe.
+ */
+
+ VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
+
+ if (VG_(strcmp)((Char *)arg1, name) == 0 ||
+ VG_(strcmp)((Char *)arg1, "/proc/self/exe") == 0) {
+ VG_(sprintf)(name, "/proc/self/fd/%d", VG_(clexecfd));
+ res = VG_(do_syscall)(SYSNO, name, arg2, arg3);
+ }
+ else {
+ res = VG_(do_syscall)(SYSNO, arg1, arg2, arg3);
+ }
+
+ if (res > 0)
+ POST_MEM_WRITE( arg2, res );
}
PRE(sys_readv, MayBlock)
diff --git a/coregrind/x86-linux/syscalls.c b/coregrind/x86-linux/syscalls.c
index 7152b08..31ef360 100644
--- a/coregrind/x86-linux/syscalls.c
+++ b/coregrind/x86-linux/syscalls.c
@@ -449,7 +449,7 @@
GENX_(__NR_symlink, sys_symlink), // 83
// (__NR_oldlstat, sys_lstat), // 84 -- obsolete
- GENXY(__NR_readlink, sys_readlink), // 85
+ GENX_(__NR_readlink, sys_readlink), // 85
// (__NR_uselib, sys_uselib), // 86 */Linux
// (__NR_swapon, sys_swapon), // 87 */Linux
// (__NR_reboot, sys_reboot), // 88 */Linux