1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 2000 PocketPenguins Inc. Linux for Hitachi SuperH 7 * port by Greg Banks <gbanks (at) 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 37 static unsigned long 38 get_pagesize() 39 { 40 static unsigned long pagesize; 41 42 if (!pagesize) 43 pagesize = sysconf(_SC_PAGESIZE); 44 return pagesize; 45 } 46 47 int 48 sys_brk(struct tcb *tcp) 49 { 50 if (entering(tcp)) { 51 tprintf("%#lx", tcp->u_arg[0]); 52 } 53 return RVAL_HEX; 54 } 55 56 #include "xlat/mmap_prot.h" 57 #include "xlat/mmap_flags.h" 58 59 static int 60 print_mmap(struct tcb *tcp, long *u_arg, unsigned long long offset) 61 { 62 if (entering(tcp)) { 63 /* addr */ 64 if (!u_arg[0]) 65 tprints("NULL, "); 66 else 67 tprintf("%#lx, ", u_arg[0]); 68 /* len */ 69 tprintf("%lu, ", u_arg[1]); 70 /* prot */ 71 printflags(mmap_prot, u_arg[2], "PROT_???"); 72 tprints(", "); 73 /* flags */ 74 #ifdef MAP_TYPE 75 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); 76 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); 77 #else 78 printflags(mmap_flags, u_arg[3], "MAP_???"); 79 #endif 80 tprints(", "); 81 /* fd */ 82 printfd(tcp, u_arg[4]); 83 /* offset */ 84 tprintf(", %#llx", offset); 85 } 86 return RVAL_HEX; 87 } 88 89 /* Syscall name<->function correspondence is messed up on many arches. 90 * For example: 91 * i386 has __NR_mmap == 90, and it is "old mmap", and 92 * also it has __NR_mmap2 == 192, which is a "new mmap with page offsets". 93 * But x86_64 has just one __NR_mmap == 9, a "new mmap with byte offsets". 94 * Confused? Me too! 95 */ 96 97 /* Params are pointed to by u_arg[0], offset is in bytes */ 98 int 99 sys_old_mmap(struct tcb *tcp) 100 { 101 long u_arg[6]; 102 #if defined(IA64) 103 /* 104 * IA64 processes never call this routine, they only use the 105 * new 'sys_mmap' interface. Only IA32 processes come here. 106 */ 107 int i; 108 unsigned narrow_arg[6]; 109 if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) 110 return 0; 111 for (i = 0; i < 6; i++) 112 u_arg[i] = (unsigned long) narrow_arg[i]; 113 #elif defined(X86_64) 114 /* We are here only in personality 1 (i386) */ 115 int i; 116 unsigned narrow_arg[6]; 117 if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) 118 return 0; 119 for (i = 0; i < 6; ++i) 120 u_arg[i] = (unsigned long) narrow_arg[i]; 121 #else 122 if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), (char *) u_arg) == -1) 123 return 0; 124 #endif 125 return print_mmap(tcp, u_arg, (unsigned long) u_arg[5]); 126 } 127 128 #if defined(S390) 129 /* Params are pointed to by u_arg[0], offset is in pages */ 130 int 131 sys_old_mmap_pgoff(struct tcb *tcp) 132 { 133 long u_arg[5]; 134 int i; 135 unsigned narrow_arg[6]; 136 unsigned long long offset; 137 if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) 138 return 0; 139 for (i = 0; i < 5; i++) 140 u_arg[i] = (unsigned long) narrow_arg[i]; 141 offset = narrow_arg[5]; 142 offset *= get_pagesize(); 143 return print_mmap(tcp, u_arg, offset); 144 } 145 #endif 146 147 /* Params are passed directly, offset is in bytes */ 148 int 149 sys_mmap(struct tcb *tcp) 150 { 151 unsigned long long offset = (unsigned long) tcp->u_arg[5]; 152 #if defined(LINUX_MIPSN32) || defined(X32) 153 /* Try test/x32_mmap.c */ 154 offset = tcp->ext_arg[5]; 155 #endif 156 /* Example of kernel-side handling of this variety of mmap: 157 * arch/x86/kernel/sys_x86_64.c::SYSCALL_DEFINE6(mmap, ...) calls 158 * sys_mmap_pgoff(..., off >> PAGE_SHIFT); i.e. off is in bytes, 159 * since the above code converts off to pages. 160 */ 161 return print_mmap(tcp, tcp->u_arg, offset); 162 } 163 164 /* Params are passed directly, offset is in pages */ 165 int 166 sys_mmap_pgoff(struct tcb *tcp) 167 { 168 /* Try test/mmap_offset_decode.c */ 169 unsigned long long offset; 170 offset = (unsigned long) tcp->u_arg[5]; 171 offset *= get_pagesize(); 172 return print_mmap(tcp, tcp->u_arg, offset); 173 } 174 175 /* Params are passed directly, offset is in 4k units */ 176 int 177 sys_mmap_4koff(struct tcb *tcp) 178 { 179 unsigned long long offset; 180 offset = (unsigned long) tcp->u_arg[5]; 181 offset <<= 12; 182 return print_mmap(tcp, tcp->u_arg, offset); 183 } 184 185 int 186 sys_munmap(struct tcb *tcp) 187 { 188 if (entering(tcp)) { 189 tprintf("%#lx, %lu", 190 tcp->u_arg[0], tcp->u_arg[1]); 191 } 192 return 0; 193 } 194 195 int 196 sys_mprotect(struct tcb *tcp) 197 { 198 if (entering(tcp)) { 199 tprintf("%#lx, %lu, ", 200 tcp->u_arg[0], tcp->u_arg[1]); 201 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 202 } 203 return 0; 204 } 205 206 #include "xlat/mremap_flags.h" 207 208 int 209 sys_mremap(struct tcb *tcp) 210 { 211 if (entering(tcp)) { 212 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1], 213 tcp->u_arg[2]); 214 printflags(mremap_flags, tcp->u_arg[3], "MREMAP_???"); 215 #ifdef MREMAP_FIXED 216 if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) == 217 (MREMAP_MAYMOVE | MREMAP_FIXED)) 218 tprintf(", %#lx", tcp->u_arg[4]); 219 #endif 220 } 221 return RVAL_HEX; 222 } 223 224 #include "xlat/madvise_cmds.h" 225 226 int 227 sys_madvise(struct tcb *tcp) 228 { 229 if (entering(tcp)) { 230 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 231 printxval(madvise_cmds, tcp->u_arg[2], "MADV_???"); 232 } 233 return 0; 234 } 235 236 #include "xlat/mlockall_flags.h" 237 238 int 239 sys_mlockall(struct tcb *tcp) 240 { 241 if (entering(tcp)) { 242 printflags(mlockall_flags, tcp->u_arg[0], "MCL_???"); 243 } 244 return 0; 245 } 246 247 #ifdef MS_ASYNC 248 249 #include "xlat/mctl_sync.h" 250 251 int 252 sys_msync(struct tcb *tcp) 253 { 254 if (entering(tcp)) { 255 /* addr */ 256 tprintf("%#lx", tcp->u_arg[0]); 257 /* len */ 258 tprintf(", %lu, ", tcp->u_arg[1]); 259 /* flags */ 260 printflags(mctl_sync, tcp->u_arg[2], "MS_???"); 261 } 262 return 0; 263 } 264 265 #endif /* MS_ASYNC */ 266 267 #ifdef MC_SYNC 268 269 #include "xlat/mctl_funcs.h" 270 #include "xlat/mctl_lockas.h" 271 272 int 273 sys_mctl(struct tcb *tcp) 274 { 275 int arg, function; 276 277 if (entering(tcp)) { 278 /* addr */ 279 tprintf("%#lx", tcp->u_arg[0]); 280 /* len */ 281 tprintf(", %lu, ", tcp->u_arg[1]); 282 /* function */ 283 function = tcp->u_arg[2]; 284 printflags(mctl_funcs, function, "MC_???"); 285 /* arg */ 286 arg = tcp->u_arg[3]; 287 tprints(", "); 288 switch (function) { 289 case MC_SYNC: 290 printflags(mctl_sync, arg, "MS_???"); 291 break; 292 case MC_LOCKAS: 293 printflags(mctl_lockas, arg, "MCL_???"); 294 break; 295 default: 296 tprintf("%#x", arg); 297 break; 298 } 299 } 300 return 0; 301 } 302 303 #endif /* MC_SYNC */ 304 305 int 306 sys_mincore(struct tcb *tcp) 307 { 308 if (entering(tcp)) { 309 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 310 } else { 311 unsigned long i, len; 312 char *vec = NULL; 313 314 len = tcp->u_arg[1]; 315 if (syserror(tcp) || tcp->u_arg[2] == 0 || 316 (vec = malloc(len)) == NULL || 317 umoven(tcp, tcp->u_arg[2], len, vec) < 0) 318 tprintf("%#lx", tcp->u_arg[2]); 319 else { 320 tprints("["); 321 for (i = 0; i < len; i++) { 322 if (abbrev(tcp) && i >= max_strlen) { 323 tprints("..."); 324 break; 325 } 326 tprints((vec[i] & 1) ? "1" : "0"); 327 } 328 tprints("]"); 329 } 330 free(vec); 331 } 332 return 0; 333 } 334 335 #if defined(ALPHA) || defined(IA64) || defined(SPARC) || defined(SPARC64) 336 int 337 sys_getpagesize(struct tcb *tcp) 338 { 339 if (exiting(tcp)) 340 return RVAL_HEX; 341 return 0; 342 } 343 #endif 344 345 int 346 sys_remap_file_pages(struct tcb *tcp) 347 { 348 if (entering(tcp)) { 349 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 350 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 351 tprintf(", %lu, ", tcp->u_arg[3]); 352 #ifdef MAP_TYPE 353 printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???"); 354 addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE); 355 #else 356 printflags(mmap_flags, tcp->u_arg[4], "MAP_???"); 357 #endif 358 } 359 return 0; 360 } 361 362 #define MPOL_DEFAULT 0 363 #define MPOL_PREFERRED 1 364 #define MPOL_BIND 2 365 #define MPOL_INTERLEAVE 3 366 367 #define MPOL_F_NODE (1<<0) 368 #define MPOL_F_ADDR (1<<1) 369 370 #define MPOL_MF_STRICT (1<<0) 371 #define MPOL_MF_MOVE (1<<1) 372 #define MPOL_MF_MOVE_ALL (1<<2) 373 374 #include "xlat/policies.h" 375 #include "xlat/mbindflags.h" 376 #include "xlat/mempolicyflags.h" 377 #include "xlat/move_pages_flags.h" 378 379 static void 380 get_nodes(struct tcb *tcp, unsigned long ptr, unsigned long maxnodes, int err) 381 { 382 unsigned long nlongs, size, end; 383 384 nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long)); 385 size = nlongs * sizeof(long); 386 end = ptr + size; 387 if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes) 388 && (end > ptr))) { 389 unsigned long n, cur, abbrev_end; 390 int failed = 0; 391 392 if (abbrev(tcp)) { 393 abbrev_end = ptr + max_strlen * sizeof(long); 394 if (abbrev_end < ptr) 395 abbrev_end = end; 396 } else { 397 abbrev_end = end; 398 } 399 tprints(", {"); 400 for (cur = ptr; cur < end; cur += sizeof(long)) { 401 if (cur > ptr) 402 tprints(", "); 403 if (cur >= abbrev_end) { 404 tprints("..."); 405 break; 406 } 407 if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) { 408 tprints("?"); 409 failed = 1; 410 break; 411 } 412 tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n); 413 } 414 tprints("}"); 415 if (failed) 416 tprintf(" %#lx", ptr); 417 } else 418 tprintf(", %#lx", ptr); 419 tprintf(", %lu", maxnodes); 420 } 421 422 int 423 sys_mbind(struct tcb *tcp) 424 { 425 if (entering(tcp)) { 426 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 427 printxval(policies, tcp->u_arg[2], "MPOL_???"); 428 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0); 429 tprints(", "); 430 printflags(mbindflags, tcp->u_arg[5], "MPOL_???"); 431 } 432 return 0; 433 } 434 435 int 436 sys_set_mempolicy(struct tcb *tcp) 437 { 438 if (entering(tcp)) { 439 printxval(policies, tcp->u_arg[0], "MPOL_???"); 440 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0); 441 } 442 return 0; 443 } 444 445 int 446 sys_get_mempolicy(struct tcb *tcp) 447 { 448 if (exiting(tcp)) { 449 int pol; 450 if (tcp->u_arg[0] == 0) 451 tprints("NULL"); 452 else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0) 453 tprintf("%#lx", tcp->u_arg[0]); 454 else 455 printxval(policies, pol, "MPOL_???"); 456 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp)); 457 tprintf(", %#lx, ", tcp->u_arg[3]); 458 printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???"); 459 } 460 return 0; 461 } 462 463 int 464 sys_migrate_pages(struct tcb *tcp) 465 { 466 if (entering(tcp)) { 467 tprintf("%ld, ", (long) (pid_t) tcp->u_arg[0]); 468 get_nodes(tcp, tcp->u_arg[2], tcp->u_arg[1], 0); 469 tprints(", "); 470 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[1], 0); 471 } 472 return 0; 473 } 474 475 int 476 sys_move_pages(struct tcb *tcp) 477 { 478 if (entering(tcp)) { 479 unsigned long npages = tcp->u_arg[1]; 480 tprintf("%ld, %lu, ", tcp->u_arg[0], npages); 481 if (tcp->u_arg[2] == 0) 482 tprints("NULL, "); 483 else { 484 int i; 485 long puser = tcp->u_arg[2]; 486 tprints("{"); 487 for (i = 0; i < npages; ++i) { 488 void *p; 489 if (i > 0) 490 tprints(", "); 491 if (umove(tcp, puser, &p) < 0) { 492 tprints("???"); 493 break; 494 } 495 tprintf("%p", p); 496 puser += sizeof(void *); 497 } 498 tprints("}, "); 499 } 500 if (tcp->u_arg[3] == 0) 501 tprints("NULL, "); 502 else { 503 int i; 504 long nodeuser = tcp->u_arg[3]; 505 tprints("{"); 506 for (i = 0; i < npages; ++i) { 507 int node; 508 if (i > 0) 509 tprints(", "); 510 if (umove(tcp, nodeuser, &node) < 0) { 511 tprints("???"); 512 break; 513 } 514 tprintf("%#x", node); 515 nodeuser += sizeof(int); 516 } 517 tprints("}, "); 518 } 519 } 520 if (exiting(tcp)) { 521 unsigned long npages = tcp->u_arg[1]; 522 if (tcp->u_arg[4] == 0) 523 tprints("NULL, "); 524 else { 525 int i; 526 long statususer = tcp->u_arg[4]; 527 tprints("{"); 528 for (i = 0; i < npages; ++i) { 529 int status; 530 if (i > 0) 531 tprints(", "); 532 if (umove(tcp, statususer, &status) < 0) { 533 tprints("???"); 534 break; 535 } 536 tprintf("%#x", status); 537 statususer += sizeof(int); 538 } 539 tprints("}, "); 540 } 541 printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???"); 542 } 543 return 0; 544 } 545 546 #if defined(POWERPC) 547 int 548 sys_subpage_prot(struct tcb *tcp) 549 { 550 if (entering(tcp)) { 551 unsigned long cur, end, abbrev_end, entries; 552 unsigned int entry; 553 554 tprintf("%#lx, %#lx, ", tcp->u_arg[0], tcp->u_arg[1]); 555 entries = tcp->u_arg[1] >> 16; 556 if (!entries || !tcp->u_arg[2]) { 557 tprints("{}"); 558 return 0; 559 } 560 cur = tcp->u_arg[2]; 561 end = cur + (sizeof(int) * entries); 562 if (!verbose(tcp) || end < tcp->u_arg[2]) { 563 tprintf("%#lx", tcp->u_arg[2]); 564 return 0; 565 } 566 if (abbrev(tcp)) { 567 abbrev_end = cur + (sizeof(int) * max_strlen); 568 if (abbrev_end > end) 569 abbrev_end = end; 570 } 571 else 572 abbrev_end = end; 573 tprints("{"); 574 for (; cur < end; cur += sizeof(int)) { 575 if (cur > tcp->u_arg[2]) 576 tprints(", "); 577 if (cur >= abbrev_end) { 578 tprints("..."); 579 break; 580 } 581 if (umove(tcp, cur, &entry) < 0) { 582 tprintf("??? [%#lx]", cur); 583 break; 584 } 585 else 586 tprintf("%#08x", entry); 587 } 588 tprints("}"); 589 } 590 591 return 0; 592 } 593 #endif 594