]> granicus.if.org Git - strace/blob - mem.c
2004-10-07 Roland McGrath <roland@redhat.com>
[strace] / mem.c
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$
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]);
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]);
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]);
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]);
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                 if (!printflags(mmap_prot, tcp->u_arg[2]))
341                         tprintf("PROT_???");
342         }
343         return 0;
344 }
345
346 #ifdef LINUX
347
348 static const struct xlat mremap_flags[] = {
349         { MREMAP_MAYMOVE,       "MREMAP_MAYMOVE"        },
350         { 0,                    NULL                    }
351 };
352
353 int
354 sys_mremap(tcp)
355 struct tcb *tcp;
356 {
357         if (entering(tcp)) {
358                 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
359                         tcp->u_arg[2]);
360                 printflags(mremap_flags, tcp->u_arg[3]);
361         }
362         return RVAL_HEX;
363 }
364
365 static const struct xlat madvise_flags[] = {
366 #ifdef MADV_NORMAL
367         { MADV_NORMAL,          "MADV_NORMAL" },
368 #endif
369 #ifdef MADZV_RANDOM
370         { MADV_RANDOM,          "MADV_RANDOM" },
371 #endif
372 #ifdef MADV_SEQUENTIAL
373         { MADV_SEQUENTIAL,      "MADV_SEQUENTIAL" },
374 #endif
375 #ifdef MADV_WILLNEED
376         { MADV_WILLNEED,        "MADV_WILLNEED" },
377 #endif
378 #ifdef MADV_DONTNED
379         { MADV_DONTNEED,        "MADV_DONTNEED" },
380 #endif
381         { 0,                    NULL },
382 };
383
384
385 int
386 sys_madvise(tcp)
387 struct tcb *tcp;
388 {
389         if (entering(tcp)) {
390                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
391                 printflags(madvise_flags, tcp->u_arg[2]);
392         }
393         return 0;
394 }
395
396
397 static const struct xlat mlockall_flags[] = {
398 #ifdef MCL_CURRENT
399         { MCL_CURRENT,  "MCL_CURRENT" },
400 #endif
401 #ifdef MCL_FUTURE
402         { MCL_FUTURE,   "MCL_FUTURE" },
403 #endif
404         { 0,            NULL}
405 };
406
407 int
408 sys_mlockall(tcp)
409 struct tcb *tcp;
410 {
411         if (entering(tcp)) {
412                 printflags(mlockall_flags, tcp->u_arg[0]);
413         }
414         return 0;
415 }
416
417
418 #endif /* LINUX */
419
420 #ifdef MS_ASYNC
421
422 static const struct xlat mctl_sync[] = {
423 #ifdef MS_SYNC
424         { MS_SYNC,      "MS_SYNC"       },
425 #endif
426         { MS_ASYNC,     "MS_ASYNC"      },
427         { MS_INVALIDATE,"MS_INVALIDATE" },
428         { 0,            NULL            },
429 };
430
431 int
432 sys_msync(tcp)
433 struct tcb *tcp;
434 {
435         if (entering(tcp)) {
436                 /* addr */
437                 tprintf("%#lx", tcp->u_arg[0]);
438                 /* len */
439                 tprintf(", %lu, ", tcp->u_arg[1]);
440                 /* flags */
441                 if (!printflags(mctl_sync, tcp->u_arg[2]))
442                         tprintf("MS_???");
443         }
444         return 0;
445 }
446
447 #endif /* MS_ASYNC */
448
449 #ifdef MC_SYNC
450
451 static const struct xlat mctl_funcs[] = {
452         { MC_LOCK,      "MC_LOCK"       },
453         { MC_LOCKAS,    "MC_LOCKAS"     },
454         { MC_SYNC,      "MC_SYNC"       },
455         { MC_UNLOCK,    "MC_UNLOCK"     },
456         { MC_UNLOCKAS,  "MC_UNLOCKAS"   },
457         { 0,            NULL            },
458 };
459
460 static const struct xlat mctl_lockas[] = {
461         { MCL_CURRENT,  "MCL_CURRENT"   },
462         { MCL_FUTURE,   "MCL_FUTURE"    },
463         { 0,            NULL            },
464 };
465
466 int
467 sys_mctl(tcp)
468 struct tcb *tcp;
469 {
470         int arg, function;
471
472         if (entering(tcp)) {
473                 /* addr */
474                 tprintf("%#lx", tcp->u_arg[0]);
475                 /* len */
476                 tprintf(", %lu, ", tcp->u_arg[1]);
477                 /* function */
478                 function = tcp->u_arg[2];
479                 if (!printflags(mctl_funcs, function))
480                         tprintf("MC_???");
481                 /* arg */
482                 arg = tcp->u_arg[3];
483                 tprintf(", ");
484                 switch (function) {
485                 case MC_SYNC:
486                         if (!printflags(mctl_sync, arg))
487                                 tprintf("MS_???");
488                         break;
489                 case MC_LOCKAS:
490                         if (!printflags(mctl_lockas, arg))
491                                 tprintf("MCL_???");
492                         break;
493                 default:
494                         tprintf("%#x", arg);
495                         break;
496                 }
497         }
498         return 0;
499 }
500
501 #endif /* MC_SYNC */
502
503 int
504 sys_mincore(tcp)
505 struct tcb *tcp;
506 {
507         int i, len;
508         char *vec = NULL;
509
510         if (entering(tcp)) {
511                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
512         } else {
513                 len = tcp->u_arg[1];
514                 if (syserror(tcp) || tcp->u_arg[2] == 0 ||
515                         (vec = malloc((u_int)len)) == NULL ||
516                         umoven(tcp, tcp->u_arg[2], len, vec) < 0)
517                         tprintf("%#lx", tcp->u_arg[2]);
518                 else {
519                         tprintf("[");
520                         for (i = 0; i < len; i++) {
521                                 if (abbrev(tcp) && i >= max_strlen) {
522                                         tprintf("...");
523                                         break;
524                                 }
525                                 tprintf((vec[i] & 1) ? "1" : "0");
526                         }
527                         tprintf("]");
528                 }
529                 if (vec)
530                         free(vec);
531         }
532         return 0;
533 }
534
535 int
536 sys_getpagesize(tcp)
537 struct tcb *tcp;
538 {
539         if (exiting(tcp))
540                 return RVAL_HEX;
541         return 0;
542 }
543
544 #if defined(LINUX) && defined(__i386__)
545 void
546 print_ldt_entry (ldt_entry)
547 struct modify_ldt_ldt_s *ldt_entry;
548 {
549         tprintf("base_addr:%#08lx, "
550                 "limit:%d, "
551                 "seg_32bit:%d, "
552                 "contents:%d, "
553                 "read_exec_only:%d, "
554                 "limit_in_pages:%d, "
555                 "seg_not_present:%d, "
556                 "useable:%d}",
557                 ldt_entry->base_addr,
558                 ldt_entry->limit,
559                 ldt_entry->seg_32bit,
560                 ldt_entry->contents,
561                 ldt_entry->read_exec_only,
562                 ldt_entry->limit_in_pages,
563                 ldt_entry->seg_not_present,
564                 ldt_entry->useable);
565 }
566
567 int
568 sys_modify_ldt(tcp)
569 struct tcb *tcp;
570 {
571         if (entering(tcp)) {
572                 struct modify_ldt_ldt_s copy;
573                 tprintf("%ld", tcp->u_arg[0]);
574                 if (tcp->u_arg[1] == 0
575                                 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
576                                 || umove(tcp, tcp->u_arg[1], &copy) == -1)
577                         tprintf(", %lx", tcp->u_arg[1]);
578                 else {
579                         tprintf(", {entry_number:%d, ", copy.entry_number);
580                         if (!verbose(tcp))
581                                 tprintf("...}");
582                         else {
583                                 print_ldt_entry(&copy);
584                         }
585                 }
586                 tprintf(", %lu", tcp->u_arg[2]);
587         }
588         return 0;
589 }
590
591 int
592 sys_set_thread_area(tcp)
593 struct tcb *tcp;
594 {
595         struct modify_ldt_ldt_s copy;
596         if (entering(tcp)) {
597                 if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
598                         if (copy.entry_number == -1)
599                                 tprintf("{entry_number:%d -> ",
600                                         copy.entry_number);
601                         else
602                                 tprintf("{entry_number:");
603                 }
604         } else {
605                 if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
606                         tprintf("%d, ", copy.entry_number);
607                         if (!verbose(tcp))
608                                 tprintf("...}");
609                         else {
610                                 print_ldt_entry(&copy);
611                         }
612                 } else {
613                         tprintf("%lx", tcp->u_arg[0]);
614                 }
615         }
616         return 0;
617
618 }
619
620 int
621 sys_get_thread_area(tcp)
622 struct tcb *tcp;
623 {
624         struct modify_ldt_ldt_s copy;
625         if (exiting(tcp)) {
626                 if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
627                         tprintf("{entry_number:%d, ", copy.entry_number);
628                         if (!verbose(tcp))
629                                 tprintf("...}");
630                         else {
631                                 print_ldt_entry(&copy);
632                         }
633                 } else {
634                         tprintf("%lx", tcp->u_arg[0]);
635                 }
636         }
637         return 0;
638
639 }
640 #endif /* LINUX && __i386__ */
641
642 #if defined(LINUX)
643 int
644 sys_remap_file_pages(tcp)
645 struct tcb *tcp;
646 {
647         if (entering(tcp)) {
648                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
649                 printflags(mmap_prot, tcp->u_arg[2]);
650                 tprintf(", %lu, ", tcp->u_arg[3]);
651 #ifdef MAP_TYPE
652                 printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???");
653                 addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE);
654 #else
655                 printflags(mmap_flags, tcp->u_arg[4]);
656 #endif
657         }
658         return 0;
659 }
660
661
662 #define MPOL_DEFAULT    0
663 #define MPOL_PREFERRED  1
664 #define MPOL_BIND       2
665 #define MPOL_INTERLEAVE 3
666
667 #define MPOL_F_NODE     (1<<0)
668 #define MPOL_F_ADDR     (1<<1)
669
670 #define MPOL_MF_STRICT  (1<<0)
671
672
673 static const struct xlat policies[] = {
674         { MPOL_DEFAULT,         "MPOL_DEFAULT"          },
675         { MPOL_PREFERRED,       "MPOL_PREFERRED"        },
676         { MPOL_BIND,            "MPOL_BIND"             },
677         { MPOL_INTERLEAVE,      "MPOL_INTERLEAVE"       },
678         { 0,                    NULL                    }
679 };
680
681 static const struct xlat mbindflags[] = {
682         { MPOL_MF_STRICT,       "MPOL_MF_STRICT"        },
683         { 0,                    NULL                    }
684 };
685
686 static const struct xlat mempolicyflags[] = {
687         { MPOL_F_NODE,          "MPOL_F_NODE"           },
688         { MPOL_F_ADDR,          "MPOL_F_ADDR"           },
689         { 0,                    NULL                    }
690 };
691
692
693 static void
694 get_nodes(tcp, ptr, maxnodes, err)
695 struct tcb *tcp;
696 unsigned long ptr;
697 unsigned long maxnodes;
698 int err;
699 {
700         int nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long));
701         if (err || !abbrev(tcp) || nlongs > getpagesize() / sizeof(long)
702             || nlongs == 0) {
703                 long buf[nlongs];
704                 if (umoven(tcp, ptr, nlongs * sizeof(long),
705                            (char *) buf) < 0)
706                         tprintf(", %lx", ptr);
707                 else {
708                         int i;
709                         tprintf(", {");
710                         for (i = 0; i < nlongs; ++i) {
711                                 if (i > 0)
712                                         tprintf(", ");
713                                 tprintf("%#0*lx", (int) sizeof(long) * 2 + 2,
714                                         buf[i]);
715                         }
716                         tprintf("}");
717                 }
718         } else
719                 tprintf(", %lx", ptr);
720         tprintf(", %lu", maxnodes);
721 }
722
723 int
724 sys_mbind(tcp)
725 struct tcb *tcp;
726 {
727         if (entering(tcp)) {
728                 tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
729                 printxval(policies, tcp->u_arg[2], "MPOL_???");
730                 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0);
731                 tprintf(", ");
732                 if (printflags(mbindflags, tcp->u_arg[5]) == 0)
733                         tprintf("0");
734         }
735         return 0;
736 }
737
738 int
739 sys_set_mempolicy(tcp)
740 struct tcb *tcp;
741 {
742         if (entering(tcp)) {
743                 printxval(policies, tcp->u_arg[0], "MPOL_???");
744                 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0);
745         }
746         return 0;
747 }
748
749 int
750 sys_get_mempolicy(tcp)
751 struct tcb *tcp;
752 {
753         if (exiting(tcp)) {
754                 int pol;
755                 if (tcp->u_arg[0] == 0)
756                         tprintf("NULL");
757                 else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0)
758                         tprintf("%#lx", tcp->u_arg[0]);
759                 else
760                         printxval(policies, pol, "MPOL_???");
761                 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp));
762                 tprintf(", %#lx, ", tcp->u_arg[3]);
763                 if (printflags(mempolicyflags, tcp->u_arg[4]) == 0)
764                         tprintf("0");
765         }
766         return 0;
767 }
768 #endif