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  * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
      7  *                    port by Greg Banks <gbanks (at) pocketpenguins.com>
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  *
     32  *	$Id$
     33  */
     34 
     35 #include "defs.h"
     36 
     37 #ifdef LINUX
     38 #include <asm/mman.h>
     39 #endif
     40 #include <sys/mman.h>
     41 
     42 #if defined(LINUX) && defined(I386)
     43 #include <asm/ldt.h>
     44 # ifdef HAVE_STRUCT_USER_DESC
     45 #  define modify_ldt_ldt_s user_desc
     46 # endif
     47 #endif
     48 #if defined(LINUX) && defined(SH64)
     49 #include <asm/page.h>	    /* for PAGE_SHIFT */
     50 #endif
     51 
     52 #ifdef HAVE_LONG_LONG_OFF_T
     53 /*
     54  * Ugly hacks for systems that have a long long off_t
     55  */
     56 #define sys_mmap64	sys_mmap
     57 #endif
     58 
     59 int
     60 sys_brk(tcp)
     61 struct tcb *tcp;
     62 {
     63 	if (entering(tcp)) {
     64 		tprintf("%#lx", tcp->u_arg[0]);
     65 	}
     66 #ifdef LINUX
     67 	return RVAL_HEX;
     68 #else
     69 	return 0;
     70 #endif
     71 }
     72 
     73 #if defined(FREEBSD) || defined(SUNOS4)
     74 int
     75 sys_sbrk(tcp)
     76 struct tcb *tcp;
     77 {
     78 	if (entering(tcp)) {
     79 		tprintf("%lu", tcp->u_arg[0]);
     80 	}
     81 	return RVAL_HEX;
     82 }
     83 #endif /* FREEBSD || SUNOS4 */
     84 
     85 static const struct xlat mmap_prot[] = {
     86 	{ PROT_NONE,	"PROT_NONE",	},
     87 	{ PROT_READ,	"PROT_READ"	},
     88 	{ PROT_WRITE,	"PROT_WRITE"	},
     89 	{ PROT_EXEC,	"PROT_EXEC"	},
     90 #ifdef PROT_SEM
     91 	{ PROT_SEM,	"PROT_SEM"	},
     92 #endif
     93 #ifdef PROT_GROWSDOWN
     94 	{ PROT_GROWSDOWN,"PROT_GROWSDOWN"},
     95 #endif
     96 #ifdef PROT_GROWSUP
     97 	{ PROT_GROWSUP, "PROT_GROWSUP"	},
     98 #endif
     99 #ifdef PROT_SAO
    100 	{ PROT_SAO,	"PROT_SAO"	},
    101 #endif
    102 	{ 0,		NULL		},
    103 };
    104 
    105 static const struct xlat mmap_flags[] = {
    106 	{ MAP_SHARED,	"MAP_SHARED"	},
    107 	{ MAP_PRIVATE,	"MAP_PRIVATE"	},
    108 	{ MAP_FIXED,	"MAP_FIXED"	},
    109 #ifdef MAP_ANONYMOUS
    110 	{ MAP_ANONYMOUS,"MAP_ANONYMOUS"	},
    111 #endif
    112 #ifdef MAP_32BIT
    113 	{ MAP_32BIT,	"MAP_32BIT"	},
    114 #endif
    115 #ifdef MAP_RENAME
    116 	{ MAP_RENAME,	"MAP_RENAME"	},
    117 #endif
    118 #ifdef MAP_NORESERVE
    119 	{ MAP_NORESERVE,"MAP_NORESERVE"	},
    120 #endif
    121 #ifdef MAP_POPULATE
    122 	{ MAP_POPULATE, "MAP_POPULATE" },
    123 #endif
    124 #ifdef MAP_NONBLOCK
    125 	{ MAP_NONBLOCK, "MAP_NONBLOCK" },
    126 #endif
    127 	/*
    128 	 * XXX - this was introduced in SunOS 4.x to distinguish between
    129 	 * the old pre-4.x "mmap()", which:
    130 	 *
    131 	 *	only let you map devices with an "mmap" routine (e.g.,
    132 	 *	frame buffers) in;
    133 	 *
    134 	 *	required you to specify the mapping address;
    135 	 *
    136 	 *	returned 0 on success and -1 on failure;
    137 	 *
    138 	 * memory and which, and the 4.x "mmap()" which:
    139 	 *
    140 	 *	can map plain files;
    141 	 *
    142 	 *	can be asked to pick where to map the file;
    143 	 *
    144 	 *	returns the address where it mapped the file on success
    145 	 *	and -1 on failure.
    146 	 *
    147 	 * It's not actually used in source code that calls "mmap()"; the
    148 	 * "mmap()" routine adds it for you.
    149 	 *
    150 	 * It'd be nice to come up with some way of eliminating it from
    151 	 * the flags, e.g. reporting calls *without* it as "old_mmap()"
    152 	 * and calls with it as "mmap()".
    153 	 */
    154 #ifdef _MAP_NEW
    155 	{ _MAP_NEW,	"_MAP_NEW"	},
    156 #endif
    157 #ifdef MAP_GROWSDOWN
    158 	{ MAP_GROWSDOWN,"MAP_GROWSDOWN"	},
    159 #endif
    160 #ifdef MAP_DENYWRITE
    161 	{ MAP_DENYWRITE,"MAP_DENYWRITE"	},
    162 #endif
    163 #ifdef MAP_EXECUTABLE
    164 	{ MAP_EXECUTABLE,"MAP_EXECUTABLE"},
    165 #endif
    166 #ifdef MAP_INHERIT
    167 	{ MAP_INHERIT,"MAP_INHERIT"	},
    168 #endif
    169 #ifdef MAP_FILE
    170 	{ MAP_FILE,"MAP_FILE"},
    171 #endif
    172 #ifdef MAP_LOCKED
    173 	{ MAP_LOCKED,"MAP_LOCKED"},
    174 #endif
    175 	/* FreeBSD ones */
    176 #ifdef MAP_ANON
    177 	{ MAP_ANON,		"MAP_ANON"	},
    178 #endif
    179 #ifdef MAP_HASSEMAPHORE
    180 	{ MAP_HASSEMAPHORE,	"MAP_HASSEMAPHORE"	},
    181 #endif
    182 #ifdef MAP_STACK
    183 	{ MAP_STACK,		"MAP_STACK"	},
    184 #endif
    185 #ifdef MAP_NOSYNC
    186 	{ MAP_NOSYNC,		"MAP_NOSYNC"	},
    187 #endif
    188 #ifdef MAP_NOCORE
    189 	{ MAP_NOCORE,		"MAP_NOCORE"	},
    190 #endif
    191 #ifdef TILE
    192 	{ MAP_CACHE_NO_LOCAL, "MAP_CACHE_NO_LOCAL" },
    193 	{ MAP_CACHE_NO_L2, "MAP_CACHE_NO_L2" },
    194 	{ MAP_CACHE_NO_L1, "MAP_CACHE_NO_L1" },
    195 #endif
    196 	{ 0,		NULL		},
    197 };
    198 
    199 #ifdef TILE
    200 static
    201 int
    202 addtileflags(flags)
    203 long flags;
    204 {
    205 	long home = flags & _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_MASK);
    206 	flags &= ~_MAP_CACHE_MKHOME(_MAP_CACHE_HOME_MASK);
    207 
    208 	if (flags & _MAP_CACHE_INCOHERENT) {
    209 		flags &= ~_MAP_CACHE_INCOHERENT;
    210 		if (home == MAP_CACHE_HOME_NONE) {
    211 			tprintf("|MAP_CACHE_INCOHERENT");
    212 			return flags;
    213 		}
    214 		tprintf("|_MAP_CACHE_INCOHERENT");
    215 	}
    216 
    217 	switch (home) {
    218 	case 0:	break;
    219 	case MAP_CACHE_HOME_HERE: tprintf("|MAP_CACHE_HOME_HERE"); break;
    220 	case MAP_CACHE_HOME_NONE: tprintf("|MAP_CACHE_HOME_NONE"); break;
    221 	case MAP_CACHE_HOME_SINGLE: tprintf("|MAP_CACHE_HOME_SINGLE"); break;
    222 	case MAP_CACHE_HOME_TASK: tprintf("|MAP_CACHE_HOME_TASK"); break;
    223 	case MAP_CACHE_HOME_HASH: tprintf("|MAP_CACHE_HOME_HASH"); break;
    224 	default:
    225 		tprintf("|MAP_CACHE_HOME(%d)",
    226 			(home >> _MAP_CACHE_HOME_SHIFT) );
    227 		break;
    228 	}
    229 
    230 	return flags;
    231 }
    232 #endif
    233 
    234 #if !HAVE_LONG_LONG_OFF_T
    235 static int
    236 print_mmap(struct tcb *tcp, long *u_arg, long long offset)
    237 {
    238 	if (entering(tcp)) {
    239 		/* addr */
    240 		if (!u_arg[0])
    241 			tprintf("NULL, ");
    242 		else
    243 			tprintf("%#lx, ", u_arg[0]);
    244 		/* len */
    245 		tprintf("%lu, ", u_arg[1]);
    246 		/* prot */
    247 		printflags(mmap_prot, u_arg[2], "PROT_???");
    248 		tprintf(", ");
    249 		/* flags */
    250 #ifdef MAP_TYPE
    251 		printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
    252 #ifdef TILE
    253 		addflags(mmap_flags, addtileflags(u_arg[3] & ~MAP_TYPE));
    254 #else
    255 		addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
    256 #endif
    257 #else
    258 		printflags(mmap_flags, u_arg[3], "MAP_???");
    259 #endif
    260 		/* fd */
    261 		tprintf(", ");
    262 		printfd(tcp, u_arg[4]);
    263 		/* offset */
    264 		tprintf(", %#llx", offset);
    265 	}
    266 	return RVAL_HEX;
    267 }
    268 
    269 #ifdef LINUX
    270 int sys_old_mmap(tcp)
    271 struct tcb *tcp;
    272 {
    273 	long u_arg[6];
    274 
    275 #if	defined(IA64)
    276 	int i, v;
    277 	/*
    278 	 *  IA64 processes never call this routine, they only use the
    279 	 *  new `sys_mmap' interface.  This code converts the integer
    280 	 *  arguments that the IA32 process pushed onto the stack into
    281 	 *  longs.
    282 	 *
    283 	 *  Note that addresses with bit 31 set will be sign extended.
    284 	 *  Fortunately, those addresses are not currently being generated
    285 	 *  for IA32 processes so it's not a problem.
    286 	 */
    287 	for (i = 0; i < 6; i++)
    288 		if (umove(tcp, tcp->u_arg[0] + (i * sizeof(int)), &v) == -1)
    289 			return 0;
    290 		else
    291 			u_arg[i] = v;
    292 #elif defined(SH) || defined(SH64)
    293 	/* SH has always passed the args in registers */
    294 	int i;
    295 	for (i=0; i<6; i++)
    296 		u_arg[i] = tcp->u_arg[i];
    297 #else
    298 # if defined(X86_64)
    299 	if (current_personality == 1) {
    300 		int i;
    301 		for (i = 0; i < 6; ++i) {
    302 			unsigned int val;
    303 			if (umove(tcp, tcp->u_arg[0] + i * 4, &val) == -1)
    304 				return 0;
    305 			u_arg[i] = val;
    306 		}
    307 	}
    308 	else
    309 # endif
    310 	if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1)
    311 		return 0;
    312 #endif	// defined(IA64)
    313 	return print_mmap(tcp, u_arg, u_arg[5]);
    314 }
    315 #endif
    316 
    317 int
    318 sys_mmap(tcp)
    319 struct tcb *tcp;
    320 {
    321 	long long offset = tcp->u_arg[5];
    322 
    323 #if defined(LINUX) && defined(SH64)
    324 	/*
    325 	 * Old mmap differs from new mmap in specifying the
    326 	 * offset in units of bytes rather than pages.  We
    327 	 * pretend it's in byte units so the user only ever
    328 	 * sees bytes in the printout.
    329 	 */
    330 	offset <<= PAGE_SHIFT;
    331 #endif
    332 #if defined(LINUX_MIPSN32)
    333 	offset = tcp->ext_arg[5];
    334 #endif
    335 	return print_mmap(tcp, tcp->u_arg, offset);
    336 }
    337 #endif /* !HAVE_LONG_LONG_OFF_T */
    338 
    339 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
    340 int
    341 sys_mmap64(struct tcb *tcp)
    342 {
    343 #ifdef linux
    344 #ifdef ALPHA
    345 	long *u_arg = tcp->u_arg;
    346 #else /* !ALPHA */
    347 	long u_arg[7];
    348 #endif /* !ALPHA */
    349 #else /* !linux */
    350 	long *u_arg = tcp->u_arg;
    351 #endif /* !linux */
    352 
    353 	if (entering(tcp)) {
    354 #ifdef linux
    355 #ifndef ALPHA
    356 		if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
    357 				(char *) u_arg) == -1)
    358 			return 0;
    359 #endif /* ALPHA */
    360 #endif /* linux */
    361 
    362 		/* addr */
    363 		tprintf("%#lx, ", u_arg[0]);
    364 		/* len */
    365 		tprintf("%lu, ", u_arg[1]);
    366 		/* prot */
    367 		printflags(mmap_prot, u_arg[2], "PROT_???");
    368 		tprintf(", ");
    369 		/* flags */
    370 #ifdef MAP_TYPE
    371 		printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
    372 		addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
    373 #else
    374 		printflags(mmap_flags, u_arg[3], "MAP_???");
    375 #endif
    376 		/* fd */
    377 		tprintf(", ");
    378 		printfd(tcp, tcp->u_arg[4]);
    379 		/* offset */
    380 		printllval(tcp, ", %#llx", 5);
    381 	}
    382 	return RVAL_HEX;
    383 }
    384 #endif
    385 
    386 
    387 int
    388 sys_munmap(tcp)
    389 struct tcb *tcp;
    390 {
    391 	if (entering(tcp)) {
    392 		tprintf("%#lx, %lu",
    393 			tcp->u_arg[0], tcp->u_arg[1]);
    394 	}
    395 	return 0;
    396 }
    397 
    398 int
    399 sys_mprotect(tcp)
    400 struct tcb *tcp;
    401 {
    402 	if (entering(tcp)) {
    403 		tprintf("%#lx, %lu, ",
    404 			tcp->u_arg[0], tcp->u_arg[1]);
    405 		printflags(mmap_prot, tcp->u_arg[2], "PROT_???");
    406 	}
    407 	return 0;
    408 }
    409 
    410 #ifdef LINUX
    411 
    412 static const struct xlat mremap_flags[] = {
    413 	{ MREMAP_MAYMOVE,	"MREMAP_MAYMOVE"	},
    414 #ifdef MREMAP_FIXED
    415 	{ MREMAP_FIXED,		"MREMAP_FIXED"		},
    416 #endif
    417 	{ 0,			NULL			}
    418 };
    419 
    420 int
    421 sys_mremap(struct tcb *tcp)
    422 {
    423 	if (entering(tcp)) {
    424 		tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
    425 			tcp->u_arg[2]);
    426 		printflags(mremap_flags, tcp->u_arg[3], "MREMAP_???");
    427 #ifdef MREMAP_FIXED
    428 		if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) ==
    429 		    (MREMAP_MAYMOVE | MREMAP_FIXED))
    430 			tprintf(", %#lx", tcp->u_arg[4]);
    431 #endif
    432 	}
    433 	return RVAL_HEX;
    434 }
    435 
    436 static const struct xlat madvise_cmds[] = {
    437 #ifdef MADV_NORMAL
    438 	{ MADV_NORMAL,		"MADV_NORMAL" },
    439 #endif
    440 #ifdef MADV_RANDOM
    441 	{ MADV_RANDOM,		"MADV_RANDOM" },
    442 #endif
    443 #ifdef MADV_SEQUENTIAL
    444 	{ MADV_SEQUENTIAL,	"MADV_SEQUENTIAL" },
    445 #endif
    446 #ifdef MADV_WILLNEED
    447 	{ MADV_WILLNEED,	"MADV_WILLNEED" },
    448 #endif
    449 #ifdef MADV_DONTNEED
    450 	{ MADV_DONTNEED,	"MADV_DONTNEED" },
    451 #endif
    452 	{ 0,			NULL },
    453 };
    454 
    455 
    456 int
    457 sys_madvise(tcp)
    458 struct tcb *tcp;
    459 {
    460 	if (entering(tcp)) {
    461 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    462 		printxval(madvise_cmds, tcp->u_arg[2], "MADV_???");
    463 	}
    464 	return 0;
    465 }
    466 
    467 
    468 static const struct xlat mlockall_flags[] = {
    469 #ifdef MCL_CURRENT
    470 	{ MCL_CURRENT,	"MCL_CURRENT" },
    471 #endif
    472 #ifdef MCL_FUTURE
    473 	{ MCL_FUTURE,	"MCL_FUTURE" },
    474 #endif
    475 	{ 0,		NULL}
    476 };
    477 
    478 int
    479 sys_mlockall(tcp)
    480 struct tcb *tcp;
    481 {
    482 	if (entering(tcp)) {
    483 		printflags(mlockall_flags, tcp->u_arg[0], "MCL_???");
    484 	}
    485 	return 0;
    486 }
    487 
    488 
    489 #endif /* LINUX */
    490 
    491 #ifdef MS_ASYNC
    492 
    493 static const struct xlat mctl_sync[] = {
    494 #ifdef MS_SYNC
    495 	{ MS_SYNC,	"MS_SYNC"	},
    496 #endif
    497 	{ MS_ASYNC,	"MS_ASYNC"	},
    498 	{ MS_INVALIDATE,"MS_INVALIDATE"	},
    499 	{ 0,		NULL		},
    500 };
    501 
    502 int
    503 sys_msync(tcp)
    504 struct tcb *tcp;
    505 {
    506 	if (entering(tcp)) {
    507 		/* addr */
    508 		tprintf("%#lx", tcp->u_arg[0]);
    509 		/* len */
    510 		tprintf(", %lu, ", tcp->u_arg[1]);
    511 		/* flags */
    512 		printflags(mctl_sync, tcp->u_arg[2], "MS_???");
    513 	}
    514 	return 0;
    515 }
    516 
    517 #endif /* MS_ASYNC */
    518 
    519 #ifdef MC_SYNC
    520 
    521 static const struct xlat mctl_funcs[] = {
    522 	{ MC_LOCK,	"MC_LOCK"	},
    523 	{ MC_LOCKAS,	"MC_LOCKAS"	},
    524 	{ MC_SYNC,	"MC_SYNC"	},
    525 	{ MC_UNLOCK,	"MC_UNLOCK"	},
    526 	{ MC_UNLOCKAS,	"MC_UNLOCKAS"	},
    527 	{ 0,		NULL		},
    528 };
    529 
    530 static const struct xlat mctl_lockas[] = {
    531 	{ MCL_CURRENT,	"MCL_CURRENT"	},
    532 	{ MCL_FUTURE,	"MCL_FUTURE"	},
    533 	{ 0,		NULL		},
    534 };
    535 
    536 int
    537 sys_mctl(tcp)
    538 struct tcb *tcp;
    539 {
    540 	int arg, function;
    541 
    542 	if (entering(tcp)) {
    543 		/* addr */
    544 		tprintf("%#lx", tcp->u_arg[0]);
    545 		/* len */
    546 		tprintf(", %lu, ", tcp->u_arg[1]);
    547 		/* function */
    548 		function = tcp->u_arg[2];
    549 		printflags(mctl_funcs, function, "MC_???");
    550 		/* arg */
    551 		arg = tcp->u_arg[3];
    552 		tprintf(", ");
    553 		switch (function) {
    554 		case MC_SYNC:
    555 			printflags(mctl_sync, arg, "MS_???");
    556 			break;
    557 		case MC_LOCKAS:
    558 			printflags(mctl_lockas, arg, "MCL_???");
    559 			break;
    560 		default:
    561 			tprintf("%#x", arg);
    562 			break;
    563 		}
    564 	}
    565 	return 0;
    566 }
    567 
    568 #endif /* MC_SYNC */
    569 
    570 int
    571 sys_mincore(tcp)
    572 struct tcb *tcp;
    573 {
    574 	unsigned long i, len;
    575 	char *vec = NULL;
    576 
    577 	if (entering(tcp)) {
    578 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    579 	} else {
    580 		len = tcp->u_arg[1];
    581 		if (syserror(tcp) || tcp->u_arg[2] == 0 ||
    582 			(vec = malloc(len)) == NULL ||
    583 			umoven(tcp, tcp->u_arg[2], len, vec) < 0)
    584 			tprintf("%#lx", tcp->u_arg[2]);
    585 		else {
    586 			tprintf("[");
    587 			for (i = 0; i < len; i++) {
    588 				if (abbrev(tcp) && i >= max_strlen) {
    589 					tprintf("...");
    590 					break;
    591 				}
    592 				tprintf((vec[i] & 1) ? "1" : "0");
    593 			}
    594 			tprintf("]");
    595 		}
    596 		if (vec)
    597 			free(vec);
    598 	}
    599 	return 0;
    600 }
    601 
    602 #if defined(ALPHA) || defined(FREEBSD) || defined(IA64) || defined(SUNOS4) || defined(SVR4) || defined(SPARC) || defined(SPARC64)
    603 int
    604 sys_getpagesize(tcp)
    605 struct tcb *tcp;
    606 {
    607 	if (exiting(tcp))
    608 		return RVAL_HEX;
    609 	return 0;
    610 }
    611 #endif /* ALPHA || FREEBSD || IA64 || SUNOS4 || SVR4 */
    612 
    613 #if defined(LINUX) && defined(__i386__)
    614 void
    615 print_ldt_entry(struct modify_ldt_ldt_s *ldt_entry)
    616 {
    617 	tprintf("base_addr:%#08lx, "
    618 		"limit:%d, "
    619 		"seg_32bit:%d, "
    620 		"contents:%d, "
    621 		"read_exec_only:%d, "
    622 		"limit_in_pages:%d, "
    623 		"seg_not_present:%d, "
    624 		"useable:%d}",
    625 		(long) ldt_entry->base_addr,
    626 		ldt_entry->limit,
    627 		ldt_entry->seg_32bit,
    628 		ldt_entry->contents,
    629 		ldt_entry->read_exec_only,
    630 		ldt_entry->limit_in_pages,
    631 		ldt_entry->seg_not_present,
    632 		ldt_entry->useable);
    633 }
    634 
    635 int
    636 sys_modify_ldt(tcp)
    637 struct tcb *tcp;
    638 {
    639 	if (entering(tcp)) {
    640 		struct modify_ldt_ldt_s copy;
    641 		tprintf("%ld", tcp->u_arg[0]);
    642 		if (tcp->u_arg[1] == 0
    643 				|| tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
    644 				|| umove(tcp, tcp->u_arg[1], &copy) == -1)
    645 			tprintf(", %lx", tcp->u_arg[1]);
    646 		else {
    647 			tprintf(", {entry_number:%d, ", copy.entry_number);
    648 			if (!verbose(tcp))
    649 				tprintf("...}");
    650 			else {
    651 				print_ldt_entry(&copy);
    652 			}
    653 		}
    654 		tprintf(", %lu", tcp->u_arg[2]);
    655 	}
    656 	return 0;
    657 }
    658 
    659 int
    660 sys_set_thread_area(tcp)
    661 struct tcb *tcp;
    662 {
    663 	struct modify_ldt_ldt_s copy;
    664 	if (entering(tcp)) {
    665 		if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
    666 			if (copy.entry_number == -1)
    667 				tprintf("{entry_number:%d -> ",
    668 					copy.entry_number);
    669 			else
    670 				tprintf("{entry_number:");
    671 		}
    672 	} else {
    673 		if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
    674 			tprintf("%d, ", copy.entry_number);
    675 			if (!verbose(tcp))
    676 				tprintf("...}");
    677 			else {
    678 				print_ldt_entry(&copy);
    679 			}
    680 		} else {
    681 			tprintf("%lx", tcp->u_arg[0]);
    682 		}
    683 	}
    684 	return 0;
    685 
    686 }
    687 
    688 int
    689 sys_get_thread_area(tcp)
    690 struct tcb *tcp;
    691 {
    692 	struct modify_ldt_ldt_s copy;
    693 	if (exiting(tcp)) {
    694 		if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
    695 			tprintf("{entry_number:%d, ", copy.entry_number);
    696 			if (!verbose(tcp))
    697 				tprintf("...}");
    698 			else {
    699 				print_ldt_entry(&copy);
    700 			}
    701 		} else {
    702 			tprintf("%lx", tcp->u_arg[0]);
    703 		}
    704 	}
    705 	return 0;
    706 
    707 }
    708 #endif /* LINUX && __i386__ */
    709 
    710 #if defined(LINUX) && defined(M68K)
    711 
    712 int
    713 sys_set_thread_area(tcp)
    714 struct tcb *tcp;
    715 {
    716 	if (entering(tcp))
    717 		tprintf("%#lx", tcp->u_arg[0]);
    718 	return 0;
    719 
    720 }
    721 
    722 int
    723 sys_get_thread_area(tcp)
    724 struct tcb *tcp;
    725 {
    726 	return RVAL_HEX;
    727 }
    728 #endif
    729 
    730 #if defined(LINUX)
    731 int
    732 sys_remap_file_pages(tcp)
    733 struct tcb *tcp;
    734 {
    735 	if (entering(tcp)) {
    736 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    737 		printflags(mmap_prot, tcp->u_arg[2], "PROT_???");
    738 		tprintf(", %lu, ", tcp->u_arg[3]);
    739 #ifdef MAP_TYPE
    740 		printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???");
    741 		addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE);
    742 #else
    743 		printflags(mmap_flags, tcp->u_arg[4], "MAP_???");
    744 #endif
    745 	}
    746 	return 0;
    747 }
    748 
    749 
    750 #define MPOL_DEFAULT    0
    751 #define MPOL_PREFERRED  1
    752 #define MPOL_BIND       2
    753 #define MPOL_INTERLEAVE 3
    754 
    755 #define MPOL_F_NODE     (1<<0)
    756 #define MPOL_F_ADDR     (1<<1)
    757 
    758 #define MPOL_MF_STRICT  (1<<0)
    759 #define MPOL_MF_MOVE	(1<<1)
    760 #define MPOL_MF_MOVE_ALL (1<<2)
    761 
    762 
    763 static const struct xlat policies[] = {
    764 	{ MPOL_DEFAULT,		"MPOL_DEFAULT"		},
    765 	{ MPOL_PREFERRED,	"MPOL_PREFERRED"	},
    766 	{ MPOL_BIND,		"MPOL_BIND"		},
    767 	{ MPOL_INTERLEAVE,	"MPOL_INTERLEAVE"	},
    768 	{ 0,			NULL			}
    769 };
    770 
    771 static const struct xlat mbindflags[] = {
    772 	{ MPOL_MF_STRICT,	"MPOL_MF_STRICT"	},
    773 	{ MPOL_MF_MOVE,		"MPOL_MF_MOVE"		},
    774 	{ MPOL_MF_MOVE_ALL,	"MPOL_MF_MOVE_ALL"	},
    775 	{ 0,			NULL			}
    776 };
    777 
    778 static const struct xlat mempolicyflags[] = {
    779 	{ MPOL_F_NODE,		"MPOL_F_NODE"		},
    780 	{ MPOL_F_ADDR,		"MPOL_F_ADDR"		},
    781 	{ 0,			NULL			}
    782 };
    783 
    784 static const struct xlat move_pages_flags[] = {
    785 	{ MPOL_MF_MOVE,		"MPOL_MF_MOVE"		},
    786 	{ MPOL_MF_MOVE_ALL,	"MPOL_MF_MOVE_ALL"	},
    787 	{ 0,			NULL			}
    788 };
    789 
    790 
    791 static void
    792 get_nodes(tcp, ptr, maxnodes, err)
    793 struct tcb *tcp;
    794 unsigned long ptr;
    795 unsigned long maxnodes;
    796 int err;
    797 {
    798 	unsigned long nlongs, size, end;
    799 
    800 	nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long));
    801 	size = nlongs * sizeof(long);
    802 	end = ptr + size;
    803 	if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes)
    804 			    && (end > ptr))) {
    805 		unsigned long n, cur, abbrev_end;
    806 		int failed = 0;
    807 
    808 		if (abbrev(tcp)) {
    809 			abbrev_end = ptr + max_strlen * sizeof(long);
    810 			if (abbrev_end < ptr)
    811 				abbrev_end = end;
    812 		} else {
    813 			abbrev_end = end;
    814 		}
    815 		tprintf(", {");
    816 		for (cur = ptr; cur < end; cur += sizeof(long)) {
    817 			if (cur > ptr)
    818 				tprintf(", ");
    819 			if (cur >= abbrev_end) {
    820 				tprintf("...");
    821 				break;
    822 			}
    823 			if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) {
    824 				tprintf("?");
    825 				failed = 1;
    826 				break;
    827 			}
    828 			tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n);
    829 		}
    830 		tprintf("}");
    831 		if (failed)
    832 			tprintf(" %#lx", ptr);
    833 	} else
    834 		tprintf(", %#lx", ptr);
    835 	tprintf(", %lu", maxnodes);
    836 }
    837 
    838 int
    839 sys_mbind(tcp)
    840 struct tcb *tcp;
    841 {
    842 	if (entering(tcp)) {
    843 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    844 		printxval(policies, tcp->u_arg[2], "MPOL_???");
    845 		get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0);
    846 		tprintf(", ");
    847 		printflags(mbindflags, tcp->u_arg[5], "MPOL_???");
    848 	}
    849 	return 0;
    850 }
    851 
    852 int
    853 sys_set_mempolicy(tcp)
    854 struct tcb *tcp;
    855 {
    856 	if (entering(tcp)) {
    857 		printxval(policies, tcp->u_arg[0], "MPOL_???");
    858 		get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0);
    859 	}
    860 	return 0;
    861 }
    862 
    863 int
    864 sys_get_mempolicy(tcp)
    865 struct tcb *tcp;
    866 {
    867 	if (exiting(tcp)) {
    868 		int pol;
    869 		if (tcp->u_arg[0] == 0)
    870 			tprintf("NULL");
    871 		else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0)
    872 			tprintf("%#lx", tcp->u_arg[0]);
    873 		else
    874 			printxval(policies, pol, "MPOL_???");
    875 		get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp));
    876 		tprintf(", %#lx, ", tcp->u_arg[3]);
    877 		printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???");
    878 	}
    879 	return 0;
    880 }
    881 
    882 int
    883 sys_move_pages(tcp)
    884 struct tcb *tcp;
    885 {
    886 	if (entering(tcp)) {
    887 		unsigned long npages = tcp->u_arg[1];
    888 		tprintf("%ld, %lu, ", tcp->u_arg[0], npages);
    889 		if (tcp->u_arg[2] == 0)
    890 			tprintf("NULL, ");
    891 		else {
    892 			int i;
    893 			long puser = tcp->u_arg[2];
    894 			tprintf("{");
    895 			for (i = 0; i < npages; ++i) {
    896 				void *p;
    897 				if (i > 0)
    898 					tprintf(", ");
    899 				if (umove(tcp, puser, &p) < 0) {
    900 					tprintf("???");
    901 					break;
    902 				}
    903 				tprintf("%p", p);
    904 				puser += sizeof (void *);
    905 			}
    906 			tprintf("}, ");
    907 		}
    908 		if (tcp->u_arg[3] == 0)
    909 			tprintf("NULL, ");
    910 		else {
    911 			int i;
    912 			long nodeuser = tcp->u_arg[3];
    913 			tprintf("{");
    914 			for (i = 0; i < npages; ++i) {
    915 				int node;
    916 				if (i > 0)
    917 					tprintf(", ");
    918 				if (umove(tcp, nodeuser, &node) < 0) {
    919 					tprintf("???");
    920 					break;
    921 				}
    922 				tprintf("%#x", node);
    923 				nodeuser += sizeof (int);
    924 			}
    925 			tprintf("}, ");
    926 		}
    927 	}
    928 	if (exiting(tcp)) {
    929 		unsigned long npages = tcp->u_arg[1];
    930 		if (tcp->u_arg[4] == 0)
    931 			tprintf("NULL, ");
    932 		else {
    933 			int i;
    934 			long statususer = tcp->u_arg[4];
    935 			tprintf("{");
    936 			for (i = 0; i < npages; ++i) {
    937 				int status;
    938 				if (i > 0)
    939 					tprintf(", ");
    940 				if (umove(tcp, statususer, &status) < 0) {
    941 					tprintf("???");
    942 					break;
    943 				}
    944 				tprintf("%#x", status);
    945 				statususer += sizeof (int);
    946 			}
    947 			tprintf("}, ");
    948 		}
    949 		printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???");
    950 	}
    951 	return 0;
    952 }
    953 #endif
    954 
    955 #if defined(LINUX) && defined(POWERPC)
    956 int
    957 sys_subpage_prot(tcp)
    958 struct tcb *tcp;
    959 {
    960 	if (entering(tcp)) {
    961 		unsigned long cur, end, abbrev_end, entries;
    962 		unsigned int entry;
    963 
    964 		tprintf("%#lx, %#lx, ", tcp->u_arg[0], tcp->u_arg[1]);
    965 		entries = tcp->u_arg[1] >> 16;
    966 		if (!entries || !tcp->u_arg[2]) {
    967 			tprintf("{}");
    968 			return 0;
    969 		}
    970 		cur = tcp->u_arg[2];
    971 		end = cur + (sizeof(int) * entries);
    972 		if (!verbose(tcp) || end < tcp->u_arg[2]) {
    973 			tprintf("%#lx", tcp->u_arg[2]);
    974 			return 0;
    975 		}
    976 		if (abbrev(tcp)) {
    977 			abbrev_end = cur + (sizeof(int) * max_strlen);
    978 			if (abbrev_end > end)
    979 				abbrev_end = end;
    980 		}
    981 		else
    982 			abbrev_end = end;
    983 		tprintf("{");
    984 		for (; cur < end; cur += sizeof(int)) {
    985 			if (cur > tcp->u_arg[2])
    986 				tprintf(", ");
    987 			if (cur >= abbrev_end) {
    988 				tprintf("...");
    989 				break;
    990 			}
    991 			if (umove(tcp, cur, &entry) < 0) {
    992 				tprintf("??? [%#lx]", cur);
    993 				break;
    994 			}
    995 			else
    996 				tprintf("%#08x", entry);
    997 		}
    998 		tprintf("}");
    999 	}
   1000 
   1001 	return 0;
   1002 }
   1003 #endif
   1004