Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1993 Ulrich Pegelow <pegelow (at) moorea.uni-muenster.de>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  *
     30  *	$Id: ipc.c,v 1.10 2005/06/01 19:02:37 roland Exp $
     31  */
     32 
     33 #include "defs.h"
     34 
     35 #if defined(LINUX) || defined(SUNOS4) || defined(FREEBSD)
     36 
     37 # ifdef HAVE_MQUEUE_H
     38 #  include <mqueue.h>
     39 # endif
     40 
     41 #include <fcntl.h>
     42 #include <sys/ipc.h>
     43 #include <sys/sem.h>
     44 #include <sys/msg.h>
     45 #include <sys/shm.h>
     46 
     47 #ifndef MSG_STAT
     48 #define MSG_STAT 11
     49 #endif
     50 #ifndef MSG_INFO
     51 #define MSG_INFO 12
     52 #endif
     53 #ifndef SHM_STAT
     54 #define SHM_STAT 13
     55 #endif
     56 #ifndef SHM_INFO
     57 #define SHM_INFO 14
     58 #endif
     59 #ifndef SEM_STAT
     60 #define SEM_STAT 18
     61 #endif
     62 #ifndef SEM_INFO
     63 #define SEM_INFO 19
     64 #endif
     65 
     66 #if defined LINUX && !defined IPC_64
     67 # define IPC_64 0x100
     68 #endif
     69 
     70 extern const struct xlat openmodes[];
     71 extern void printsigevent(struct tcb *tcp, long arg);
     72 
     73 static const struct xlat msgctl_flags[] = {
     74 	{ IPC_RMID,	"IPC_RMID"	},
     75 	{ IPC_SET,	"IPC_SET"	},
     76 	{ IPC_STAT,	"IPC_STAT"	},
     77 #ifdef LINUX
     78 	{ IPC_INFO,	"IPC_INFO"	},
     79 	{ MSG_STAT,	"MSG_STAT"	},
     80 	{ MSG_INFO,	"MSG_INFO"	},
     81 #endif /* LINUX */
     82 	{ 0,		NULL		},
     83 };
     84 
     85 static const struct xlat semctl_flags[] = {
     86 	{ IPC_RMID,	"IPC_RMID"	},
     87 	{ IPC_SET,	"IPC_SET"	},
     88 	{ IPC_STAT,	"IPC_STAT"	},
     89 #ifdef LINUX
     90 	{ IPC_INFO,	"IPC_INFO"	},
     91 	{ SEM_STAT,	"SEM_STAT"	},
     92 	{ SEM_INFO,	"SEM_INFO"	},
     93 #endif /* LINUX */
     94 	{ GETPID,	"GETPID"	},
     95 	{ GETVAL,	"GETVAL"	},
     96 	{ GETALL,	"GETALL"	},
     97 	{ GETNCNT,	"GETNCNT"	},
     98 	{ GETZCNT,	"GETZCNT"	},
     99 	{ SETVAL,	"SETVAL"	},
    100 	{ SETALL,	"SETALL"	},
    101 	{ 0,		NULL		},
    102 };
    103 
    104 static const struct xlat shmctl_flags[] = {
    105 	{ IPC_RMID,	"IPC_RMID"	},
    106 	{ IPC_SET,	"IPC_SET"	},
    107 	{ IPC_STAT,	"IPC_STAT"	},
    108 #ifdef LINUX
    109 	{ IPC_INFO,	"IPC_INFO"	},
    110 	{ SHM_STAT,	"SHM_STAT"	},
    111 	{ SHM_INFO,	"SHM_INFO"	},
    112 #endif /* LINUX */
    113 #ifdef SHM_LOCK
    114 	{ SHM_LOCK,	"SHM_LOCK"	},
    115 #endif
    116 #ifdef SHM_UNLOCK
    117 	{ SHM_UNLOCK,	"SHM_UNLOCK"	},
    118 #endif
    119 	{ 0,		NULL		},
    120 };
    121 
    122 static const struct xlat resource_flags[] = {
    123 	{ IPC_CREAT,	"IPC_CREAT"	},
    124 	{ IPC_EXCL,	"IPC_EXCL"	},
    125 	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
    126 	{ 0,		NULL		},
    127 };
    128 
    129 static const struct xlat shm_resource_flags[] = {
    130 	{ IPC_CREAT,	"IPC_CREAT"	},
    131 	{ IPC_EXCL,	"IPC_EXCL"	},
    132 #ifdef SHM_HUGETLB
    133 	{ SHM_HUGETLB,	"SHM_HUGETLB"	},
    134 #endif
    135 	{ 0,		NULL		},
    136 };
    137 
    138 static const struct xlat shm_flags[] = {
    139 #ifdef LINUX
    140 	{ SHM_REMAP,	"SHM_REMAP"	},
    141 #endif /* LINUX */
    142 	{ SHM_RDONLY,	"SHM_RDONLY"	},
    143 	{ SHM_RND,	"SHM_RND"	},
    144 	{ 0,		NULL		},
    145 };
    146 
    147 static const struct xlat msg_flags[] = {
    148 	{ MSG_NOERROR,	"MSG_NOERROR"	},
    149 #ifdef LINUX
    150 	{ MSG_EXCEPT,	"MSG_EXCEPT"	},
    151 #endif /* LINUX */
    152 	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
    153 	{ 0,		NULL		},
    154 };
    155 
    156 int sys_msgget(tcp)
    157 struct tcb *tcp;
    158 {
    159 	if (entering(tcp)) {
    160 		if (tcp->u_arg[0])
    161 			tprintf("%lu", tcp->u_arg[0]);
    162 		else
    163 			tprintf("IPC_PRIVATE");
    164 		tprintf(", ");
    165 		if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
    166 			tprintf("|");
    167 		tprintf("%#lo", tcp->u_arg[1] & 0777);
    168 	}
    169 	return 0;
    170 }
    171 
    172 #ifdef IPC_64
    173 # define PRINTCTL(flagset, arg, dflt) \
    174 	if ((arg) & IPC_64) tprintf("IPC_64|"); \
    175 	printxval((flagset), (arg) &~ IPC_64, dflt)
    176 #else
    177 # define PRINTCTL printxval
    178 #endif
    179 
    180 int sys_msgctl(tcp)
    181 struct tcb *tcp;
    182 {
    183 	if (entering(tcp)) {
    184 		tprintf("%lu, ", tcp->u_arg[0]);
    185 		PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
    186 #ifdef LINUX
    187 		tprintf(", %#lx", tcp->u_arg[3]);
    188 #else /* !LINUX */
    189 		tprintf(", %#lx", tcp->u_arg[2]);
    190 #endif /* !LINUX */
    191 	}
    192 	return 0;
    193 }
    194 
    195 int sys_msgsnd(tcp)
    196 struct tcb *tcp;
    197 {
    198 	long mtype;
    199 
    200 	if (entering(tcp)) {
    201 		tprintf("%lu", tcp->u_arg[0]);
    202 #ifdef LINUX
    203 		umove(tcp, tcp->u_arg[3], &mtype);
    204 		tprintf(", {%lu, ", mtype);
    205 		printstr(tcp, tcp->u_arg[3] + sizeof(long),
    206 			tcp->u_arg[1]);
    207 		tprintf("}, %lu", tcp->u_arg[1]);
    208 		tprintf(", ");
    209 		printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    210 #else /* !LINUX */
    211 		umove(tcp, tcp->u_arg[1], &mtype);
    212 		tprintf(", {%lu, ", mtype);
    213 		printstr(tcp, tcp->u_arg[1] + sizeof(long),
    214 			tcp->u_arg[2]);
    215 		tprintf("}, %lu", tcp->u_arg[2]);
    216 		tprintf(", ");
    217 		printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    218 #endif /* !LINUX */
    219 	}
    220 	return 0;
    221 }
    222 
    223 int sys_msgrcv(tcp)
    224 struct tcb *tcp;
    225 {
    226 	long mtype;
    227 #ifdef LINUX
    228 	struct ipc_wrapper {
    229 		struct msgbuf *msgp;
    230 		long msgtyp;
    231 	} tmp;
    232 #endif
    233 
    234 
    235 	if (exiting(tcp)) {
    236 		tprintf("%lu", tcp->u_arg[0]);
    237 #ifdef LINUX
    238 		umove(tcp, tcp->u_arg[3], &tmp);
    239 		umove(tcp, (long) tmp.msgp, &mtype);
    240 		tprintf(", {%lu, ", mtype);
    241 		printstr(tcp, (long) (tmp.msgp) + sizeof(long),
    242 			tcp->u_arg[1]);
    243 		tprintf("}, %lu", tcp->u_arg[1]);
    244 		tprintf(", %ld", tmp.msgtyp);
    245 		tprintf(", ");
    246 		printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    247 #else /* !LINUX */
    248 		umove(tcp, tcp->u_arg[1], &mtype);
    249 		tprintf(", {%lu, ", mtype);
    250 		printstr(tcp, tcp->u_arg[1] + sizeof(long),
    251 			tcp->u_arg[2]);
    252 		tprintf("}, %lu", tcp->u_arg[2]);
    253 		tprintf(", %ld", tcp->u_arg[3]);
    254 		tprintf(", ");
    255 		printflags(msg_flags, tcp->u_arg[4], "MSG_???");
    256 #endif /* !LINUX */
    257 	}
    258 	return 0;
    259 }
    260 
    261 int sys_semop(tcp)
    262 struct tcb *tcp;
    263 {
    264 	if (entering(tcp)) {
    265 		tprintf("%lu", tcp->u_arg[0]);
    266 #ifdef LINUX
    267 		tprintf(", %#lx", tcp->u_arg[3]);
    268 		tprintf(", %lu", tcp->u_arg[1]);
    269 #else /* !LINUX */
    270 		tprintf(", %#lx", tcp->u_arg[1]);
    271 		tprintf(", %lu", tcp->u_arg[2]);
    272 #endif /* !LINUX */
    273 	}
    274 	return 0;
    275 }
    276 
    277 #ifdef LINUX
    278 int sys_semtimedop(tcp)
    279 struct tcb *tcp;
    280 {
    281 	if (entering(tcp)) {
    282 		tprintf("%lu", tcp->u_arg[0]);
    283 		tprintf(", %#lx", tcp->u_arg[3]);
    284 		tprintf(", %lu, ", tcp->u_arg[1]);
    285 		printtv(tcp, tcp->u_arg[5]);
    286 	}
    287 	return 0;
    288 }
    289 #endif
    290 
    291 int sys_semget(tcp)
    292 struct tcb *tcp;
    293 {
    294 	if (entering(tcp)) {
    295 		if (tcp->u_arg[0])
    296 			tprintf("%lu", tcp->u_arg[0]);
    297 		else
    298 			tprintf("IPC_PRIVATE");
    299 		tprintf(", %lu", tcp->u_arg[1]);
    300 		tprintf(", ");
    301 		if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    302 			tprintf("|");
    303 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    304 	}
    305 	return 0;
    306 }
    307 
    308 int sys_semctl(tcp)
    309 struct tcb *tcp;
    310 {
    311 	if (entering(tcp)) {
    312 		tprintf("%lu", tcp->u_arg[0]);
    313 		tprintf(", %lu, ", tcp->u_arg[1]);
    314 		PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
    315 		tprintf(", %#lx", tcp->u_arg[3]);
    316 	}
    317 	return 0;
    318 }
    319 
    320 int sys_shmget(tcp)
    321 struct tcb *tcp;
    322 {
    323 	if (entering(tcp)) {
    324 		if (tcp->u_arg[0])
    325 			tprintf("%lu", tcp->u_arg[0]);
    326 		else
    327 			tprintf("IPC_PRIVATE");
    328 		tprintf(", %lu", tcp->u_arg[1]);
    329 		tprintf(", ");
    330 		if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    331 			tprintf("|");
    332 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    333 	}
    334 	return 0;
    335 }
    336 
    337 int sys_shmctl(tcp)
    338 struct tcb *tcp;
    339 {
    340 	if (entering(tcp)) {
    341 		tprintf("%lu, ", tcp->u_arg[0]);
    342 		PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
    343 #ifdef LINUX
    344 		tprintf(", %#lx", tcp->u_arg[3]);
    345 #else /* !LINUX */
    346 		tprintf(", %#lx", tcp->u_arg[2]);
    347 #endif /* !LINUX */
    348 	}
    349 	return 0;
    350 }
    351 
    352 int sys_shmat(tcp)
    353 struct tcb *tcp;
    354 {
    355 #ifdef LINUX
    356 	unsigned long raddr;
    357 #endif /* LINUX */
    358 
    359 	if (exiting(tcp)) {
    360 		tprintf("%lu", tcp->u_arg[0]);
    361 #ifdef LINUX
    362 		tprintf(", %#lx", tcp->u_arg[3]);
    363 		tprintf(", ");
    364 		printflags(shm_flags, tcp->u_arg[1], "SHM_???");
    365 #else /* !LINUX */
    366 		tprintf(", %#lx", tcp->u_arg[1]);
    367 		tprintf(", ");
    368 		printflags(shm_flags, tcp->u_arg[2], "SHM_???");
    369 #endif /* !LINUX */
    370 		if (syserror(tcp))
    371 			return 0;
    372 #ifdef LINUX
    373 		if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
    374 			return RVAL_NONE;
    375 		tcp->u_rval = raddr;
    376 #endif /* LINUX */
    377 		return RVAL_HEX;
    378 	}
    379 	return 0;
    380 }
    381 
    382 int sys_shmdt(tcp)
    383 struct tcb *tcp;
    384 {
    385 	if (entering(tcp))
    386 #ifdef LINUX
    387 		tprintf("%#lx", tcp->u_arg[3]);
    388 #else /* !LINUX */
    389 		tprintf("%#lx", tcp->u_arg[0]);
    390 #endif /* !LINUX */
    391 	return 0;
    392 }
    393 
    394 #endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
    395 
    396 #ifdef LINUX
    397 int sys_mq_open(tcp)
    398 struct tcb *tcp;
    399 {
    400 	if (entering(tcp)) {
    401 		printpath(tcp, tcp->u_arg[0]);
    402 		tprintf(", ");
    403 		/* flags */
    404 		printflags(openmodes, tcp->u_arg[1] + 1, "O_???");
    405 		if (tcp->u_arg[1] & O_CREAT) {
    406 # ifndef HAVE_MQUEUE_H
    407 			tprintf(", %lx", tcp->u_arg[2]);
    408 # else
    409 			struct mq_attr attr;
    410 			/* mode */
    411 			tprintf(", %#lo, ", tcp->u_arg[2]);
    412 			if (umove(tcp, tcp->u_arg[3], &attr) < 0)
    413 				tprintf("{ ??? }");
    414 			else
    415 				tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
    416 					attr.mq_maxmsg, attr.mq_msgsize);
    417 # endif
    418 		}
    419 	}
    420 	return 0;
    421 }
    422 
    423 int sys_mq_timedsend(tcp)
    424 struct tcb *tcp;
    425 {
    426 	if (entering(tcp)) {
    427 		tprintf("%ld, ", tcp->u_arg[0]);
    428 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    429 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    430 		printtv(tcp, tcp->u_arg[4]);
    431 	}
    432 	return 0;
    433 }
    434 
    435 int sys_mq_timedreceive(tcp)
    436 struct tcb *tcp;
    437 {
    438 	if (entering(tcp))
    439 		tprintf("%ld, ", tcp->u_arg[0]);
    440 	else {
    441 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    442 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    443 		printtv(tcp, tcp->u_arg[4]);
    444 	}
    445 	return 0;
    446 }
    447 
    448 int sys_mq_notify(tcp)
    449 struct tcb *tcp;
    450 {
    451 	if (entering(tcp)) {
    452 		tprintf("%ld, ", tcp->u_arg[0]);
    453 		printsigevent(tcp, tcp->u_arg[1]);
    454 	}
    455 	return 0;
    456 }
    457 
    458 static void printmqattr(tcp, addr)
    459 struct tcb *tcp;
    460 long addr;
    461 {
    462 	if (addr == 0)
    463 		tprintf("NULL");
    464 	else {
    465 # ifndef HAVE_MQUEUE_H
    466 		tprintf("%#lx", addr);
    467 # else
    468 		struct mq_attr attr;
    469 		if (umove(tcp, addr, &attr) < 0) {
    470 			tprintf("{...}");
    471 			return;
    472 		}
    473 		tprintf("{mq_flags=");
    474 		printflags(openmodes, attr.mq_flags + 1, "O_???");
    475 		tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
    476 			attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
    477 # endif
    478 	}
    479 }
    480 
    481 int sys_mq_getsetattr(tcp)
    482 struct tcb *tcp;
    483 {
    484 	if (entering(tcp)) {
    485 		tprintf("%ld, ", tcp->u_arg[0]);
    486 		printmqattr(tcp, tcp->u_arg[1]);
    487 		tprintf(", ");
    488 	} else
    489 		printmqattr(tcp, tcp->u_arg[2]);
    490 	return 0;
    491 }
    492 #endif
    493