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