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@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))
81void 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 */
85asm (
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
123ULong 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
131asm(
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 */
186static void setup_child ( ThreadArchState *, ThreadArchState *);
187static 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. */
196static 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   ------------------------------------------------------------------ */
287void VG_(cleanup_thread) ( ThreadArchState * arch ) { };
288
289void 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
298SysRes 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
316DECL_TEMPLATE (mips_linux, sys_set_thread_area);
317DECL_TEMPLATE (mips_linux, sys_clone);
318DECL_TEMPLATE (mips_linux, sys_tee);
319DECL_TEMPLATE (mips_linux, sys_splice);
320DECL_TEMPLATE (mips_linux, sys_vmsplice);
321DECL_TEMPLATE (mips_linux, sys_ustat);
322DECL_TEMPLATE (mips_linux, sys_sysfs);
323DECL_TEMPLATE (mips_linux, sys_swapon);
324DECL_TEMPLATE (mips_linux, sys_swapoff);
325DECL_TEMPLATE (mips_linux, sys_setdomainname);
326DECL_TEMPLATE (mips_linux, sys_sethostname);
327DECL_TEMPLATE (mips_linux, sys_reboot);
328DECL_TEMPLATE (mips_linux, sys_cacheflush);
329DECL_TEMPLATE (mips_linux, sys_sched_rr_get_interval);
330DECL_TEMPLATE (mips_linux, sys_unshare);
331DECL_TEMPLATE (mips_linux, sys_arch_prctl);
332DECL_TEMPLATE (mips_linux, sys_ptrace);
333DECL_TEMPLATE (mips_linux, sys_mmap);
334DECL_TEMPLATE (mips_linux, sys_rt_sigreturn);
335DECL_TEMPLATE (mips_linux, sys_pipe);
336
337PRE(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
344PRE(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
353PRE(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
360PRE(sys_unshare)
361{
362   PRINT("sys_unshare ( %ld )", ARG1);
363   PRE_REG_READ1(long, "sys_unshare", int, flags);
364}
365
366PRE(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
374PRE(sys_ustat)
375{
376   PRINT("sys_ustat ( %ld, %#lx)", ARG1, ARG2);
377   PRE_REG_READ2(long, "ustat", int, flags, const void *, path);
378}
379
380PRE(sys_swapon)
381{
382   PRINT("sys_swapon ( %#lx, %ld )", ARG1, ARG2);
383   PRE_REG_READ2(long, "swapon", const void *, path, int, flags);
384}
385
386PRE(sys_swapoff)
387{
388   PRINT("sys_swapoff ( %#lx )", ARG1);
389   PRE_REG_READ1(long, "swapoff", const void *, path);
390}
391
392PRE(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 */
399PRE(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
409PRE(sys_reboot)
410{
411   PRINT("sys_reboot ( %ld )", ARG1);
412   PRE_REG_READ1(int, "reboot", int, flags);
413   *flags |= SfMayBlock;
414}
415
416PRE(sys_setdomainname)
417{
418   PRINT ("sys_setdomainname ( %#lx, %ld )", ARG1, ARG2);
419   PRE_REG_READ2 (long, "setdomainname", const void *, name, int, len);
420}
421
422PRE(sys_sethostname)
423{
424   PRINT ("sys_sethostname ( %ld, %ld )", ARG1, ARG2);
425   PRE_REG_READ2 (long, "sethostname", const void *, name, int, len);
426}
427
428PRE(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
456POST(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
478PRE (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
490PRE(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
567PRE(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
596PRE(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
603PRE(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
610POST(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
641static 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
929SyscallTableEntry * 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