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