Add wrappers for a load of new 2.6.16 system calls. Fixes bug #123248.

Also expands pathname arguments as strings in a lot more system call
trace messages and fixed the poll wrapper to not be x86 specific.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5785 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
index addb5bc..0837c1a 100644
--- a/coregrind/m_syswrap/priv_syswrap-linux.h
+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
@@ -74,6 +74,8 @@
 DECL_TEMPLATE(linux, sys_sendfile);
 DECL_TEMPLATE(linux, sys_sendfile64);
 DECL_TEMPLATE(linux, sys_futex);
+DECL_TEMPLATE(linux, sys_pselect6);
+DECL_TEMPLATE(linux, sys_ppoll);
 
 DECL_TEMPLATE(linux, sys_epoll_create);
 DECL_TEMPLATE(linux, sys_epoll_ctl);
@@ -122,6 +124,20 @@
 DECL_TEMPLATE(linux, sys_capget);
 DECL_TEMPLATE(linux, sys_capset);
 
+DECL_TEMPLATE(linux, sys_openat);
+DECL_TEMPLATE(linux, sys_mkdirat);
+DECL_TEMPLATE(linux, sys_mknodat);
+DECL_TEMPLATE(linux, sys_fchownat);
+DECL_TEMPLATE(linux, sys_futimesat);
+DECL_TEMPLATE(linux, sys_newfstatat);
+DECL_TEMPLATE(linux, sys_unlinkat);
+DECL_TEMPLATE(linux, sys_renameat);
+DECL_TEMPLATE(linux, sys_linkat);
+DECL_TEMPLATE(linux, sys_symlinkat);
+DECL_TEMPLATE(linux, sys_readlinkat);
+DECL_TEMPLATE(linux, sys_fchmodat);
+DECL_TEMPLATE(linux, sys_faccessat);
+
 // These ones have 32-bit generic equivalents, but the 16-bit versions (they
 // use 16-bit gid_t and uid_t types) seem to be Linux-specific.
 DECL_TEMPLATE(linux, sys_getuid16);
diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
index 4e6bd6e..de44187 100644
--- a/coregrind/m_syswrap/syswrap-amd64-linux.c
+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
@@ -1271,6 +1271,26 @@
    LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 254
 
    LINX_(__NR_inotify_rm_watch,	 sys_inotify_rm_watch), // 255
+//   LINX_(__NR_migrate_pages,	 sys_migrate_pages),    // 256
+   LINXY(__NR_openat,		 sys_openat),           // 257
+   LINX_(__NR_mkdirat,		 sys_mkdirat),          // 258
+   LINX_(__NR_mknodat,		 sys_mknodat),          // 259
+
+   LINX_(__NR_fchownat,		 sys_fchownat),         // 260
+   LINX_(__NR_futimesat,	 sys_futimesat),        // 261
+   LINXY(__NR_newfstatat,	 sys_newfstatat),       // 262
+   LINX_(__NR_unlinkat,		 sys_unlinkat),         // 263
+   LINX_(__NR_renameat,		 sys_renameat),         // 264
+
+   LINX_(__NR_linkat,		 sys_linkat),           // 265
+   LINX_(__NR_symlinkat,	 sys_symlinkat),        // 266
+   LINX_(__NR_readlinkat,	 sys_readlinkat),       // 267
+   LINX_(__NR_fchmodat,		 sys_fchmodat),         // 268
+   LINX_(__NR_faccessat,	 sys_faccessat),        // 269
+
+//   LINX_(__NR_pselect6,		 sys_ni_syscall),       // 270
+//   LINXY(__NR_ppoll,		 sys_ni_syscall),       // 271
+//   LINX_(__NR_unshare,		 sys_unshare),          // 272
 };
 
 const UInt ML_(syscall_table_size) = 
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index 1338e3f..0c272da 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -2237,7 +2237,7 @@
 
 PRE(sys_mknod)
 {
-   PRINT("sys_mknod ( %p, 0x%x, 0x%x )", ARG1, ARG2, ARG3 );
+   PRINT("sys_mknod ( %p(%s), 0x%x, 0x%x )", ARG1, ARG1, ARG2, ARG3 );
    PRE_REG_READ3(long, "mknod",
                  const char *, pathname, int, mode, unsigned, dev);
    PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
@@ -2581,21 +2581,21 @@
 
 PRE(sys_chdir)
 {
-   PRINT("sys_chdir ( %p )", ARG1);
+   PRINT("sys_chdir ( %p(%s) )", ARG1,ARG1);
    PRE_REG_READ1(long, "chdir", const char *, path);
    PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
 }
 
 PRE(sys_chmod)
 {
-   PRINT("sys_chmod ( %p, %d )", ARG1,ARG2);
+   PRINT("sys_chmod ( %p(%s), %d )", ARG1,ARG1,ARG2);
    PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
    PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
 }
 
 PRE(sys_chown)
 {
-   PRINT("sys_chown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
+   PRINT("sys_chown ( %p(%s), 0x%x, 0x%x )", ARG1,ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "chown",
                  const char *, path, vki_uid_t, owner, vki_gid_t, group);
    PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
@@ -2603,7 +2603,7 @@
 
 PRE(sys_lchown)
 {
-   PRINT("sys_lchown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
+   PRINT("sys_lchown ( %p(%s), 0x%x, 0x%x )", ARG1,ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "lchown",
                  const char *, path, vki_uid_t, owner, vki_gid_t, group);
    PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
@@ -4587,7 +4587,7 @@
 PRE(sys_link)
 {
    *flags |= SfMayBlock;
-   PRINT("sys_link ( %p, %p)", ARG1, ARG2);
+   PRINT("sys_link ( %p(%s), %p(%s) )", ARG1,ARG1,ARG2,ARG2);
    PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
    PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
    PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
@@ -4612,7 +4612,7 @@
 PRE(sys_mkdir)
 {
    *flags |= SfMayBlock;
-   PRINT("sys_mkdir ( %p, %d )", ARG1,ARG2);
+   PRINT("sys_mkdir ( %p(%s), %d )", ARG1,ARG1,ARG2);
    PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
    PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
 }
@@ -4865,7 +4865,6 @@
    }
 }
 
-// XXX: x86-specific, due to pollfd struct
 PRE(sys_poll)
 {
    /* struct pollfd {
@@ -4880,16 +4879,16 @@
    *flags |= SfMayBlock;
    PRINT("sys_poll ( %p, %d, %d )\n", ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "poll",
-                 struct pollfd *, ufds, unsigned int, nfds, long, timeout);
-                     
+                 struct vki_pollfd *, ufds, unsigned int, nfds, long, timeout);
+
    for (i = 0; i < ARG2; i++) {
-      // 'fd' and 'events' field are inputs;  'revents' is output.
-      // XXX: this is x86 specific -- the pollfd struct varies across
-      // different architectures.
-      PRE_MEM_READ( "poll(ufds)",
-                    (Addr)(&ufds[i]), sizeof(int) + sizeof(short) );
-      PRE_MEM_WRITE( "poll(ufds)", (Addr)(&ufds[i].revents), sizeof(short) );
-   }  
+      PRE_MEM_READ( "poll(ufds.fd)",
+                    (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
+      PRE_MEM_READ( "poll(ufds.events)",
+                    (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
+      PRE_MEM_WRITE( "poll(ufd.reventss)",
+                     (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
+   }
 }
 
 POST(sys_poll)
@@ -4897,9 +4896,8 @@
    if (RES > 0) {
       UInt i;
       struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
-      // XXX: again, this is x86-specific
       for (i = 0; i < ARG2; i++)
-	 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(Short) );
+	 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
    }
 }
 
@@ -4908,7 +4906,7 @@
    HChar name[25];
    Word  saved = SYSNO;
 
-   PRINT("sys_readlink ( %p, %p, %llu )", ARG1,ARG2,(ULong)ARG3);
+   PRINT("sys_readlink ( %p(%s), %p, %llu )", ARG1,ARG1,ARG2,(ULong)ARG3);
    PRE_REG_READ3(long, "readlink",
                  const char *, path, char *, buf, int, bufsiz);
    PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
@@ -4979,7 +4977,7 @@
 
 PRE(sys_rename)
 {
-   PRINT("sys_rename ( %p, %p )", ARG1, ARG2 );
+   PRINT("sys_rename ( %p(%s), %p(%s) )", ARG1,ARG1,ARG2,ARG2);
    PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
    PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
    PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
@@ -4988,7 +4986,7 @@
 PRE(sys_rmdir)
 {
    *flags |= SfMayBlock;
-   PRINT("sys_rmdir ( %p )", ARG1);
+   PRINT("sys_rmdir ( %p(%s) )", ARG1,ARG1);
    PRE_REG_READ1(long, "rmdir", const char *, pathname);
    PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
 }
@@ -4999,7 +4997,7 @@
    PRINT("sys_select ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
    PRE_REG_READ5(long, "select",
                  int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
-                 vki_fd_set *, exceptfds, struct timeval *, timeout);
+                 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
    // XXX: this possibly understates how much memory is read.
    if (ARG2 != 0)
       PRE_MEM_READ( "select(readfds)",   
@@ -5113,7 +5111,7 @@
 
 PRE(sys_statfs)
 {
-   PRINT("sys_statfs ( %p, %p )",ARG1,ARG2);
+   PRINT("sys_statfs ( %p(%s), %p )",ARG1,ARG1,ARG2);
    PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
    PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
    PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
@@ -5125,7 +5123,7 @@
 
 PRE(sys_statfs64)
 {
-   PRINT("sys_statfs64 ( %p, %llu, %p )",ARG1,(ULong)ARG2,ARG3);
+   PRINT("sys_statfs64 ( %p(%s), %llu, %p )",ARG1,ARG1,(ULong)ARG2,ARG3);
    PRE_REG_READ3(long, "statfs64",
                  const char *, path, vki_size_t, size, struct statfs64 *, buf);
    PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
@@ -5139,7 +5137,7 @@
 PRE(sys_symlink)
 {
    *flags |= SfMayBlock;
-   PRINT("sys_symlink ( %p, %p )",ARG1,ARG2);
+   PRINT("sys_symlink ( %p(%s), %p(%s) )",ARG1,ARG1,ARG2,ARG2);
    PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
    PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
    PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
@@ -5271,7 +5269,7 @@
 
 PRE(sys_utimes)
 {
-   PRINT("sys_utimes ( %p, %p )", ARG1,ARG2);
+   PRINT("sys_utimes ( %p(%s), %p )", ARG1,ARG1,ARG2);
    PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
    PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
    if (ARG2 != 0)
@@ -5280,7 +5278,7 @@
 
 PRE(sys_acct)
 {
-   PRINT("sys_acct ( %p )", ARG1);
+   PRINT("sys_acct ( %p(%s) )", ARG1,ARG1);
    PRE_REG_READ1(long, "acct", const char *, filename);
    PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
 }
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 3ceebf2..bc98648 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -33,6 +33,7 @@
 #include "pub_core_aspacemgr.h"
 #include "pub_core_debuginfo.h"    // VG_(di_notify_*)
 #include "pub_core_transtab.h"     // VG_(discard_translations)
+#include "pub_core_clientstate.h"
 #include "pub_core_debuglog.h"
 #include "pub_core_libcbase.h"
 #include "pub_core_libcassert.h"
@@ -798,6 +799,66 @@
    }
 }
 
+PRE(sys_pselect6)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_pselect6 ( %d, %p, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+   PRE_REG_READ6(long, "pselect6",
+                 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
+                 vki_fd_set *, exceptfds, struct vki_timeval *, timeout,
+                 void *, sig);
+   // XXX: this possibly understates how much memory is read.
+   if (ARG2 != 0)
+      PRE_MEM_READ( "pselect6(readfds)",   
+		     ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
+   if (ARG3 != 0)
+      PRE_MEM_READ( "pselect6(writefds)",  
+		     ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
+   if (ARG4 != 0)
+      PRE_MEM_READ( "pselect6(exceptfds)", 
+		     ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
+   if (ARG5 != 0)
+      PRE_MEM_READ( "pselect6(timeout)", ARG5, sizeof(struct vki_timeval) );
+   if (ARG6 != 0)
+      PRE_MEM_READ( "pselect6(sig)", ARG6, sizeof(void *)+sizeof(vki_size_t) );
+}
+
+PRE(sys_ppoll)
+{
+   UInt i;
+   struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
+   *flags |= SfMayBlock;
+   PRINT("sys_ppoll ( %p, %d, %p, %p, %llu )\n", ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ5(long, "ppoll",
+                 struct vki_pollfd *, ufds, unsigned int, nfds,
+                 struct vki_timespec *, tsp, vki_sigset_t *, sigmask,
+                 vki_size_t, sigsetsize);
+
+   for (i = 0; i < ARG2; i++) {
+      PRE_MEM_READ( "ppoll(ufds.fd)",
+                    (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
+      PRE_MEM_READ( "ppoll(ufds.events)",
+                    (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
+      PRE_MEM_WRITE( "ppoll(ufd.reventss)",
+                     (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
+   }
+
+   if (ARG3)
+      PRE_MEM_READ( "ppoll(tsp)", ARG3, sizeof(struct vki_timespec) );
+   if (ARG4)
+      PRE_MEM_READ( "ppoll(sigmask)", ARG4, sizeof(vki_sigset_t) );
+}
+
+POST(sys_ppoll)
+{
+   if (RES > 0) {
+      UInt i;
+      struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
+      for (i = 0; i < ARG2; i++)
+	 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
+   }
+}
+
 
 /* ---------------------------------------------------------------------
    epoll_* wrappers
@@ -2215,6 +2276,201 @@
    }
 }
 
+/* ---------------------------------------------------------------------
+   *at wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_openat)
+{
+   HChar  name[30];
+   SysRes sres;
+
+   if (ARG3 & VKI_O_CREAT) {
+      // 4-arg version
+      PRINT("sys_openat ( %d, %p(%s), %d, %d )",ARG1,ARG2,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "openat",
+                    int, dfd, const char *, filename, int, flags, int, mode);
+   } else {
+      // 3-arg version
+      PRINT("sys_openat ( %d, %p(%s), %d )",ARG1,ARG2,ARG2,ARG3);
+      PRE_REG_READ3(long, "openat",
+                    int, dfd, const char *, filename, int, flags);
+   }
+
+   if (!ML_(fd_allowed)(ARG1, "openat", tid, False))
+      SET_STATUS_Failure( VKI_EBADF );
+   else
+      PRE_MEM_RASCIIZ( "openat(filename)", ARG2 );
+
+   /* Handle the case where the open is of /proc/self/cmdline or
+      /proc/<pid>/cmdline, and just give it a copy of the fd for the
+      fake file we cooked up at startup (in m_main).  Also, seek the
+      cloned fd back to the start. */
+
+   VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
+   if (ML_(safe_to_deref)( (void*)ARG2, 1 )
+       && (VG_(strcmp)((Char *)ARG2, name) == 0 
+           || VG_(strcmp)((Char *)ARG2, "/proc/self/cmdline") == 0)) {
+      sres = VG_(dup)( VG_(cl_cmdline_fd) );
+      SET_STATUS_from_SysRes( sres );
+      if (!sres.isError) {
+         OffT off = VG_(lseek)( sres.val, 0, VKI_SEEK_SET );
+         if (off < 0)
+            SET_STATUS_Failure( VKI_EMFILE );
+      }
+      return;
+   }
+
+   /* Otherwise handle normally */
+   *flags |= SfMayBlock;
+}
+
+POST(sys_openat)
+{
+   vg_assert(SUCCESS);
+   if (!ML_(fd_allowed)(RES, "openat", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG2);
+   }
+}
+
+PRE(sys_mkdirat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_mkdirat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3);
+   PRE_REG_READ3(long, "mkdirat",
+                 int, dfd, const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "mkdirat(pathname)", ARG2 );
+}
+
+PRE(sys_mknodat)
+{
+   PRINT("sys_mknodat ( %d, %p(%s), 0x%x, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4 );
+   PRE_REG_READ4(long, "mknodat",
+                 int, dfd, const char *, pathname, int, mode, unsigned, dev);
+   PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 );
+}
+
+PRE(sys_fchownat)
+{
+   PRINT("sys_fchownat ( %d, %p(%s), 0x%x, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "fchownat",
+                 int, dfd, const char *, path,
+                 vki_uid_t, owner, vki_gid_t, group);
+   PRE_MEM_RASCIIZ( "fchownat(path)", ARG2 );
+}
+
+PRE(sys_futimesat)
+{
+   PRINT("sys_futimesat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3);
+   PRE_REG_READ3(long, "futimesat",
+                 int, dfd, char *, filename, struct timeval *, tvp);
+   PRE_MEM_RASCIIZ( "futimesat(filename)", ARG2 );
+   if (ARG3 != 0)
+      PRE_MEM_READ( "futimesat(tvp)", ARG3, sizeof(struct vki_timeval) );
+}
+
+PRE(sys_newfstatat)
+{
+   PRINT("sys_newfstatat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3);
+   PRE_REG_READ3(long, "fstatat",
+                 int, dfd, char *, file_name, struct stat *, buf);
+   PRE_MEM_RASCIIZ( "fstatat(file_name)", ARG2 );
+   PRE_MEM_WRITE( "fstatat(buf)", ARG3, sizeof(struct vki_stat) );
+}
+
+POST(sys_newfstatat)
+{
+   POST_MEM_WRITE( ARG3, sizeof(struct vki_stat) );
+}
+
+PRE(sys_unlinkat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_unlinkat ( %d, %p(%s) )", ARG1,ARG2,ARG2);
+   PRE_REG_READ2(long, "unlinkat", int, dfd, const char *, pathname);
+   PRE_MEM_RASCIIZ( "unlinkat(pathname)", ARG2 );
+}
+
+PRE(sys_renameat)
+{
+   PRINT("sys_renameat ( %d, %p(%s), %p(%s) )", ARG1,ARG2,ARG2,ARG3,ARG3);
+   PRE_REG_READ3(long, "renameat",
+                 int, dfd, const char *, oldpath, const char *, newpath);
+   PRE_MEM_RASCIIZ( "renameat(oldpath)", ARG2 );
+   PRE_MEM_RASCIIZ( "renameat(newpath)", ARG3 );
+}
+
+PRE(sys_linkat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_linkat ( %d, %p(%s), %p(%s) )", ARG1,ARG2,ARG2,ARG3,ARG3);
+   PRE_REG_READ3(long, "linkat",
+                 int, dfd, const char *, oldpath, const char *, newpath);
+   PRE_MEM_RASCIIZ( "linkat(oldpath)", ARG2);
+   PRE_MEM_RASCIIZ( "linkat(newpath)", ARG3);
+}
+
+PRE(sys_symlinkat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_symlinkat ( %d, %p(%s), %p(%s) )",ARG1,ARG2,ARG2,ARG3,ARG3);
+   PRE_REG_READ3(long, "symlinkat",
+                 int, dfd, const char *, oldpath, const char *, newpath);
+   PRE_MEM_RASCIIZ( "symlinkat(oldpath)", ARG2 );
+   PRE_MEM_RASCIIZ( "symlinkat(newpath)", ARG3 );
+}
+
+PRE(sys_readlinkat)
+{
+   HChar name[25];
+   Word  saved = SYSNO;
+
+   PRINT("sys_readlinkat ( %d, %p(%s), %p, %llu )", ARG1,ARG2,ARG2,ARG3,(ULong)ARG4);
+   PRE_REG_READ4(long, "readlinkat",
+                 int, dfd, const char *, path, char *, buf, int, bufsiz);
+   PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
+   PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
+
+   /*
+    * Handle the case where readlinkat is looking at /proc/self/exe or
+    * /proc/<pid>/exe.
+    */
+   VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
+   if (ML_(safe_to_deref)((void*)ARG2, 1)
+       && (VG_(strcmp)((Char *)ARG2, name) == 0 
+           || VG_(strcmp)((Char *)ARG2, "/proc/self/exe") == 0)) {
+      VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
+      SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name, 
+                                                      ARG3, ARG4));
+   } else {
+      /* Normal case */
+      SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
+   }
+
+   if (SUCCESS && RES > 0)
+      POST_MEM_WRITE( ARG3, RES );
+}
+
+PRE(sys_fchmodat)
+{
+   PRINT("sys_fchmodat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3);
+   PRE_REG_READ3(long, "fchmodat",
+                 int, dfd, const char *, path, vki_mode_t, mode);
+   PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 );
+}
+
+PRE(sys_faccessat)
+{
+   PRINT("sys_faccessat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3);
+   PRE_REG_READ3(long, "faccessat",
+                 int, dfd, const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 );
+}
+
 #undef PRE
 #undef POST
 
diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
index 4861a7c..949f082 100644
--- a/coregrind/m_syswrap/syswrap-x86-linux.c
+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
@@ -758,6 +758,7 @@
    magic. */
 DECL_TEMPLATE(x86_linux, sys_socketcall);
 DECL_TEMPLATE(x86_linux, sys_stat64);
+DECL_TEMPLATE(x86_linux, sys_fstatat64);
 DECL_TEMPLATE(x86_linux, sys_fstat64);
 DECL_TEMPLATE(x86_linux, sys_lstat64);
 DECL_TEMPLATE(x86_linux, sys_clone);
@@ -1332,7 +1333,7 @@
 
 PRE(sys_stat64)
 {
-   PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
+   PRINT("sys_stat64 ( %p(%s), %p )",ARG1,ARG2,ARG2);
    PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
    PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
    PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
@@ -1343,6 +1344,20 @@
    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
 }
 
+PRE(sys_fstatat64)
+{
+   PRINT("sys_fstatat64 ( %d, %p(%s), %p )",ARG1,ARG2,ARG2,ARG3);
+   PRE_REG_READ3(long, "fstatat64",
+                 int, dfd, char *, file_name, struct stat64 *, buf);
+   PRE_MEM_RASCIIZ( "fstatat64(file_name)", ARG2 );
+   PRE_MEM_WRITE( "fstatat64(buf)", ARG3, sizeof(struct vki_stat64) );
+}
+
+POST(sys_fstatat64)
+{
+   POST_MEM_WRITE( ARG3, sizeof(struct vki_stat64) );
+}
+
 PRE(sys_fstat64)
 {
    PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
@@ -2117,6 +2132,27 @@
    LINX_(__NR_inotify_init,	 sys_inotify_init),   // 291
    LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
    LINX_(__NR_inotify_rm_watch,	 sys_inotify_rm_watch), // 293
+//   LINX_(__NR_migrate_pages,	 sys_migrate_pages),    // 294
+
+   LINXY(__NR_openat,		 sys_openat),           // 295
+   LINX_(__NR_mkdirat,		 sys_mkdirat),          // 296
+   LINX_(__NR_mknodat,		 sys_mknodat),          // 297
+   LINX_(__NR_fchownat,		 sys_fchownat),         // 298
+   LINX_(__NR_futimesat,	 sys_futimesat),        // 299
+
+   PLAXY(__NR_fstatat64,	 sys_fstatat64),        // 300
+   LINX_(__NR_unlinkat,		 sys_unlinkat),         // 301
+   LINX_(__NR_renameat,		 sys_renameat),         // 302
+   LINX_(__NR_linkat,		 sys_linkat),           // 303
+   LINX_(__NR_symlinkat,	 sys_symlinkat),        // 304
+
+   LINX_(__NR_readlinkat,	 sys_readlinkat),       // 305
+   LINX_(__NR_fchmodat,		 sys_fchmodat),         // 306
+   LINX_(__NR_faccessat,	 sys_faccessat),        // 307
+   LINX_(__NR_pselect6,		 sys_pselect6),         // 308
+   LINXY(__NR_ppoll,		 sys_ppoll),            // 309
+
+//   LINX_(__NR_unshare,		 sys_unshare),          // 310
 };
 
 const UInt ML_(syscall_table_size) =