mem.c revision 586d6ab9f239e912ad3a7b781a2f302abdf7788c
1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * Copyright (c) 2000 PocketPenguins Inc. Linux for Hitachi SuperH 7 * port by Greg Banks <gbanks@pocketpenguins.com> 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * $Id$ 33 */ 34 35#include "defs.h" 36 37#ifdef LINUX 38#include <asm/mman.h> 39#endif 40#include <sys/mman.h> 41 42#if defined(LINUX) && defined(I386) 43#include <asm/ldt.h> 44# ifdef HAVE_STRUCT_USER_DESC 45# define modify_ldt_ldt_s user_desc 46# endif 47#endif 48#if defined(LINUX) && defined(SH64) 49#include <asm/page.h> /* for PAGE_SHIFT */ 50#endif 51 52#ifdef HAVE_LONG_LONG_OFF_T 53/* 54 * Ugly hacks for systems that have a long long off_t 55 */ 56#define sys_mmap64 sys_mmap 57#endif 58 59int 60sys_brk(tcp) 61struct tcb *tcp; 62{ 63 if (entering(tcp)) { 64 tprintf("%#lx", tcp->u_arg[0]); 65 } 66#ifdef LINUX 67 return RVAL_HEX; 68#else 69 return 0; 70#endif 71} 72 73#if defined(FREEBSD) || defined(SUNOS4) 74int 75sys_sbrk(tcp) 76struct tcb *tcp; 77{ 78 if (entering(tcp)) { 79 tprintf("%lu", tcp->u_arg[0]); 80 } 81 return RVAL_HEX; 82} 83#endif /* FREEBSD || SUNOS4 */ 84 85static const struct xlat mmap_prot[] = { 86 { PROT_NONE, "PROT_NONE", }, 87 { PROT_READ, "PROT_READ" }, 88 { PROT_WRITE, "PROT_WRITE" }, 89 { PROT_EXEC, "PROT_EXEC" }, 90#ifdef PROT_SEM 91 { PROT_SEM, "PROT_SEM" }, 92#endif 93#ifdef PROT_GROWSDOWN 94 { PROT_GROWSDOWN,"PROT_GROWSDOWN"}, 95#endif 96#ifdef PROT_GROWSUP 97 { PROT_GROWSUP, "PROT_GROWSUP" }, 98#endif 99#ifdef PROT_SAO 100 { PROT_SAO, "PROT_SAO" }, 101#endif 102 { 0, NULL }, 103}; 104 105static const struct xlat mmap_flags[] = { 106 { MAP_SHARED, "MAP_SHARED" }, 107 { MAP_PRIVATE, "MAP_PRIVATE" }, 108 { MAP_FIXED, "MAP_FIXED" }, 109#ifdef MAP_ANONYMOUS 110 { MAP_ANONYMOUS,"MAP_ANONYMOUS" }, 111#endif 112#ifdef MAP_32BIT 113 { MAP_32BIT, "MAP_32BIT" }, 114#endif 115#ifdef MAP_RENAME 116 { MAP_RENAME, "MAP_RENAME" }, 117#endif 118#ifdef MAP_NORESERVE 119 { MAP_NORESERVE,"MAP_NORESERVE" }, 120#endif 121#ifdef MAP_POPULATE 122 { MAP_POPULATE, "MAP_POPULATE" }, 123#endif 124#ifdef MAP_NONBLOCK 125 { MAP_NONBLOCK, "MAP_NONBLOCK" }, 126#endif 127 /* 128 * XXX - this was introduced in SunOS 4.x to distinguish between 129 * the old pre-4.x "mmap()", which: 130 * 131 * only let you map devices with an "mmap" routine (e.g., 132 * frame buffers) in; 133 * 134 * required you to specify the mapping address; 135 * 136 * returned 0 on success and -1 on failure; 137 * 138 * memory and which, and the 4.x "mmap()" which: 139 * 140 * can map plain files; 141 * 142 * can be asked to pick where to map the file; 143 * 144 * returns the address where it mapped the file on success 145 * and -1 on failure. 146 * 147 * It's not actually used in source code that calls "mmap()"; the 148 * "mmap()" routine adds it for you. 149 * 150 * It'd be nice to come up with some way of eliminating it from 151 * the flags, e.g. reporting calls *without* it as "old_mmap()" 152 * and calls with it as "mmap()". 153 */ 154#ifdef _MAP_NEW 155 { _MAP_NEW, "_MAP_NEW" }, 156#endif 157#ifdef MAP_GROWSDOWN 158 { MAP_GROWSDOWN,"MAP_GROWSDOWN" }, 159#endif 160#ifdef MAP_DENYWRITE 161 { MAP_DENYWRITE,"MAP_DENYWRITE" }, 162#endif 163#ifdef MAP_EXECUTABLE 164 { MAP_EXECUTABLE,"MAP_EXECUTABLE"}, 165#endif 166#ifdef MAP_INHERIT 167 { MAP_INHERIT,"MAP_INHERIT" }, 168#endif 169#ifdef MAP_FILE 170 { MAP_FILE,"MAP_FILE"}, 171#endif 172#ifdef MAP_LOCKED 173 { MAP_LOCKED,"MAP_LOCKED"}, 174#endif 175 /* FreeBSD ones */ 176#ifdef MAP_ANON 177 { MAP_ANON, "MAP_ANON" }, 178#endif 179#ifdef MAP_HASSEMAPHORE 180 { MAP_HASSEMAPHORE, "MAP_HASSEMAPHORE" }, 181#endif 182#ifdef MAP_STACK 183 { MAP_STACK, "MAP_STACK" }, 184#endif 185#ifdef MAP_NOSYNC 186 { MAP_NOSYNC, "MAP_NOSYNC" }, 187#endif 188#ifdef MAP_NOCORE 189 { MAP_NOCORE, "MAP_NOCORE" }, 190#endif 191 { 0, NULL }, 192}; 193 194#if !HAVE_LONG_LONG_OFF_T 195static 196int 197print_mmap(tcp,u_arg, offset) 198struct tcb *tcp; 199long *u_arg; 200long long offset; 201{ 202 if (entering(tcp)) { 203 /* addr */ 204 if (!u_arg[0]) 205 tprintf("NULL, "); 206 else 207 tprintf("%#lx, ", u_arg[0]); 208 /* len */ 209 tprintf("%lu, ", u_arg[1]); 210 /* prot */ 211 printflags(mmap_prot, u_arg[2], "PROT_???"); 212 tprintf(", "); 213 /* flags */ 214#ifdef MAP_TYPE 215 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); 216 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); 217#else 218 printflags(mmap_flags, u_arg[3], "MAP_???"); 219#endif 220 /* fd (is always int, not long) */ 221 tprintf(", %d, ", (int)u_arg[4]); 222 /* offset */ 223 tprintf("%#llx", offset); 224 } 225 return RVAL_HEX; 226} 227 228#ifdef LINUX 229int sys_old_mmap(tcp) 230struct tcb *tcp; 231{ 232 long u_arg[6]; 233 234#if defined(IA64) 235 int i, v; 236 /* 237 * IA64 processes never call this routine, they only use the 238 * new `sys_mmap' interface. This code converts the integer 239 * arguments that the IA32 process pushed onto the stack into 240 * longs. 241 * 242 * Note that addresses with bit 31 set will be sign extended. 243 * Fortunately, those addresses are not currently being generated 244 * for IA32 processes so it's not a problem. 245 */ 246 for (i = 0; i < 6; i++) 247 if (umove(tcp, tcp->u_arg[0] + (i * sizeof(int)), &v) == -1) 248 return 0; 249 else 250 u_arg[i] = v; 251#elif defined(SH) || defined(SH64) 252 /* SH has always passed the args in registers */ 253 int i; 254 for (i=0; i<6; i++) 255 u_arg[i] = tcp->u_arg[i]; 256#else 257# if defined(X86_64) 258 if (current_personality == 1) { 259 int i; 260 for (i = 0; i < 6; ++i) { 261 unsigned int val; 262 if (umove(tcp, tcp->u_arg[0] + i * 4, &val) == -1) 263 return 0; 264 u_arg[i] = val; 265 } 266 } 267 else 268# endif 269 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1) 270 return 0; 271#endif // defined(IA64) 272 return print_mmap(tcp, u_arg, u_arg[5]); 273 274} 275#endif 276 277int 278sys_mmap(tcp) 279struct tcb *tcp; 280{ 281 long long offset = tcp->u_arg[5]; 282 283#if defined(LINUX) && defined(SH64) 284 /* 285 * Old mmap differs from new mmap in specifying the 286 * offset in units of bytes rather than pages. We 287 * pretend it's in byte units so the user only ever 288 * sees bytes in the printout. 289 */ 290 offset <<= PAGE_SHIFT; 291#endif 292#if defined(LINUX_MIPSN32) 293 offset = tcp->ext_arg[5]; 294#endif 295 return print_mmap(tcp, tcp->u_arg, offset); 296} 297#endif /* !HAVE_LONG_LONG_OFF_T */ 298 299#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T 300int 301sys_mmap64(tcp) 302struct tcb *tcp; 303{ 304#ifdef linux 305#ifdef ALPHA 306 long *u_arg = tcp->u_arg; 307#else /* !ALPHA */ 308 long u_arg[7]; 309#endif /* !ALPHA */ 310#else /* !linux */ 311 long *u_arg = tcp->u_arg; 312#endif /* !linux */ 313 314 if (entering(tcp)) { 315#ifdef linux 316#ifndef ALPHA 317 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, 318 (char *) u_arg) == -1) 319 return 0; 320#endif /* ALPHA */ 321#endif /* linux */ 322 ALIGN64 (tcp, 5); /* FreeBSD wierdies */ 323 324 /* addr */ 325 tprintf("%#lx, ", u_arg[0]); 326 /* len */ 327 tprintf("%lu, ", u_arg[1]); 328 /* prot */ 329 printflags(mmap_prot, u_arg[2], "PROT_???"); 330 tprintf(", "); 331 /* flags */ 332#ifdef MAP_TYPE 333 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); 334 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); 335#else 336 printflags(mmap_flags, u_arg[3], "MAP_???"); 337#endif 338 /* fd */ 339 tprintf(", %ld, ", u_arg[4]); 340 /* offset */ 341 tprintf("%#llx", LONG_LONG(u_arg[5], u_arg[6])); 342 } 343 return RVAL_HEX; 344} 345#endif 346 347 348int 349sys_munmap(tcp) 350struct tcb *tcp; 351{ 352 if (entering(tcp)) { 353 tprintf("%#lx, %lu", 354 tcp->u_arg[0], tcp->u_arg[1]); 355 } 356 return 0; 357} 358 359int 360sys_mprotect(tcp) 361struct tcb *tcp; 362{ 363 if (entering(tcp)) { 364 tprintf("%#lx, %lu, ", 365 tcp->u_arg[0], tcp->u_arg[1]); 366 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 367 } 368 return 0; 369} 370 371#ifdef LINUX 372 373static const struct xlat mremap_flags[] = { 374 { MREMAP_MAYMOVE, "MREMAP_MAYMOVE" }, 375 { 0, NULL } 376}; 377 378int 379sys_mremap(tcp) 380struct tcb *tcp; 381{ 382 if (entering(tcp)) { 383 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1], 384 tcp->u_arg[2]); 385 printflags(mremap_flags, tcp->u_arg[3], "MREMAP_???"); 386 } 387 return RVAL_HEX; 388} 389 390static const struct xlat madvise_cmds[] = { 391#ifdef MADV_NORMAL 392 { MADV_NORMAL, "MADV_NORMAL" }, 393#endif 394#ifdef MADV_RANDOM 395 { MADV_RANDOM, "MADV_RANDOM" }, 396#endif 397#ifdef MADV_SEQUENTIAL 398 { MADV_SEQUENTIAL, "MADV_SEQUENTIAL" }, 399#endif 400#ifdef MADV_WILLNEED 401 { MADV_WILLNEED, "MADV_WILLNEED" }, 402#endif 403#ifdef MADV_DONTNEED 404 { MADV_DONTNEED, "MADV_DONTNEED" }, 405#endif 406 { 0, NULL }, 407}; 408 409 410int 411sys_madvise(tcp) 412struct tcb *tcp; 413{ 414 if (entering(tcp)) { 415 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 416 printxval(madvise_cmds, tcp->u_arg[2], "MADV_???"); 417 } 418 return 0; 419} 420 421 422static const struct xlat mlockall_flags[] = { 423#ifdef MCL_CURRENT 424 { MCL_CURRENT, "MCL_CURRENT" }, 425#endif 426#ifdef MCL_FUTURE 427 { MCL_FUTURE, "MCL_FUTURE" }, 428#endif 429 { 0, NULL} 430}; 431 432int 433sys_mlockall(tcp) 434struct tcb *tcp; 435{ 436 if (entering(tcp)) { 437 printflags(mlockall_flags, tcp->u_arg[0], "MCL_???"); 438 } 439 return 0; 440} 441 442 443#endif /* LINUX */ 444 445#ifdef MS_ASYNC 446 447static const struct xlat mctl_sync[] = { 448#ifdef MS_SYNC 449 { MS_SYNC, "MS_SYNC" }, 450#endif 451 { MS_ASYNC, "MS_ASYNC" }, 452 { MS_INVALIDATE,"MS_INVALIDATE" }, 453 { 0, NULL }, 454}; 455 456int 457sys_msync(tcp) 458struct tcb *tcp; 459{ 460 if (entering(tcp)) { 461 /* addr */ 462 tprintf("%#lx", tcp->u_arg[0]); 463 /* len */ 464 tprintf(", %lu, ", tcp->u_arg[1]); 465 /* flags */ 466 printflags(mctl_sync, tcp->u_arg[2], "MS_???"); 467 } 468 return 0; 469} 470 471#endif /* MS_ASYNC */ 472 473#ifdef MC_SYNC 474 475static const struct xlat mctl_funcs[] = { 476 { MC_LOCK, "MC_LOCK" }, 477 { MC_LOCKAS, "MC_LOCKAS" }, 478 { MC_SYNC, "MC_SYNC" }, 479 { MC_UNLOCK, "MC_UNLOCK" }, 480 { MC_UNLOCKAS, "MC_UNLOCKAS" }, 481 { 0, NULL }, 482}; 483 484static const struct xlat mctl_lockas[] = { 485 { MCL_CURRENT, "MCL_CURRENT" }, 486 { MCL_FUTURE, "MCL_FUTURE" }, 487 { 0, NULL }, 488}; 489 490int 491sys_mctl(tcp) 492struct tcb *tcp; 493{ 494 int arg, function; 495 496 if (entering(tcp)) { 497 /* addr */ 498 tprintf("%#lx", tcp->u_arg[0]); 499 /* len */ 500 tprintf(", %lu, ", tcp->u_arg[1]); 501 /* function */ 502 function = tcp->u_arg[2]; 503 printflags(mctl_funcs, function, "MC_???"); 504 /* arg */ 505 arg = tcp->u_arg[3]; 506 tprintf(", "); 507 switch (function) { 508 case MC_SYNC: 509 printflags(mctl_sync, arg, "MS_???"); 510 break; 511 case MC_LOCKAS: 512 printflags(mctl_lockas, arg, "MCL_???"); 513 break; 514 default: 515 tprintf("%#x", arg); 516 break; 517 } 518 } 519 return 0; 520} 521 522#endif /* MC_SYNC */ 523 524int 525sys_mincore(tcp) 526struct tcb *tcp; 527{ 528 unsigned long i, len; 529 char *vec = NULL; 530 531 if (entering(tcp)) { 532 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 533 } else { 534 len = tcp->u_arg[1]; 535 if (syserror(tcp) || tcp->u_arg[2] == 0 || 536 (vec = malloc(len)) == NULL || 537 umoven(tcp, tcp->u_arg[2], len, vec) < 0) 538 tprintf("%#lx", tcp->u_arg[2]); 539 else { 540 tprintf("["); 541 for (i = 0; i < len; i++) { 542 if (abbrev(tcp) && i >= max_strlen) { 543 tprintf("..."); 544 break; 545 } 546 tprintf((vec[i] & 1) ? "1" : "0"); 547 } 548 tprintf("]"); 549 } 550 if (vec) 551 free(vec); 552 } 553 return 0; 554} 555 556#if defined(ALPHA) || defined(FREEBSD) || defined(IA64) || defined(SUNOS4) || defined(SVR4) || defined(SPARC) || defined(SPARC64) 557int 558sys_getpagesize(tcp) 559struct tcb *tcp; 560{ 561 if (exiting(tcp)) 562 return RVAL_HEX; 563 return 0; 564} 565#endif /* ALPHA || FREEBSD || IA64 || SUNOS4 || SVR4 */ 566 567#if defined(LINUX) && defined(__i386__) 568void 569print_ldt_entry (ldt_entry) 570struct modify_ldt_ldt_s *ldt_entry; 571{ 572 tprintf("base_addr:%#08lx, " 573 "limit:%d, " 574 "seg_32bit:%d, " 575 "contents:%d, " 576 "read_exec_only:%d, " 577 "limit_in_pages:%d, " 578 "seg_not_present:%d, " 579 "useable:%d}", 580 ldt_entry->base_addr, 581 ldt_entry->limit, 582 ldt_entry->seg_32bit, 583 ldt_entry->contents, 584 ldt_entry->read_exec_only, 585 ldt_entry->limit_in_pages, 586 ldt_entry->seg_not_present, 587 ldt_entry->useable); 588} 589 590int 591sys_modify_ldt(tcp) 592struct tcb *tcp; 593{ 594 if (entering(tcp)) { 595 struct modify_ldt_ldt_s copy; 596 tprintf("%ld", tcp->u_arg[0]); 597 if (tcp->u_arg[1] == 0 598 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s) 599 || umove(tcp, tcp->u_arg[1], ©) == -1) 600 tprintf(", %lx", tcp->u_arg[1]); 601 else { 602 tprintf(", {entry_number:%d, ", copy.entry_number); 603 if (!verbose(tcp)) 604 tprintf("...}"); 605 else { 606 print_ldt_entry(©); 607 } 608 } 609 tprintf(", %lu", tcp->u_arg[2]); 610 } 611 return 0; 612} 613 614int 615sys_set_thread_area(tcp) 616struct tcb *tcp; 617{ 618 struct modify_ldt_ldt_s copy; 619 if (entering(tcp)) { 620 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 621 if (copy.entry_number == -1) 622 tprintf("{entry_number:%d -> ", 623 copy.entry_number); 624 else 625 tprintf("{entry_number:"); 626 } 627 } else { 628 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 629 tprintf("%d, ", copy.entry_number); 630 if (!verbose(tcp)) 631 tprintf("...}"); 632 else { 633 print_ldt_entry(©); 634 } 635 } else { 636 tprintf("%lx", tcp->u_arg[0]); 637 } 638 } 639 return 0; 640 641} 642 643int 644sys_get_thread_area(tcp) 645struct tcb *tcp; 646{ 647 struct modify_ldt_ldt_s copy; 648 if (exiting(tcp)) { 649 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 650 tprintf("{entry_number:%d, ", copy.entry_number); 651 if (!verbose(tcp)) 652 tprintf("...}"); 653 else { 654 print_ldt_entry(©); 655 } 656 } else { 657 tprintf("%lx", tcp->u_arg[0]); 658 } 659 } 660 return 0; 661 662} 663#endif /* LINUX && __i386__ */ 664 665#if defined(LINUX) 666int 667sys_remap_file_pages(tcp) 668struct tcb *tcp; 669{ 670 if (entering(tcp)) { 671 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 672 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 673 tprintf(", %lu, ", tcp->u_arg[3]); 674#ifdef MAP_TYPE 675 printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???"); 676 addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE); 677#else 678 printflags(mmap_flags, tcp->u_arg[4], "MAP_???"); 679#endif 680 } 681 return 0; 682} 683 684 685#define MPOL_DEFAULT 0 686#define MPOL_PREFERRED 1 687#define MPOL_BIND 2 688#define MPOL_INTERLEAVE 3 689 690#define MPOL_F_NODE (1<<0) 691#define MPOL_F_ADDR (1<<1) 692 693#define MPOL_MF_STRICT (1<<0) 694#define MPOL_MF_MOVE (1<<1) 695#define MPOL_MF_MOVE_ALL (1<<2) 696 697 698static const struct xlat policies[] = { 699 { MPOL_DEFAULT, "MPOL_DEFAULT" }, 700 { MPOL_PREFERRED, "MPOL_PREFERRED" }, 701 { MPOL_BIND, "MPOL_BIND" }, 702 { MPOL_INTERLEAVE, "MPOL_INTERLEAVE" }, 703 { 0, NULL } 704}; 705 706static const struct xlat mbindflags[] = { 707 { MPOL_MF_STRICT, "MPOL_MF_STRICT" }, 708 { MPOL_MF_MOVE, "MPOL_MF_MOVE" }, 709 { MPOL_MF_MOVE_ALL, "MPOL_MF_MOVE_ALL" }, 710 { 0, NULL } 711}; 712 713static const struct xlat mempolicyflags[] = { 714 { MPOL_F_NODE, "MPOL_F_NODE" }, 715 { MPOL_F_ADDR, "MPOL_F_ADDR" }, 716 { 0, NULL } 717}; 718 719static const struct xlat move_pages_flags[] = { 720 { MPOL_MF_MOVE, "MPOL_MF_MOVE" }, 721 { MPOL_MF_MOVE_ALL, "MPOL_MF_MOVE_ALL" }, 722 { 0, NULL } 723}; 724 725 726static void 727get_nodes(tcp, ptr, maxnodes, err) 728struct tcb *tcp; 729unsigned long ptr; 730unsigned long maxnodes; 731int err; 732{ 733 unsigned long nlongs, size, end; 734 735 nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long)); 736 size = nlongs * sizeof(long); 737 end = ptr + size; 738 if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes) 739 && (end > ptr))) { 740 unsigned long n, cur, abbrev_end; 741 int failed = 0; 742 743 if (abbrev(tcp)) { 744 abbrev_end = ptr + max_strlen * sizeof(long); 745 if (abbrev_end < ptr) 746 abbrev_end = end; 747 } else { 748 abbrev_end = end; 749 } 750 tprintf(", {"); 751 for (cur = ptr; cur < end; cur += sizeof(long)) { 752 if (cur > ptr) 753 tprintf(", "); 754 if (cur >= abbrev_end) { 755 tprintf("..."); 756 break; 757 } 758 if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) { 759 tprintf("?"); 760 failed = 1; 761 break; 762 } 763 tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n); 764 } 765 tprintf("}"); 766 if (failed) 767 tprintf(" %#lx", ptr); 768 } else 769 tprintf(", %#lx", ptr); 770 tprintf(", %lu", maxnodes); 771} 772 773int 774sys_mbind(tcp) 775struct tcb *tcp; 776{ 777 if (entering(tcp)) { 778 tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 779 printxval(policies, tcp->u_arg[2], "MPOL_???"); 780 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0); 781 tprintf(", "); 782 printflags(mbindflags, tcp->u_arg[5], "MPOL_???"); 783 } 784 return 0; 785} 786 787int 788sys_set_mempolicy(tcp) 789struct tcb *tcp; 790{ 791 if (entering(tcp)) { 792 printxval(policies, tcp->u_arg[0], "MPOL_???"); 793 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0); 794 } 795 return 0; 796} 797 798int 799sys_get_mempolicy(tcp) 800struct tcb *tcp; 801{ 802 if (exiting(tcp)) { 803 int pol; 804 if (tcp->u_arg[0] == 0) 805 tprintf("NULL"); 806 else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0) 807 tprintf("%#lx", tcp->u_arg[0]); 808 else 809 printxval(policies, pol, "MPOL_???"); 810 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp)); 811 tprintf(", %#lx, ", tcp->u_arg[3]); 812 printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???"); 813 } 814 return 0; 815} 816 817int 818sys_move_pages(tcp) 819struct tcb *tcp; 820{ 821 if (entering(tcp)) { 822 unsigned long npages = tcp->u_arg[1]; 823 tprintf("%ld, %lu, ", tcp->u_arg[0], npages); 824 if (tcp->u_arg[2] == 0) 825 tprintf("NULL, "); 826 else { 827 int i; 828 long puser = tcp->u_arg[2]; 829 tprintf("{"); 830 for (i = 0; i < npages; ++i) { 831 void *p; 832 if (i > 0) 833 tprintf(", "); 834 if (umove(tcp, puser, &p) < 0) { 835 tprintf("???"); 836 break; 837 } 838 tprintf("%p", p); 839 puser += sizeof (void *); 840 } 841 tprintf("}, "); 842 } 843 if (tcp->u_arg[3] == 0) 844 tprintf("NULL, "); 845 else { 846 int i; 847 long nodeuser = tcp->u_arg[3]; 848 tprintf("{"); 849 for (i = 0; i < npages; ++i) { 850 int node; 851 if (i > 0) 852 tprintf(", "); 853 if (umove(tcp, nodeuser, &node) < 0) { 854 tprintf("???"); 855 break; 856 } 857 tprintf("%#x", node); 858 nodeuser += sizeof (int); 859 } 860 tprintf("}, "); 861 } 862 } 863 if (exiting(tcp)) { 864 unsigned long npages = tcp->u_arg[1]; 865 if (tcp->u_arg[4] == 0) 866 tprintf("NULL, "); 867 else { 868 int i; 869 long statususer = tcp->u_arg[4]; 870 tprintf("{"); 871 for (i = 0; i < npages; ++i) { 872 int status; 873 if (i > 0) 874 tprintf(", "); 875 if (umove(tcp, statususer, &status) < 0) { 876 tprintf("???"); 877 break; 878 } 879 tprintf("%#x", status); 880 statususer += sizeof (int); 881 } 882 tprintf("}, "); 883 } 884 printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???"); 885 } 886 return 0; 887} 888#endif 889