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$
     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 #ifdef HAVE_ANDROID_OS
     44 #include <linux/sem.h>
     45 #include <linux/msg.h>
     46 #include <linux/shm.h>
     47 #else
     48 #include <sys/sem.h>
     49 #include <sys/msg.h>
     50 #include <sys/shm.h>
     51 #endif
     52 
     53 #ifndef MSG_STAT
     54 #define MSG_STAT 11
     55 #endif
     56 #ifndef MSG_INFO
     57 #define MSG_INFO 12
     58 #endif
     59 #ifndef SHM_STAT
     60 #define SHM_STAT 13
     61 #endif
     62 #ifndef SHM_INFO
     63 #define SHM_INFO 14
     64 #endif
     65 #ifndef SEM_STAT
     66 #define SEM_STAT 18
     67 #endif
     68 #ifndef SEM_INFO
     69 #define SEM_INFO 19
     70 #endif
     71 
     72 #if defined LINUX && !defined IPC_64
     73 # define IPC_64 0x100
     74 #endif
     75 
     76 extern void printsigevent(struct tcb *tcp, long arg);
     77 
     78 static const struct xlat msgctl_flags[] = {
     79 	{ IPC_RMID,	"IPC_RMID"	},
     80 	{ IPC_SET,	"IPC_SET"	},
     81 	{ IPC_STAT,	"IPC_STAT"	},
     82 #ifdef LINUX
     83 	{ IPC_INFO,	"IPC_INFO"	},
     84 	{ MSG_STAT,	"MSG_STAT"	},
     85 	{ MSG_INFO,	"MSG_INFO"	},
     86 #endif /* LINUX */
     87 	{ 0,		NULL		},
     88 };
     89 
     90 static const struct xlat semctl_flags[] = {
     91 	{ IPC_RMID,	"IPC_RMID"	},
     92 	{ IPC_SET,	"IPC_SET"	},
     93 	{ IPC_STAT,	"IPC_STAT"	},
     94 #ifdef LINUX
     95 	{ IPC_INFO,	"IPC_INFO"	},
     96 	{ SEM_STAT,	"SEM_STAT"	},
     97 	{ SEM_INFO,	"SEM_INFO"	},
     98 #endif /* LINUX */
     99 	{ GETPID,	"GETPID"	},
    100 	{ GETVAL,	"GETVAL"	},
    101 	{ GETALL,	"GETALL"	},
    102 	{ GETNCNT,	"GETNCNT"	},
    103 	{ GETZCNT,	"GETZCNT"	},
    104 	{ SETVAL,	"SETVAL"	},
    105 	{ SETALL,	"SETALL"	},
    106 	{ 0,		NULL		},
    107 };
    108 
    109 static const struct xlat shmctl_flags[] = {
    110 	{ IPC_RMID,	"IPC_RMID"	},
    111 	{ IPC_SET,	"IPC_SET"	},
    112 	{ IPC_STAT,	"IPC_STAT"	},
    113 #ifdef LINUX
    114 	{ IPC_INFO,	"IPC_INFO"	},
    115 	{ SHM_STAT,	"SHM_STAT"	},
    116 	{ SHM_INFO,	"SHM_INFO"	},
    117 #endif /* LINUX */
    118 #ifdef SHM_LOCK
    119 	{ SHM_LOCK,	"SHM_LOCK"	},
    120 #endif
    121 #ifdef SHM_UNLOCK
    122 	{ SHM_UNLOCK,	"SHM_UNLOCK"	},
    123 #endif
    124 	{ 0,		NULL		},
    125 };
    126 
    127 static const struct xlat resource_flags[] = {
    128 	{ IPC_CREAT,	"IPC_CREAT"	},
    129 	{ IPC_EXCL,	"IPC_EXCL"	},
    130 	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
    131 	{ 0,		NULL		},
    132 };
    133 
    134 static const struct xlat shm_resource_flags[] = {
    135 	{ IPC_CREAT,	"IPC_CREAT"	},
    136 	{ IPC_EXCL,	"IPC_EXCL"	},
    137 #ifdef SHM_HUGETLB
    138 	{ SHM_HUGETLB,	"SHM_HUGETLB"	},
    139 #endif
    140 	{ 0,		NULL		},
    141 };
    142 
    143 static const struct xlat shm_flags[] = {
    144 #ifdef LINUX
    145 	{ SHM_REMAP,	"SHM_REMAP"	},
    146 #endif /* LINUX */
    147 	{ SHM_RDONLY,	"SHM_RDONLY"	},
    148 	{ SHM_RND,	"SHM_RND"	},
    149 	{ 0,		NULL		},
    150 };
    151 
    152 static const struct xlat msg_flags[] = {
    153 	{ MSG_NOERROR,	"MSG_NOERROR"	},
    154 #ifdef LINUX
    155 	{ MSG_EXCEPT,	"MSG_EXCEPT"	},
    156 #endif /* LINUX */
    157 	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
    158 	{ 0,		NULL		},
    159 };
    160 
    161 static const struct xlat semop_flags[] = {
    162 	{ SEM_UNDO,	"SEM_UNDO"	},
    163 	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
    164 	{ 0,		NULL		},
    165 };
    166 
    167 int sys_msgget(tcp)
    168 struct tcb *tcp;
    169 {
    170 	if (entering(tcp)) {
    171 		if (tcp->u_arg[0])
    172 			tprintf("%#lx", tcp->u_arg[0]);
    173 		else
    174 			tprintf("IPC_PRIVATE");
    175 		tprintf(", ");
    176 		if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
    177 			tprintf("|");
    178 		tprintf("%#lo", tcp->u_arg[1] & 0777);
    179 	}
    180 	return 0;
    181 }
    182 
    183 #ifdef IPC_64
    184 # define PRINTCTL(flagset, arg, dflt) \
    185 	if ((arg) & IPC_64) tprintf("IPC_64|"); \
    186 	printxval((flagset), (arg) &~ IPC_64, dflt)
    187 #else
    188 # define PRINTCTL printxval
    189 #endif
    190 
    191 static int
    192 indirect_ipccall(tcp)
    193 struct tcb *tcp;
    194 {
    195 #ifdef LINUX
    196 #ifdef X86_64
    197 	return current_personality > 0;
    198 #endif
    199 #if defined IA64
    200 	return tcp->scno < 1024; /* ia32 emulation syscalls are low */
    201 #endif
    202 #if !defined MIPS && !defined HPPA
    203 	return 1;
    204 #endif
    205 #endif	/* LINUX */
    206 	return 0;
    207 }
    208 
    209 int sys_msgctl(tcp)
    210 struct tcb *tcp;
    211 {
    212 	if (entering(tcp)) {
    213 		tprintf("%lu, ", tcp->u_arg[0]);
    214 		PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
    215 		tprintf(", %#lx", tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]);
    216 	}
    217 	return 0;
    218 }
    219 
    220 static void
    221 tprint_msgsnd(struct tcb *tcp, long addr, unsigned long count,
    222 	      unsigned long flags)
    223 {
    224 	long mtype;
    225 
    226 	if (umove(tcp, addr, &mtype) < 0) {
    227 		tprintf("%#lx", addr);
    228 	} else {
    229 		tprintf("{%lu, ", mtype);
    230 		printstr(tcp, addr + sizeof(mtype), count);
    231 		tprintf("}");
    232 	}
    233 	tprintf(", %lu, ", count);
    234 	printflags(msg_flags, flags, "MSG_???");
    235 }
    236 
    237 int sys_msgsnd(struct tcb *tcp)
    238 {
    239 	if (entering(tcp)) {
    240 		tprintf("%d, ", (int) tcp->u_arg[0]);
    241 		if (indirect_ipccall(tcp)) {
    242 			tprint_msgsnd(tcp, tcp->u_arg[3], tcp->u_arg[1],
    243 				      tcp->u_arg[2]);
    244 		} else {
    245 			tprint_msgsnd(tcp, tcp->u_arg[1], tcp->u_arg[2],
    246 				      tcp->u_arg[3]);
    247 		}
    248 	}
    249 	return 0;
    250 }
    251 
    252 static void
    253 tprint_msgrcv(struct tcb *tcp, long addr, unsigned long count, long msgtyp)
    254 {
    255 	long mtype;
    256 
    257 	if (syserror(tcp) || umove(tcp, addr, &mtype) < 0) {
    258 		tprintf("%#lx", addr);
    259 	} else {
    260 		tprintf("{%lu, ", mtype);
    261 		printstr(tcp, addr + sizeof(mtype), count);
    262 		tprintf("}");
    263 	}
    264 	tprintf(", %lu, %ld, ", count, msgtyp);
    265 }
    266 
    267 int sys_msgrcv(struct tcb *tcp)
    268 {
    269 	if (entering(tcp)) {
    270 		tprintf("%d, ", (int) tcp->u_arg[0]);
    271 	} else {
    272 		if (indirect_ipccall(tcp)) {
    273 			struct ipc_wrapper {
    274 				struct msgbuf *msgp;
    275 				long msgtyp;
    276 			} tmp;
    277 
    278 			if (umove(tcp, tcp->u_arg[3], &tmp) < 0) {
    279 				tprintf("%#lx, %lu, ",
    280 					tcp->u_arg[3], tcp->u_arg[1]);
    281 			} else {
    282 				tprint_msgrcv(tcp, (long) tmp.msgp,
    283 					tcp->u_arg[1], tmp.msgtyp);
    284 			}
    285 			printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    286 		} else {
    287 			tprint_msgrcv(tcp, tcp->u_arg[1],
    288 				tcp->u_arg[2], tcp->u_arg[3]);
    289 			printflags(msg_flags, tcp->u_arg[4], "MSG_???");
    290 		}
    291 	}
    292 	return 0;
    293 }
    294 
    295 static void
    296 tprint_sembuf(struct tcb *tcp, long addr, unsigned long count)
    297 {
    298 	unsigned long i, max_count;
    299 
    300 	if (abbrev(tcp))
    301 		max_count = (max_strlen < count) ? max_strlen : count;
    302 	else
    303 		max_count = count;
    304 
    305 	if (!max_count) {
    306 		tprintf("%#lx, %lu", addr, count);
    307 		return;
    308 	}
    309 
    310 	for(i = 0; i < max_count; ++i) {
    311 		struct sembuf sb;
    312 		if (i)
    313 			tprintf(", ");
    314 		if (umove(tcp, addr + i * sizeof(struct sembuf), &sb) < 0) {
    315 			if (i) {
    316 				tprintf("{???}");
    317 				break;
    318 			} else {
    319 				tprintf("%#lx, %lu", addr, count);
    320 				return;
    321 			}
    322 		} else {
    323 			if (!i)
    324 				tprintf("{");
    325 			tprintf("{%u, %d, ", sb.sem_num, sb.sem_op);
    326 			printflags(semop_flags, sb.sem_flg, "SEM_???");
    327 			tprintf("}");
    328 		}
    329 	}
    330 
    331 	if (i < max_count || max_count < count)
    332 		tprintf(", ...");
    333 
    334 	tprintf("}, %lu", count);
    335 }
    336 
    337 int sys_semop(struct tcb *tcp)
    338 {
    339 	if (entering(tcp)) {
    340 		tprintf("%lu, ", tcp->u_arg[0]);
    341 		if (indirect_ipccall(tcp)) {
    342 			tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
    343 		} else {
    344 			tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    345 		}
    346 	}
    347 	return 0;
    348 }
    349 
    350 #ifdef LINUX
    351 int sys_semtimedop(struct tcb *tcp)
    352 {
    353 	if (entering(tcp)) {
    354 		tprintf("%lu, ", tcp->u_arg[0]);
    355 		if (indirect_ipccall(tcp)) {
    356 			tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
    357 			tprintf(", ");
    358 			printtv(tcp, tcp->u_arg[5]);
    359 		} else {
    360 			tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    361 			tprintf(", ");
    362 			printtv(tcp, tcp->u_arg[3]);
    363 		}
    364 	}
    365 	return 0;
    366 }
    367 #endif
    368 
    369 int sys_semget(tcp)
    370 struct tcb *tcp;
    371 {
    372 	if (entering(tcp)) {
    373 		if (tcp->u_arg[0])
    374 			tprintf("%#lx", tcp->u_arg[0]);
    375 		else
    376 			tprintf("IPC_PRIVATE");
    377 		tprintf(", %lu", tcp->u_arg[1]);
    378 		tprintf(", ");
    379 		if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    380 			tprintf("|");
    381 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    382 	}
    383 	return 0;
    384 }
    385 
    386 int sys_semctl(tcp)
    387 struct tcb *tcp;
    388 {
    389 	if (entering(tcp)) {
    390 		tprintf("%lu", tcp->u_arg[0]);
    391 		tprintf(", %lu, ", tcp->u_arg[1]);
    392 		PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
    393 		tprintf(", %#lx", tcp->u_arg[3]);
    394 	}
    395 	return 0;
    396 }
    397 
    398 int sys_shmget(tcp)
    399 struct tcb *tcp;
    400 {
    401 	if (entering(tcp)) {
    402 		if (tcp->u_arg[0])
    403 			tprintf("%#lx", tcp->u_arg[0]);
    404 		else
    405 			tprintf("IPC_PRIVATE");
    406 		tprintf(", %lu", tcp->u_arg[1]);
    407 		tprintf(", ");
    408 		if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    409 			tprintf("|");
    410 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    411 	}
    412 	return 0;
    413 }
    414 
    415 int sys_shmctl(tcp)
    416 struct tcb *tcp;
    417 {
    418 	if (entering(tcp)) {
    419 		tprintf("%lu, ", tcp->u_arg[0]);
    420 		PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
    421 		if (indirect_ipccall(tcp)) {
    422 			tprintf(", %#lx", tcp->u_arg[3]);
    423 		} else {
    424 			tprintf(", %#lx", tcp->u_arg[2]);
    425 		}
    426 	}
    427 	return 0;
    428 }
    429 
    430 int sys_shmat(tcp)
    431 struct tcb *tcp;
    432 {
    433 #ifdef LINUX
    434 	unsigned long raddr;
    435 #endif /* LINUX */
    436 
    437 	if (exiting(tcp)) {
    438 		tprintf("%lu", tcp->u_arg[0]);
    439 		if (indirect_ipccall(tcp)) {
    440 			tprintf(", %#lx", tcp->u_arg[3]);
    441 			tprintf(", ");
    442 			printflags(shm_flags, tcp->u_arg[1], "SHM_???");
    443 		} else {
    444 			tprintf(", %#lx", tcp->u_arg[1]);
    445 			tprintf(", ");
    446 			printflags(shm_flags, tcp->u_arg[2], "SHM_???");
    447 		}
    448 		if (syserror(tcp))
    449 			return 0;
    450 /* HPPA does not use an IPC multiplexer on Linux.  */
    451 #if defined(LINUX) && !defined(HPPA)
    452 		if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
    453 			return RVAL_NONE;
    454 		tcp->u_rval = raddr;
    455 #endif /* LINUX */
    456 		return RVAL_HEX;
    457 	}
    458 	return 0;
    459 }
    460 
    461 int sys_shmdt(tcp)
    462 struct tcb *tcp;
    463 {
    464 	if (entering(tcp)) {
    465 		if (indirect_ipccall(tcp)) {
    466 			tprintf("%#lx", tcp->u_arg[3]);
    467 		} else {
    468 			tprintf("%#lx", tcp->u_arg[0]);
    469 		}
    470 	}
    471 	return 0;
    472 }
    473 
    474 #endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
    475 
    476 #ifdef LINUX
    477 int
    478 sys_mq_open(struct tcb *tcp)
    479 {
    480 	if (entering(tcp)) {
    481 		printpath(tcp, tcp->u_arg[0]);
    482 		tprintf(", ");
    483 		/* flags */
    484 		tprint_open_modes(tcp->u_arg[1]);
    485 		if (tcp->u_arg[1] & O_CREAT) {
    486 # ifndef HAVE_MQUEUE_H
    487 			tprintf(", %lx", tcp->u_arg[2]);
    488 # else
    489 			struct mq_attr attr;
    490 			/* mode */
    491 			tprintf(", %#lo, ", tcp->u_arg[2]);
    492 			if (umove(tcp, tcp->u_arg[3], &attr) < 0)
    493 				tprintf("{ ??? }");
    494 			else
    495 				tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
    496 					attr.mq_maxmsg, attr.mq_msgsize);
    497 # endif
    498 		}
    499 	}
    500 	return 0;
    501 }
    502 
    503 int
    504 sys_mq_timedsend(struct tcb *tcp)
    505 {
    506 	if (entering(tcp)) {
    507 		tprintf("%ld, ", tcp->u_arg[0]);
    508 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    509 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    510 		printtv(tcp, tcp->u_arg[4]);
    511 	}
    512 	return 0;
    513 }
    514 
    515 int
    516 sys_mq_timedreceive(struct tcb *tcp)
    517 {
    518 	if (entering(tcp))
    519 		tprintf("%ld, ", tcp->u_arg[0]);
    520 	else {
    521 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    522 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    523 		printtv(tcp, tcp->u_arg[4]);
    524 	}
    525 	return 0;
    526 }
    527 
    528 int
    529 sys_mq_notify(struct tcb *tcp)
    530 {
    531 	if (entering(tcp)) {
    532 		tprintf("%ld, ", tcp->u_arg[0]);
    533 		printsigevent(tcp, tcp->u_arg[1]);
    534 	}
    535 	return 0;
    536 }
    537 
    538 static void
    539 printmqattr(struct tcb *tcp, long addr)
    540 {
    541 	if (addr == 0)
    542 		tprintf("NULL");
    543 	else {
    544 # ifndef HAVE_MQUEUE_H
    545 		tprintf("%#lx", addr);
    546 # else
    547 		struct mq_attr attr;
    548 		if (umove(tcp, addr, &attr) < 0) {
    549 			tprintf("{...}");
    550 			return;
    551 		}
    552 		tprintf("{mq_flags=");
    553 		tprint_open_modes(attr.mq_flags);
    554 		tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
    555 			attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
    556 # endif
    557 	}
    558 }
    559 
    560 int
    561 sys_mq_getsetattr(struct tcb *tcp)
    562 {
    563 	if (entering(tcp)) {
    564 		tprintf("%ld, ", tcp->u_arg[0]);
    565 		printmqattr(tcp, tcp->u_arg[1]);
    566 		tprintf(", ");
    567 	} else
    568 		printmqattr(tcp, tcp->u_arg[2]);
    569 	return 0;
    570 }
    571 #endif
    572