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