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: mem.c,v 1.36 2005/06/01 19:22:07 roland Exp $
     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 int
     74 sys_sbrk(tcp)
     75 struct tcb *tcp;
     76 {
     77 	if (entering(tcp)) {
     78 		tprintf("%lu", tcp->u_arg[0]);
     79 	}
     80 	return RVAL_HEX;
     81 }
     82 
     83 static const struct xlat mmap_prot[] = {
     84 	{ PROT_NONE,	"PROT_NONE",	},
     85 	{ PROT_READ,	"PROT_READ"	},
     86 	{ PROT_WRITE,	"PROT_WRITE"	},
     87 	{ PROT_EXEC,	"PROT_EXEC"	},
     88 #ifdef PROT_SEM
     89 	{ PROT_SEM,	"PROT_SEM"	},
     90 #endif
     91 #ifdef PROT_GROWSDOWN
     92 	{ PROT_GROWSDOWN,"PROT_GROWSDOWN"},
     93 #endif
     94 #ifdef PROT_GROWSUP
     95 	{ PROT_GROWSUP, "PROT_GROWSUP"	},
     96 #endif
     97 	{ 0,		NULL		},
     98 };
     99 
    100 static const struct xlat mmap_flags[] = {
    101 	{ MAP_SHARED,	"MAP_SHARED"	},
    102 	{ MAP_PRIVATE,	"MAP_PRIVATE"	},
    103 	{ MAP_FIXED,	"MAP_FIXED"	},
    104 #ifdef MAP_ANONYMOUS
    105 	{ MAP_ANONYMOUS,"MAP_ANONYMOUS"	},
    106 #endif
    107 #ifdef MAP_RENAME
    108 	{ MAP_RENAME,	"MAP_RENAME"	},
    109 #endif
    110 #ifdef MAP_NORESERVE
    111 	{ MAP_NORESERVE,"MAP_NORESERVE"	},
    112 #endif
    113 #ifdef MAP_POPULATE
    114 	{ MAP_POPULATE, "MAP_POPULATE" },
    115 #endif
    116 #ifdef MAP_NONBLOCK
    117 	{ MAP_NONBLOCK, "MAP_NONBLOCK" },
    118 #endif
    119 	/*
    120 	 * XXX - this was introduced in SunOS 4.x to distinguish between
    121 	 * the old pre-4.x "mmap()", which:
    122 	 *
    123 	 *	only let you map devices with an "mmap" routine (e.g.,
    124 	 *	frame buffers) in;
    125 	 *
    126 	 *	required you to specify the mapping address;
    127 	 *
    128 	 *	returned 0 on success and -1 on failure;
    129 	 *
    130 	 * memory and which, and the 4.x "mmap()" which:
    131 	 *
    132 	 *	can map plain files;
    133 	 *
    134 	 *	can be asked to pick where to map the file;
    135 	 *
    136 	 *	returns the address where it mapped the file on success
    137 	 *	and -1 on failure.
    138 	 *
    139 	 * It's not actually used in source code that calls "mmap()"; the
    140 	 * "mmap()" routine adds it for you.
    141 	 *
    142 	 * It'd be nice to come up with some way of eliminating it from
    143 	 * the flags, e.g. reporting calls *without* it as "old_mmap()"
    144 	 * and calls with it as "mmap()".
    145 	 */
    146 #ifdef _MAP_NEW
    147 	{ _MAP_NEW,	"_MAP_NEW"	},
    148 #endif
    149 #ifdef MAP_GROWSDOWN
    150 	{ MAP_GROWSDOWN,"MAP_GROWSDOWN"	},
    151 #endif
    152 #ifdef MAP_DENYWRITE
    153 	{ MAP_DENYWRITE,"MAP_DENYWRITE"	},
    154 #endif
    155 #ifdef MAP_EXECUTABLE
    156 	{ MAP_EXECUTABLE,"MAP_EXECUTABLE"},
    157 #endif
    158 #ifdef MAP_INHERIT
    159 	{ MAP_INHERIT,"MAP_INHERIT"	},
    160 #endif
    161 #ifdef MAP_FILE
    162 	{ MAP_FILE,"MAP_FILE"},
    163 #endif
    164 #ifdef MAP_LOCKED
    165 	{ MAP_LOCKED,"MAP_LOCKED"},
    166 #endif
    167 	/* FreeBSD ones */
    168 #ifdef MAP_ANON
    169 	{ MAP_ANON,		"MAP_ANON"	},
    170 #endif
    171 #ifdef MAP_HASSEMAPHORE
    172 	{ MAP_HASSEMAPHORE,	"MAP_HASSEMAPHORE"	},
    173 #endif
    174 #ifdef MAP_STACK
    175 	{ MAP_STACK,		"MAP_STACK"	},
    176 #endif
    177 #ifdef MAP_NOSYNC
    178 	{ MAP_NOSYNC,		"MAP_NOSYNC"	},
    179 #endif
    180 #ifdef MAP_NOCORE
    181 	{ MAP_NOCORE,		"MAP_NOCORE"	},
    182 #endif
    183 	{ 0,		NULL		},
    184 };
    185 
    186 #if !HAVE_LONG_LONG_OFF_T
    187 static
    188 int
    189 print_mmap(tcp,u_arg)
    190 struct tcb *tcp;
    191 long *u_arg;
    192 {
    193 	if (entering(tcp)) {
    194 		/* addr */
    195 		if (!u_arg[0])
    196 			tprintf("NULL, ");
    197 		else
    198 			tprintf("%#lx, ", u_arg[0]);
    199 		/* len */
    200 		tprintf("%lu, ", u_arg[1]);
    201 		/* prot */
    202 		printflags(mmap_prot, u_arg[2], "PROT_???");
    203 		tprintf(", ");
    204 		/* flags */
    205 #ifdef MAP_TYPE
    206 		printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
    207 		addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
    208 #else
    209 		printflags(mmap_flags, u_arg[3], "MAP_???");
    210 #endif
    211 		/* fd (is always int, not long) */
    212 		tprintf(", %d, ", (int)u_arg[4]);
    213 		/* offset */
    214 		tprintf("%#lx", u_arg[5]);
    215 	}
    216 	return RVAL_HEX;
    217 }
    218 
    219 #ifdef LINUX
    220 int sys_old_mmap(tcp)
    221 struct tcb *tcp;
    222 {
    223     long u_arg[6];
    224 
    225 #if	defined(IA64)
    226     int i, v;
    227     /*
    228      *  IA64 processes never call this routine, they only use the
    229      *  new `sys_mmap' interface.  This code converts the integer
    230      *  arguments that the IA32 process pushed onto the stack into
    231      *  longs.
    232      *
    233      *  Note that addresses with bit 31 set will be sign extended.
    234      *  Fortunately, those addresses are not currently being generated
    235      *  for IA32 processes so it's not a problem.
    236      */
    237     for (i = 0; i < 6; i++)
    238 	if (umove(tcp, tcp->u_arg[0] + (i * sizeof(int)), &v) == -1)
    239 		return 0;
    240 	else
    241 		u_arg[i] = v;
    242 #elif defined(SH) || defined(SH64)
    243     /* SH has always passed the args in registers */
    244     int i;
    245     for (i=0; i<6; i++)
    246         u_arg[i] = tcp->u_arg[i];
    247 #else
    248     if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1)
    249 	    return 0;
    250 #endif	// defined(IA64)
    251     return print_mmap(tcp, u_arg);
    252 
    253 }
    254 #endif
    255 
    256 int
    257 sys_mmap(tcp)
    258 struct tcb *tcp;
    259 {
    260 #if defined(LINUX) && defined(SH64)
    261     /*
    262      * Old mmap differs from new mmap in specifying the
    263      * offset in units of bytes rather than pages.  We
    264      * pretend it's in byte units so the user only ever
    265      * sees bytes in the printout.
    266      */
    267     tcp->u_arg[5] <<= PAGE_SHIFT;
    268 #endif
    269     return print_mmap(tcp, tcp->u_arg);
    270 }
    271 #endif /* !HAVE_LONG_LONG_OFF_T */
    272 
    273 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
    274 int
    275 sys_mmap64(tcp)
    276 struct tcb *tcp;
    277 {
    278 #ifdef linux
    279 #ifdef ALPHA
    280 	long *u_arg = tcp->u_arg;
    281 #else /* !ALPHA */
    282 	long u_arg[7];
    283 #endif /* !ALPHA */
    284 #else /* !linux */
    285 	long *u_arg = tcp->u_arg;
    286 #endif /* !linux */
    287 
    288 	if (entering(tcp)) {
    289 #ifdef linux
    290 #ifndef ALPHA
    291 		if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
    292 				(char *) u_arg) == -1)
    293 			return 0;
    294 #endif /* ALPHA */
    295 #endif /* linux */
    296 		ALIGN64 (tcp, 5);	/* FreeBSD wierdies */
    297 
    298 		/* addr */
    299 		tprintf("%#lx, ", u_arg[0]);
    300 		/* len */
    301 		tprintf("%lu, ", u_arg[1]);
    302 		/* prot */
    303 		printflags(mmap_prot, u_arg[2], "PROT_???");
    304 		tprintf(", ");
    305 		/* flags */
    306 #ifdef MAP_TYPE
    307 		printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
    308 		addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
    309 #else
    310 		printflags(mmap_flags, u_arg[3], "MAP_???");
    311 #endif
    312 		/* fd */
    313 		tprintf(", %ld, ", u_arg[4]);
    314 		/* offset */
    315 		tprintf("%#llx", LONG_LONG(u_arg[5], u_arg[6]));
    316 	}
    317 	return RVAL_HEX;
    318 }
    319 #endif
    320 
    321 
    322 int
    323 sys_munmap(tcp)
    324 struct tcb *tcp;
    325 {
    326 	if (entering(tcp)) {
    327 		tprintf("%#lx, %lu",
    328 			tcp->u_arg[0], tcp->u_arg[1]);
    329 	}
    330 	return 0;
    331 }
    332 
    333 int
    334 sys_mprotect(tcp)
    335 struct tcb *tcp;
    336 {
    337 	if (entering(tcp)) {
    338 		tprintf("%#lx, %lu, ",
    339 			tcp->u_arg[0], tcp->u_arg[1]);
    340 		printflags(mmap_prot, tcp->u_arg[2], "PROT_???");
    341 	}
    342 	return 0;
    343 }
    344 
    345 #ifdef LINUX
    346 
    347 static const struct xlat mremap_flags[] = {
    348 	{ MREMAP_MAYMOVE,	"MREMAP_MAYMOVE"	},
    349 	{ 0,			NULL			}
    350 };
    351 
    352 int
    353 sys_mremap(tcp)
    354 struct tcb *tcp;
    355 {
    356 	if (entering(tcp)) {
    357 		tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
    358 			tcp->u_arg[2]);
    359 		printflags(mremap_flags, tcp->u_arg[3], "MREMAP_???");
    360 	}
    361 	return RVAL_HEX;
    362 }
    363 
    364 static const struct xlat madvise_flags[] = {
    365 #ifdef MADV_NORMAL
    366 	{ MADV_NORMAL,		"MADV_NORMAL" },
    367 #endif
    368 #ifdef MADZV_RANDOM
    369 	{ MADV_RANDOM,		"MADV_RANDOM" },
    370 #endif
    371 #ifdef MADV_SEQUENTIAL
    372 	{ MADV_SEQUENTIAL,	"MADV_SEQUENTIAL" },
    373 #endif
    374 #ifdef MADV_WILLNEED
    375 	{ MADV_WILLNEED,	"MADV_WILLNEED" },
    376 #endif
    377 #ifdef MADV_DONTNED
    378 	{ MADV_DONTNEED,	"MADV_DONTNEED" },
    379 #endif
    380 	{ 0,			NULL },
    381 };
    382 
    383 
    384 int
    385 sys_madvise(tcp)
    386 struct tcb *tcp;
    387 {
    388 	if (entering(tcp)) {
    389 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    390 		printflags(madvise_flags, tcp->u_arg[2], "MADV_???");
    391 	}
    392 	return 0;
    393 }
    394 
    395 
    396 static const struct xlat mlockall_flags[] = {
    397 #ifdef MCL_CURRENT
    398 	{ MCL_CURRENT,	"MCL_CURRENT" },
    399 #endif
    400 #ifdef MCL_FUTURE
    401 	{ MCL_FUTURE,	"MCL_FUTURE" },
    402 #endif
    403 	{ 0,		NULL}
    404 };
    405 
    406 int
    407 sys_mlockall(tcp)
    408 struct tcb *tcp;
    409 {
    410 	if (entering(tcp)) {
    411 		printflags(mlockall_flags, tcp->u_arg[0], "MCL_???");
    412 	}
    413 	return 0;
    414 }
    415 
    416 
    417 #endif /* LINUX */
    418 
    419 #ifdef MS_ASYNC
    420 
    421 static const struct xlat mctl_sync[] = {
    422 #ifdef MS_SYNC
    423 	{ MS_SYNC,	"MS_SYNC"	},
    424 #endif
    425 	{ MS_ASYNC,	"MS_ASYNC"	},
    426 	{ MS_INVALIDATE,"MS_INVALIDATE"	},
    427 	{ 0,		NULL		},
    428 };
    429 
    430 int
    431 sys_msync(tcp)
    432 struct tcb *tcp;
    433 {
    434 	if (entering(tcp)) {
    435 		/* addr */
    436 		tprintf("%#lx", tcp->u_arg[0]);
    437 		/* len */
    438 		tprintf(", %lu, ", tcp->u_arg[1]);
    439 		/* flags */
    440 		printflags(mctl_sync, tcp->u_arg[2], "MS_???");
    441 	}
    442 	return 0;
    443 }
    444 
    445 #endif /* MS_ASYNC */
    446 
    447 #ifdef MC_SYNC
    448 
    449 static const struct xlat mctl_funcs[] = {
    450 	{ MC_LOCK,	"MC_LOCK"	},
    451 	{ MC_LOCKAS,	"MC_LOCKAS"	},
    452 	{ MC_SYNC,	"MC_SYNC"	},
    453 	{ MC_UNLOCK,	"MC_UNLOCK"	},
    454 	{ MC_UNLOCKAS,	"MC_UNLOCKAS"	},
    455 	{ 0,		NULL		},
    456 };
    457 
    458 static const struct xlat mctl_lockas[] = {
    459 	{ MCL_CURRENT,	"MCL_CURRENT"	},
    460 	{ MCL_FUTURE,	"MCL_FUTURE"	},
    461 	{ 0,		NULL		},
    462 };
    463 
    464 int
    465 sys_mctl(tcp)
    466 struct tcb *tcp;
    467 {
    468 	int arg, function;
    469 
    470 	if (entering(tcp)) {
    471 		/* addr */
    472 		tprintf("%#lx", tcp->u_arg[0]);
    473 		/* len */
    474 		tprintf(", %lu, ", tcp->u_arg[1]);
    475 		/* function */
    476 		function = tcp->u_arg[2];
    477 		printflags(mctl_funcs, function, "MC_???");
    478 		/* arg */
    479 		arg = tcp->u_arg[3];
    480 		tprintf(", ");
    481 		switch (function) {
    482 		case MC_SYNC:
    483 			printflags(mctl_sync, arg, "MS_???");
    484 			break;
    485 		case MC_LOCKAS:
    486 			printflags(mctl_lockas, arg, "MCL_???");
    487 			break;
    488 		default:
    489 			tprintf("%#x", arg);
    490 			break;
    491 		}
    492 	}
    493 	return 0;
    494 }
    495 
    496 #endif /* MC_SYNC */
    497 
    498 int
    499 sys_mincore(tcp)
    500 struct tcb *tcp;
    501 {
    502 	unsigned long i, len;
    503 	char *vec = NULL;
    504 
    505 	if (entering(tcp)) {
    506 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    507 	} else {
    508 		len = tcp->u_arg[1];
    509 		if (syserror(tcp) || tcp->u_arg[2] == 0 ||
    510 			(vec = malloc(len)) == NULL ||
    511 			umoven(tcp, tcp->u_arg[2], len, vec) < 0)
    512 			tprintf("%#lx", tcp->u_arg[2]);
    513 		else {
    514 			tprintf("[");
    515 			for (i = 0; i < len; i++) {
    516 				if (abbrev(tcp) && i >= max_strlen) {
    517 					tprintf("...");
    518 					break;
    519 				}
    520 				tprintf((vec[i] & 1) ? "1" : "0");
    521 			}
    522 			tprintf("]");
    523 		}
    524 		if (vec)
    525 			free(vec);
    526 	}
    527 	return 0;
    528 }
    529 
    530 int
    531 sys_getpagesize(tcp)
    532 struct tcb *tcp;
    533 {
    534 	if (exiting(tcp))
    535 		return RVAL_HEX;
    536 	return 0;
    537 }
    538 
    539 #if defined(LINUX) && defined(__i386__)
    540 void
    541 print_ldt_entry (ldt_entry)
    542 struct modify_ldt_ldt_s *ldt_entry;
    543 {
    544 	tprintf("base_addr:%#08lx, "
    545 		"limit:%d, "
    546 		"seg_32bit:%d, "
    547 		"contents:%d, "
    548 		"read_exec_only:%d, "
    549 		"limit_in_pages:%d, "
    550 		"seg_not_present:%d, "
    551 		"useable:%d}",
    552 		ldt_entry->base_addr,
    553 		ldt_entry->limit,
    554 		ldt_entry->seg_32bit,
    555 		ldt_entry->contents,
    556 		ldt_entry->read_exec_only,
    557 		ldt_entry->limit_in_pages,
    558 		ldt_entry->seg_not_present,
    559 		ldt_entry->useable);
    560 }
    561 
    562 int
    563 sys_modify_ldt(tcp)
    564 struct tcb *tcp;
    565 {
    566 	if (entering(tcp)) {
    567 		struct modify_ldt_ldt_s copy;
    568 		tprintf("%ld", tcp->u_arg[0]);
    569 		if (tcp->u_arg[1] == 0
    570 				|| tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
    571 				|| umove(tcp, tcp->u_arg[1], &copy) == -1)
    572 			tprintf(", %lx", tcp->u_arg[1]);
    573 		else {
    574 			tprintf(", {entry_number:%d, ", copy.entry_number);
    575 			if (!verbose(tcp))
    576 				tprintf("...}");
    577 			else {
    578 				print_ldt_entry(&copy);
    579 			}
    580 		}
    581 		tprintf(", %lu", tcp->u_arg[2]);
    582 	}
    583 	return 0;
    584 }
    585 
    586 int
    587 sys_set_thread_area(tcp)
    588 struct tcb *tcp;
    589 {
    590 	struct modify_ldt_ldt_s copy;
    591 	if (entering(tcp)) {
    592 		if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
    593 			if (copy.entry_number == -1)
    594 				tprintf("{entry_number:%d -> ",
    595 					copy.entry_number);
    596 			else
    597 				tprintf("{entry_number:");
    598 		}
    599 	} else {
    600 		if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
    601 			tprintf("%d, ", copy.entry_number);
    602 			if (!verbose(tcp))
    603 				tprintf("...}");
    604 			else {
    605 				print_ldt_entry(&copy);
    606 			}
    607 		} else {
    608 			tprintf("%lx", tcp->u_arg[0]);
    609 		}
    610 	}
    611 	return 0;
    612 
    613 }
    614 
    615 int
    616 sys_get_thread_area(tcp)
    617 struct tcb *tcp;
    618 {
    619 	struct modify_ldt_ldt_s copy;
    620 	if (exiting(tcp)) {
    621 		if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
    622 			tprintf("{entry_number:%d, ", copy.entry_number);
    623 			if (!verbose(tcp))
    624 				tprintf("...}");
    625 			else {
    626 				print_ldt_entry(&copy);
    627 			}
    628 		} else {
    629 			tprintf("%lx", tcp->u_arg[0]);
    630 		}
    631 	}
    632 	return 0;
    633 
    634 }
    635 #endif /* LINUX && __i386__ */
    636 
    637 #if defined(LINUX)
    638 int
    639 sys_remap_file_pages(tcp)
    640 struct tcb *tcp;
    641 {
    642 	if (entering(tcp)) {
    643 		tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    644 		printflags(mmap_prot, tcp->u_arg[2], "PROT_???");
    645 		tprintf(", %lu, ", tcp->u_arg[3]);
    646 #ifdef MAP_TYPE
    647 		printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???");
    648 		addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE);
    649 #else
    650 		printflags(mmap_flags, tcp->u_arg[4], "MAP_???");
    651 #endif
    652 	}
    653 	return 0;
    654 }
    655 
    656 
    657 #define MPOL_DEFAULT    0
    658 #define MPOL_PREFERRED  1
    659 #define MPOL_BIND       2
    660 #define MPOL_INTERLEAVE 3
    661 
    662 #define MPOL_F_NODE     (1<<0)
    663 #define MPOL_F_ADDR     (1<<1)
    664 
    665 #define MPOL_MF_STRICT  (1<<0)
    666 
    667 
    668 static const struct xlat policies[] = {
    669 	{ MPOL_DEFAULT,		"MPOL_DEFAULT"		},
    670 	{ MPOL_PREFERRED,	"MPOL_PREFERRED"	},
    671 	{ MPOL_BIND,		"MPOL_BIND"		},
    672 	{ MPOL_INTERLEAVE,	"MPOL_INTERLEAVE"	},
    673 	{ 0,			NULL			}
    674 };
    675 
    676 static const struct xlat mbindflags[] = {
    677 	{ MPOL_MF_STRICT,	"MPOL_MF_STRICT"	},
    678 	{ 0,			NULL			}
    679 };
    680 
    681 static const struct xlat mempolicyflags[] = {
    682 	{ MPOL_F_NODE,		"MPOL_F_NODE"		},
    683 	{ MPOL_F_ADDR,		"MPOL_F_ADDR"		},
    684 	{ 0,			NULL			}
    685 };
    686 
    687 
    688 static void
    689 get_nodes(tcp, ptr, maxnodes, err)
    690 struct tcb *tcp;
    691 unsigned long ptr;
    692 unsigned long maxnodes;
    693 int err;
    694 {
    695 	unsigned long nlongs, size, end;
    696 
    697 	nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long));
    698 	size = nlongs * sizeof(long);
    699 	end = ptr + size;
    700 	if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes)
    701 			    && (end > ptr))) {
    702 		unsigned long n, cur, abbrev_end;
    703 		int failed = 0;
    704 
    705 		if (abbrev(tcp)) {
    706 			abbrev_end = ptr + max_strlen * sizeof(long);
    707 			if (abbrev_end < ptr)
    708 				abbrev_end = end;
    709 		} else {
    710 			abbrev_end = end;
    711 		}
    712 		tprintf(", {");
    713 		for (cur = ptr; cur < end; cur += sizeof(long)) {
    714 			if (cur > ptr)
    715 				tprintf(", ");
    716 			if (cur >= abbrev_end) {
    717 				tprintf("...");
    718 				break;
    719 			}
    720 			if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) {
    721 				tprintf("?");
    722 				failed = 1;
    723 				break;
    724 			}
    725 			tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n);
    726 		}
    727 		tprintf("}");
    728 		if (failed)
    729 			tprintf(" %#lx", ptr);
    730 	} else
    731 		tprintf(", %#lx", ptr);
    732 	tprintf(", %lu", maxnodes);
    733 }
    734 
    735 int
    736 sys_mbind(tcp)
    737 struct tcb *tcp;
    738 {
    739 	if (entering(tcp)) {
    740 		tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    741 		printxval(policies, tcp->u_arg[2], "MPOL_???");
    742 		get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0);
    743 		tprintf(", ");
    744 		printflags(mbindflags, tcp->u_arg[5], "MPOL_???");
    745 	}
    746 	return 0;
    747 }
    748 
    749 int
    750 sys_set_mempolicy(tcp)
    751 struct tcb *tcp;
    752 {
    753 	if (entering(tcp)) {
    754 		printxval(policies, tcp->u_arg[0], "MPOL_???");
    755 		get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0);
    756 	}
    757 	return 0;
    758 }
    759 
    760 int
    761 sys_get_mempolicy(tcp)
    762 struct tcb *tcp;
    763 {
    764 	if (exiting(tcp)) {
    765 		int pol;
    766 		if (tcp->u_arg[0] == 0)
    767 			tprintf("NULL");
    768 		else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0)
    769 			tprintf("%#lx", tcp->u_arg[0]);
    770 		else
    771 			printxval(policies, pol, "MPOL_???");
    772 		get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp));
    773 		tprintf(", %#lx, ", tcp->u_arg[3]);
    774 		printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???");
    775 	}
    776 	return 0;
    777 }
    778 #endif
    779