]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Use statx rather than other stat system calls
authorPetar Jovanovic <mips32r2@gmail.com>
Fri, 16 Aug 2019 15:57:50 +0000 (15:57 +0000)
committerPetar Jovanovic <mips32r2@gmail.com>
Fri, 16 Aug 2019 15:59:29 +0000 (15:59 +0000)
*STAT* system calls other than statx are becoming deprecated.
Coregrind should use statx as the first candidate in order to achieve
"stat" functionality.

There are also systems that do not even support older "stats".

This fixes KDE #400593.

Patch by Aleksandar Rikalo.

coregrind/m_aspacemgr/aspacemgr-common.c
coregrind/m_libcfile.c
include/pub_tool_libcbase.h
include/vki/vki-linux.h

index 79f5252c21e93e187a13e8d54c305c76781eedaa..789cc9b0cac43650749d6b4b267257c7650cbe0e 100644 (file)
@@ -314,9 +314,21 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
 {
 #  if defined(VGO_linux) || defined(VGO_darwin)
    SysRes          res;
-   struct vki_stat buf;
+#  if defined(VGO_linux)
+   /* First try with statx. */
+   struct vki_statx bufx;
+   const char* file_name = "";
+   res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
+                          VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&bufx);
+   if (!sr_isError(res)) {
+      *dev  = VG_MAKEDEV(bufx.stx_dev_major, bufx.stx_dev_minor);
+      *ino  = (ULong)bufx.stx_ino;
+      *mode = (UInt)bufx.stx_mode;
+      return True;
+   }
+#  endif
 #  if defined(VGO_linux) && defined(__NR_fstat64)
-   /* Try fstat64 first as it can cope with minor and major device
+   /* fstat64 is second candidate as it can cope with minor and major device
       numbers outside the 0-255 range and it works properly for x86
       binaries on amd64 systems where fstat seems to be broken. */
    struct vki_stat64 buf64;
@@ -328,6 +340,8 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
       return True;
    }
 #  endif
+#  if defined(__NR_fstat)
+   struct vki_stat buf;
    res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
    if (!sr_isError(res)) {
       *dev  = (ULong)buf.st_dev;
@@ -335,6 +349,7 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
       *mode = (UInt) buf.st_mode;
       return True;
    }
+#  endif
    return False;
 #  elif defined(VGO_solaris)
 #  if defined(VGP_x86_solaris)
index c65551a2300782e65f85f0e0f70d304101a1a837..5c356ade6cdfc77813eeb412d6dff06d12d16faa 100644 (file)
@@ -337,14 +337,51 @@ Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
       (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
    } while (0)
 
+#define TRANSLATE_statx_TO_vg_stat(_p_vgstat, _p_vkistat)                   \
+   do {                                                                     \
+      (_p_vgstat)->dev        = VG_MAKEDEV( (_p_vkistat)->stx_dev_major,    \
+                                            (_p_vkistat)->stx_dev_minor );  \
+      (_p_vgstat)->ino        = (ULong)( (_p_vkistat)->stx_ino );           \
+      (_p_vgstat)->nlink      = (ULong)( (_p_vkistat)->stx_nlink );         \
+      (_p_vgstat)->mode       = (UInt) ( (_p_vkistat)->stx_mode );          \
+      (_p_vgstat)->uid        = (UInt) ( (_p_vkistat)->stx_uid );           \
+      (_p_vgstat)->gid        = (UInt) ( (_p_vkistat)->stx_gid );           \
+      (_p_vgstat)->rdev       = VG_MAKEDEV( (_p_vkistat)->stx_rdev_major,   \
+                                            (_p_vkistat)->stx_rdev_minor ); \
+      (_p_vgstat)->size       = (Long) ( (_p_vkistat)->stx_size );          \
+      (_p_vgstat)->blksize    = (ULong)( (_p_vkistat)->stx_blksize );       \
+      (_p_vgstat)->blocks     = (ULong)( (_p_vkistat)->stx_blocks );        \
+      (_p_vgstat)->atime      = (ULong)( (_p_vkistat)->stx_atime.tv_sec );  \
+      (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->stx_atime.tv_nsec ); \
+      (_p_vgstat)->mtime      = (ULong)( (_p_vkistat)->stx_mtime.tv_sec );  \
+      (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->stx_mtime.tv_nsec ); \
+      (_p_vgstat)->ctime      = (ULong)( (_p_vkistat)->stx_ctime.tv_sec );  \
+      (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->stx_ctime.tv_nsec ); \
+   } while (0)
+
 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
 {
    SysRes res;
    VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
 
+#  if defined(VGO_linux)
+   /* On Linux, first try with statx. If that doesn't work out, fall back to
+      the stat64 or vanilla version. */
+   { struct vki_statx buf;
+     res = VG_(do_syscall5)(__NR_statx, VKI_AT_FDCWD, (UWord)file_name, 0,
+                            VKI_STATX_ALL, (UWord)&buf);
+     if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
+        /* Success, or any failure except ENOSYS */
+        if (!sr_isError(res))
+           TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
+        return res;
+     }
+   }
+#  endif
 #  if defined(VGO_linux) || defined(VGO_darwin)
-   /* First try with stat64.  If that doesn't work out, fall back to
-      the vanilla version. */
+   /* Try with stat64. This is the second candidate on Linux, and the first
+      one on Darwin. If that doesn't work out, fall back to vanilla version.
+    */
 #  if defined(__NR_stat64)
    { struct vki_stat64 buf64;
      res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
@@ -356,6 +393,7 @@ SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
      }
    }
 #  endif /* defined(__NR_stat64) */
+#  if defined(__NR_stat)
    /* This is the fallback ("vanilla version"). */
    { struct vki_stat buf;
 #    if defined(VGP_arm64_linux)
@@ -368,6 +406,7 @@ SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
         TRANSLATE_TO_vg_stat(vgbuf, &buf);
      return res;
    }
+#  endif
 #  elif defined(VGO_solaris)
    {
 #     if defined(VGP_x86_solaris)
@@ -395,9 +434,25 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
    SysRes res;
    VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
 
+#  if defined(VGO_linux)
+   /* On Linux, first try with statx. If that doesn't work out, fall back to
+      the fstat64 or vanilla version. */
+   { struct vki_statx buf;
+     const char* file_name = "";
+     res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
+                            VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&buf);
+     if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
+        /* Success, or any failure except ENOSYS */
+        if (!sr_isError(res))
+           TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
+        return sr_isError(res) ? (-1) : 0;
+     }
+   }
+#endif
 #  if defined(VGO_linux) || defined(VGO_darwin)
-   /* First try with fstat64.  If that doesn't work out, fall back to
-      the vanilla version. */
+   /* Try with fstat64. This is the second candidate on Linux, and the first
+      one on Darwin. If that doesn't work out, fall back to vanilla version.
+    */
 #  if defined(__NR_fstat64)
    { struct vki_stat64 buf64;
      res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
@@ -408,13 +463,15 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
         return sr_isError(res) ? (-1) : 0;
      }
    }
-#  endif /* if defined(__NR_fstat64) */
+#  endif /* defined(__NR_fstat64) */
+#  if defined(__NR_fstat)
    { struct vki_stat buf;
      res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
      if (!sr_isError(res))
         TRANSLATE_TO_vg_stat(vgbuf, &buf);
      return sr_isError(res) ? (-1) : 0;
    }
+#  endif
 #  elif defined(VGO_solaris)
    { 
 #     if defined(VGP_x86_solaris)
@@ -436,7 +493,7 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
 }
 
 #undef TRANSLATE_TO_vg_stat
-
+#undef TRANSLATE_statx_TO_vg_stat
 
 Long VG_(fsize) ( Int fd )
 {
index 33444ac32a498590aefd592a2c9fab358be5f296..b71066e25ea0f70023fb67462d719af6f5706c08 100644 (file)
@@ -202,6 +202,18 @@ static void VG_(bzero_inline) ( void* s, SizeT sz )
 #define VG_PGROUNDDN(p)    VG_ROUNDDN(p, VKI_PAGE_SIZE)
 #define VG_PGROUNDUP(p)    VG_ROUNDUP(p, VKI_PAGE_SIZE)
 
+/* Converts `Device ID` given as pair of 32-bit values (dev_major, dev_minor)
+ * to 64-bit dev_t using MMMM Mmmm mmmM MMmm encoding. This is
+ * downward compatible with legacy systems where dev_t is 16 bits wide,
+ * encoded as MMmm. It is also downward compatible with the Linux kernel,
+ * which uses 32-bit dev_t, encoded as mmmM MMmm.
+ * Original macro can be found in bits/sysmacros.h. */
+#define VG_MAKEDEV(__major, __minor)            \
+   ((((ULong) (__major & 0x00000fffu)) <<  8) | \
+    (((ULong) (__major & 0xfffff000u)) << 32) | \
+    (((ULong) (__minor & 0x000000ffu)) <<  0) | \
+    (((ULong) (__minor & 0xffffff00u)) << 12))
+
 /* ---------------------------------------------------------------------
    Misc useful functions
    ------------------------------------------------------------------ */
index 76bc7837b58ade44da2a27c7c4efe83f631e28cb..6024f2165baebd8d8965dbc0f98ad59f6023bc46 100644 (file)
@@ -1385,6 +1385,8 @@ struct vki_robust_list_head {
 #define VKI_S_IWOTH 00002
 #define VKI_S_IXOTH 00001
 
+#define VKI_STATX_ALL 0x00000FFFU
+
 struct vki_statx_timestamp {
         __vki_s64   tv_sec;
         __vki_u32   tv_nsec;
@@ -1476,6 +1478,8 @@ struct vki_flock64 {
        __vki_kernel_pid_t      l_pid;
 };
 
+#define VKI_AT_EMPTY_PATH       0x1000  /* Allow empty relative pathname */
+
 //----------------------------------------------------------------------
 // From linux-2.6.8.1/include/linux/sysctl.h
 //----------------------------------------------------------------------