• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
7  *                    port by Greg Banks <gbanks@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
sys_brk(tcp)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
sys_sbrk(tcp)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
print_mmap(tcp,u_arg)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
sys_old_mmap(tcp)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
sys_mmap(tcp)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
sys_mmap64(tcp)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
sys_munmap(tcp)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
sys_mprotect(tcp)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
sys_mremap(tcp)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
sys_madvise(tcp)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
sys_mlockall(tcp)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
sys_msync(tcp)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
sys_mctl(tcp)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
sys_mincore(tcp)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
sys_getpagesize(tcp)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
print_ldt_entry(ldt_entry)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
sys_modify_ldt(tcp)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
sys_set_thread_area(tcp)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
sys_get_thread_area(tcp)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
sys_remap_file_pages(tcp)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
get_nodes(tcp,ptr,maxnodes,err)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
sys_mbind(tcp)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
sys_set_mempolicy(tcp)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
sys_get_mempolicy(tcp)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