diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 2336c29..0f8e07a 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -5277,8 +5277,25 @@ PRE(sys_utimensat) int, dfd, char *, filename, struct timespec *, utimes, int, flags); if (ARG2 != 0) PRE_MEM_RASCIIZ( "utimensat(filename)", ARG2 ); - if (ARG3 != 0) - PRE_MEM_READ( "utimensat(tvp)", ARG3, 2 * sizeof(struct vki_timespec) ); + if (ARG3 != 0) { + /* If timespec.tv_nsec has the special value UTIME_NOW or UTIME_OMIT + then the tv_sec field is ignored. */ + struct vki_timespec *times = (struct vki_timespec *)(Addr)ARG3; + PRE_MEM_READ( "utimensat(times[0].tv_nsec)", + (Addr)×[0].tv_nsec, sizeof(times[0].tv_nsec)); + PRE_MEM_READ( "utimensat(times[1].tv_nsec)", + (Addr)×[1].tv_nsec, sizeof(times[1].tv_nsec)); + if (ML_(safe_to_deref)(times, 2 * sizeof(struct vki_timespec))) { + if (times[0].tv_nsec != VKI_UTIME_NOW + && times[0].tv_nsec != VKI_UTIME_OMIT) + PRE_MEM_READ( "utimensat(times[0].tv_sec)", + (Addr)×[0].tv_sec, sizeof(times[0].tv_sec)); + if (times[1].tv_nsec != VKI_UTIME_NOW + && times[1].tv_nsec != VKI_UTIME_OMIT) + PRE_MEM_READ( "utimensat(times[1].tv_sec)", + (Addr)×[1].tv_sec, sizeof(times[1].tv_sec)); + } + } } PRE(sys_newfstatat) diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index 7072080..bf0c1aa 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -283,6 +283,10 @@ struct vki_timespec { long tv_nsec; /* nanoseconds */ }; +/* Special values for vki_timespec.tv_nsec when used with utimensat. */ +#define VKI_UTIME_NOW ((1l << 30) - 1l) +#define VKI_UTIME_OMIT ((1l << 30) - 2l) + struct vki_timeval { vki_time_t tv_sec; /* seconds */ vki_suseconds_t tv_usec; /* microseconds */