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