Add support for the sendmmsg and recvmmsg system calls. Fixes BZ#277779.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12376
This commit is contained in:
Tom Hughes 2012-02-10 11:30:09 +00:00
parent dc42e147f5
commit baec53c5f1
12 changed files with 131 additions and 66 deletions

View File

@ -235,9 +235,9 @@ extern void ML_(generic_PRE_sys_getsockname) ( TId, UW, UW, UW );
extern void ML_(generic_POST_sys_getsockname) ( TId, SR, UW, UW, UW );
extern void ML_(generic_PRE_sys_getpeername) ( TId, UW, UW, UW );
extern void ML_(generic_POST_sys_getpeername) ( TId, SR, UW, UW, UW );
extern void ML_(generic_PRE_sys_sendmsg) ( TId, UW, UW );
extern void ML_(generic_PRE_sys_recvmsg) ( TId, UW, UW );
extern void ML_(generic_POST_sys_recvmsg) ( TId, UW, UW );
extern void ML_(generic_PRE_sys_sendmsg) ( TId, Char *, struct vki_msghdr * );
extern void ML_(generic_PRE_sys_recvmsg) ( TId, Char *, struct vki_msghdr * );
extern void ML_(generic_POST_sys_recvmsg) ( TId, Char *, struct vki_msghdr * );
extern void ML_(generic_PRE_sys_semop) ( TId, UW, UW, UW );
extern void ML_(generic_PRE_sys_semtimedop) ( TId, UW, UW, UW, UW );

View File

@ -50,6 +50,8 @@ DECL_TEMPLATE(linux, sys_umount);
DECL_TEMPLATE(linux, sys_perf_event_open);
DECL_TEMPLATE(linux, sys_preadv);
DECL_TEMPLATE(linux, sys_pwritev);
DECL_TEMPLATE(linux, sys_sendmmsg);
DECL_TEMPLATE(linux, sys_recvmmsg);
DECL_TEMPLATE(linux, sys_dup3);
DECL_TEMPLATE(linux, sys_getcpu);
DECL_TEMPLATE(linux, sys_splice);

View File

@ -747,7 +747,7 @@ PRE(sys_sendmsg)
PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
PRE_REG_READ3(long, "sendmsg",
int, s, const struct msghdr *, msg, int, flags);
ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
PRE(sys_recvmsg)
@ -755,11 +755,11 @@ PRE(sys_recvmsg)
*flags |= SfMayBlock;
PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
POST(sys_recvmsg)
{
ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
PRE(sys_shutdown)
@ -1411,7 +1411,7 @@ static SyscallTableEntry syscall_table[] = {
LINX_(__NR_pwritev, sys_pwritev), // 296
LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 297
LINXY(__NR_perf_event_open, sys_perf_event_open), // 298
// LINX_(__NR_recvmmsg, sys_ni_syscall), // 299
LINXY(__NR_recvmmsg, sys_recvmmsg), // 299
// LINX_(__NR_fanotify_init, sys_ni_syscall), // 300
// LINX_(__NR_fanotify_mark, sys_ni_syscall), // 301
@ -1421,7 +1421,7 @@ static SyscallTableEntry syscall_table[] = {
// LINX_(__NR_clock_adjtime, sys_ni_syscall), // 305
// LINX_(__NR_syncfs, sys_ni_syscall), // 306
// LINX_(__NR_sendmmsg, sys_ni_syscall), // 307
LINX_(__NR_sendmmsg, sys_sendmmsg), // 307
// LINX_(__NR_setns, sys_ni_syscall), // 308
LINXY(__NR_getcpu, sys_getcpu), // 309

View File

@ -472,7 +472,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_sendmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -483,7 +483,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -587,7 +587,7 @@ POST(sys_socketcall)
break;
case VKI_SYS_RECVMSG:
ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_POST_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
default:
@ -699,7 +699,7 @@ PRE(sys_sendmsg)
PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
PRE_REG_READ3(long, "sendmsg",
int, s, const struct msghdr *, msg, int, flags);
ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
PRE(sys_recvmsg)
@ -707,11 +707,11 @@ PRE(sys_recvmsg)
*flags |= SfMayBlock;
PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
POST(sys_recvmsg)
{
ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
//XXX: Semaphore code ripped from AMD64.

View File

@ -3107,7 +3107,7 @@ PRE(sendmsg)
PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
PRE_REG_READ3(long, "sendmsg",
int, s, const struct msghdr *, msg, int, flags);
ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
@ -3116,12 +3116,12 @@ PRE(recvmsg)
*flags |= SfMayBlock;
PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}
POST(recvmsg)
{
ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
}

View File

@ -816,7 +816,7 @@ void pre_mem_read_sendmsg ( ThreadId tid, Bool read,
Char *msg, Addr base, SizeT size )
{
Char *outmsg = strdupcat ( "di.syswrap.pmrs.1",
"socketcall.sendmsg", msg, VG_AR_CORE );
"sendmsg", msg, VG_AR_CORE );
PRE_MEM_READ( outmsg, base, size );
VG_(arena_free) ( VG_AR_CORE, outmsg );
}
@ -826,7 +826,7 @@ void pre_mem_write_recvmsg ( ThreadId tid, Bool read,
Char *msg, Addr base, SizeT size )
{
Char *outmsg = strdupcat ( "di.syswrap.pmwr.1",
"socketcall.recvmsg", msg, VG_AR_CORE );
"recvmsg", msg, VG_AR_CORE );
if ( read )
PRE_MEM_READ( outmsg, base, size );
else
@ -844,45 +844,60 @@ void post_mem_write_recvmsg ( ThreadId tid, Bool read,
static
void msghdr_foreachfield (
ThreadId tid,
ThreadId tid,
Char *name,
struct vki_msghdr *msg,
void (*foreach_func)( ThreadId, Bool, Char *, Addr, SizeT )
)
{
Char *fieldName;
if ( !msg )
return;
foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
foreach_func ( tid, False, "(msg)", (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
fieldName = VG_(arena_malloc) ( VG_AR_CORE, "di.syswrap.mfef", VG_(strlen)(name) + 32 );
if ( msg->msg_name )
foreach_func ( tid, False,
"(msg.msg_name)",
VG_(sprintf) ( fieldName, "(%s)", name );
foreach_func ( tid, True, fieldName, (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
foreach_func ( tid, True, fieldName, (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
foreach_func ( tid, True, fieldName, (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
foreach_func ( tid, True, fieldName, (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
foreach_func ( tid, True, fieldName, (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
foreach_func ( tid, True, fieldName, (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
foreach_func ( tid, False, fieldName, (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
if ( msg->msg_name ) {
VG_(sprintf) ( fieldName, "(%s.msg_name)", name );
foreach_func ( tid, False, fieldName,
(Addr)msg->msg_name, msg->msg_namelen );
}
if ( msg->msg_iov ) {
struct vki_iovec *iov = msg->msg_iov;
UInt i;
foreach_func ( tid, True,
"(msg.msg_iov)",
VG_(sprintf) ( fieldName, "(%s.msg_iov)", name );
foreach_func ( tid, True, fieldName,
(Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) );
for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
foreach_func ( tid, False,
"(msg.msg_iov[i])",
for ( i = 0; i < msg->msg_iovlen; ++i, ++iov ) {
VG_(sprintf) ( fieldName, "(%s.msg_iov[%u])", name, i );
foreach_func ( tid, False, fieldName,
(Addr)iov->iov_base, iov->iov_len );
}
}
if ( msg->msg_control )
foreach_func ( tid, False,
"(msg.msg_control)",
if ( msg->msg_control )
{
VG_(sprintf) ( fieldName, "(%s.msg_control)", name );
foreach_func ( tid, False, fieldName,
(Addr)msg->msg_control, msg->msg_controllen );
}
VG_(arena_free) ( VG_AR_CORE, fieldName );
}
static void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
@ -1490,31 +1505,23 @@ ML_(generic_POST_sys_getpeername) ( ThreadId tid,
/* ------ */
void
ML_(generic_PRE_sys_sendmsg) ( ThreadId tid,
UWord arg0, UWord arg1 )
ML_(generic_PRE_sys_sendmsg) ( ThreadId tid, Char *name, struct vki_msghdr *msg )
{
/* int sendmsg(int s, const struct msghdr *msg, int flags); */
struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
msghdr_foreachfield ( tid, name, msg, pre_mem_read_sendmsg );
}
/* ------ */
void
ML_(generic_PRE_sys_recvmsg) ( ThreadId tid,
UWord arg0, UWord arg1 )
ML_(generic_PRE_sys_recvmsg) ( ThreadId tid, Char *name, struct vki_msghdr *msg )
{
/* int recvmsg(int s, struct msghdr *msg, int flags); */
struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
msghdr_foreachfield ( tid, name, msg, pre_mem_write_recvmsg );
}
void
ML_(generic_POST_sys_recvmsg) ( ThreadId tid,
UWord arg0, UWord arg1 )
ML_(generic_POST_sys_recvmsg) ( ThreadId tid, Char *name, struct vki_msghdr *msg )
{
struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
msghdr_foreachfield( tid, name, msg, post_mem_write_recvmsg );
check_cmsg_for_fds( tid, msg );
}

View File

@ -3538,6 +3538,57 @@ PRE(sys_process_vm_writev)
}
}
/* ---------------------------------------------------------------------
{send,recv}mmsg wrappers
------------------------------------------------------------------ */
PRE(sys_sendmmsg)
{
struct vki_mmsghdr *mmsg = (struct vki_mmsghdr *)ARG2;
Char name[32];
UInt i;
*flags |= SfMayBlock;
PRINT("sys_sendmmsg ( %ld, %#lx, %ld, %ld )",ARG1,ARG2,ARG3,ARG4);
PRE_REG_READ4(long, "sendmmsg",
int, s, const struct mmsghdr *, mmsg, int, vlen, int, flags);
for (i = 0; i < ARG3; i++) {
VG_(sprintf)(name, "mmsg[%u]", i);
ML_(generic_PRE_sys_sendmsg)(tid, name, &mmsg[i].msg_hdr);
}
}
PRE(sys_recvmmsg)
{
struct vki_mmsghdr *mmsg = (struct vki_mmsghdr *)ARG2;
Char name[32];
UInt i;
*flags |= SfMayBlock;
PRINT("sys_recvmmsg ( %ld, %#lx, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
PRE_REG_READ5(long, "recvmmsg",
int, s, struct mmsghdr *, mmsg, int, vlen,
int, flags, struct timespec *, timeout);
for (i = 0; i < ARG3; i++) {
VG_(sprintf)(name, "mmsg[%u]", i);
ML_(generic_PRE_sys_recvmsg)(tid, name, &mmsg[i].msg_hdr);
}
if (ARG5)
PRE_MEM_READ( "recvmmsg(timeout)", ARG5, sizeof(struct vki_timespec) );
}
POST(sys_recvmmsg)
{
if (RES > 0) {
struct vki_mmsghdr *mmsg = (struct vki_mmsghdr *)ARG2;
Char name[32];
UInt i;
for (i = 0; i < RES; i++) {
VG_(sprintf)(name, "mmsg[%u]", i);
ML_(generic_POST_sys_recvmsg)(tid, name, &mmsg[i].msg_hdr);
POST_MEM_WRITE( (Addr)&mmsg[i].msg_len, sizeof(mmsg[i].msg_len) );
}
}
}
/* ---------------------------------------------------------------------
key retention service wrappers
------------------------------------------------------------------ */

View File

@ -556,7 +556,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_sendmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -567,7 +567,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -672,7 +672,7 @@ POST(sys_socketcall)
break;
case VKI_SYS_RECVMSG:
ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_POST_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
default:

View File

@ -583,7 +583,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_sendmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -594,7 +594,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -700,7 +700,7 @@ POST(sys_socketcall)
break;
case VKI_SYS_RECVMSG:
ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_POST_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
default:

View File

@ -625,7 +625,7 @@ PRE(sys_socketcall)
SET_STATUS_Failure( VKI_EFAULT );
break;
}
ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_sendmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -636,7 +636,7 @@ PRE(sys_socketcall)
SET_STATUS_Failure( VKI_EFAULT );
break;
}
ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_recvmsg)( tid, "msg2", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -740,7 +740,7 @@ POST(sys_socketcall)
break;
case VKI_SYS_RECVMSG:
ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_POST_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
default:

View File

@ -1576,7 +1576,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_sendmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -1587,7 +1587,7 @@ PRE(sys_socketcall)
* (after all it's glibc providing the arguments array)
PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
*/
ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_PRE_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
}
@ -1693,7 +1693,7 @@ POST(sys_socketcall)
break;
case VKI_SYS_RECVMSG:
ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
ML_(generic_POST_sys_recvmsg)( tid, "msg", (struct vki_msghdr *)ARG2_1 );
break;
default:
@ -2219,7 +2219,7 @@ static SyscallTableEntry syscall_table[] = {
LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 335
LINXY(__NR_perf_event_open, sys_perf_event_open), // 336
// LINX_(__NR_recvmmsg, sys_ni_syscall), // 337
LINXY(__NR_recvmmsg, sys_recvmmsg), // 337
// LINX_(__NR_fanotify_init, sys_ni_syscall), // 338
// LINX_(__NR_fanotify_mark, sys_ni_syscall), // 339
@ -2229,7 +2229,7 @@ static SyscallTableEntry syscall_table[] = {
// LINX_(__NR_clock_adjtime, sys_ni_syscall), // 343
// LINX_(__NR_syncfs, sys_ni_syscall), // 344
// LINX_(__NR_sendmmsg, sys_ni_syscall), // 345
LINX_(__NR_sendmmsg, sys_sendmmsg), // 345
// LINX_(__NR_setns, sys_ni_syscall), // 346
LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 347
LINX_(__NR_process_vm_writev, sys_process_vm_writev) // 348

View File

@ -605,6 +605,11 @@ struct vki_msghdr {
unsigned msg_flags;
};
struct vki_mmsghdr {
struct vki_msghdr msg_hdr;
unsigned msg_len;
};
struct vki_cmsghdr {
__vki_kernel_size_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */