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#ifdef TILE 192 { MAP_CACHE_NO_LOCAL, "MAP_CACHE_NO_LOCAL" }, 193 { MAP_CACHE_NO_L2, "MAP_CACHE_NO_L2" }, 194 { MAP_CACHE_NO_L1, "MAP_CACHE_NO_L1" }, 195#endif 196 { 0, NULL }, 197}; 198 199#ifdef TILE 200static 201int 202addtileflags(flags) 203long flags; 204{ 205 long home = flags & _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_MASK); 206 flags &= ~_MAP_CACHE_MKHOME(_MAP_CACHE_HOME_MASK); 207 208 if (flags & _MAP_CACHE_INCOHERENT) { 209 flags &= ~_MAP_CACHE_INCOHERENT; 210 if (home == MAP_CACHE_HOME_NONE) { 211 tprintf("|MAP_CACHE_INCOHERENT"); 212 return flags; 213 } 214 tprintf("|_MAP_CACHE_INCOHERENT"); 215 } 216 217 switch (home) { 218 case 0: break; 219 case MAP_CACHE_HOME_HERE: tprintf("|MAP_CACHE_HOME_HERE"); break; 220 case MAP_CACHE_HOME_NONE: tprintf("|MAP_CACHE_HOME_NONE"); break; 221 case MAP_CACHE_HOME_SINGLE: tprintf("|MAP_CACHE_HOME_SINGLE"); break; 222 case MAP_CACHE_HOME_TASK: tprintf("|MAP_CACHE_HOME_TASK"); break; 223 case MAP_CACHE_HOME_HASH: tprintf("|MAP_CACHE_HOME_HASH"); break; 224 default: 225 tprintf("|MAP_CACHE_HOME(%d)", 226 (home >> _MAP_CACHE_HOME_SHIFT) ); 227 break; 228 } 229 230 return flags; 231} 232#endif 233 234#if !HAVE_LONG_LONG_OFF_T 235static int 236print_mmap(struct tcb *tcp, long *u_arg, long long offset) 237{ 238 if (entering(tcp)) { 239 /* addr */ 240 if (!u_arg[0]) 241 tprintf("NULL, "); 242 else 243 tprintf("%#lx, ", u_arg[0]); 244 /* len */ 245 tprintf("%lu, ", u_arg[1]); 246 /* prot */ 247 printflags(mmap_prot, u_arg[2], "PROT_???"); 248 tprintf(", "); 249 /* flags */ 250#ifdef MAP_TYPE 251 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); 252#ifdef TILE 253 addflags(mmap_flags, addtileflags(u_arg[3] & ~MAP_TYPE)); 254#else 255 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); 256#endif 257#else 258 printflags(mmap_flags, u_arg[3], "MAP_???"); 259#endif 260 /* fd */ 261 tprintf(", "); 262 printfd(tcp, u_arg[4]); 263 /* offset */ 264 tprintf(", %#llx", offset); 265 } 266 return RVAL_HEX; 267} 268 269#ifdef LINUX 270int sys_old_mmap(tcp) 271struct tcb *tcp; 272{ 273 long u_arg[6]; 274 275#if defined(IA64) 276 int i, v; 277 /* 278 * IA64 processes never call this routine, they only use the 279 * new `sys_mmap' interface. This code converts the integer 280 * arguments that the IA32 process pushed onto the stack into 281 * longs. 282 * 283 * Note that addresses with bit 31 set will be sign extended. 284 * Fortunately, those addresses are not currently being generated 285 * for IA32 processes so it's not a problem. 286 */ 287 for (i = 0; i < 6; i++) 288 if (umove(tcp, tcp->u_arg[0] + (i * sizeof(int)), &v) == -1) 289 return 0; 290 else 291 u_arg[i] = v; 292#elif defined(SH) || defined(SH64) 293 /* SH has always passed the args in registers */ 294 int i; 295 for (i=0; i<6; i++) 296 u_arg[i] = tcp->u_arg[i]; 297#else 298# if defined(X86_64) 299 if (current_personality == 1) { 300 int i; 301 for (i = 0; i < 6; ++i) { 302 unsigned int val; 303 if (umove(tcp, tcp->u_arg[0] + i * 4, &val) == -1) 304 return 0; 305 u_arg[i] = val; 306 } 307 } 308 else 309# endif 310 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1) 311 return 0; 312#endif // defined(IA64) 313 return print_mmap(tcp, u_arg, u_arg[5]); 314} 315#endif 316 317int 318sys_mmap(tcp) 319struct tcb *tcp; 320{ 321 long long offset = tcp->u_arg[5]; 322 323#if defined(LINUX) && defined(SH64) 324 /* 325 * Old mmap differs from new mmap in specifying the 326 * offset in units of bytes rather than pages. We 327 * pretend it's in byte units so the user only ever 328 * sees bytes in the printout. 329 */ 330 offset <<= PAGE_SHIFT; 331#endif 332#if defined(LINUX_MIPSN32) 333 offset = tcp->ext_arg[5]; 334#endif 335 return print_mmap(tcp, tcp->u_arg, offset); 336} 337#endif /* !HAVE_LONG_LONG_OFF_T */ 338 339#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T 340int 341sys_mmap64(struct tcb *tcp) 342{ 343#ifdef linux 344#ifdef ALPHA 345 long *u_arg = tcp->u_arg; 346#else /* !ALPHA */ 347 long u_arg[7]; 348#endif /* !ALPHA */ 349#else /* !linux */ 350 long *u_arg = tcp->u_arg; 351#endif /* !linux */ 352 353 if (entering(tcp)) { 354#ifdef linux 355#ifndef ALPHA 356 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, 357 (char *) u_arg) == -1) 358 return 0; 359#endif /* ALPHA */ 360#endif /* linux */ 361 362 /* addr */ 363 tprintf("%#lx, ", u_arg[0]); 364 /* len */ 365 tprintf("%lu, ", u_arg[1]); 366 /* prot */ 367 printflags(mmap_prot, u_arg[2], "PROT_???"); 368 tprintf(", "); 369 /* flags */ 370#ifdef MAP_TYPE 371 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); 372 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); 373#else 374 printflags(mmap_flags, u_arg[3], "MAP_???"); 375#endif 376 /* fd */ 377 tprintf(", "); 378 printfd(tcp, tcp->u_arg[4]); 379 /* offset */ 380 printllval(tcp, ", %#llx", 5); 381 } 382 return RVAL_HEX; 383} 384#endif 385 386 387int 388sys_munmap(tcp) 389struct tcb *tcp; 390{ 391 if (entering(tcp)) { 392 tprintf("%#lx, %lu", 393 tcp->u_arg[0], tcp->u_arg[1]); 394 } 395 return 0; 396} 397 398int 399sys_mprotect(tcp) 400struct tcb *tcp; 401{ 402 if (entering(tcp)) { 403 tprintf("%#lx, %lu, ", 404 tcp->u_arg[0], tcp->u_arg[1]); 405 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 406 } 407 return 0; 408} 409 410#ifdef LINUX 411 412static const struct xlat mremap_flags[] = { 413 { MREMAP_MAYMOVE, "MREMAP_MAYMOVE" }, 414#ifdef MREMAP_FIXED 415 { MREMAP_FIXED, "MREMAP_FIXED" }, 416#endif 417 { 0, NULL } 418}; 419 420int 421sys_mremap(struct tcb *tcp) 422{ 423 if (entering(tcp)) { 424 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1], 425 tcp->u_arg[2]); 426 printflags(mremap_flags, tcp->u_arg[3], "MREMAP_???"); 427#ifdef MREMAP_FIXED 428 if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) == 429 (MREMAP_MAYMOVE | MREMAP_FIXED)) 430 tprintf(", %#lx", tcp->u_arg[4]); 431#endif 432 } 433 return RVAL_HEX; 434} 435 436static const struct xlat madvise_cmds[] = { 437#ifdef MADV_NORMAL 438 { MADV_NORMAL, "MADV_NORMAL" }, 439#endif 440#ifdef MADV_RANDOM 441 { MADV_RANDOM, "MADV_RANDOM" }, 442#endif 443#ifdef MADV_SEQUENTIAL 444 { MADV_SEQUENTIAL, "MADV_SEQUENTIAL" }, 445#endif 446#ifdef MADV_WILLNEED 447 { MADV_WILLNEED, "MADV_WILLNEED" }, 448#endif 449#ifdef MADV_DONTNEED 450 { MADV_DONTNEED, "MADV_DONTNEED" }, 451#endif 452 { 0, NULL }, 453}; 454 455 456int 457sys_madvise(tcp) 458struct tcb *tcp; 459{ 460 if (entering(tcp)) { 461 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 462 printxval(madvise_cmds, tcp->u_arg[2], "MADV_???"); 463 } 464 return 0; 465} 466 467 468static const struct xlat mlockall_flags[] = { 469#ifdef MCL_CURRENT 470 { MCL_CURRENT, "MCL_CURRENT" }, 471#endif 472#ifdef MCL_FUTURE 473 { MCL_FUTURE, "MCL_FUTURE" }, 474#endif 475 { 0, NULL} 476}; 477 478int 479sys_mlockall(tcp) 480struct tcb *tcp; 481{ 482 if (entering(tcp)) { 483 printflags(mlockall_flags, tcp->u_arg[0], "MCL_???"); 484 } 485 return 0; 486} 487 488 489#endif /* LINUX */ 490 491#ifdef MS_ASYNC 492 493static const struct xlat mctl_sync[] = { 494#ifdef MS_SYNC 495 { MS_SYNC, "MS_SYNC" }, 496#endif 497 { MS_ASYNC, "MS_ASYNC" }, 498 { MS_INVALIDATE,"MS_INVALIDATE" }, 499 { 0, NULL }, 500}; 501 502int 503sys_msync(tcp) 504struct 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 521static 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 530static const struct xlat mctl_lockas[] = { 531 { MCL_CURRENT, "MCL_CURRENT" }, 532 { MCL_FUTURE, "MCL_FUTURE" }, 533 { 0, NULL }, 534}; 535 536int 537sys_mctl(tcp) 538struct tcb *tcp; 539{ 540 int arg, function; 541 542 if (entering(tcp)) { 543 /* addr */ 544 tprintf("%#lx", tcp->u_arg[0]); 545 /* len */ 546 tprintf(", %lu, ", tcp->u_arg[1]); 547 /* function */ 548 function = tcp->u_arg[2]; 549 printflags(mctl_funcs, function, "MC_???"); 550 /* arg */ 551 arg = tcp->u_arg[3]; 552 tprintf(", "); 553 switch (function) { 554 case MC_SYNC: 555 printflags(mctl_sync, arg, "MS_???"); 556 break; 557 case MC_LOCKAS: 558 printflags(mctl_lockas, arg, "MCL_???"); 559 break; 560 default: 561 tprintf("%#x", arg); 562 break; 563 } 564 } 565 return 0; 566} 567 568#endif /* MC_SYNC */ 569 570int 571sys_mincore(tcp) 572struct tcb *tcp; 573{ 574 unsigned long i, len; 575 char *vec = NULL; 576 577 if (entering(tcp)) { 578 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 579 } else { 580 len = tcp->u_arg[1]; 581 if (syserror(tcp) || tcp->u_arg[2] == 0 || 582 (vec = malloc(len)) == NULL || 583 umoven(tcp, tcp->u_arg[2], len, vec) < 0) 584 tprintf("%#lx", tcp->u_arg[2]); 585 else { 586 tprintf("["); 587 for (i = 0; i < len; i++) { 588 if (abbrev(tcp) && i >= max_strlen) { 589 tprintf("..."); 590 break; 591 } 592 tprintf((vec[i] & 1) ? "1" : "0"); 593 } 594 tprintf("]"); 595 } 596 if (vec) 597 free(vec); 598 } 599 return 0; 600} 601 602#if defined(ALPHA) || defined(FREEBSD) || defined(IA64) || defined(SUNOS4) || defined(SVR4) || defined(SPARC) || defined(SPARC64) 603int 604sys_getpagesize(tcp) 605struct tcb *tcp; 606{ 607 if (exiting(tcp)) 608 return RVAL_HEX; 609 return 0; 610} 611#endif /* ALPHA || FREEBSD || IA64 || SUNOS4 || SVR4 */ 612 613#if defined(LINUX) && defined(__i386__) 614void 615print_ldt_entry(struct modify_ldt_ldt_s *ldt_entry) 616{ 617 tprintf("base_addr:%#08lx, " 618 "limit:%d, " 619 "seg_32bit:%d, " 620 "contents:%d, " 621 "read_exec_only:%d, " 622 "limit_in_pages:%d, " 623 "seg_not_present:%d, " 624 "useable:%d}", 625 (long) ldt_entry->base_addr, 626 ldt_entry->limit, 627 ldt_entry->seg_32bit, 628 ldt_entry->contents, 629 ldt_entry->read_exec_only, 630 ldt_entry->limit_in_pages, 631 ldt_entry->seg_not_present, 632 ldt_entry->useable); 633} 634 635int 636sys_modify_ldt(tcp) 637struct tcb *tcp; 638{ 639 if (entering(tcp)) { 640 struct modify_ldt_ldt_s copy; 641 tprintf("%ld", tcp->u_arg[0]); 642 if (tcp->u_arg[1] == 0 643 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s) 644 || umove(tcp, tcp->u_arg[1], ©) == -1) 645 tprintf(", %lx", tcp->u_arg[1]); 646 else { 647 tprintf(", {entry_number:%d, ", copy.entry_number); 648 if (!verbose(tcp)) 649 tprintf("...}"); 650 else { 651 print_ldt_entry(©); 652 } 653 } 654 tprintf(", %lu", tcp->u_arg[2]); 655 } 656 return 0; 657} 658 659int 660sys_set_thread_area(tcp) 661struct tcb *tcp; 662{ 663 struct modify_ldt_ldt_s copy; 664 if (entering(tcp)) { 665 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 666 if (copy.entry_number == -1) 667 tprintf("{entry_number:%d -> ", 668 copy.entry_number); 669 else 670 tprintf("{entry_number:"); 671 } 672 } else { 673 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 674 tprintf("%d, ", copy.entry_number); 675 if (!verbose(tcp)) 676 tprintf("...}"); 677 else { 678 print_ldt_entry(©); 679 } 680 } else { 681 tprintf("%lx", tcp->u_arg[0]); 682 } 683 } 684 return 0; 685 686} 687 688int 689sys_get_thread_area(tcp) 690struct tcb *tcp; 691{ 692 struct modify_ldt_ldt_s copy; 693 if (exiting(tcp)) { 694 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 695 tprintf("{entry_number:%d, ", copy.entry_number); 696 if (!verbose(tcp)) 697 tprintf("...}"); 698 else { 699 print_ldt_entry(©); 700 } 701 } else { 702 tprintf("%lx", tcp->u_arg[0]); 703 } 704 } 705 return 0; 706 707} 708#endif /* LINUX && __i386__ */ 709 710#if defined(LINUX) && defined(M68K) 711 712int 713sys_set_thread_area(tcp) 714struct tcb *tcp; 715{ 716 if (entering(tcp)) 717 tprintf("%#lx", tcp->u_arg[0]); 718 return 0; 719 720} 721 722int 723sys_get_thread_area(tcp) 724struct tcb *tcp; 725{ 726 return RVAL_HEX; 727} 728#endif 729 730#if defined(LINUX) 731int 732sys_remap_file_pages(tcp) 733struct tcb *tcp; 734{ 735 if (entering(tcp)) { 736 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 737 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 738 tprintf(", %lu, ", tcp->u_arg[3]); 739#ifdef MAP_TYPE 740 printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???"); 741 addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE); 742#else 743 printflags(mmap_flags, tcp->u_arg[4], "MAP_???"); 744#endif 745 } 746 return 0; 747} 748 749 750#define MPOL_DEFAULT 0 751#define MPOL_PREFERRED 1 752#define MPOL_BIND 2 753#define MPOL_INTERLEAVE 3 754 755#define MPOL_F_NODE (1<<0) 756#define MPOL_F_ADDR (1<<1) 757 758#define MPOL_MF_STRICT (1<<0) 759#define MPOL_MF_MOVE (1<<1) 760#define MPOL_MF_MOVE_ALL (1<<2) 761 762 763static const struct xlat policies[] = { 764 { MPOL_DEFAULT, "MPOL_DEFAULT" }, 765 { MPOL_PREFERRED, "MPOL_PREFERRED" }, 766 { MPOL_BIND, "MPOL_BIND" }, 767 { MPOL_INTERLEAVE, "MPOL_INTERLEAVE" }, 768 { 0, NULL } 769}; 770 771static const struct xlat mbindflags[] = { 772 { MPOL_MF_STRICT, "MPOL_MF_STRICT" }, 773 { MPOL_MF_MOVE, "MPOL_MF_MOVE" }, 774 { MPOL_MF_MOVE_ALL, "MPOL_MF_MOVE_ALL" }, 775 { 0, NULL } 776}; 777 778static const struct xlat mempolicyflags[] = { 779 { MPOL_F_NODE, "MPOL_F_NODE" }, 780 { MPOL_F_ADDR, "MPOL_F_ADDR" }, 781 { 0, NULL } 782}; 783 784static const struct xlat move_pages_flags[] = { 785 { MPOL_MF_MOVE, "MPOL_MF_MOVE" }, 786 { MPOL_MF_MOVE_ALL, "MPOL_MF_MOVE_ALL" }, 787 { 0, NULL } 788}; 789 790 791static void 792get_nodes(tcp, ptr, maxnodes, err) 793struct tcb *tcp; 794unsigned long ptr; 795unsigned long maxnodes; 796int err; 797{ 798 unsigned long nlongs, size, end; 799 800 nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long)); 801 size = nlongs * sizeof(long); 802 end = ptr + size; 803 if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes) 804 && (end > ptr))) { 805 unsigned long n, cur, abbrev_end; 806 int failed = 0; 807 808 if (abbrev(tcp)) { 809 abbrev_end = ptr + max_strlen * sizeof(long); 810 if (abbrev_end < ptr) 811 abbrev_end = end; 812 } else { 813 abbrev_end = end; 814 } 815 tprintf(", {"); 816 for (cur = ptr; cur < end; cur += sizeof(long)) { 817 if (cur > ptr) 818 tprintf(", "); 819 if (cur >= abbrev_end) { 820 tprintf("..."); 821 break; 822 } 823 if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) { 824 tprintf("?"); 825 failed = 1; 826 break; 827 } 828 tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n); 829 } 830 tprintf("}"); 831 if (failed) 832 tprintf(" %#lx", ptr); 833 } else 834 tprintf(", %#lx", ptr); 835 tprintf(", %lu", maxnodes); 836} 837 838int 839sys_mbind(tcp) 840struct tcb *tcp; 841{ 842 if (entering(tcp)) { 843 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 844 printxval(policies, tcp->u_arg[2], "MPOL_???"); 845 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0); 846 tprintf(", "); 847 printflags(mbindflags, tcp->u_arg[5], "MPOL_???"); 848 } 849 return 0; 850} 851 852int 853sys_set_mempolicy(tcp) 854struct tcb *tcp; 855{ 856 if (entering(tcp)) { 857 printxval(policies, tcp->u_arg[0], "MPOL_???"); 858 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0); 859 } 860 return 0; 861} 862 863int 864sys_get_mempolicy(tcp) 865struct tcb *tcp; 866{ 867 if (exiting(tcp)) { 868 int pol; 869 if (tcp->u_arg[0] == 0) 870 tprintf("NULL"); 871 else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0) 872 tprintf("%#lx", tcp->u_arg[0]); 873 else 874 printxval(policies, pol, "MPOL_???"); 875 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp)); 876 tprintf(", %#lx, ", tcp->u_arg[3]); 877 printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???"); 878 } 879 return 0; 880} 881 882int 883sys_move_pages(tcp) 884struct tcb *tcp; 885{ 886 if (entering(tcp)) { 887 unsigned long npages = tcp->u_arg[1]; 888 tprintf("%ld, %lu, ", tcp->u_arg[0], npages); 889 if (tcp->u_arg[2] == 0) 890 tprintf("NULL, "); 891 else { 892 int i; 893 long puser = tcp->u_arg[2]; 894 tprintf("{"); 895 for (i = 0; i < npages; ++i) { 896 void *p; 897 if (i > 0) 898 tprintf(", "); 899 if (umove(tcp, puser, &p) < 0) { 900 tprintf("???"); 901 break; 902 } 903 tprintf("%p", p); 904 puser += sizeof (void *); 905 } 906 tprintf("}, "); 907 } 908 if (tcp->u_arg[3] == 0) 909 tprintf("NULL, "); 910 else { 911 int i; 912 long nodeuser = tcp->u_arg[3]; 913 tprintf("{"); 914 for (i = 0; i < npages; ++i) { 915 int node; 916 if (i > 0) 917 tprintf(", "); 918 if (umove(tcp, nodeuser, &node) < 0) { 919 tprintf("???"); 920 break; 921 } 922 tprintf("%#x", node); 923 nodeuser += sizeof (int); 924 } 925 tprintf("}, "); 926 } 927 } 928 if (exiting(tcp)) { 929 unsigned long npages = tcp->u_arg[1]; 930 if (tcp->u_arg[4] == 0) 931 tprintf("NULL, "); 932 else { 933 int i; 934 long statususer = tcp->u_arg[4]; 935 tprintf("{"); 936 for (i = 0; i < npages; ++i) { 937 int status; 938 if (i > 0) 939 tprintf(", "); 940 if (umove(tcp, statususer, &status) < 0) { 941 tprintf("???"); 942 break; 943 } 944 tprintf("%#x", status); 945 statususer += sizeof (int); 946 } 947 tprintf("}, "); 948 } 949 printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???"); 950 } 951 return 0; 952} 953#endif 954 955#if defined(LINUX) && defined(POWERPC) 956int 957sys_subpage_prot(tcp) 958struct tcb *tcp; 959{ 960 if (entering(tcp)) { 961 unsigned long cur, end, abbrev_end, entries; 962 unsigned int entry; 963 964 tprintf("%#lx, %#lx, ", tcp->u_arg[0], tcp->u_arg[1]); 965 entries = tcp->u_arg[1] >> 16; 966 if (!entries || !tcp->u_arg[2]) { 967 tprintf("{}"); 968 return 0; 969 } 970 cur = tcp->u_arg[2]; 971 end = cur + (sizeof(int) * entries); 972 if (!verbose(tcp) || end < tcp->u_arg[2]) { 973 tprintf("%#lx", tcp->u_arg[2]); 974 return 0; 975 } 976 if (abbrev(tcp)) { 977 abbrev_end = cur + (sizeof(int) * max_strlen); 978 if (abbrev_end > end) 979 abbrev_end = end; 980 } 981 else 982 abbrev_end = end; 983 tprintf("{"); 984 for (; cur < end; cur += sizeof(int)) { 985 if (cur > tcp->u_arg[2]) 986 tprintf(", "); 987 if (cur >= abbrev_end) { 988 tprintf("..."); 989 break; 990 } 991 if (umove(tcp, cur, &entry) < 0) { 992 tprintf("??? [%#lx]", cur); 993 break; 994 } 995 else 996 tprintf("%#08x", entry); 997 } 998 tprintf("}"); 999 } 1000 1001 return 0; 1002} 1003#endif 1004