From: Tom Hughes Date: Sat, 14 Aug 2004 18:52:27 +0000 (+0000) Subject: Add support for the POSIX message queue system calls. X-Git-Tag: svn/VALGRIND_2_2_0~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=546afbe6960b7890f8d3b33d855152e982a41df9;p=thirdparty%2Fvalgrind.git Add support for the POSIX message queue system calls. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2585 --- diff --git a/configure.in b/configure.in index b77a869c66..6d65c2ecdd 100644 --- a/configure.in +++ b/configure.in @@ -331,7 +331,7 @@ AC_SUBST(PREFERRED_STACK_BOUNDARY) # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/statfs.h sys/time.h sys/endian.h endian.h termios.h unistd.h utime.h linux/fb.h linux/mii.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/statfs.h sys/time.h sys/endian.h endian.h termios.h unistd.h utime.h linux/fb.h linux/mii.h mqueue.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c index 687c10b8f4..15246e3b74 100644 --- a/coregrind/vg_syscalls.c +++ b/coregrind/vg_syscalls.c @@ -5548,6 +5548,118 @@ POST(io_cancel) VG_TRACK( post_mem_write, arg3, sizeof(vki_io_event) ); } +PRE(mq_open) +{ + /* mqd_t mq_open(const char *name, int oflag, ...); */ + MAYBE_PRINTF("mq_open( %p(%s), %d )\n", arg1,arg1,arg2); + SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mq_open(name)", arg1 ); + if ((arg2 & VKI_O_CREAT) != 0 && arg4 != 0) { + const struct vki_mq_attr *attr = (struct vki_mq_attr *)arg4; + SYSCALL_TRACK( pre_mem_read, tid, "mq_open(attr->mq_maxmsg)", + (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) ); + SYSCALL_TRACK( pre_mem_read, tid, "mq_open(attr->mq_msgsize)", + (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) ); + } +} + +POST(mq_open) +{ + if (!fd_allowed(res, "mq_open", tid, True)) { + VG_(close)(res); + res = -VKI_EMFILE; + } else { + if (VG_(clo_track_fds)) + record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1)); + } + MAYBE_PRINTF("%d\n",res); +} + +PRE(mq_unlink) +{ + /* int mq_unlink(const char *name) */ + MAYBE_PRINTF("mq_unlink ( %p \"%s\" )\n",arg1, arg1); + SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mq_unlink(name)", arg1 ); +} + +PRE(mq_timedsend) +{ + /* int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned msg_prio, const struct timespec *abs_timeout); */ + MAYBE_PRINTF("mq_timedsend ( %d, %p, %d, %d, %p )\n", + arg1,arg2,arg3,arg4,arg5); + if (!fd_allowed(arg1, "mq_timedsend", tid, False)) { + res = -VKI_EBADF; + } else { + SYSCALL_TRACK( pre_mem_read, tid, "mq_timedsend(msg_ptr)", arg2, arg3 ); + if (arg5 != 0) + SYSCALL_TRACK( pre_mem_read, tid, "mq_timedsend(abs_timeout)", arg5, + sizeof(struct timespec) ); + } +} + +PRE(mq_timedreceive) +{ + /* ssize_t mq_timedreceive(mqd_t mqdes, char *restrict msg_ptr, + size_t msg_len, unsigned *restrict msg_prio, + const struct timespec *restrict abs_timeout); */ + MAYBE_PRINTF("mq_timedreceive( %d, %p, %d, %p, %p )\n", + arg1,arg2,arg3,arg4,arg5); + if (!fd_allowed(arg1, "mq_timedreceive", tid, False)) { + res = -VKI_EBADF; + } else { + SYSCALL_TRACK( pre_mem_write, tid, "mq_timedreceive(msg_ptr)", arg2, arg3 ); + if (arg4 != 0) + SYSCALL_TRACK( pre_mem_write, tid, "mq_timedreceive(msg_prio)", + arg4, sizeof(unsigned int) ); + if (arg5 != 0) + SYSCALL_TRACK( pre_mem_read, tid, "mq_timedreceive(abs_timeout)", + arg5, sizeof(struct timespec) ); + } +} + +POST(mq_timedreceive) +{ + VG_TRACK( post_mem_write, arg2, arg3 ); + if (arg4 != 0) + VG_TRACK( post_mem_write, arg4, sizeof(unsigned int) ); +} + +PRE(mq_notify) +{ + /* int mq_notify(mqd_t mqdes, const struct sigevent *notification); */ + MAYBE_PRINTF("mq_notify( %d, %p )\n", arg1,arg2 ); + if (!fd_allowed(arg1, "mq_notify", tid, False)) + res = -VKI_EBADF; + else if (arg2 != 0) + SYSCALL_TRACK( pre_mem_read, tid, "mq_notify", arg2, + sizeof(struct sigevent) ); +} + +PRE(mq_getsetattr) +{ + /* int mq_getsetattr(mqd_t mqdes, const struct mq_attr *restrict mqstat, + struct mq_attr *restrict omqstat); */ + MAYBE_PRINTF("mq_getsetattr( %d, %p, %p )\n", arg1,arg2,arg3 ); + if (!fd_allowed(arg1, "mq_getsetattr", tid, False)) { + res = -VKI_EBADF; + } else { + if (arg2 != 0) { + const struct vki_mq_attr *attr = (struct vki_mq_attr *)arg2; + SYSCALL_TRACK( pre_mem_read, tid, "mq_getsetattr(mqstat->mq_flags)", + (Addr)&attr->mq_flags, sizeof(attr->mq_flags) ); + } + if (arg3 != 0) + SYSCALL_TRACK( pre_mem_write, tid, "mq_getsetattr(omqstat)", arg3, + sizeof(struct vki_mq_attr) ); + } +} + +POST(mq_getsetattr) +{ + if (arg3 != 0) + VG_TRACK( post_mem_write, arg3, sizeof(struct vki_mq_attr) ); +} + #undef SYSNO #undef res #undef arg1 @@ -5822,6 +5934,13 @@ static const struct sys_info sys_info[] = { SYSB_(io_submit, 0), SYSBA(io_cancel, 0), + SYSBA(mq_open, 0), + SYSB_(mq_unlink, 0), + SYSB_(mq_timedsend, MayBlock), + SYSBA(mq_timedreceive, MayBlock), + SYSB_(mq_notify, 0), + SYSBA(mq_getsetattr, 0), + #if !SIGNAL_SIMULATION SYSBA(sigaltstack, 0), SYSBA(rt_sigaction, 0), diff --git a/include/vg_kerneliface.h b/include/vg_kerneliface.h index c4b02202ee..6038623294 100644 --- a/include/vg_kerneliface.h +++ b/include/vg_kerneliface.h @@ -953,6 +953,17 @@ enum { VKI_IOCB_CMD_NOOP = 6, }; +/* + * linux/mqueue.h + */ + +struct vki_mq_attr { + long mq_flags; /* message queue flags */ + long mq_maxmsg; /* maximum number of messages */ + long mq_msgsize; /* maximum message size */ + long mq_curmsgs; /* number of messages currently queued */ + long __reserved[4]; /* ignored for input, zeroed for output */ +}; #endif /* __VG_KERNELIFACE_H */ diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am index 6dc2564e74..6ddfca3c88 100644 --- a/none/tests/Makefile.am +++ b/none/tests/Makefile.am @@ -41,6 +41,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ $(addsuffix .vgtest,$(INSN_TESTS)) \ int.stderr.exp int.stdout.exp int.vgtest \ map_unmap.stderr.exp map_unmap.stdout.exp map_unmap.vgtest \ + mq.stderr.exp mq.vgtest \ mremap.stderr.exp mremap.stdout.exp mremap.vgtest \ munmap_exe.stderr.exp munmap_exe.vgtest \ pth_blockedsig.stderr.exp \ @@ -71,7 +72,7 @@ check_PROGRAMS = \ args badseg bitfield1 bt_everything bt_literal closeall coolo_strlen \ cpuid dastest discard exec-sigmask execve fcntl_setown floored fork \ fpu_lazy_eflags fucomip $(INSN_TESTS) \ - int munmap_exe map_unmap mremap rcl_assert rcrl readline1 \ + int munmap_exe map_unmap mq mremap rcl_assert rcrl readline1 \ resolv rlimit_nofile seg_override sem semlimit sha1_test \ shortpush shorts smc1 susphello pth_blockedsig pushpopseg \ syscall-restart1 syscall-restart2 system \ @@ -115,6 +116,8 @@ insn_sse2_SOURCES = insn_sse2.def insn_sse2_LDADD = -lm int_SOURCES = int.c map_unmap_SOURCES = map_unmap.c +mq_SOURCES = mq.c +mq_LDADD = -lrt mremap_SOURCES = mremap.c munmap_exe_SOURCES = munmap_exe.c pushpopseg_SOURCES = pushpopseg.c diff --git a/none/tests/mq.c b/none/tests/mq.c new file mode 100644 index 0000000000..2e7cf209b8 --- /dev/null +++ b/none/tests/mq.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include + +#ifdef HAVE_MQUEUE_H + +#include + +#define MSGMAX 10 +#define MSGSIZEMAX 1024 + +int main(int argc, char **argv) +{ + struct mq_attr mqa; + mqd_t mqdw; + mqd_t mqdr; + char buffer[MSGSIZEMAX]; + unsigned int priority; + int len; + + mqa.mq_maxmsg = MSGMAX; + mqa.mq_msgsize = MSGSIZEMAX; + + if ((mqdw = mq_open("/valgrind-mqueue", O_CREAT|O_EXCL|O_WRONLY, 0600, &mqa)) < 0) + { + perror("mq_open"); + exit(1); + } + + if ((mqdr = mq_open("/valgrind-mqueue", O_RDONLY)) < 0) + { + perror("mq_open"); + mq_unlink("/valgrind-mqueue"); + mq_close(mqdw); + exit(1); + } + + if (mq_unlink("/valgrind-mqueue") < 0) + { + perror("mq_unlink"); + mq_close(mqdw); + mq_close(mqdr); + exit(1); + } + + if (mq_send(mqdw, "PING", 4, 0) < 0) + { + perror("mq_send"); + mq_close(mqdr); + mq_close(mqdw); + exit(1); + } + + if ((len = mq_receive(mqdr, buffer, sizeof(buffer), &priority)) < 0) + { + perror("mq_receive"); + mq_close(mqdr); + mq_close(mqdw); + exit(1); + } + + if (len != 4 || memcmp(buffer, "PING", 4) != 0) + { + fprintf(stderr, "Message corrupt!"); + } + + if (mq_notify(mqdr, NULL) < 0) + { + perror("mq_notify"); + mq_close(mqdr); + mq_close(mqdw); + exit(1); + } + + if (mq_getattr(mqdr, &mqa) < 0) + { + perror("mq_getattr"); + mq_close(mqdr); + mq_close(mqdw); + exit(1); + } + + if (mq_setattr(mqdw, &mqa, &mqa) < 0) + { + perror("mq_getattr"); + mq_close(mqdr); + mq_close(mqdw); + exit(1); + } + + if (mq_close(mqdr) < 0) + { + perror("mq_close"); + mq_close(mqdw); + exit(1); + } + + if (mq_close(mqdw) < 0) + { + perror("mq_close"); + exit(1); + } + + exit(0); +} + +#else + +int main(int argc, char **argv) +{ + exit(0); +} + +#endif diff --git a/none/tests/mq.stderr.exp b/none/tests/mq.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/mq.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/mq.vgtest b/none/tests/mq.vgtest new file mode 100644 index 0000000000..8a5fe3fc3e --- /dev/null +++ b/none/tests/mq.vgtest @@ -0,0 +1 @@ +prog: mq