Home | History | Annotate | Download | only in m_syswrap
      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