Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      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 #include <fcntl.h>
     33 #include <sys/file.h>
     34 #ifdef HAVE_SYS_EPOLL_H
     35 # include <sys/epoll.h>
     36 #endif
     37 #ifdef HAVE_LINUX_PERF_EVENT_H
     38 # include  <linux/perf_event.h>
     39 #endif
     40 
     41 #include "xlat/fcntlcmds.h"
     42 #include "xlat/fdflags.h"
     43 #include "xlat/flockcmds.h"
     44 #include "xlat/lockfcmds.h"
     45 #include "xlat/notifyflags.h"
     46 #include "xlat/perf_event_open_flags.h"
     47 
     48 /*
     49  * Assume that F_SETLK64, F_SETLKW64, and F_GETLK64 are either defined
     50  * or not defined altogether.
     51  */
     52 #if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
     53 # define USE_PRINTFLOCK64 1
     54 #else
     55 # define USE_PRINTFLOCK64 0
     56 #endif
     57 
     58 #if USE_PRINTFLOCK64
     59 
     60 # ifndef HAVE_STRUCT_FLOCK64
     61 struct flock64 {
     62 	short int l_type, l_whence;
     63 	int64_t l_start, l_len;
     64 	int l_pid;
     65 };
     66 # endif
     67 
     68 static void
     69 printflock64(struct tcb *tcp, long addr, int getlk)
     70 {
     71 	struct flock64 fl;
     72 
     73 	if (umove(tcp, addr, &fl) < 0) {
     74 		tprints("{...}");
     75 		return;
     76 	}
     77 	tprints("{type=");
     78 	printxval(lockfcmds, fl.l_type, "F_???");
     79 	tprints(", whence=");
     80 	printxval(whence_codes, fl.l_whence, "SEEK_???");
     81 	tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
     82 	if (getlk)
     83 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
     84 	else
     85 		tprints("}");
     86 }
     87 #endif /* USE_PRINTFLOCK64 */
     88 
     89 static void
     90 printflock(struct tcb *tcp, long addr, int getlk)
     91 {
     92 	struct flock fl;
     93 	int r;
     94 
     95 #if SUPPORTED_PERSONALITIES > 1
     96 	if (
     97 # if SIZEOF_OFF_T > SIZEOF_LONG
     98 	    current_personality > 0 &&
     99 #endif
    100 	    current_wordsize != sizeof(fl.l_start)) {
    101 		if (current_wordsize == 4) {
    102 			/* 32-bit x86 app on x86_64 and similar cases */
    103 			struct {
    104 				short int l_type;
    105 				short int l_whence;
    106 				int32_t l_start; /* off_t */
    107 				int32_t l_len; /* off_t */
    108 				int32_t l_pid; /* pid_t */
    109 			} fl32;
    110 			r = umove(tcp, addr, &fl32);
    111 			if (r >= 0) {
    112 				fl.l_type = fl32.l_type;
    113 				fl.l_whence = fl32.l_whence;
    114 				fl.l_start = fl32.l_start;
    115 				fl.l_len = fl32.l_len;
    116 				fl.l_pid = fl32.l_pid;
    117 			}
    118 		} else {
    119 			/* let people know we have a problem here */
    120 			tprintf("<decode error: unsupported wordsize %d>",
    121 				current_wordsize);
    122 			return;
    123 		}
    124 	} else
    125 #endif
    126 	{
    127 		r = umove(tcp, addr, &fl);
    128 	}
    129 	if (r < 0) {
    130 		tprints("{...}");
    131 		return;
    132 	}
    133 	tprints("{type=");
    134 	printxval(lockfcmds, fl.l_type, "F_???");
    135 	tprints(", whence=");
    136 	printxval(whence_codes, fl.l_whence, "SEEK_???");
    137 #if SIZEOF_OFF_T > SIZEOF_LONG
    138 	tprintf(", start=%lld, len=%lld", fl.l_start, fl.l_len);
    139 #else
    140 	tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
    141 #endif
    142 	if (getlk)
    143 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
    144 	else
    145 		tprints("}");
    146 }
    147 
    148 SYS_FUNC(fcntl)
    149 {
    150 	if (entering(tcp)) {
    151 		printfd(tcp, tcp->u_arg[0]);
    152 		tprints(", ");
    153 		printxval(fcntlcmds, tcp->u_arg[1], "F_???");
    154 		switch (tcp->u_arg[1]) {
    155 		case F_SETFD:
    156 			tprints(", ");
    157 			printflags(fdflags, tcp->u_arg[2], "FD_???");
    158 			break;
    159 		case F_SETOWN: case F_DUPFD:
    160 #ifdef F_DUPFD_CLOEXEC
    161 		case F_DUPFD_CLOEXEC:
    162 #endif
    163 			tprintf(", %ld", tcp->u_arg[2]);
    164 			break;
    165 		case F_SETFL:
    166 			tprints(", ");
    167 			tprint_open_modes(tcp->u_arg[2]);
    168 			break;
    169 		case F_SETLK: case F_SETLKW:
    170 			tprints(", ");
    171 			printflock(tcp, tcp->u_arg[2], 0);
    172 			break;
    173 #if USE_PRINTFLOCK64
    174 		case F_SETLK64: case F_SETLKW64:
    175 			tprints(", ");
    176 			printflock64(tcp, tcp->u_arg[2], 0);
    177 			break;
    178 #endif /* USE_PRINTFLOCK64 */
    179 #ifdef F_NOTIFY
    180 		case F_NOTIFY:
    181 			tprints(", ");
    182 			printflags(notifyflags, tcp->u_arg[2], "DN_???");
    183 			break;
    184 #endif
    185 #ifdef F_SETLEASE
    186 		case F_SETLEASE:
    187 			tprints(", ");
    188 			printxval(lockfcmds, tcp->u_arg[2], "F_???");
    189 			break;
    190 #endif
    191 		}
    192 	}
    193 	else {
    194 		switch (tcp->u_arg[1]) {
    195 		case F_DUPFD:
    196 #ifdef F_DUPFD_CLOEXEC
    197 		case F_DUPFD_CLOEXEC:
    198 #endif
    199 		case F_SETFD: case F_SETFL:
    200 		case F_SETLK: case F_SETLKW:
    201 		case F_SETOWN: case F_GETOWN:
    202 #ifdef F_NOTIFY
    203 		case F_NOTIFY:
    204 #endif
    205 #ifdef F_SETLEASE
    206 		case F_SETLEASE:
    207 #endif
    208 			break;
    209 		case F_GETFD:
    210 			if (syserror(tcp) || tcp->u_rval == 0)
    211 				return 0;
    212 			tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
    213 			return RVAL_HEX|RVAL_STR;
    214 		case F_GETFL:
    215 			if (syserror(tcp))
    216 				return 0;
    217 			tcp->auxstr = sprint_open_modes(tcp->u_rval);
    218 			return RVAL_HEX|RVAL_STR;
    219 		case F_GETLK:
    220 			tprints(", ");
    221 			printflock(tcp, tcp->u_arg[2], 1);
    222 			break;
    223 #if USE_PRINTFLOCK64
    224 		case F_GETLK64:
    225 			tprints(", ");
    226 			printflock64(tcp, tcp->u_arg[2], 1);
    227 			break;
    228 #endif
    229 #ifdef F_GETLEASE
    230 		case F_GETLEASE:
    231 			if (syserror(tcp))
    232 				return 0;
    233 			tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
    234 			return RVAL_HEX|RVAL_STR;
    235 #endif
    236 		default:
    237 			tprintf(", %#lx", tcp->u_arg[2]);
    238 			break;
    239 		}
    240 	}
    241 	return 0;
    242 }
    243 
    244 #ifdef LOCK_SH
    245 
    246 SYS_FUNC(flock)
    247 {
    248 	if (entering(tcp)) {
    249 		printfd(tcp, tcp->u_arg[0]);
    250 		tprints(", ");
    251 		printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
    252 	}
    253 	return 0;
    254 }
    255 #endif /* LOCK_SH */
    256 
    257 SYS_FUNC(close)
    258 {
    259 	if (entering(tcp)) {
    260 		printfd(tcp, tcp->u_arg[0]);
    261 	}
    262 	return 0;
    263 }
    264 
    265 SYS_FUNC(dup)
    266 {
    267 	if (entering(tcp)) {
    268 		printfd(tcp, tcp->u_arg[0]);
    269 	}
    270 	return RVAL_FD;
    271 }
    272 
    273 static int
    274 do_dup2(struct tcb *tcp, int flags_arg)
    275 {
    276 	if (entering(tcp)) {
    277 		printfd(tcp, tcp->u_arg[0]);
    278 		tprints(", ");
    279 		printfd(tcp, tcp->u_arg[1]);
    280 		if (flags_arg >= 0) {
    281 			tprints(", ");
    282 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
    283 		}
    284 	}
    285 	return RVAL_FD;
    286 }
    287 
    288 SYS_FUNC(dup2)
    289 {
    290 	return do_dup2(tcp, -1);
    291 }
    292 
    293 SYS_FUNC(dup3)
    294 {
    295 	return do_dup2(tcp, 2);
    296 }
    297 
    298 #if defined(ALPHA)
    299 SYS_FUNC(getdtablesize)
    300 {
    301 	return 0;
    302 }
    303 #endif
    304 
    305 static int
    306 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
    307 {
    308 	int i, j;
    309 	int nfds, fdsize;
    310 	fd_set *fds = NULL;
    311 	const char *sep;
    312 	long arg;
    313 
    314 	/* Kernel truncates arg[0] to int, we do the same. */
    315 	nfds = (int) args[0];
    316 
    317 	/* Kernel rejects negative nfds, so we don't parse it either. */
    318 	if (nfds < 0)
    319 		nfds = 0;
    320 
    321 	/* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
    322 	if (nfds > 1024*1024)
    323 		nfds = 1024*1024;
    324 
    325 	/*
    326 	 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
    327 	 * Instead of args[0], use nfds for fd count, fdsize for array lengths.
    328 	 */
    329 	fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
    330 
    331 	if (entering(tcp)) {
    332 		tprintf("%d", (int) args[0]);
    333 
    334 		if (verbose(tcp) && fdsize > 0) {
    335 			fds = malloc(fdsize);
    336 			if (!fds)
    337 				die_out_of_memory();
    338 		}
    339 		for (i = 0; i < 3; i++) {
    340 			arg = args[i+1];
    341 			if (arg == 0) {
    342 				tprints(", NULL");
    343 				continue;
    344 			}
    345 			if (!fds) {
    346 				tprintf(", %#lx", arg);
    347 				continue;
    348 			}
    349 			if (umoven(tcp, arg, fdsize, fds) < 0) {
    350 				tprints(", [?]");
    351 				continue;
    352 			}
    353 			tprints(", [");
    354 			for (j = 0, sep = "";; j++) {
    355 				j = next_set_bit(fds, j, nfds);
    356 				if (j < 0)
    357 					break;
    358 				tprints(sep);
    359 				printfd(tcp, j);
    360 				sep = " ";
    361 			}
    362 			tprints("]");
    363 		}
    364 		free(fds);
    365 		tprints(", ");
    366 		printtv_bitness(tcp, args[4], bitness, 0);
    367 	}
    368 	else {
    369 		static char outstr[1024];
    370 		char *outptr;
    371 #define end_outstr (outstr + sizeof(outstr))
    372 		int ready_fds;
    373 
    374 		if (syserror(tcp))
    375 			return 0;
    376 
    377 		ready_fds = tcp->u_rval;
    378 		if (ready_fds == 0) {
    379 			tcp->auxstr = "Timeout";
    380 			return RVAL_STR;
    381 		}
    382 
    383 		fds = malloc(fdsize);
    384 		if (!fds)
    385 			die_out_of_memory();
    386 
    387 		outptr = outstr;
    388 		sep = "";
    389 		for (i = 0; i < 3 && ready_fds > 0; i++) {
    390 			int first = 1;
    391 
    392 			arg = args[i+1];
    393 			if (!arg || umoven(tcp, arg, fdsize, fds) < 0)
    394 				continue;
    395 			for (j = 0;; j++) {
    396 				j = next_set_bit(fds, j, nfds);
    397 				if (j < 0)
    398 					break;
    399 				/* +2 chars needed at the end: ']',NUL */
    400 				if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
    401 					if (first) {
    402 						outptr += sprintf(outptr, "%s%s [%u",
    403 							sep,
    404 							i == 0 ? "in" : i == 1 ? "out" : "except",
    405 							j
    406 						);
    407 						first = 0;
    408 						sep = ", ";
    409 					}
    410 					else {
    411 						outptr += sprintf(outptr, " %u", j);
    412 					}
    413 				}
    414 				if (--ready_fds == 0)
    415 					break;
    416 			}
    417 			if (outptr != outstr)
    418 				*outptr++ = ']';
    419 		}
    420 		free(fds);
    421 		/* This contains no useful information on SunOS.  */
    422 		if (args[4]) {
    423 			if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) {
    424 				outptr += sprintf(outptr, "%sleft ", sep);
    425 				outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0);
    426 			}
    427 		}
    428 		*outptr = '\0';
    429 		tcp->auxstr = outstr;
    430 		return RVAL_STR;
    431 #undef end_outstr
    432 	}
    433 	return 0;
    434 }
    435 
    436 SYS_FUNC(oldselect)
    437 {
    438 	long args[5];
    439 
    440 	if (umoven(tcp, tcp->u_arg[0], sizeof args, args) < 0) {
    441 		tprints("[...]");
    442 		return 0;
    443 	}
    444 	return decode_select(tcp, args, BITNESS_CURRENT);
    445 }
    446 
    447 #ifdef ALPHA
    448 SYS_FUNC(osf_select)
    449 {
    450 	long *args = tcp->u_arg;
    451 	return decode_select(tcp, args, BITNESS_32);
    452 }
    453 #endif
    454 
    455 #include "xlat/epollctls.h"
    456 #include "xlat/epollevents.h"
    457 #include "xlat/epollflags.h"
    458 
    459 /* Not aliased to printargs_ld: we want it to have a distinct address */
    460 SYS_FUNC(epoll_create)
    461 {
    462 	return printargs_ld(tcp);
    463 }
    464 
    465 SYS_FUNC(epoll_create1)
    466 {
    467 	if (entering(tcp))
    468 		printflags(epollflags, tcp->u_arg[0], "EPOLL_???");
    469 	return 0;
    470 }
    471 
    472 #ifdef HAVE_SYS_EPOLL_H
    473 static void
    474 print_epoll_event(struct epoll_event *ev)
    475 {
    476 	tprints("{");
    477 	printflags(epollevents, ev->events, "EPOLL???");
    478 	/* We cannot know what format the program uses, so print u32 and u64
    479 	   which will cover every value.  */
    480 	tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
    481 		ev->data.u32, ev->data.u64);
    482 }
    483 #endif
    484 
    485 SYS_FUNC(epoll_ctl)
    486 {
    487 	if (entering(tcp)) {
    488 		printfd(tcp, tcp->u_arg[0]);
    489 		tprints(", ");
    490 		printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
    491 		tprints(", ");
    492 		printfd(tcp, tcp->u_arg[2]);
    493 		tprints(", ");
    494 		if (tcp->u_arg[3] == 0)
    495 			tprints("NULL");
    496 		else {
    497 #ifdef HAVE_SYS_EPOLL_H
    498 			struct epoll_event ev;
    499 			if (
    500 #ifdef EPOLL_CTL_DEL
    501 			    (tcp->u_arg[1] != EPOLL_CTL_DEL) &&
    502 #endif
    503 			    umove(tcp, tcp->u_arg[3], &ev) == 0)
    504 				print_epoll_event(&ev);
    505 			else
    506 #endif
    507 				tprintf("%lx", tcp->u_arg[3]);
    508 		}
    509 	}
    510 	return 0;
    511 }
    512 
    513 static void
    514 epoll_wait_common(struct tcb *tcp)
    515 {
    516 	if (entering(tcp)) {
    517 		printfd(tcp, tcp->u_arg[0]);
    518 		tprints(", ");
    519 	} else {
    520 		if (syserror(tcp))
    521 			tprintf("%lx", tcp->u_arg[1]);
    522 		else if (tcp->u_rval == 0)
    523 			tprints("{}");
    524 		else {
    525 #ifdef HAVE_SYS_EPOLL_H
    526 			struct epoll_event ev, *start, *cur, *end;
    527 			int failed = 0;
    528 
    529 			tprints("{");
    530 			start = (struct epoll_event *) tcp->u_arg[1];
    531 			end = start + tcp->u_rval;
    532 			for (cur = start; cur < end; ++cur) {
    533 				if (cur > start)
    534 					tprints(", ");
    535 				if (umove(tcp, (long) cur, &ev) == 0)
    536 					print_epoll_event(&ev);
    537 				else {
    538 					tprints("?");
    539 					failed = 1;
    540 					break;
    541 				}
    542 			}
    543 			tprints("}");
    544 			if (failed)
    545 				tprintf(" %#lx", (long) start);
    546 #else
    547 			tprints("{...}");
    548 #endif
    549 		}
    550 		tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]);
    551 	}
    552 }
    553 
    554 SYS_FUNC(epoll_wait)
    555 {
    556 	epoll_wait_common(tcp);
    557 	return 0;
    558 }
    559 
    560 SYS_FUNC(epoll_pwait)
    561 {
    562 	epoll_wait_common(tcp);
    563 	if (exiting(tcp)) {
    564 		tprints(", ");
    565 		/* NB: kernel requires arg[5] == NSIG / 8 */
    566 		print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]);
    567 		tprintf(", %lu", tcp->u_arg[5]);
    568 	}
    569 	return 0;
    570 }
    571 
    572 SYS_FUNC(select)
    573 {
    574 	return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
    575 }
    576 
    577 SYS_FUNC(pselect6)
    578 {
    579 	int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
    580 	if (entering(tcp)) {
    581 		long r;
    582 		struct {
    583 			unsigned long ptr;
    584 			unsigned long len;
    585 		} data;
    586 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    587 		if (current_wordsize == 4) {
    588 			struct {
    589 				uint32_t ptr;
    590 				uint32_t len;
    591 			} data32;
    592 			r = umove(tcp, tcp->u_arg[5], &data32);
    593 			data.ptr = data32.ptr;
    594 			data.len = data32.len;
    595 		} else
    596 #endif
    597 			r = umove(tcp, tcp->u_arg[5], &data);
    598 		if (r < 0)
    599 			tprintf(", %#lx", tcp->u_arg[5]);
    600 		else {
    601 			tprints(", {");
    602 			/* NB: kernel requires data.len == NSIG / 8 */
    603 			print_sigset_addr_len(tcp, data.ptr, data.len);
    604 			tprintf(", %lu}", data.len);
    605 		}
    606 	}
    607 	return rc;
    608 }
    609 
    610 static int
    611 do_eventfd(struct tcb *tcp, int flags_arg)
    612 {
    613 	if (entering(tcp)) {
    614 		tprintf("%lu", tcp->u_arg[0]);
    615 		if (flags_arg >= 0) {
    616 			tprints(", ");
    617 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
    618 		}
    619 	}
    620 	return 0;
    621 }
    622 
    623 SYS_FUNC(eventfd)
    624 {
    625 	return do_eventfd(tcp, -1);
    626 }
    627 
    628 SYS_FUNC(eventfd2)
    629 {
    630 	return do_eventfd(tcp, 1);
    631 }
    632 
    633 SYS_FUNC(perf_event_open)
    634 {
    635 	if (entering(tcp)) {
    636 		tprintf("%#lx, %d, %d, %d, ",
    637 			tcp->u_arg[0],
    638 			(int) tcp->u_arg[1],
    639 			(int) tcp->u_arg[2],
    640 			(int) tcp->u_arg[3]);
    641 		printflags(perf_event_open_flags, tcp->u_arg[4],
    642 			   "PERF_FLAG_???");
    643 	}
    644 	return 0;
    645 }
    646