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 
     31 #include "defs.h"
     32 #ifdef HAVE_MQUEUE_H
     33 # include <mqueue.h>
     34 #endif
     35 #include <fcntl.h>
     36 #include <sys/ipc.h>
     37 #include <sys/sem.h>
     38 #include <sys/msg.h>
     39 #include <sys/shm.h>
     40 
     41 #ifndef MSG_STAT
     42 #define MSG_STAT 11
     43 #endif
     44 #ifndef MSG_INFO
     45 #define MSG_INFO 12
     46 #endif
     47 #ifndef SHM_STAT
     48 #define SHM_STAT 13
     49 #endif
     50 #ifndef SHM_INFO
     51 #define SHM_INFO 14
     52 #endif
     53 #ifndef SEM_STAT
     54 #define SEM_STAT 18
     55 #endif
     56 #ifndef SEM_INFO
     57 #define SEM_INFO 19
     58 #endif
     59 
     60 #if !defined IPC_64
     61 # define IPC_64 0x100
     62 #endif
     63 
     64 extern void printsigevent(struct tcb *tcp, long arg);
     65 
     66 #include "xlat/msgctl_flags.h"
     67 #include "xlat/semctl_flags.h"
     68 #include "xlat/shmctl_flags.h"
     69 #include "xlat/resource_flags.h"
     70 #include "xlat/shm_resource_flags.h"
     71 #include "xlat/shm_flags.h"
     72 #include "xlat/ipc_msg_flags.h"
     73 #include "xlat/semop_flags.h"
     74 
     75 SYS_FUNC(msgget)
     76 {
     77 	if (entering(tcp)) {
     78 		if (tcp->u_arg[0])
     79 			tprintf("%#lx, ", tcp->u_arg[0]);
     80 		else
     81 			tprints("IPC_PRIVATE, ");
     82 		if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
     83 			tprints("|");
     84 		tprintf("%#lo", tcp->u_arg[1] & 0777);
     85 	}
     86 	return 0;
     87 }
     88 
     89 #ifdef IPC_64
     90 # define PRINTCTL(flagset, arg, dflt) \
     91 	if ((arg) & IPC_64) tprints("IPC_64|"); \
     92 	printxval((flagset), (arg) &~ IPC_64, dflt)
     93 #else
     94 # define PRINTCTL printxval
     95 #endif
     96 
     97 static int
     98 indirect_ipccall(struct tcb *tcp)
     99 {
    100 	return tcp->s_ent->sys_flags & TRACE_INDIRECT_SUBCALL;
    101 }
    102 
    103 SYS_FUNC(msgctl)
    104 {
    105 	if (entering(tcp)) {
    106 		tprintf("%lu, ", tcp->u_arg[0]);
    107 		PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
    108 		tprintf(", %#lx", tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]);
    109 	}
    110 	return 0;
    111 }
    112 
    113 static void
    114 tprint_msgsnd(struct tcb *tcp, long addr, unsigned long count,
    115 	      unsigned long flags)
    116 {
    117 	long mtype;
    118 
    119 	if (umove(tcp, addr, &mtype) < 0) {
    120 		tprintf("%#lx", addr);
    121 	} else {
    122 		tprintf("{%lu, ", mtype);
    123 		printstr(tcp, addr + sizeof(mtype), count);
    124 		tprints("}");
    125 	}
    126 	tprintf(", %lu, ", count);
    127 	printflags(ipc_msg_flags, flags, "MSG_???");
    128 }
    129 
    130 SYS_FUNC(msgsnd)
    131 {
    132 	if (entering(tcp)) {
    133 		tprintf("%d, ", (int) tcp->u_arg[0]);
    134 		if (indirect_ipccall(tcp)) {
    135 			tprint_msgsnd(tcp, tcp->u_arg[3], tcp->u_arg[1],
    136 				      tcp->u_arg[2]);
    137 		} else {
    138 			tprint_msgsnd(tcp, tcp->u_arg[1], tcp->u_arg[2],
    139 				      tcp->u_arg[3]);
    140 		}
    141 	}
    142 	return 0;
    143 }
    144 
    145 static void
    146 tprint_msgrcv(struct tcb *tcp, long addr, unsigned long count, long msgtyp)
    147 {
    148 	long mtype;
    149 
    150 	if (syserror(tcp) || umove(tcp, addr, &mtype) < 0) {
    151 		tprintf("%#lx", addr);
    152 	} else {
    153 		tprintf("{%lu, ", mtype);
    154 		printstr(tcp, addr + sizeof(mtype), count);
    155 		tprints("}");
    156 	}
    157 	tprintf(", %lu, %ld, ", count, msgtyp);
    158 }
    159 
    160 SYS_FUNC(msgrcv)
    161 {
    162 	if (entering(tcp)) {
    163 		tprintf("%d, ", (int) tcp->u_arg[0]);
    164 	} else {
    165 		if (indirect_ipccall(tcp)) {
    166 			struct ipc_wrapper {
    167 				struct msgbuf *msgp;
    168 				long msgtyp;
    169 			} tmp;
    170 
    171 			if (umove(tcp, tcp->u_arg[3], &tmp) < 0) {
    172 				tprintf("%#lx, %lu, ",
    173 					tcp->u_arg[3], tcp->u_arg[1]);
    174 			} else {
    175 				tprint_msgrcv(tcp, (long) tmp.msgp,
    176 					tcp->u_arg[1], tmp.msgtyp);
    177 			}
    178 			printflags(ipc_msg_flags, tcp->u_arg[2], "MSG_???");
    179 		} else {
    180 			tprint_msgrcv(tcp, tcp->u_arg[1],
    181 				tcp->u_arg[2], tcp->u_arg[3]);
    182 			printflags(ipc_msg_flags, tcp->u_arg[4], "MSG_???");
    183 		}
    184 	}
    185 	return 0;
    186 }
    187 
    188 static void
    189 tprint_sembuf(struct tcb *tcp, long addr, unsigned long count)
    190 {
    191 	unsigned long i, max_count;
    192 
    193 	if (abbrev(tcp))
    194 		max_count = (max_strlen < count) ? max_strlen : count;
    195 	else
    196 		max_count = count;
    197 
    198 	if (!max_count) {
    199 		tprintf("%#lx, %lu", addr, count);
    200 		return;
    201 	}
    202 
    203 	for (i = 0; i < max_count; ++i) {
    204 		struct sembuf sb;
    205 		if (i)
    206 			tprints(", ");
    207 		if (umove(tcp, addr + i * sizeof(struct sembuf), &sb) < 0) {
    208 			if (i) {
    209 				tprints("{???}");
    210 				break;
    211 			} else {
    212 				tprintf("%#lx, %lu", addr, count);
    213 				return;
    214 			}
    215 		} else {
    216 			if (!i)
    217 				tprints("{");
    218 			tprintf("{%u, %d, ", sb.sem_num, sb.sem_op);
    219 			printflags(semop_flags, sb.sem_flg, "SEM_???");
    220 			tprints("}");
    221 		}
    222 	}
    223 
    224 	if (i < max_count || max_count < count)
    225 		tprints(", ...");
    226 
    227 	tprintf("}, %lu", count);
    228 }
    229 
    230 SYS_FUNC(semop)
    231 {
    232 	if (entering(tcp)) {
    233 		tprintf("%lu, ", tcp->u_arg[0]);
    234 		if (indirect_ipccall(tcp)) {
    235 			tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
    236 		} else {
    237 			tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    238 		}
    239 	}
    240 	return 0;
    241 }
    242 
    243 SYS_FUNC(semtimedop)
    244 {
    245 	if (entering(tcp)) {
    246 		tprintf("%lu, ", tcp->u_arg[0]);
    247 		if (indirect_ipccall(tcp)) {
    248 			tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
    249 			tprints(", ");
    250 #if defined(S390) || defined(S390X)
    251 			printtv(tcp, tcp->u_arg[2]);
    252 #else
    253 			printtv(tcp, tcp->u_arg[4]);
    254 #endif
    255 		} else {
    256 			tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    257 			tprints(", ");
    258 			printtv(tcp, tcp->u_arg[3]);
    259 		}
    260 	}
    261 	return 0;
    262 }
    263 
    264 SYS_FUNC(semget)
    265 {
    266 	if (entering(tcp)) {
    267 		if (tcp->u_arg[0])
    268 			tprintf("%#lx", tcp->u_arg[0]);
    269 		else
    270 			tprints("IPC_PRIVATE");
    271 		tprintf(", %lu, ", tcp->u_arg[1]);
    272 		if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    273 			tprints("|");
    274 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    275 	}
    276 	return 0;
    277 }
    278 
    279 SYS_FUNC(semctl)
    280 {
    281 	if (entering(tcp)) {
    282 		tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    283 		PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
    284 		tprints(", ");
    285 		if (indirect_ipccall(tcp)) {
    286 			if (current_wordsize == sizeof(int)) {
    287 				printnum_int(tcp, tcp->u_arg[3], "%#x");
    288 			} else {
    289 				printnum_long(tcp, tcp->u_arg[3], "%#lx");
    290 			}
    291 		} else {
    292 			tprintf("%#lx", tcp->u_arg[3]);
    293 		}
    294 	}
    295 	return 0;
    296 }
    297 
    298 SYS_FUNC(shmget)
    299 {
    300 	if (entering(tcp)) {
    301 		if (tcp->u_arg[0])
    302 			tprintf("%#lx", tcp->u_arg[0]);
    303 		else
    304 			tprints("IPC_PRIVATE");
    305 		tprintf(", %lu, ", tcp->u_arg[1]);
    306 		if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    307 			tprints("|");
    308 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    309 	}
    310 	return 0;
    311 }
    312 
    313 SYS_FUNC(shmctl)
    314 {
    315 	if (entering(tcp)) {
    316 		tprintf("%lu, ", tcp->u_arg[0]);
    317 		PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
    318 		if (indirect_ipccall(tcp)) {
    319 			tprintf(", %#lx", tcp->u_arg[3]);
    320 		} else {
    321 			tprintf(", %#lx", tcp->u_arg[2]);
    322 		}
    323 	}
    324 	return 0;
    325 }
    326 
    327 SYS_FUNC(shmat)
    328 {
    329 	if (exiting(tcp)) {
    330 		tprintf("%lu", tcp->u_arg[0]);
    331 		if (indirect_ipccall(tcp)) {
    332 			tprintf(", %#lx, ", tcp->u_arg[3]);
    333 			printflags(shm_flags, tcp->u_arg[1], "SHM_???");
    334 		} else {
    335 			tprintf(", %#lx, ", tcp->u_arg[1]);
    336 			printflags(shm_flags, tcp->u_arg[2], "SHM_???");
    337 		}
    338 		if (syserror(tcp))
    339 			return 0;
    340 		if (indirect_ipccall(tcp)) {
    341 			unsigned long raddr;
    342 			if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
    343 				return RVAL_NONE;
    344 			tcp->u_rval = raddr;
    345 		}
    346 		return RVAL_HEX;
    347 	}
    348 	return 0;
    349 }
    350 
    351 SYS_FUNC(shmdt)
    352 {
    353 	if (entering(tcp)) {
    354 		if (indirect_ipccall(tcp)) {
    355 			tprintf("%#lx", tcp->u_arg[3]);
    356 		} else {
    357 			tprintf("%#lx", tcp->u_arg[0]);
    358 		}
    359 	}
    360 	return 0;
    361 }
    362 
    363 SYS_FUNC(mq_open)
    364 {
    365 	if (entering(tcp)) {
    366 		printpath(tcp, tcp->u_arg[0]);
    367 		tprints(", ");
    368 		/* flags */
    369 		tprint_open_modes(tcp->u_arg[1]);
    370 		if (tcp->u_arg[1] & O_CREAT) {
    371 # ifndef HAVE_MQUEUE_H
    372 			tprintf(", %lx", tcp->u_arg[2]);
    373 # else
    374 			struct mq_attr attr;
    375 			/* mode */
    376 			tprintf(", %#lo, ", tcp->u_arg[2]);
    377 			if (umove(tcp, tcp->u_arg[3], &attr) < 0)
    378 				tprints("{???}");
    379 			else
    380 				tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
    381 					(long) attr.mq_maxmsg,
    382 					(long) attr.mq_msgsize);
    383 # endif
    384 		}
    385 	}
    386 	return 0;
    387 }
    388 
    389 SYS_FUNC(mq_timedsend)
    390 {
    391 	if (entering(tcp)) {
    392 		tprintf("%ld, ", tcp->u_arg[0]);
    393 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    394 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    395 		printtv(tcp, tcp->u_arg[4]);
    396 	}
    397 	return 0;
    398 }
    399 
    400 SYS_FUNC(mq_timedreceive)
    401 {
    402 	if (entering(tcp))
    403 		tprintf("%ld, ", tcp->u_arg[0]);
    404 	else {
    405 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    406 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    407 		printtv(tcp, tcp->u_arg[4]);
    408 	}
    409 	return 0;
    410 }
    411 
    412 SYS_FUNC(mq_notify)
    413 {
    414 	if (entering(tcp)) {
    415 		tprintf("%ld, ", tcp->u_arg[0]);
    416 		printsigevent(tcp, tcp->u_arg[1]);
    417 	}
    418 	return 0;
    419 }
    420 
    421 static void
    422 printmqattr(struct tcb *tcp, long addr)
    423 {
    424 	if (addr == 0)
    425 		tprints("NULL");
    426 	else {
    427 # ifndef HAVE_MQUEUE_H
    428 		tprintf("%#lx", addr);
    429 # else
    430 		struct mq_attr attr;
    431 		if (umove(tcp, addr, &attr) < 0) {
    432 			tprints("{...}");
    433 			return;
    434 		}
    435 		tprints("{mq_flags=");
    436 		tprint_open_modes(attr.mq_flags);
    437 		tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
    438 			(long) attr.mq_maxmsg, (long) attr.mq_msgsize,
    439 			(long) attr.mq_curmsgs);
    440 # endif
    441 	}
    442 }
    443 
    444 SYS_FUNC(mq_getsetattr)
    445 {
    446 	if (entering(tcp)) {
    447 		tprintf("%ld, ", tcp->u_arg[0]);
    448 		printmqattr(tcp, tcp->u_arg[1]);
    449 		tprints(", ");
    450 	} else
    451 		printmqattr(tcp, tcp->u_arg[2]);
    452 	return 0;
    453 }
    454 
    455 SYS_FUNC(ipc)
    456 {
    457 	return printargs(tcp);
    458 }
    459