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