From: Bart Van Assche Date: Sat, 26 Apr 2008 07:45:10 +0000 (+0000) Subject: Added support for epoll_pwait(), utimensat(), eventfd(), timerfd() and signalfd(... X-Git-Tag: svn/VALGRIND_3_4_0~706 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e31611fb5ccf484df48fec7f12dc5b281009ea67;p=thirdparty%2Fvalgrind.git Added support for epoll_pwait(), utimensat(), eventfd(), timerfd() and signalfd(). Fixes bug 160907. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7917 --- diff --git a/configure.in b/configure.in index c3fd234d5e..97d2980293 100644 --- a/configure.in +++ b/configure.in @@ -953,7 +953,15 @@ fi # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([sys/endian.h endian.h mqueue.h]) +AC_CHECK_HEADERS([ \ + endian.h \ + mqueue.h \ + sys/endian.h \ + sys/epoll.h \ + sys/eventfd.h \ + sys/poll.h \ + sys/signalfd.h \ + ]) # Checks for typedefs, structures, and compiler characteristics. @@ -968,8 +976,27 @@ AC_FUNC_MEMCMP AC_FUNC_MMAP AC_TYPE_SIGNAL -AC_CHECK_FUNCS([floor memchr memset mkdir strchr strdup strpbrk strrchr strstr semtimedop]) -AC_CHECK_FUNCS([mallinfo]) +AC_CHECK_FUNCS([ \ + epoll_create \ + epoll_pwait \ + eventfd \ + eventfd_read \ + floor \ + mallinfo \ + memchr \ + memset \ + mkdir \ + ppoll \ + semtimedop \ + signalfd \ + strchr \ + strdup \ + strpbrk \ + strrchr \ + strstr \ + timerfd \ + utimensat \ + ]) # Do we have a useable MPI setup on the primary and/or secondary targets? diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h index 115c4363ae..0033494fbf 100644 --- a/coregrind/m_syswrap/priv_syswrap-linux.h +++ b/coregrind/m_syswrap/priv_syswrap-linux.h @@ -82,6 +82,8 @@ DECL_TEMPLATE(linux, sys_ppoll); DECL_TEMPLATE(linux, sys_epoll_create); DECL_TEMPLATE(linux, sys_epoll_ctl); DECL_TEMPLATE(linux, sys_epoll_wait); +DECL_TEMPLATE(linux, sys_epoll_pwait); +DECL_TEMPLATE(linux, sys_eventfd); DECL_TEMPLATE(linux, sys_gettid); DECL_TEMPLATE(linux, sys_set_tid_address); @@ -124,6 +126,9 @@ DECL_TEMPLATE(linux, sys_timer_settime); DECL_TEMPLATE(linux, sys_timer_gettime); DECL_TEMPLATE(linux, sys_timer_getoverrun); DECL_TEMPLATE(linux, sys_timer_delete); +DECL_TEMPLATE(linux, sys_timerfd); + +DECL_TEMPLATE(linux, sys_signalfd); DECL_TEMPLATE(linux, sys_capget); DECL_TEMPLATE(linux, sys_capset); diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index b49c27d60f..24c1a539d1 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -1370,7 +1370,7 @@ const SyscallTableEntry ML_(syscall_table)[] = { LINX_(__NR_faccessat, sys_faccessat), // 269 LINX_(__NR_pselect6, sys_pselect6), // 270 -// LINXY(__NR_ppoll, sys_ni_syscall), // 271 + LINXY(__NR_ppoll, sys_ppoll), // 271 // LINX_(__NR_unshare, sys_unshare), // 272 LINX_(__NR_set_robust_list, sys_set_robust_list), // 273 LINXY(__NR_get_robust_list, sys_get_robust_list), // 274 @@ -1380,6 +1380,12 @@ const SyscallTableEntry ML_(syscall_table)[] = { LINX_(__NR_sync_file_range, sys_sync_file_range), // 277 // LINX_(__NR_vmsplice, sys_ni_syscall), // 278 // LINX_(__NR_move_pages, sys_ni_syscall), // 279 + LINX_(__NR_utimensat, sys_utimensat), // 280 + LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 281 + LINXY(__NR_signalfd, sys_signalfd), // 282 + LINXY(__NR_timerfd, sys_timerfd), // 283 + LINX_(__NR_eventfd, sys_eventfd), // 284 +// LINX_(__NR_fallocate, sys_ni_syscall), // 285 }; const UInt ML_(syscall_table_size) = diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 4820713da9..d7e0755ca2 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -5638,7 +5638,7 @@ PRE(sys_utimes) PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp); PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 ); if (ARG2 != 0) - PRE_MEM_READ( "utimes(tvp)", ARG2, sizeof(struct vki_timeval) ); + PRE_MEM_READ( "utimes(tvp)", ARG2, 2 * sizeof(struct vki_timeval) ); } PRE(sys_acct) diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 0f4b8f33af..a0cabc324f 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -988,7 +988,7 @@ 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); + PRINT("sys_ppoll ( %p, %d, %p, %p, %llu )\n", ARG1,ARG2,ARG3,ARG4,(ULong)ARG5); PRE_REG_READ5(long, "ppoll", struct vki_pollfd *, ufds, unsigned int, nfds, struct vki_timespec *, tsp, vki_sigset_t *, sigmask, @@ -1072,6 +1072,41 @@ POST(sys_epoll_wait) POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ; } +PRE(sys_epoll_pwait) +{ + *flags |= SfMayBlock; + PRINT("sys_epoll_pwait ( %d, %p, %d, %d, %p, %llu )", ARG1,ARG2,ARG3,ARG4,ARG5,(ULong)ARG6); + PRE_REG_READ6(long, "epoll_pwait", + int, epfd, struct vki_epoll_event *, events, + int, maxevents, int, timeout, vki_sigset_t *, sigmask, + vki_size_t, sigsetsize); + PRE_MEM_WRITE( "epoll_pwait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3); + if (ARG4) + PRE_MEM_READ( "epoll_pwait(sigmask)", ARG5, sizeof(vki_sigset_t) ); +} +POST(sys_epoll_pwait) +{ + vg_assert(SUCCESS); + if (RES > 0) + POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ; +} + +PRE(sys_eventfd) +{ + PRINT("sys_eventfd ( %u )", ARG1); + PRE_REG_READ1(long, "sys_eventfd", unsigned int, count); +} +POST(sys_eventfd) +{ + if (!ML_(fd_allowed)(RES, "eventfd", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless) (tid, RES); + } +} + /* --------------------------------------------------------------------- tid-related wrappers ------------------------------------------------------------------ */ @@ -1672,6 +1707,27 @@ PRE(sys_timer_delete) PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid); } +PRE(sys_timerfd) +{ + PRINT("sys_timerfd ( %d, %d, %p )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sys_timerfd", + int, fd, int, clockid, const struct itimerspec *, tmr); + PRE_MEM_READ( "timerfd(tmr)", ARG3, + sizeof(struct vki_itimerspec) ); + if (ARG1 != -1 && !ML_(fd_allowed)(ARG1, "timerfd", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); +} +POST(sys_timerfd) +{ + if (!ML_(fd_allowed)(RES, "timerfd", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless) (tid, RES); + } +} + /* --------------------------------------------------------------------- capabilities wrappers ------------------------------------------------------------------ */ @@ -2220,6 +2276,27 @@ POST(sys_sigprocmask) } #endif +PRE(sys_signalfd) +{ + PRINT("sys_signalfd ( %d, %p, %llu )", ARG1, ARG2, (ULong) ARG3); + PRE_REG_READ3(long, "sys_signalfd", + int, fd, vki_sigset_t *, sigmask, vki_size_t, sigsetsize); + PRE_MEM_READ( "signalfd(sigmask)", ARG2, sizeof(vki_sigset_t) ); + if (ARG1 != -1 && !ML_(fd_allowed)(ARG1, "signalfd", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); +} +POST(sys_signalfd) +{ + if (!ML_(fd_allowed)(RES, "signalfd", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless) (tid, RES); + } +} + + /* --------------------------------------------------------------------- rt_sig* wrappers ------------------------------------------------------------------ */ @@ -2542,7 +2619,17 @@ PRE(sys_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_MEM_READ( "futimesat(tvp)", ARG3, 2 * sizeof(struct vki_timeval) ); +} + +PRE(sys_utimensat) +{ + PRINT("sys_utimensat ( %d, %p(%s), %p, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "utimensat", + int, dfd, char *, filename, struct timespec *, utimes, int, flags); + PRE_MEM_RASCIIZ( "utimensat(filename)", ARG2 ); + if (ARG3 != 0) + PRE_MEM_READ( "utimensat(tvp)", ARG3, 2 * sizeof(struct vki_timespec) ); } PRE(sys_newfstatat) @@ -2823,19 +2910,6 @@ PRE(sys_ioprio_set) PRE_REG_READ3(int, "ioprio_set", int, which, int, who, int, ioprio); } - -/* XXX I don't think this is really the right place for this. - Move it elsewhere in this file? */ -PRE(sys_utimensat) -{ - PRINT("sys_utimensat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3); - PRE_REG_READ3(long, "utimensat", - int, dfd, char *, filename, struct timespec *, tvp); - PRE_MEM_RASCIIZ( "utimensat(filename)", ARG2 ); - if (ARG3 != 0) - PRE_MEM_READ( "utimensat(tvp)", ARG3, sizeof(struct vki_timespec) ); -} - #undef PRE #undef POST diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c index 2da51116c1..92e4d40356 100644 --- a/coregrind/m_syswrap/syswrap-ppc32-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c @@ -1823,6 +1823,15 @@ const SyscallTableEntry ML_(syscall_table)[] = { LINX_(__NR_faccessat, sys_faccessat), // 298 LINX_(__NR_set_robust_list, sys_set_robust_list), // 299 LINXY(__NR_get_robust_list, sys_get_robust_list), // 300 +// LINX_(__NR_move_pages, sys_ni_syscall), // 301 +// LINX_(__NR_getcpu, sys_ni_syscall), // 302 + LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 303 + LINX_(__NR_utimensat, sys_utimensat), // 304 + LINXY(__NR_signalfd, sys_signalfd), // 305 + LINXY(__NR_timerfd, sys_timerfd), // 306 + LINX_(__NR_eventfd, sys_eventfd), // 307 +// LINX_(__NR_sync_file_range2, sys_ni_syscall), // 308 +// LINX_(__NR_fallocate, sys_ni_syscall), // 309 }; const UInt ML_(syscall_table_size) = diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c index ebf975fba0..28934e48c6 100644 --- a/coregrind/m_syswrap/syswrap-ppc64-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c @@ -1478,7 +1478,15 @@ const SyscallTableEntry ML_(syscall_table)[] = { LINX_(__NR_faccessat, sys_faccessat), // 298 LINX_(__NR_set_robust_list, sys_set_robust_list), // 299 LINXY(__NR_get_robust_list, sys_get_robust_list), // 300 - +// LINX_(__NR_move_pages, sys_ni_syscall), // 301 +// LINX_(__NR_getcpu, sys_ni_syscall), // 302 + LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 303 + LINX_(__NR_utimensat, sys_utimensat), // 304 + LINXY(__NR_signalfd, sys_signalfd), // 305 + LINXY(__NR_timerfd, sys_timerfd), // 306 + LINX_(__NR_eventfd, sys_eventfd), // 307 +// LINX_(__NR_sync_file_range2, sys_ni_syscall), // 308 +// LINX_(__NR_fallocate, sys_ni_syscall), // 309 }; const UInt ML_(syscall_table_size) = diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 80193101ff..b96007cc28 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -2224,9 +2224,13 @@ const SyscallTableEntry ML_(syscall_table)[] = { // LINX_(__NR_vmsplice, sys_ni_syscall), // 316 // LINX_(__NR_move_pages, sys_ni_syscall), // 317 // LINX_(__NR_getcpu, sys_ni_syscall), // 318 -// LINX_(__NR_epoll_pwait, sys_ni_syscall), // 319 + LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 319 LINX_(__NR_utimensat, sys_utimensat), // 320 + LINXY(__NR_signalfd, sys_signalfd), // 321 + LINXY(__NR_timerfd, sys_timerfd), // 322 + LINX_(__NR_eventfd, sys_eventfd), // 323 +// LINX_(__NR_fallocate, sys_ni_syscall), // 324 }; const UInt ML_(syscall_table_size) = diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 8bc298b051..e75c2d38f6 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -65,6 +65,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ leak-tree.stderr.exp2 leak-tree.stderr.exp64 \ leak-regroot.vgtest leak-regroot.stderr.exp \ leakotron.vgtest leakotron.stdout.exp leakotron.stderr.exp \ + linux-syscalls-2007 linux-syscalls-2007.stderr.exp \ long_namespace_xml.vgtest long_namespace_xml.stdout.exp \ long_namespace_xml.stderr.exp \ lsframe1.vgtest lsframe1.stdout.exp lsframe1.stderr.exp \ @@ -170,6 +171,7 @@ check_PROGRAMS = \ doublefree error_counts errs1 exitprog execve execve2 erringfds \ fprw fwrite hello inits inline \ leak-0 leak-cycle leak-pool leak-tree leak-regroot leakotron \ + linux-syscalls-2007 \ long_namespace_xml \ lsframe1 lsframe2 \ mallinfo \ diff --git a/memcheck/tests/linux-syscalls-2007.c b/memcheck/tests/linux-syscalls-2007.c new file mode 100644 index 0000000000..0cbafa1df4 --- /dev/null +++ b/memcheck/tests/linux-syscalls-2007.c @@ -0,0 +1,75 @@ +/** + * Test program for some Linux syscalls introduced during 2006 and 2007: + * - epoll_pwait() was introduced in the 2.6.19 kernel, released in November + * 2006. + * - utimensat(), eventfd(), timerfd() and signalfd() were introduced in the + * 2.6.22 kernel, released in July 2007. + * + * See also http://bugs.kde.org/show_bug.cgi?id=160907. + */ + +#define _GNU_SOURCE + +#include "../../config.h" +#include +#include +#if defined(HAVE_SYS_EPOLL_H) +#include +#endif +#if defined(HAVE_SYS_EVENTFD_H) +#include +#endif +#if defined(HAVE_SYS_POLL_H) +#include +#endif +#if defined(HAVE_SYS_SIGNALFD_H) +#include +#endif +#include +#include + +int main (void) +{ +#if defined(HAVE_SIGNALFD) && defined(HAVE_EVENTFD) \ + && defined(HAVE_EVENTFD_READ) && defined(HAVE_PPOLL) + { + sigset_t mask; + sigemptyset (&mask); + sigaddset (&mask, SIGUSR1); + int fd = signalfd (-1, &mask, 0); + sigaddset (&mask, SIGUSR2); + fd = signalfd (fd, &mask, 0); + int fd2 = eventfd (5, 0); + eventfd_t ev; + eventfd_read (fd2, &ev); + struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 }; + struct pollfd pfd[2] = { [0].fd = fd, [0].events = POLLIN|POLLOUT, + [1].fd = fd2, [1].events = POLLIN|POLLOUT }; + ppoll (pfd, 2, &ts, &mask); + } +#endif + +#if defined(HAVE_UTIMENSAT) + unlink("/tmp/valgrind-utimensat-test"); + close (creat ("/tmp/valgrind-utimensat-test", S_IRUSR | S_IWUSR)); + { + struct timespec ts2[2] = { [0].tv_sec = 10000000, [1].tv_sec = 20000000 }; + utimensat (AT_FDCWD, "/tmp/valgrind-utimensat-test", ts2, 0); + } + unlink("/tmp/valgrind-utimensat-test"); +#endif + +#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_EPOLL_PWAIT) + { + int fd3 = epoll_create (10); + struct epoll_event evs[10]; + sigset_t mask; + sigemptyset (&mask); + sigaddset (&mask, SIGUSR1); + sigaddset (&mask, SIGUSR2); + epoll_pwait (fd3, evs, 10, 0, &mask); + } +#endif + + return 0; +} diff --git a/memcheck/tests/linux-syscalls-2007.stderr.exp b/memcheck/tests/linux-syscalls-2007.stderr.exp new file mode 100644 index 0000000000..c4aa6f04fe --- /dev/null +++ b/memcheck/tests/linux-syscalls-2007.stderr.exp @@ -0,0 +1,7 @@ + + +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +malloc/free: in use at exit: 0 bytes in 0 blocks. +malloc/free: 0 allocs, 0 frees, 0 bytes allocated. +For a detailed leak analysis, rerun with: --leak-check=yes +For counts of detected errors, rerun with: -v diff --git a/memcheck/tests/linux-syscalls-2007.vgtest b/memcheck/tests/linux-syscalls-2007.vgtest new file mode 100644 index 0000000000..55e548aec3 --- /dev/null +++ b/memcheck/tests/linux-syscalls-2007.vgtest @@ -0,0 +1 @@ +prog: linux-syscalls-2007