1 2 /*--------------------------------------------------------------------*/ 3 /*--- Platform-specific syscalls stuff. syswrap-mips64-linux.c ----*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2010-2013 RT-RK 11 mips-valgrind (at) rt-rk.com 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #if defined(VGP_mips64_linux) 32 #include "pub_core_basics.h" 33 #include "pub_core_vki.h" 34 #include "pub_core_vkiscnums.h" 35 #include "pub_core_libcsetjmp.h" /* to keep _threadstate.h happy */ 36 #include "pub_core_threadstate.h" 37 #include "pub_core_aspacemgr.h" 38 #include "pub_core_debuglog.h" 39 #include "pub_core_libcbase.h" 40 #include "pub_core_libcassert.h" 41 #include "pub_core_libcprint.h" 42 #include "pub_core_libcproc.h" 43 #include "pub_core_libcsignal.h" 44 #include "pub_core_options.h" 45 #include "pub_core_scheduler.h" 46 #include "pub_core_sigframe.h" /* For VG_(sigframe_destroy)() */ 47 #include "pub_core_signals.h" 48 #include "pub_core_syscall.h" 49 #include "pub_core_syswrap.h" 50 #include "pub_core_tooliface.h" 51 #include "pub_core_stacks.h" /* VG_(register_stack) */ 52 #include "pub_core_transtab.h" /* VG_(discard_translations) */ 53 #include "priv_types_n_macros.h" 54 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */ 55 #include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */ 56 #include "priv_syswrap-main.h" 57 58 #include "pub_core_debuginfo.h" /* VG_(di_notify_*) */ 59 #include "pub_core_xarray.h" 60 #include "pub_core_clientstate.h" /* VG_(brk_base), VG_(brk_limit) */ 61 #include "pub_core_errormgr.h" 62 #include "pub_core_gdbserver.h" /* VG_(gdbserver) */ 63 #include "pub_core_libcfile.h" 64 #include "pub_core_machine.h" /* VG_(get_SP) */ 65 #include "pub_core_mallocfree.h" 66 #include "pub_core_stacktrace.h" /* For VG_(get_and_pp_StackTrace)() */ 67 #include "pub_core_ume.h" 68 69 #include "config.h" 70 71 #include <errno.h> 72 73 /* --------------------------------------------------------------------- 74 clone() handling 75 ------------------------------------------------------------------ */ 76 77 /* Call f(arg1), but first switch stacks, using 'stack' as the new stack, and 78 use 'retaddr' as f's return-to address. Also, clear all the integer registers 79 before entering f. */ 80 __attribute__ ((noreturn)) 81 void ML_(call_on_new_stack_0_1) ( Addr stack, /* $4 - $a0 */ 82 Addr retaddr, /* $5 - $a1 */ 83 void (*f_desc) (Word), /* $6 - $a2 */ 84 Word arg1 ); /* $7 - $a3 */ 85 asm ( 86 ".text\n" 87 ".globl vgModuleLocal_call_on_new_stack_0_1\n" 88 "vgModuleLocal_call_on_new_stack_0_1:\n" 89 " move $29, $4\n" /* set stack */ 90 " move $4, $7\n" /* arg1 to $4 */ 91 " move $25, $6\n" 92 " move $31, $5\n" /* retaddr to $ra */ 93 " jr $25\n" /* jump to f */ 94 " break 0x7\n" /* should never get here */ 95 ".previous\n" 96 ); 97 98 /* Perform a clone system call. clone is strange because it has fork()-like 99 return-twice semantics, so it needs special handling here. 100 101 Upon entry, we have: 102 103 word (fn)(void*) in a0 = 4 104 void* child_stack in a1 = 5 105 word flags in a2 = 6 106 void* arg in a3 = 7 107 pid_t* parent_tid in a4 = 8 108 void* tls in a5 = 9 109 pid_t* child_tid in a6 = 10 110 111 System call requires: 112 113 int $__NR_clone in v0 114 int flags in a0 = 4 115 void* child_stack in a1 = 5 116 pid_t* parent_tid in a2 = 6 117 void* tls_ptr in a3 = 7 118 pid_t* child_tid in a4 = 8 */ 119 120 #define __NR_CLONE __NR_clone 121 #define __NR_EXIT __NR_exit 122 123 ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *), /* a0 - 4 */ 124 void* stack, /* a1 - 5 */ 125 Int flags, /* a2 - 6 */ 126 void* arg, /* a3 - 7 */ 127 Int* parent_tid, /* a4 - 8 */ 128 void* /* Int tls */, /* a5 - 9 */ 129 Int* child_tid ); /* a6 - 10 */ 130 131 asm( 132 ".text\n" 133 ".set noreorder\n" 134 ".set nomacro\n" 135 ".globl do_syscall_clone_mips64_linux\n" 136 "do_syscall_clone_mips64_linux:\n" 137 " daddiu $29, $29, -32\n" 138 " sd $31, 0($29)\n" 139 " sd $30, 8($29)\n" 140 " sd $28, 16($29)\n" 141 142 " daddiu $5, $5, -32\n" 143 " sd $4, 0($5)\n" /* fn */ 144 " sd $7, 8($5)\n" /* arg */ 145 " sd $6, 16($5)\n" /* flags */ 146 147 /* 1. arg for syscalls */ 148 " move $4, $6\n" /* flags */ 149 " move $6, $8\n" /* parent */ 150 " move $7, $a5\n" /* tls */ 151 " move $8, $a6\n" /* child */ 152 153 /* 2. do a syscall to clone */ 154 " li $2, 5055\n" /* syscall num for clone */ 155 " syscall\n" 156 157 /* 3. See if we are a child, call fn and after that exit */ 158 " bnez $7, p_or_error\n" 159 " nop\n" 160 161 " bnez $2, p_or_error\n" 162 " nop\n" 163 164 " ld $25,0($29)\n" 165 " jalr $25\n" 166 " ld $4,8($29)\n" 167 168 " move $4, $2\n\t" /* retval from fn is in $v0 */ 169 " li $2, 5058\n\t" /* NR_exit */ 170 " syscall\n\t" 171 " nop\n\t" 172 /* 4. If we are parent or error, just return to caller */ 173 " p_or_error:\n" 174 " ld $31, 0($29)\n" 175 " ld $30, 8($29)\n" 176 " ld $28, 16($29)\n" 177 " jr $31\n" 178 " daddi $29,$29, 32\n" 179 ".previous\n" 180 ); 181 182 #undef __NR_CLONE 183 #undef __NR_EXIT 184 185 /* forward declarations */ 186 static void setup_child ( ThreadArchState *, ThreadArchState *); 187 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr); 188 189 /* When a client clones, we need to keep track of the new thread. This means: 190 1. allocate a ThreadId+ThreadState+stack for the the thread 191 192 2. initialize the thread's new VCPU state 193 194 3. create the thread using the same args as the client requested, but using 195 the scheduler entrypoint for IP, and a separate stack for SP. */ 196 static SysRes do_clone ( ThreadId ptid, 197 UInt flags, Addr sp, 198 Int* parent_tidptr, 199 Int* child_tidptr, 200 Addr child_tls ) 201 { 202 const Bool debug = False; 203 ThreadId ctid = VG_ (alloc_ThreadState) (); 204 ThreadState * ptst = VG_ (get_ThreadState) (ptid); 205 ThreadState * ctst = VG_ (get_ThreadState) (ctid); 206 UInt ret = 0; 207 UWord * stack; 208 NSegment const *seg; 209 SysRes res; 210 vki_sigset_t blockall, savedmask; 211 212 VG_(sigfillset)(&blockall); 213 vg_assert(VG_(is_running_thread)(ptid)); 214 vg_assert(VG_(is_valid_tid)(ctid)); 215 stack = (UWord *)ML_(allocstack)(ctid); 216 if (stack == NULL) { 217 res = VG_(mk_SysRes_Error)(VKI_ENOMEM); 218 goto out; 219 } 220 setup_child(&ctst->arch, &ptst->arch); 221 222 /* on MIPS we need to set V0 and A3 to zero */ 223 ctst->arch.vex.guest_r2 = 0; 224 ctst->arch.vex.guest_r7 = 0; 225 if (sp != 0) 226 ctst->arch.vex.guest_r29 = sp; 227 228 ctst->os_state.parent = ptid; 229 ctst->sig_mask = ptst->sig_mask; 230 ctst->tmp_sig_mask = ptst->sig_mask; 231 232 ctst->os_state.threadgroup = ptst->os_state.threadgroup; 233 seg = VG_(am_find_nsegment)((Addr)sp); 234 235 if (seg && seg->kind != SkResvn) { 236 ctst->client_stack_highest_word = sp; 237 ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start; 238 VG_(register_stack)(seg->start, ctst->client_stack_highest_word); 239 if (debug) 240 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n", 241 ctid, seg->start, sp /* VG_PGROUNDUP (sp) */ ); 242 } else { 243 VG_(message)(Vg_UserMsg, 244 "!? New thread %d starts with sp+%#lx) unmapped\n", 245 ctid, sp); 246 ctst->client_stack_szB = 0; 247 } 248 249 VG_TRACK(pre_thread_ll_create, ptid, ctid); 250 if (flags & VKI_CLONE_SETTLS) { 251 if (debug) 252 VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls); 253 res = sys_set_tls(ctid, child_tls); 254 if (sr_isError(res)) 255 goto out; 256 ctst->arch.vex.guest_r27 = child_tls; 257 } 258 259 flags &= ~VKI_CLONE_SETTLS; 260 VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask); 261 /* Create the new thread */ 262 ret = do_syscall_clone_mips64_linux(ML_(start_thread_NORETURN), 263 stack, flags, &VG_(threads)[ctid], 264 parent_tidptr, NULL /*child_tls*/, 265 child_tidptr); 266 if (debug) 267 VG_(printf)("ret: 0x%x\n", ret); 268 269 res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0); 270 271 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); 272 273 out: 274 if (sr_isError (res)) { 275 VG_ (cleanup_thread) (&ctst->arch); 276 ctst->status = VgTs_Empty; 277 VG_TRACK (pre_thread_ll_exit, ctid); 278 } 279 ptst->arch.vex.guest_r2 = 0; 280 281 return res; 282 } 283 284 /* --------------------------------------------------------------------- 285 More thread stuff 286 ------------------------------------------------------------------ */ 287 void VG_(cleanup_thread) ( ThreadArchState * arch ) { }; 288 289 void setup_child ( /* OUT */ ThreadArchState * child, 290 /* IN */ ThreadArchState * parent ) 291 { 292 /* We inherit our parent's guest state. */ 293 child->vex = parent->vex; 294 child->vex_shadow1 = parent->vex_shadow1; 295 child->vex_shadow2 = parent->vex_shadow2; 296 } 297 298 SysRes sys_set_tls ( ThreadId tid, Addr tlsptr ) 299 { 300 VG_(threads)[tid].arch.vex.guest_ULR = tlsptr; 301 return VG_(mk_SysRes_Success)( 0 ); 302 } 303 304 /* --------------------------------------------------------------------- 305 PRE/POST wrappers for mips/Linux-specific syscalls 306 ------------------------------------------------------------------ */ 307 308 #define PRE(name) DEFN_PRE_TEMPLATE(mips_linux, name) 309 #define POST(name) DEFN_POST_TEMPLATE(mips_linux, name) 310 311 /* Add prototypes for the wrappers declared here, so that gcc doesn't harass us 312 for not having prototypes. Really this is a kludge -- the right thing to do 313 is to make these wrappers 'static' since they aren't visible outside this 314 file, but that requires even more macro magic. */ 315 316 DECL_TEMPLATE (mips_linux, sys_set_thread_area); 317 DECL_TEMPLATE (mips_linux, sys_clone); 318 DECL_TEMPLATE (mips_linux, sys_tee); 319 DECL_TEMPLATE (mips_linux, sys_splice); 320 DECL_TEMPLATE (mips_linux, sys_vmsplice); 321 DECL_TEMPLATE (mips_linux, sys_ustat); 322 DECL_TEMPLATE (mips_linux, sys_sysfs); 323 DECL_TEMPLATE (mips_linux, sys_swapon); 324 DECL_TEMPLATE (mips_linux, sys_swapoff); 325 DECL_TEMPLATE (mips_linux, sys_setdomainname); 326 DECL_TEMPLATE (mips_linux, sys_sethostname); 327 DECL_TEMPLATE (mips_linux, sys_reboot); 328 DECL_TEMPLATE (mips_linux, sys_cacheflush); 329 DECL_TEMPLATE (mips_linux, sys_sched_rr_get_interval); 330 DECL_TEMPLATE (mips_linux, sys_unshare); 331 DECL_TEMPLATE (mips_linux, sys_arch_prctl); 332 DECL_TEMPLATE (mips_linux, sys_ptrace); 333 DECL_TEMPLATE (mips_linux, sys_mmap); 334 DECL_TEMPLATE (mips_linux, sys_rt_sigreturn); 335 DECL_TEMPLATE (mips_linux, sys_pipe); 336 337 PRE(sys_tee) 338 { 339 PRINT("sys_tee ( %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4); 340 PRE_REG_READ4(long, "sys_tee", int, fdin, int, fdout, vki_size_t, len, 341 int, flags); 342 } 343 344 PRE(sys_splice) 345 { 346 PRINT("sys_splice ( %ld, %ld, %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, 347 ARG4, ARG5, ARG6); 348 349 PRE_REG_READ6(long, "sys_splice", int, fdin, vki_loff_t, sizein, int, 350 fdout, vki_loff_t, sizeout, vki_size_t, len, int, flags); 351 } 352 353 PRE(sys_vmsplice) 354 { 355 PRINT("sys_vmsplice ( %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4); 356 PRE_REG_READ4(long, "sys_vmsplice", int, fdin, struct vki_iovec *, v, 357 vki_size_t, len, int, flags); 358 } 359 360 PRE(sys_unshare) 361 { 362 PRINT("sys_unshare ( %ld )", ARG1); 363 PRE_REG_READ1(long, "sys_unshare", int, flags); 364 } 365 366 PRE(sys_sched_rr_get_interval) 367 { 368 PRINT("sys_sched_rr_get_interval ( %ld, %#lx)", ARG1, ARG2); 369 PRE_REG_READ2(long, "sched_rr_get_interval", int, flags, 370 struct timespec *, timer); 371 *flags |= SfMayBlock; 372 } 373 374 PRE(sys_ustat) 375 { 376 PRINT("sys_ustat ( %ld, %#lx)", ARG1, ARG2); 377 PRE_REG_READ2(long, "ustat", int, flags, const void *, path); 378 } 379 380 PRE(sys_swapon) 381 { 382 PRINT("sys_swapon ( %#lx, %ld )", ARG1, ARG2); 383 PRE_REG_READ2(long, "swapon", const void *, path, int, flags); 384 } 385 386 PRE(sys_swapoff) 387 { 388 PRINT("sys_swapoff ( %#lx )", ARG1); 389 PRE_REG_READ1(long, "swapoff", const void *, path); 390 } 391 392 PRE(sys_sysfs) 393 { 394 PRINT("sys_sysfs ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); 395 PRE_REG_READ3(long, "sysfs", int, flags, int, desc, const void *, path); 396 } 397 398 /* Very much MIPS specific */ 399 PRE(sys_cacheflush) 400 { 401 PRINT("cacheflush (%lx, %lx, %lx)", ARG1, ARG2, ARG3); 402 PRE_REG_READ3(long, "cacheflush", unsigned long, addr, 403 int, nbytes, int, cache); 404 VG_ (discard_translations) ((Addr64) ARG1, ((ULong) ARG2), 405 "PRE(sys_cacheflush)"); 406 SET_STATUS_Success(0); 407 } 408 409 PRE(sys_reboot) 410 { 411 PRINT("sys_reboot ( %ld )", ARG1); 412 PRE_REG_READ1(int, "reboot", int, flags); 413 *flags |= SfMayBlock; 414 } 415 416 PRE(sys_setdomainname) 417 { 418 PRINT ("sys_setdomainname ( %#lx, %ld )", ARG1, ARG2); 419 PRE_REG_READ2 (long, "setdomainname", const void *, name, int, len); 420 } 421 422 PRE(sys_sethostname) 423 { 424 PRINT ("sys_sethostname ( %ld, %ld )", ARG1, ARG2); 425 PRE_REG_READ2 (long, "sethostname", const void *, name, int, len); 426 } 427 428 PRE(sys_ptrace) 429 { 430 PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4); 431 PRE_REG_READ4(int, "ptrace", long, request, long, pid, long, addr, 432 long, data); 433 switch (ARG1) { 434 case VKI_PTRACE_PEEKTEXT: 435 case VKI_PTRACE_PEEKDATA: 436 case VKI_PTRACE_PEEKUSR: 437 PRE_MEM_WRITE("ptrace(peek)", ARG4, sizeof(long)); 438 break; 439 case VKI_PTRACE_GETEVENTMSG: 440 PRE_MEM_WRITE("ptrace(geteventmsg)", ARG4, sizeof(unsigned long)); 441 break; 442 case VKI_PTRACE_GETSIGINFO: 443 PRE_MEM_WRITE("ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t)); 444 break; 445 case VKI_PTRACE_SETSIGINFO: 446 PRE_MEM_READ("ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t)); 447 break; 448 case VKI_PTRACE_GETREGSET: 449 ML_(linux_PRE_getregset)(tid, ARG3, ARG4); 450 break; 451 default: 452 break; 453 } 454 } 455 456 POST(sys_ptrace) 457 { 458 switch (ARG1) { 459 case VKI_PTRACE_PEEKTEXT: 460 case VKI_PTRACE_PEEKDATA: 461 case VKI_PTRACE_PEEKUSR: 462 POST_MEM_WRITE (ARG4, sizeof(long)); 463 break; 464 case VKI_PTRACE_GETEVENTMSG: 465 POST_MEM_WRITE (ARG4, sizeof(unsigned long)); 466 break; 467 case VKI_PTRACE_GETSIGINFO: 468 POST_MEM_WRITE (ARG4, sizeof(vki_siginfo_t)); 469 break; 470 case VKI_PTRACE_GETREGSET: 471 ML_(linux_POST_getregset)(tid, ARG3, ARG4); 472 break; 473 default: 474 break; 475 } 476 } 477 478 PRE (sys_mmap) 479 { 480 SysRes r; 481 PRINT("sys_mmap ( %#lx, %llu, %lu, %lu, %lu, %ld )", ARG1, (ULong)ARG2, 482 ARG3, ARG4, ARG5, ARG6); 483 PRE_REG_READ6(long, "mmap", unsigned long, start, vki_size_t, length, 484 int, prot, int, flags, int, fd, unsigned long, offset); 485 r = ML_(generic_PRE_sys_mmap)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, 486 (Off64T) ARG6); 487 SET_STATUS_from_SysRes(r); 488 } 489 490 PRE(sys_clone) 491 { 492 Bool badarg = False; 493 UInt cloneflags; 494 PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3, 495 ARG4, ARG5); 496 PRE_REG_READ2(int, "clone", unsigned long, flags, void *, child_stack); 497 if (ARG1 & VKI_CLONE_PARENT_SETTID) { 498 if (VG_(tdict).track_pre_reg_read) { 499 PRA3("clone", int *, parent_tidptr); 500 } 501 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int)); 502 if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) { 503 badarg = True; 504 } 505 } 506 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) { 507 if (VG_(tdict).track_pre_reg_read) { 508 PRA5("clone", int *, child_tidptr); 509 } 510 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof (Int)); 511 if (!VG_(am_is_valid_for_client)(ARG5, sizeof (Int), VKI_PROT_WRITE)) 512 badarg = True; 513 } 514 if (badarg) { 515 SET_STATUS_Failure(VKI_EFAULT); 516 return; 517 } 518 cloneflags = ARG1; 519 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) { 520 SET_STATUS_Failure(VKI_EINVAL); 521 return; 522 } 523 /* Only look at the flags we really care about */ 524 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 525 |VKI_CLONE_FILES | VKI_CLONE_VFORK)) { 526 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES: 527 /* thread creation */ 528 SET_STATUS_from_SysRes(do_clone(tid, 529 ARG1, /* flags */ 530 (Addr)ARG2, /* child SP */ 531 (Int *)ARG3, /* parent_tidptr */ 532 (Int *)ARG5, /* child_tidptr */ 533 (Addr)ARG4)); /* child_tls */ 534 break; 535 536 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */ 537 /* FALLTHROUGH - assume vfork == fork */ 538 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM); 539 case 0: /* plain fork */ 540 SET_STATUS_from_SysRes(ML_(do_fork_clone)(tid, 541 cloneflags, /* flags */ 542 (Int *)ARG3, /* parent_tidptr */ 543 (Int *)ARG5)); /* child_tidptr */ 544 break; 545 546 default: 547 /* should we just ENOSYS? */ 548 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1); 549 VG_(message)(Vg_UserMsg, "\n"); 550 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n"); 551 VG_(message)(Vg_UserMsg, 552 " - via a threads library (LinuxThreads or NPTL)\n"); 553 VG_(message)(Vg_UserMsg, 554 " - via the implementation of fork or vfork\n"); 555 VG_(unimplemented)("Valgrind does not support general clone()."); 556 } 557 if (SUCCESS) { 558 if (ARG1 & VKI_CLONE_PARENT_SETTID) 559 POST_MEM_WRITE(ARG3, sizeof(Int)); 560 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) 561 POST_MEM_WRITE(ARG5, sizeof(Int)); 562 /* Thread creation was successful; let the child have the chance to run */ 563 *flags |= SfYieldAfter; 564 } 565 } 566 567 PRE(sys_rt_sigreturn) 568 { 569 /* See comments on PRE(sys_rt_sigreturn) in syswrap-s390x-linux.c for 570 an explanation of what follows. */ 571 ThreadState* tst; 572 PRINT("sys_rt_sigreturn ( )"); 573 574 vg_assert(VG_(is_valid_tid)(tid)); 575 vg_assert(tid >= 1 && tid < VG_N_THREADS); 576 vg_assert(VG_(is_running_thread)(tid)); 577 578 tst = VG_(get_ThreadState)(tid); 579 580 /* This is only so that the IA is (might be) useful to report if 581 something goes wrong in the sigreturn */ 582 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch); 583 584 /* Restore register state from frame and remove it */ 585 VG_(sigframe_destroy)(tid, True); 586 587 /* Tell the driver not to update the guest state with the "result", 588 and set a bogus result to keep it happy. */ 589 *flags |= SfNoWriteResult; 590 SET_STATUS_Success(0); 591 592 /* Check to see if any signals arose as a result of this. */ 593 *flags |= SfPollAfter; 594 } 595 596 PRE(sys_set_thread_area) 597 { 598 PRINT("set_thread_area (%lx)", ARG1); 599 PRE_REG_READ1(long, "set_thread_area", unsigned long, addr); 600 SET_STATUS_from_SysRes(sys_set_tls(tid, ARG1)); 601 } 602 603 PRE(sys_pipe) 604 { 605 PRINT("sys_pipe ( %#lx )", ARG1); 606 PRE_REG_READ1(int, "pipe", int *, filedes); 607 PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) ); 608 } 609 610 POST(sys_pipe) 611 { 612 Int p0, p1; 613 vg_assert(SUCCESS); 614 p0 = RES; 615 p1 = sr_ResEx(status->sres); 616 617 if (!ML_(fd_allowed)(p0, "pipe", tid, True) || 618 !ML_(fd_allowed)(p1, "pipe", tid, True)) { 619 VG_(close)(p0); 620 VG_(close)(p1); 621 SET_STATUS_Failure( VKI_EMFILE ); 622 } else { 623 if (VG_(clo_track_fds)) { 624 ML_(record_fd_open_nameless)(tid, p0); 625 ML_(record_fd_open_nameless)(tid, p1); 626 } 627 } 628 } 629 630 #undef PRE 631 #undef POST 632 633 /* --------------------------------------------------------------------- 634 The mips64/Linux syscall table 635 ------------------------------------------------------------------ */ 636 637 /* Add an mips64-linux specific wrapper to a syscall table. */ 638 #define PLAX_(sysno, name) WRAPPER_ENTRY_X_(mips_linux, sysno, name) 639 #define PLAXY(sysno, name) WRAPPER_ENTRY_XY(mips_linux, sysno, name) 640 641 static SyscallTableEntry syscall_main_table[] = { 642 GENXY (__NR_read, sys_read), /* 5000 */ 643 GENX_ (__NR_write, sys_write), 644 GENXY (__NR_open, sys_open), 645 GENXY (__NR_close, sys_close), 646 GENXY (__NR_stat, sys_newstat), 647 GENXY (__NR_fstat, sys_newfstat), 648 GENXY (__NR_lstat, sys_newlstat), 649 GENXY (__NR_poll, sys_poll), 650 LINX_ (__NR_lseek, sys_lseek), 651 PLAX_ (__NR_mmap, sys_mmap), 652 GENXY (__NR_mprotect, sys_mprotect), 653 GENXY (__NR_munmap, sys_munmap), 654 GENX_ (__NR_brk, sys_brk), 655 LINXY (__NR_rt_sigaction, sys_rt_sigaction), 656 LINXY (__NR_rt_sigprocmask, sys_rt_sigprocmask), 657 LINXY (__NR_ioctl, sys_ioctl), 658 LINXY (__NR_eventfd2, sys_eventfd2), 659 LINXY (__NR_signalfd4, sys_signalfd4), 660 GENXY (__NR_pread64, sys_pread64), 661 GENX_ (__NR_pwrite64, sys_pwrite64), 662 GENXY (__NR_readv, sys_readv), 663 GENX_ (__NR_writev, sys_writev), 664 GENX_ (__NR_access, sys_access), 665 PLAXY (__NR_pipe, sys_pipe), 666 LINXY (__NR_pipe2, sys_pipe2), 667 GENX_ (__NR__newselect,sys_select), 668 LINX_ (__NR_sched_yield, sys_sched_yield), 669 GENX_ (__NR_mremap, sys_mremap), 670 GENX_ (__NR_msync, sys_msync), 671 GENXY (__NR_mincore, sys_mincore), 672 GENX_ (__NR_madvise, sys_madvise), 673 LINX_ (__NR_shmget, sys_shmget), 674 LINXY (__NR_shmat, wrap_sys_shmat), 675 LINXY (__NR_shmctl, sys_shmctl), 676 GENXY (__NR_dup, sys_dup), 677 GENXY (__NR_dup2, sys_dup2), 678 LINXY (__NR_dup3, sys_dup3), 679 GENX_ (__NR_pause, sys_pause), 680 GENXY (__NR_nanosleep, sys_nanosleep), 681 GENXY (__NR_getitimer, sys_getitimer), 682 GENXY (__NR_setitimer, sys_setitimer), 683 GENX_ (__NR_alarm, sys_alarm), 684 GENX_ (__NR_getpid, sys_getpid), 685 /* LINX_(__NR_fallocate,sys_fallocate), */ 686 LINXY (__NR_sendfile, sys_sendfile), 687 LINXY (__NR_socket, sys_socket), 688 LINX_ (__NR_connect, sys_connect), 689 LINXY (__NR_accept, sys_accept), 690 LINXY (__NR_accept4, sys_accept4), 691 LINX_ (__NR_sendto, sys_sendto), 692 LINXY (__NR_recvfrom, sys_recvfrom), 693 LINX_ (__NR_sendmsg, sys_sendmsg), 694 LINXY (__NR_recvmsg, sys_recvmsg), 695 LINX_ (__NR_shutdown, sys_shutdown), 696 LINX_ (__NR_bind, sys_bind), 697 LINX_ (__NR_listen, sys_listen), 698 LINXY (__NR_getsockname, sys_getsockname), 699 LINXY (__NR_getpeername, sys_getpeername), 700 LINXY (__NR_socketpair, sys_socketpair), 701 LINX_ (__NR_setsockopt, sys_setsockopt), 702 LINXY (__NR_getsockopt, sys_getsockopt), 703 PLAX_ (__NR_clone, sys_clone), 704 GENX_ (__NR_fork, sys_fork), 705 GENX_ (__NR_execve, sys_execve), 706 GENX_ (__NR_exit, sys_exit), 707 GENXY (__NR_wait4, sys_wait4), 708 GENX_ (__NR_kill, sys_kill), 709 GENXY (__NR_uname, sys_newuname), 710 LINX_ (__NR_semget, sys_semget), 711 LINX_ (__NR_semop, sys_semop), 712 LINXY (__NR_semctl, sys_semctl), 713 LINXY (__NR_shmdt, sys_shmdt), 714 LINX_ (__NR_msgget, sys_msgget), 715 LINX_ (__NR_msgsnd, sys_msgsnd), 716 LINXY (__NR_msgrcv, sys_msgrcv), 717 LINXY (__NR_msgctl, sys_msgctl), 718 LINXY (__NR_fcntl, sys_fcntl), 719 GENX_ (__NR_flock, sys_flock), 720 GENX_ (__NR_fsync, sys_fsync), 721 GENX_ (__NR_fdatasync, sys_fdatasync), 722 GENX_ (__NR_truncate, sys_truncate), 723 GENX_ (__NR_ftruncate, sys_ftruncate), 724 GENXY (__NR_getdents, sys_getdents), 725 GENXY (__NR_getcwd, sys_getcwd), 726 GENX_ (__NR_chdir, sys_chdir), 727 GENX_ (__NR_fchdir, sys_fchdir), 728 GENX_ (__NR_rename, sys_rename), 729 GENX_ (__NR_mkdir, sys_mkdir), 730 GENX_ (__NR_rmdir, sys_rmdir), 731 GENXY (__NR_creat, sys_creat), 732 GENX_ (__NR_link, sys_link), 733 GENX_ (__NR_unlink, sys_unlink), 734 GENX_ (__NR_symlink, sys_symlink), 735 GENX_ (__NR_readlink, sys_readlink), 736 GENX_ (__NR_chmod, sys_chmod), 737 GENX_ (__NR_fchmod, sys_fchmod), 738 GENX_ (__NR_chown, sys_chown), 739 GENX_ (__NR_fchown, sys_fchown), 740 GENX_ (__NR_lchown, sys_lchown), 741 GENX_ (__NR_umask, sys_umask), 742 GENXY (__NR_gettimeofday, sys_gettimeofday), 743 GENXY (__NR_getrlimit, sys_getrlimit), 744 GENXY (__NR_getrusage, sys_getrusage), 745 LINXY (__NR_sysinfo, sys_sysinfo), 746 GENXY (__NR_times, sys_times), 747 PLAXY (__NR_ptrace, sys_ptrace), 748 GENX_ (__NR_getuid, sys_getuid), 749 LINXY (__NR_syslog, sys_syslog), 750 GENX_ (__NR_getgid, sys_getgid), 751 GENX_ (__NR_setuid, sys_setuid), 752 GENX_ (__NR_setgid, sys_setgid), 753 GENX_ (__NR_geteuid, sys_geteuid), 754 GENX_ (__NR_getegid, sys_getegid), 755 GENX_ (__NR_setpgid, sys_setpgid), 756 GENX_ (__NR_getppid, sys_getppid), 757 GENX_ (__NR_getpgrp, sys_getpgrp), 758 GENX_ (__NR_setsid, sys_setsid), 759 GENX_ (__NR_setreuid, sys_setreuid), 760 GENX_ (__NR_setregid, sys_setregid), 761 GENXY (__NR_getgroups, sys_getgroups), 762 GENX_ (__NR_setgroups, sys_setgroups), 763 LINX_ (__NR_setresuid, sys_setresuid), 764 LINXY (__NR_getresuid, sys_getresuid), 765 LINX_ (__NR_setresgid, sys_setresgid), 766 LINXY (__NR_getresgid, sys_getresgid), 767 GENX_ (__NR_getpgid, sys_getpgid), 768 LINX_ (__NR_setfsuid, sys_setfsuid), 769 LINX_ (__NR_setfsgid, sys_setfsgid), 770 GENX_ (__NR_getsid, sys_getsid), 771 LINXY (__NR_capget, sys_capget), 772 LINX_ (__NR_capset, sys_capset), 773 LINXY (__NR_rt_sigpending, sys_rt_sigpending), 774 LINXY (__NR_rt_sigtimedwait, sys_rt_sigtimedwait), 775 LINXY (__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), 776 LINX_ (__NR_rt_sigsuspend, sys_rt_sigsuspend), 777 GENXY (__NR_sigaltstack, sys_sigaltstack), 778 LINX_ (__NR_utime, sys_utime), 779 GENX_ (__NR_mknod, sys_mknod), 780 LINX_ (__NR_personality, sys_personality), 781 PLAX_ (__NR_ustat, sys_ustat), 782 GENXY (__NR_statfs, sys_statfs), 783 GENXY (__NR_fstatfs, sys_fstatfs), 784 PLAX_ (__NR_sysfs, sys_sysfs), 785 GENX_ (__NR_getpriority, sys_getpriority), 786 GENX_ (__NR_setpriority, sys_setpriority), 787 LINXY (__NR_sched_setparam, sys_sched_setparam), 788 LINXY (__NR_sched_getparam, sys_sched_getparam), 789 LINX_ (__NR_sched_setscheduler, sys_sched_setscheduler), 790 LINX_ (__NR_sched_getscheduler, sys_sched_getscheduler), 791 LINX_ (__NR_sched_get_priority_max, sys_sched_get_priority_max), 792 LINX_ (__NR_sched_get_priority_min, sys_sched_get_priority_min), 793 PLAX_ (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), 794 GENX_ (__NR_mlock, sys_mlock), 795 GENX_ (__NR_munlock, sys_munlock), 796 GENX_ (__NR_mlockall, sys_mlockall), 797 LINX_ (__NR_munlockall, sys_munlockall), 798 LINX_ (__NR_vhangup, sys_vhangup), 799 /* GENX_(__NR_pivot_root,sys_pivot_root), */ 800 LINXY (__NR__sysctl, sys_sysctl), 801 LINXY (__NR_prctl, sys_prctl), 802 LINXY (__NR_adjtimex, sys_adjtimex), 803 GENX_ (__NR_setrlimit, sys_setrlimit), 804 GENX_ (__NR_chroot, sys_chroot), 805 GENX_ (__NR_sync, sys_sync), 806 GENX_ (__NR_acct, sys_acct), 807 GENX_ (__NR_settimeofday, sys_settimeofday), 808 LINX_ (__NR_mount, sys_mount), 809 LINX_ (__NR_umount2, sys_umount), 810 PLAX_ (__NR_swapon, sys_swapon), 811 PLAX_ (__NR_swapoff, sys_swapoff), 812 PLAX_ (__NR_reboot, sys_reboot), 813 PLAX_ (__NR_sethostname, sys_sethostname), 814 PLAX_ (__NR_setdomainname, sys_setdomainname), 815 GENX_ (__NR_create_module, sys_ni_syscall), 816 LINX_ (__NR_init_module, sys_init_module), 817 LINX_ (__NR_delete_module, sys_delete_module), 818 GENX_ (__NR_get_kernel_syms, sys_ni_syscall), 819 GENX_ (__NR_query_module, sys_ni_syscall), 820 LINX_ (__NR_quotactl, sys_quotactl), 821 /* GENX_(__NR_nfsservctl,sys_nfsservctl), */ 822 GENXY (__NR_getpmsg, sys_getpmsg), 823 GENX_ (__NR_putpmsg, sys_putpmsg), 824 GENX_ (__NR_afs_syscall, sys_ni_syscall), 825 /* GENX_(__NR_reserved177,sys_reserved177), */ 826 LINX_ (__NR_gettid, sys_gettid), 827 /* GENX_(__NR_readahead,sys_readahead), */ 828 LINX_ (__NR_setxattr, sys_setxattr), 829 LINX_ (__NR_lsetxattr, sys_lsetxattr), 830 LINX_ (__NR_fsetxattr, sys_fsetxattr), 831 LINXY (__NR_getxattr, sys_getxattr), 832 LINXY (__NR_lgetxattr, sys_lgetxattr), 833 LINXY (__NR_fgetxattr, sys_fgetxattr), 834 LINXY (__NR_listxattr, sys_listxattr), 835 LINXY (__NR_llistxattr, sys_llistxattr), 836 LINXY (__NR_flistxattr, sys_flistxattr), 837 LINX_ (__NR_removexattr, sys_removexattr), 838 LINX_ (__NR_lremovexattr, sys_lremovexattr), 839 LINX_ (__NR_fremovexattr, sys_fremovexattr), 840 LINXY (__NR_tkill, sys_tkill), 841 /* GENX_(__NR_reserved193,sys_reserved193), */ 842 LINXY (__NR_futex, sys_futex), 843 LINX_ (__NR_sched_setaffinity, sys_sched_setaffinity), 844 LINXY (__NR_sched_getaffinity, sys_sched_getaffinity), 845 PLAX_ (__NR_cacheflush, sys_cacheflush), 846 LINXY (__NR_io_setup, sys_io_setup), 847 LINX_ (__NR_io_destroy, sys_io_destroy), 848 LINXY (__NR_io_getevents, sys_io_getevents), 849 LINX_ (__NR_io_submit, sys_io_submit), 850 LINXY (__NR_io_cancel, sys_io_cancel), 851 LINX_ (__NR_exit_group, sys_exit_group), 852 /* LINXY (__NR_lookup_dcookie, sys_lookup_dcookie), */ 853 LINXY (__NR_epoll_create, sys_epoll_create), 854 LINXY (__NR_epoll_create1, sys_epoll_create1), 855 LINX_ (__NR_epoll_ctl, sys_epoll_ctl), 856 LINXY (__NR_epoll_wait, sys_epoll_wait), 857 PLAX_(__NR_rt_sigreturn,sys_rt_sigreturn), 858 /* LINXY(__NR_fcntl64,sys_fcntl64), */ 859 LINX_ (__NR_set_tid_address, sys_set_tid_address), 860 LINX_ (__NR_semtimedop, sys_semtimedop), 861 LINX_ (__NR_fadvise64, sys_fadvise64), 862 LINXY (__NR_timer_create, sys_timer_create), 863 LINXY (__NR_timer_settime, sys_timer_settime), 864 LINXY (__NR_timer_gettime, sys_timer_gettime), 865 LINX_ (__NR_timer_getoverrun, sys_timer_getoverrun), 866 LINX_ (__NR_timer_delete, sys_timer_delete), 867 LINX_ (__NR_clock_settime, sys_clock_settime), 868 LINXY (__NR_clock_gettime, sys_clock_gettime), 869 LINXY (__NR_clock_getres, sys_clock_getres), 870 LINXY (__NR_clock_nanosleep, sys_clock_nanosleep), 871 LINX_ (__NR_tgkill, sys_tgkill), 872 GENX_ (__NR_utimes, sys_utimes), 873 LINX_ (__NR_mbind, sys_mbind), 874 LINXY (__NR_get_mempolicy, sys_get_mempolicy), 875 LINX_ (__NR_set_mempolicy, sys_set_mempolicy), 876 LINXY (__NR_mq_open, sys_mq_open), 877 LINX_ (__NR_mq_unlink, sys_mq_unlink), 878 LINX_ (__NR_mq_timedsend, sys_mq_timedsend), 879 LINXY (__NR_mq_timedreceive, sys_mq_timedreceive), 880 LINX_ (__NR_mq_notify, sys_mq_notify), 881 LINXY (__NR_mq_getsetattr, sys_mq_getsetattr), 882 GENX_ (__NR_vserver, sys_ni_syscall), 883 LINXY (__NR_waitid, sys_waitid), 884 LINX_ (__NR_add_key, sys_add_key), 885 LINX_ (__NR_request_key, sys_request_key), 886 LINXY (__NR_keyctl, sys_keyctl), 887 PLAX_ (__NR_set_thread_area, sys_set_thread_area), 888 LINX_ (__NR_inotify_init, sys_inotify_init), 889 LINX_ (__NR_inotify_add_watch, sys_inotify_add_watch), 890 LINX_ (__NR_inotify_rm_watch, sys_inotify_rm_watch), 891 LINXY (__NR_openat, sys_openat), 892 LINX_ (__NR_mkdirat, sys_mkdirat), 893 LINX_ (__NR_mknodat, sys_mknodat), 894 LINX_ (__NR_fchownat, sys_fchownat), 895 LINX_ (__NR_futimesat, sys_futimesat), 896 LINX_ (__NR_unlinkat, sys_unlinkat), 897 LINX_ (__NR_renameat, sys_renameat), 898 LINX_ (__NR_linkat, sys_linkat), 899 LINX_ (__NR_symlinkat, sys_symlinkat), 900 LINX_ (__NR_readlinkat, sys_readlinkat), 901 LINX_ (__NR_fchmodat, sys_fchmodat), 902 LINX_ (__NR_faccessat, sys_faccessat), 903 LINX_ (__NR_pselect6, sys_pselect6), 904 LINXY (__NR_ppoll, sys_ppoll), 905 PLAX_ (__NR_unshare, sys_unshare), 906 PLAX_ (__NR_splice, sys_splice), 907 LINX_ (__NR_sync_file_range, sys_sync_file_range), 908 PLAX_ (__NR_tee, sys_tee), 909 PLAX_ (__NR_vmsplice, sys_vmsplice), 910 LINX_ (__NR_set_robust_list, sys_set_robust_list), 911 LINXY (__NR_get_robust_list, sys_get_robust_list), 912 LINXY (__NR_epoll_pwait, sys_epoll_pwait), 913 LINX_ (__NR_ioprio_set, sys_ioprio_set), 914 LINX_ (__NR_ioprio_get, sys_ioprio_get), 915 LINX_ (__NR_utimensat, sys_utimensat), 916 LINXY (__NR_signalfd, sys_signalfd), 917 LINXY (__NR_eventfd, sys_eventfd), 918 LINX_ (__NR_fallocate, sys_fallocate), 919 LINXY (__NR_timerfd_create, sys_timerfd_create), 920 LINXY (__NR_timerfd_gettime, sys_timerfd_gettime), 921 LINXY (__NR_timerfd_settime, sys_timerfd_settime), 922 LINXY (__NR_newfstatat, sys_newfstatat), 923 LINXY (__NR_prlimit64, sys_prlimit64), 924 LINXY (__NR_clock_adjtime, sys_clock_adjtime), 925 LINXY (__NR_process_vm_readv, sys_process_vm_readv), 926 LINX_ (__NR_process_vm_writev, sys_process_vm_writev) 927 }; 928 929 SyscallTableEntry * ML_(get_linux_syscall_entry) ( UInt sysno ) 930 { 931 const UInt syscall_main_table_size 932 = sizeof(syscall_main_table) / sizeof(syscall_main_table[0]); 933 934 if (sysno < syscall_main_table_size) { 935 SyscallTableEntry * sys = &syscall_main_table[sysno]; 936 if (sys->before == NULL) 937 return NULL; /* no entry */ 938 else 939 return sys; 940 } 941 /* Can't find a wrapper */ 942 return NULL; 943 } 944 945 #endif /* defined(VGP_mips64_linux) */ 946 947 /*--------------------------------------------------------------------*/ 948 /*--- end syswrap-mips64-linux.c ---*/ 949 /*--------------------------------------------------------------------*/ 950