1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Handle system calls. syswrap-main.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2000-2012 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_offsets.h" 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_trc_values.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" 37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" // For VG_(getpid)() 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h" // For VG_({acquire,release}_BigLock), 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // and VG_(vg_yield) 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" // For VG_SIGVGKILL, VG_(poll_signals) 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h" 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_types_n_macros.h" 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-main.h" 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-darwin.h" 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Useful info which needs to be recorded somewhere: 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Use of registers in syscalls is: 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LINUX: 66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM) 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM) 68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1) 71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng mips v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM) 72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov On s390x the svc instruction is used for system calls. The system call 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov number is encoded in the instruction (8 bit immediate field). Since Linux 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2.6 it is also allowed to use svc 0 with the system call number in r1. 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov This was introduced for system calls >255, but works for all. It is 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov also possible to see the svc 0 together with an EXecute instruction, that 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fills in the immediate field. 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s390x r1/SVC r2 r3 r4 r5 r6 r7 n/a n/a r2 (== ARG1) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DARWIN: 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For x86-darwin, "+N" denotes "in memory at N(%esp)"; ditto 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64-darwin. Apparently 0(%esp) is some kind of return address 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (perhaps for syscalls done with "sysenter"?) I don't think it is 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown relevant for syscalls done with "int $0x80/1/2". 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the top level of the system-call handler module. All 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown system calls are channelled through here, doing two things: 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * notify the tool of the events (mem/reg reads, writes) happening 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * perform the syscall, usually by passing it along to the kernel 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unmodified. 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A magical piece of assembly code, do_syscall_for_client_WRK, in 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall-$PLATFORM.S does the tricky bit of passing a syscall to the 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel, whilst having the simulator retain control. 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The main function is VG_(client_syscall). The simulation calls it 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whenever a client thread wants to do a syscall. The following is a 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sketch of what it does. 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Ensures the root thread's stack is suitably mapped. Tedious and 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arcane. See big big comment in VG_(client_syscall). 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * First, it rounds up the syscall number and args (which is a 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform dependent activity) and puts them in a struct ("args") 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and also a copy in "orig_args". 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The pre/post wrappers refer to these structs and so no longer 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown need magic macros to access any specific registers. This struct 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is stored in thread-specific storage. 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The pre-wrapper is called, passing it a pointer to struct 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "args". 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The pre-wrapper examines the args and pokes the tool 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appropriately. It may modify the args; this is why "orig_args" 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is also stored. 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The pre-wrapper may choose to 'do' the syscall itself, and 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown concludes one of three outcomes: 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Success(N) -- syscall is already complete, with success; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result is N 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fail(N) -- syscall is already complete, with failure; 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error code is N 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HandToKernel -- (the usual case): this needs to be given to 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the kernel to be done, using the values in 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the possibly-modified "args" struct. 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In addition, the pre-wrapper may set some flags: 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MayBlock -- only applicable when outcome==HandToKernel 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PostOnFail -- only applicable when outcome==HandToKernel or Fail 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If the pre-outcome is HandToKernel, the syscall is duly handed 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown off to the kernel (perhaps involving some thread switchery, but 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that's not important). This reduces the possible set of outcomes 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to either Success(N) or Fail(N). 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The outcome (Success(N) or Fail(N)) is written back to the guest 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register(s). This is platform specific: 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86: Success(N) ==> eax = N 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fail(N) ==> eax = -N 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ditto amd64 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppc32: Success(N) ==> r3 = N, CR0.SO = 0 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fail(N) ==> r3 = N, CR0.SO = 1 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Darwin: 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86: Success(N) ==> edx:eax = N, cc = 0 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fail(N) ==> edx:eax = N, cc = 1 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s390x: Success(N) ==> r2 = N 170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Fail(N) ==> r2 = -N 171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The post wrapper is called if: 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - it exists, and 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - outcome==Success or (outcome==Fail and PostOnFail is set) 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The post wrapper is passed the adulterated syscall args (struct 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "args"), and the syscall outcome (viz, Success(N) or Fail(N)). 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There are several other complications, primarily to do with 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscalls getting interrupted, explained in comments in the code. 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CAVEATS for writing wrappers. It is important to follow these! 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The macros defined in priv_types_n_macros.h are designed to help 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown decouple the wrapper logic from the actual representation of 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall args/results, since these wrappers are designed to work on 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown multiple platforms. 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Sometimes a PRE wrapper will complete the syscall itself, without 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handing it to the kernel. It will use one of SET_STATUS_Success, 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure or SET_STATUS_from_SysRes to set the return 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value. It is critical to appreciate that use of the macro does not 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown immediately cause the underlying guest state to be updated -- that 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is done by the driver logic in this file, when the wrapper returns. 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown As a result, PRE wrappers of the following form will malfunction: 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE(fooble) 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ... do stuff ... 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Somehow(...) 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // do something that assumes guest state is up to date 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In particular, direct or indirect calls to VG_(poll_signals) after 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown setting STATUS can cause the guest state to be read (in order to 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown build signal frames). Do not do this. If you want a signal poll 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown after the syscall goes through, do "*flags |= SfPollAfter" and the 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown driver logic will do it for you. 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ----------- 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Another critical requirement following introduction of new address 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown space manager (JRS, 20050923): 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In a situation where the mappedness of memory has changed, aspacem 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should be notified BEFORE the tool. Hence the following is 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown correct: 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d = VG_(am_notify_munmap)(s->start, s->end+1 - s->start); 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_munmap, s->start, s->end+1 - s->start ); 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)(s->start, s->end+1 - s->start); 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whilst this is wrong: 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_munmap, s->start, s->end+1 - s->start ); 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d = VG_(am_notify_munmap)(s->start, s->end+1 - s->start); 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)(s->start, s->end+1 - s->start); 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The reason is that the tool may itself ask aspacem for more shadow 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memory as a result of the VG_TRACK call. In such a situation it is 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown critical that aspacem's segment array is up to date -- hence the 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown need to notify aspacem first. 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ----------- 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also .. take care to call VG_(discard_translations) whenever 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memory with execute permissions is unmapped. 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Do potentially blocking syscall for the client, and mess with 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal masks at the same time. 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Perform a syscall on behalf of a client thread, using a specific 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal mask. On completion, the signal mask is set to restore_mask 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (which presumably blocks almost everything). If a signal happens 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown during the syscall, the handler should call 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) to adjust the 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread's context to do the right thing. 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The _WRK function is handwritten assembly, implemented per-platform 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in coregrind/m_syswrap/syscall-$PLAT.S. It has some very magic 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown properties. See comments at the top of 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) below for details. 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This function (these functions) are required to return zero in case 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of success (even if the syscall itself failed), and nonzero if the 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigprocmask-swizzling calls failed. We don't actually care about 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the failure values from sigprocmask, although most of the assembly 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown implementations do attempt to return that, using the convention 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0 for success, or 0x8000 | error-code for failure. 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord ML_(do_syscall_for_client_WRK)( Word syscallno, 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* guest_state, 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *syscall_mask, 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *restore_mask, 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sigsetSzB ); 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord ML_(do_syscall_for_client_unix_WRK)( Word syscallno, 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* guest_state, 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *syscall_mask, 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *restore_mask, 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sigsetSzB ); /* unused */ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord ML_(do_syscall_for_client_mach_WRK)( Word syscallno, 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* guest_state, 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *syscall_mask, 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *restore_mask, 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sigsetSzB ); /* unused */ 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord ML_(do_syscall_for_client_mdep_WRK)( Word syscallno, 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* guest_state, 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *syscall_mask, 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *restore_mask, 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sigsetSzB ); /* unused */ 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_syscall_for_client ( Int syscallno, 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst, 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t* syscall_mask ) 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t saved; 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord err; 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = ML_(do_syscall_for_client_WRK)( 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscallno, &tst->arch.vex, 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall_mask, &saved, sizeof(vki_sigset_t) 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_DARWIN_SYSNO_CLASS(syscallno)) { 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_UNIX: 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = ML_(do_syscall_for_client_unix_WRK)( 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex, 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall_mask, &saved, 0/*unused:sigsetSzB*/ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MACH: 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = ML_(do_syscall_for_client_mach_WRK)( 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex, 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall_mask, &saved, 0/*unused:sigsetSzB*/ 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MDEP: 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = ML_(do_syscall_for_client_mdep_WRK)( 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex, 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall_mask, &saved, 0/*unused:sigsetSzB*/ 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2( 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err == 0, 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ML_(do_syscall_for_client_WRK): sigprocmask error %d", 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)(err & 0xFFF) 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Impedance matchers and misc helpers 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool eq_SyscallArgs ( SyscallArgs* a1, SyscallArgs* a2 ) 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return a1->sysno == a2->sysno 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg1 == a2->arg1 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg2 == a2->arg2 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg3 == a2->arg3 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg4 == a2->arg4 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg5 == a2->arg5 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg6 == a2->arg6 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg7 == a2->arg7 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a1->arg8 == a2->arg8; 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool eq_SyscallStatus ( SyscallStatus* s1, SyscallStatus* s2 ) 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* was: return s1->what == s2->what && sr_EQ( s1->sres, s2->sres ); */ 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->what == s2->what && sr_EQ( s1->sres, s2->sres )) 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Darwin-specific debugging guff */ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(s1->what == s2->what); 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("eq_SyscallStatus:\n"); 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" {%lu %lu %u}\n", s1->sres._wLO, s1->sres._wHI, s1->sres._mode); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" {%lu %lu %u}\n", s2->sres._wLO, s2->sres._wHI, s2->sres._mode); 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert between SysRes and SyscallStatus, to the extent possible. */ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSyscallStatus convert_SysRes_to_SyscallStatus ( SysRes res ) 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallStatus status; 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown status.what = SsComplete; 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown status.sres = res; 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return status; 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Impedance matchers. These convert syscall arg or result data from 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the platform-specific in-guest-state format to the canonical 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown formats, and back. */ 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical, 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*IN*/ VexGuestArchState* gst_vanilla, 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*IN*/ UInt trc ) 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_EAX; 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_EBX; 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_ECX; 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_EDX; 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_ESI; 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_EDI; 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = gst->guest_EBP; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = 0; 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = 0; 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_RAX; 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_RDI; 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_RSI; 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_RDX; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_R10; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_R8; 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = gst->guest_R9; 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = 0; 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = 0; 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla; 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_GPR0; 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_GPR3; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_GPR4; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_GPR5; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_GPR6; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_GPR7; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = gst->guest_GPR8; 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = 0; 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = 0; 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_GPR0; 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_GPR3; 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_GPR4; 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_GPR5; 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_GPR6; 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_GPR7; 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = gst->guest_GPR8; 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = 0; 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = 0; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_R7; 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_R0; 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_R1; 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_R2; 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_R3; 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_R4; 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = gst->guest_R5; 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = 0; 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = 0; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux) 467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; 468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->sysno = gst->guest_r2; // v0 469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (canonical->sysno != __NR_syscall) { 470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg1 = gst->guest_r4; // a0 471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg2 = gst->guest_r5; // a1 472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg3 = gst->guest_r6; // a2 473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg4 = gst->guest_r7; // a3 474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg5 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP/sp) 475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg6 = *((UInt*) (gst->guest_r29 + 20)); // 20(sp) 476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg8 = 0; 477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Fixme hack handle syscall() 479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->sysno = gst->guest_r4; // a0 480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg1 = gst->guest_r5; // a1 481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg2 = gst->guest_r6; // a2 482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg3 = gst->guest_r7; // a3 483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg4 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP/sp) 484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg5 = *((UInt*) (gst->guest_r29 + 20)); // 20(guest_SP/sp) 485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg6 = *((UInt*) (gst->guest_r29 + 24)); // 24(guest_SP/sp) 486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg8 = __NR_syscall; 487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord *stack = (UWord *)gst->guest_ESP; 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hope syscalls aren't called with really shallow stacks... 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_EAX; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (canonical->sysno != 0) { 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack[0] is return address 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = stack[1]; 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = stack[2]; 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = stack[3]; 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = stack[4]; 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = stack[5]; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = stack[6]; 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = stack[7]; 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = stack[8]; 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hack handle syscall() 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme what about __syscall() ? 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack[0] is return address 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: the tool can't see that the params have been shifted! Can 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // lead to incorrect checking, I think, because the PRRAn/PSARn 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // macros will mention the pre-shifted args. 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = stack[1]; 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->sysno != 0); 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = stack[2]; 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = stack[3]; 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = stack[4]; 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = stack[5]; 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = stack[6]; 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = stack[7]; 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = stack[8]; 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = stack[9]; 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("SYSCALL[%d,?](%s) syscall(%s, ...); please stand by...\n", 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getpid)(), /*tid,*/ 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_SYSNUM_STRING(0), VG_SYSNUM_STRING(canonical->sysno)); 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Here we determine what kind of syscall it was by looking at the 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // interrupt kind, and then encode the syscall number using the 64-bit 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // encoding for Valgrind's internal use. 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: Would it be better to stash the JMP kind into the Darwin 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // thread state rather than passing in the trc? 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (trc) { 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT128: 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // int $0x80 = Unix, 64-bit result 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->sysno >= 0); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(canonical->sysno); 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSENTER: 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // syscall = Unix, 32-bit result 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // OR Mach, 32-bit result 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (canonical->sysno >= 0) { 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hack: 0xffff == I386_SYSCALL_NUMBER_MASK 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(canonical->sysno 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & 0xffff); 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MACH(-canonical->sysno); 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT129: 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // int $0x81 = Mach, 32-bit result 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->sysno < 0); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MACH(-canonical->sysno); 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT130: 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // int $0x82 = mdep, 32-bit result 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->sysno >= 0); 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MDEP(canonical->sysno); 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord *stack = (UWord *)gst->guest_RSP; 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(trc == VEX_TRC_JMP_SYS_SYSCALL); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hope syscalls aren't called with really shallow stacks... 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = gst->guest_RAX; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (canonical->sysno != __NR_syscall) { 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack[0] is return address 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_RDI; 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_RSI; 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_RDX; 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_R10; // not rcx with syscall insn 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_R8; 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = gst->guest_R9; 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = stack[1]; 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = stack[2]; 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hack handle syscall() 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme what about __syscall() ? 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack[0] is return address 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: the tool can't see that the params have been shifted! Can 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // lead to incorrect checking, I think, because the PRRAn/PSARn 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // macros will mention the pre-shifted args. 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(gst->guest_RDI); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->sysno != __NR_syscall); 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg1 = gst->guest_RSI; 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg2 = gst->guest_RDX; 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg3 = gst->guest_R10; // not rcx with syscall insn 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg4 = gst->guest_R8; 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg5 = gst->guest_R9; 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg6 = stack[1]; 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg7 = stack[2]; 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->arg8 = stack[3]; 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("SYSCALL[%d,?](%s) syscall(%s, ...); please stand by...\n", 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getpid)(), /*tid,*/ 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_SYSNUM_STRING(0), VG_SYSNUM_STRING(canonical->sysno)); 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // no canonical->sysno adjustment needed 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; 610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->sysno = gst->guest_SYSNO; 611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg1 = gst->guest_r2; 612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg2 = gst->guest_r3; 613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg3 = gst->guest_r4; 614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg4 = gst->guest_r5; 615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg5 = gst->guest_r6; 616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg6 = gst->guest_r7; 617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg7 = 0; 618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->arg8 = 0; 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "getSyscallArgsFromGuestState: unknown arch" 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical, 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/VexGuestArchState* gst_vanilla ) 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EAX = canonical->sysno; 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EBX = canonical->arg1; 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_ECX = canonical->arg2; 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EDX = canonical->arg3; 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_ESI = canonical->arg4; 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EDI = canonical->arg5; 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EBP = canonical->arg6; 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RAX = canonical->sysno; 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RDI = canonical->arg1; 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RSI = canonical->arg2; 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RDX = canonical->arg3; 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R10 = canonical->arg4; 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R8 = canonical->arg5; 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R9 = canonical->arg6; 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla; 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR0 = canonical->sysno; 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR3 = canonical->arg1; 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR4 = canonical->arg2; 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR5 = canonical->arg3; 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR6 = canonical->arg4; 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR7 = canonical->arg5; 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR8 = canonical->arg6; 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR0 = canonical->sysno; 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR3 = canonical->arg1; 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR4 = canonical->arg2; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR5 = canonical->arg3; 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR6 = canonical->arg4; 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR7 = canonical->arg5; 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR8 = canonical->arg6; 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R7 = canonical->sysno; 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R0 = canonical->arg1; 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R1 = canonical->arg2; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R2 = canonical->arg3; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R3 = canonical->arg4; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R4 = canonical->arg5; 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R5 = canonical->arg6; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord *stack = (UWord *)gst->guest_ESP; 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EAX = VG_DARWIN_SYSNO_FOR_KERNEL(canonical->sysno); 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme? gst->guest_TEMP_EFLAG_C = 0; 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack[0] is return address 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[1] = canonical->arg1; 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[2] = canonical->arg2; 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[3] = canonical->arg3; 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[4] = canonical->arg4; 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[5] = canonical->arg5; 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[6] = canonical->arg6; 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[7] = canonical->arg7; 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[8] = canonical->arg8; 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord *stack = (UWord *)gst->guest_RSP; 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RAX = VG_DARWIN_SYSNO_FOR_KERNEL(canonical->sysno); 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme? gst->guest_TEMP_EFLAG_C = 0; 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack[0] is return address 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RDI = canonical->arg1; 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RSI = canonical->arg2; 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RDX = canonical->arg3; 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RCX = canonical->arg4; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R8 = canonical->arg5; 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R9 = canonical->arg6; 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[1] = canonical->arg7; 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack[2] = canonical->arg8; 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; 714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_SYSNO = canonical->sysno; 715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r2 = canonical->arg1; 716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r3 = canonical->arg2; 717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r4 = canonical->arg3; 718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r5 = canonical->arg4; 719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r6 = canonical->arg5; 720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r7 = canonical->arg6; 721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux) 723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; 724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (canonical->arg8 != __NR_syscall) { 725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r2 = canonical->sysno; 726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r4 = canonical->arg1; 727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r5 = canonical->arg2; 728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r6 = canonical->arg3; 729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r7 = canonical->arg4; 730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5; // 16(guest_GPR29/sp) 731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6; // 20(sp) 732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->arg8 = 0; 734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r2 = __NR_syscall; 735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r4 = canonical->sysno; 736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r5 = canonical->arg1; 737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r6 = canonical->arg2; 738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r7 = canonical->arg3; 739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *((UInt*) (gst->guest_r29 + 16)) = canonical->arg4; // 16(guest_GPR29/sp) 740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5; // 20(sp) 741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6; // 24(sp) 742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "putSyscallArgsIntoGuestState: unknown arch" 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*IN*/ VexGuestArchState* gst_vanilla ) 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_x86_linux)( gst->guest_EAX ); 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_amd64_linux)( gst->guest_RAX ); 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc32_linux) 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla; 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt cr = LibVEX_GuestPPC32_get_CR( gst ); 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt cr0so = (cr >> 28) & 1; 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_ppc32_linux)( gst->guest_GPR3, cr0so ); 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_linux) 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt cr = LibVEX_GuestPPC64_get_CR( gst ); 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt cr0so = (cr >> 28) & 1; 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so ); 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_arm_linux) 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 ); 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_mips32_linux) 782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; 783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt v0 = gst->guest_r2; // v0 784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt v1 = gst->guest_r3; // v1 785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt a3 = gst->guest_r7; // a3 786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->sres = VG_(mk_SysRes_mips32_linux)( v0, v1, a3 ); 787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng canonical->what = SsComplete; 788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt carry = 1 & LibVEX_GuestX86_get_eflags(gst); 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt err = 0; 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wLO = 0; 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wHI = 0; 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (gst->guest_SC_CLASS) { 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_UNIX: 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // int $0x80 = Unix, 64-bit result 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = carry; 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = gst->guest_EAX; 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI = gst->guest_EDX; 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MACH: 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // int $0x81 = Mach, 32-bit result 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = gst->guest_EAX; 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MDEP: 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // int $0x82 = mdep, 32-bit result 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = gst->guest_EAX; 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_x86_darwin)( 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_SC_CLASS, err ? True : False, 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI, wLO 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong carry = 1 & LibVEX_GuestAMD64_get_rflags(gst); 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong err = 0; 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong wLO = 0; 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong wHI = 0; 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (gst->guest_SC_CLASS) { 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_UNIX: 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // syscall = Unix, 128-bit result 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = carry; 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = gst->guest_RAX; 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI = gst->guest_RDX; 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MACH: 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // syscall = Mach, 64-bit result 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = gst->guest_RAX; 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MDEP: 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // syscall = mdep, 64-bit result 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = gst->guest_RAX; 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->sres = VG_(mk_SysRes_amd64_darwin)( 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_SC_CLASS, err ? True : False, 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI, wLO 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical->what = SsComplete; 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGP_s390x_linux) 854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; 855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 ); 856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov canonical->what = SsComplete; 857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "getSyscallStatusFromGuestState: unknown arch" 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid, 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*IN*/ SyscallStatus* canonical, 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/VexGuestArchState* gst_vanilla ) 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(canonical->sres)) { 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This isn't exactly right, in that really a Failure with res 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not in the range 1 .. 4095 is unrepresentable in the 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux-x86 scheme. Oh well. */ 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EAX = - (Int)sr_Err(canonical->sres); 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EAX = sr_Res(canonical->sres); 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_x86_EAX, sizeof(UWord) ); 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(canonical->sres)) { 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This isn't exactly right, in that really a Failure with res 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not in the range 1 .. 4095 is unrepresentable in the 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux-amd64 scheme. Oh well. */ 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RAX = - (Long)sr_Err(canonical->sres); 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RAX = sr_Res(canonical->sres); 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_amd64_RAX, sizeof(UWord) ); 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc32_linux) 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla; 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt old_cr = LibVEX_GuestPPC32_get_CR(gst); 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(canonical->sres)) { 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set CR0.SO */ 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestPPC32_put_CR( old_cr | (1<<28), gst ); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR3 = sr_Err(canonical->sres); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* clear CR0.SO */ 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), gst ); 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR3 = sr_Res(canonical->sres); 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_ppc32_GPR3, sizeof(UWord) ); 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_ppc32_CR0_0, sizeof(UChar) ); 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_linux) 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt old_cr = LibVEX_GuestPPC64_get_CR(gst); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(canonical->sres)) { 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set CR0.SO */ 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst ); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR3 = sr_Err(canonical->sres); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* clear CR0.SO */ 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst ); 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_GPR3 = sr_Res(canonical->sres); 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_ppc64_GPR3, sizeof(UWord) ); 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_ppc64_CR0_0, sizeof(UChar) ); 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_arm_linux) 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(canonical->sres)) { 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This isn't exactly right, in that really a Failure with res 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not in the range 1 .. 4095 is unrepresentable in the 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux-arm scheme. Oh well. */ 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R0 = - (Int)sr_Err(canonical->sres); 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_R0 = sr_Res(canonical->sres); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_arm_R0, sizeof(UWord) ); 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres = canonical->sres; 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Unfortunately here we have to break abstraction and look 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown directly inside 'res', in order to decide what to do. */ 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sres._mode) { 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_MACH: // int $0x81 = Mach, 32-bit result 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_MDEP: // int $0x82 = mdep, 32-bit result 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EAX = sres._wLO; 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_x86_EAX, sizeof(UInt) ); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_UNIX_OK: // int $0x80 = Unix, 64-bit result 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_UNIX_ERR: // int $0x80 = Unix, 64-bit error 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EAX = sres._wLO; 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_x86_EAX, sizeof(UInt) ); 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_EDX = sres._wHI; 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_x86_EDX, sizeof(UInt) ); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestX86_put_eflag_c( sres._mode==SysRes_UNIX_ERR ? 1 : 0, 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst ); 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme sets defined for entire eflags, not just bit c 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: this breaks exp-ptrcheck. 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) ); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres = canonical->sres; 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(canonical->what == SsComplete); 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Unfortunately here we have to break abstraction and look 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown directly inside 'res', in order to decide what to do. */ 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sres._mode) { 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_MACH: // syscall = Mach, 64-bit result 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_MDEP: // syscall = mdep, 64-bit result 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RAX = sres._wLO; 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_amd64_RAX, sizeof(ULong) ); 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_UNIX_OK: // syscall = Unix, 128-bit result 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SysRes_UNIX_ERR: // syscall = Unix, 128-bit error 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RAX = sres._wLO; 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_amd64_RAX, sizeof(ULong) ); 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_RDX = sres._wHI; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OFFSET_amd64_RDX, sizeof(ULong) ); 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestAMD64_put_rflag_c( sres._mode==SysRes_UNIX_ERR ? 1 : 0, 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst ); 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme sets defined for entire rflags, not just bit c 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: this breaks exp-ptrcheck. 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(ULong) ); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGP_s390x_linux) 1013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla; 1014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(canonical->what == SsComplete); 1015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sr_isError(canonical->sres)) { 1016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r2 = - (Long)sr_Err(canonical->sres); 1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gst->guest_r2 = sr_Res(canonical->sres); 1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_mips32_linux) 1022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; 1023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(canonical->what == SsComplete); 1024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (sr_isError(canonical->sres)) { 1025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r2 = (Int)sr_Err(canonical->sres); 1026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r7 = (Int)sr_Err(canonical->sres); 1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r2 = sr_Res(canonical->sres); 1029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r3 = sr_ResEx(canonical->sres); 1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng gst->guest_r7 = (Int)sr_Err(canonical->sres); 1031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng OFFSET_mips32_r2, sizeof(UWord) ); 1034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 1035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng OFFSET_mips32_r3, sizeof(UWord) ); 1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng OFFSET_mips32_r7, sizeof(UWord) ); 1038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "putSyscallStatusIntoGuestState: unknown arch" 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tell me the offsets in the guest state of the syscall params, so 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the scalar argument checkers don't have to have this info 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hardwired. */ 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_x86_EAX; 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg1 = OFFSET_x86_EBX; 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg2 = OFFSET_x86_ECX; 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg3 = OFFSET_x86_EDX; 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg4 = OFFSET_x86_ESI; 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg5 = OFFSET_x86_EDI; 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg6 = OFFSET_x86_EBP; 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg7 = -1; /* impossible value */ 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg8 = -1; /* impossible value */ 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_amd64_RAX; 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg1 = OFFSET_amd64_RDI; 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg2 = OFFSET_amd64_RSI; 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg3 = OFFSET_amd64_RDX; 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg4 = OFFSET_amd64_R10; 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg5 = OFFSET_amd64_R8; 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg6 = OFFSET_amd64_R9; 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg7 = -1; /* impossible value */ 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg8 = -1; /* impossible value */ 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_ppc32_GPR0; 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg1 = OFFSET_ppc32_GPR3; 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg2 = OFFSET_ppc32_GPR4; 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg3 = OFFSET_ppc32_GPR5; 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg4 = OFFSET_ppc32_GPR6; 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg5 = OFFSET_ppc32_GPR7; 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg6 = OFFSET_ppc32_GPR8; 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg7 = -1; /* impossible value */ 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg8 = -1; /* impossible value */ 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_ppc64_GPR0; 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg1 = OFFSET_ppc64_GPR3; 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg2 = OFFSET_ppc64_GPR4; 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg3 = OFFSET_ppc64_GPR5; 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg4 = OFFSET_ppc64_GPR6; 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg5 = OFFSET_ppc64_GPR7; 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg6 = OFFSET_ppc64_GPR8; 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg7 = -1; /* impossible value */ 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg8 = -1; /* impossible value */ 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_arm_R7; 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg1 = OFFSET_arm_R0; 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg2 = OFFSET_arm_R1; 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg3 = OFFSET_arm_R2; 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg4 = OFFSET_arm_R3; 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg5 = OFFSET_arm_R4; 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg6 = OFFSET_arm_R5; 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg7 = -1; /* impossible value */ 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->uu_arg8 = -1; /* impossible value */ 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux) 1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->o_sysno = OFFSET_mips32_r2; 1109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->o_arg1 = OFFSET_mips32_r4; 1110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->o_arg2 = OFFSET_mips32_r5; 1111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->o_arg3 = OFFSET_mips32_r6; 1112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->o_arg4 = OFFSET_mips32_r7; 1113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->s_arg5 = sizeof(UWord) * 4; 1114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->s_arg6 = sizeof(UWord) * 5; 1115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->uu_arg7 = -1; /* impossible value */ 1116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng layout->uu_arg8 = -1; /* impossible value */ 1117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_x86_EAX; 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // syscall parameters are on stack in C convention 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg1 = sizeof(UWord) * 1; 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg2 = sizeof(UWord) * 2; 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg3 = sizeof(UWord) * 3; 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg4 = sizeof(UWord) * 4; 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg5 = sizeof(UWord) * 5; 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg6 = sizeof(UWord) * 6; 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg7 = sizeof(UWord) * 7; 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg8 = sizeof(UWord) * 8; 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_sysno = OFFSET_amd64_RAX; 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg1 = OFFSET_amd64_RDI; 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg2 = OFFSET_amd64_RSI; 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg3 = OFFSET_amd64_RDX; 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg4 = OFFSET_amd64_RCX; 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg5 = OFFSET_amd64_R8; 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->o_arg6 = OFFSET_amd64_R9; 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg7 = sizeof(UWord) * 1; 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout->s_arg8 = sizeof(UWord) * 2; 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 1142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_sysno = OFFSET_s390x_SYSNO; 1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_arg1 = OFFSET_s390x_r2; 1144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_arg2 = OFFSET_s390x_r3; 1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_arg3 = OFFSET_s390x_r4; 1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_arg4 = OFFSET_s390x_r5; 1147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_arg5 = OFFSET_s390x_r6; 1148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->o_arg6 = OFFSET_s390x_r7; 1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->uu_arg7 = -1; /* impossible value */ 1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout->uu_arg8 = -1; /* impossible value */ 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "getSyscallLayout: unknown arch" 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The main driver logic 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Finding the handlers for a given syscall, or faking up one 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when no handler is found. */ 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid bad_before ( ThreadId tid, 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallArgLayout* layout, 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/SyscallArgs* args, 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/SyscallStatus* status, 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/UWord* flags ) 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("WARNING: unhandled syscall: %s\n", 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_SYSNUM_STRING_EXTRA(args->sysno)); 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) { 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("You may be able to write your own handler.\n"); 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n"); 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Nevertheless we consider this a bug. Please report\n"); 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html.\n"); 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure(VKI_ENOSYS); 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SyscallTableEntry bad_sys = 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { bad_before, NULL }; 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const SyscallTableEntry* get_syscall_entry ( Int syscallno ) 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const SyscallTableEntry* sys = NULL; 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sys = ML_(get_linux_syscall_entry)( syscallno ); 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int idx = VG_DARWIN_SYSNO_INDEX(syscallno); 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_DARWIN_SYSNO_CLASS(syscallno)) { 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_UNIX: 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (idx >= 0 && idx < ML_(syscall_table_size) && 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(syscall_table)[idx].before != NULL) 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sys = &ML_(syscall_table)[idx]; 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MACH: 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (idx >= 0 && idx < ML_(mach_trap_table_size) && 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(mach_trap_table)[idx].before != NULL) 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sys = &ML_(mach_trap_table)[idx]; 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MDEP: 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (idx >= 0 && idx < ML_(mdep_trap_table_size) && 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(mdep_trap_table)[idx].before != NULL) 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sys = &ML_(mdep_trap_table)[idx]; 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sys == NULL ? &bad_sys : sys; 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add and remove signals from mask so that we end up telling the 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel the state we actually want rather than what the client 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wants. */ 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sanitize_client_sigmask(vki_sigset_t *mask) 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(mask, VKI_SIGKILL); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(mask, VKI_SIGSTOP); 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(mask, VG_SIGVGKILL); /* never block */ 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallArgs orig_args; 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallArgs args; 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallStatus status; 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord flags; 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallInfo; 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSyscallInfo syscallInfo[VG_N_THREADS]; 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The scheduler needs to be able to zero out these records after a 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fork, hence this is exported from m_syswrap. */ 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(clear_syscallInfo) ( Int tid ) 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 0 && tid < VG_N_THREADS); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( & syscallInfo[tid], 0, sizeof( syscallInfo[tid] )); 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscallInfo[tid].status.what = SsIdle; 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ensure_initialised ( void ) 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool init_done = False; 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (init_done) 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_done = True; 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_N_THREADS; i++) { 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clear_syscallInfo)( i ); 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- This is the main function of this file. --- */ 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(client_syscall) ( ThreadId tid, UInt trc ) 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sysno; 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const SyscallTableEntry* ent; 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallArgLayout layout; 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallInfo* sci; 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ensure_initialised(); 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 1 && tid < VG_N_THREADS); 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* BEGIN ensure root thread's stack is suitably mapped */ 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In some rare circumstances, we may do the syscall without the 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bottom page of the stack being mapped, because the stack pointer 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown was moved down just a few instructions before the syscall 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction, and there have been no memory references since 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then, that would cause a call to VG_(extend_stack) to have 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown happened. 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In native execution that's OK: the kernel automagically extends 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the stack's mapped area down to cover the stack pointer (or sp - 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redzone, really). In simulated normal execution that's OK too, 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown since any signals we get from accessing below the mapped area of 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the (guest's) stack lead us to VG_(extend_stack), where we 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simulate the kernel's stack extension logic. But that leaves 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the problem of entering a syscall with the SP unmapped. Because 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the kernel doesn't know that the segment immediately above SP is 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown supposed to be a grow-down segment, it causes the syscall to 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fail, and thereby causes a divergence between native behaviour 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (syscall succeeds) and simulated behaviour (syscall fails). 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is quite a rare failure mode. It has only been seen 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown affecting calls to sys_readlink on amd64-linux, and even then it 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown requires a certain code sequence around the syscall to trigger 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. Here is one: 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern int my_readlink ( const char* path ); 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asm( 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".globl my_readlink\n" 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_readlink:\n" 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tsubq $0x1008,%rsp\n" 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tmovq %rdi,%rdi\n" // path is in rdi 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tmovq %rsp,%rsi\n" // &buf[0] -> rsi 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tmovl $0x1000,%edx\n" // sizeof(buf) in rdx 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tmovl $"__NR_READLINK",%eax\n" // syscall number 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tsyscall\n" 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\taddq $0x1008,%rsp\n" 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\tret\n" 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For more details, see bug #156404 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (https://bugs.kde.org/show_bug.cgi?id=156404). 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The fix is actually very simple. We simply need to call 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(extend_stack) for this thread, handing it the lowest 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown possible valid address for stack (sp - redzone), to ensure the 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pages all the way down to that address, are mapped. Because 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this is a potentially expensive and frequent operation, we 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown filter in two ways: 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown First, only the main thread (tid=1) has a growdown stack. So 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ignore all others. It is conceivable, although highly unlikely, 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the main thread exits, and later another thread is 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated tid=1, but that's harmless, I believe; 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(extend_stack) will do nothing when applied to a non-root 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread. 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Secondly, first call VG_(am_find_nsegment) directly, to see if 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the page holding (sp - redzone) is mapped correctly. If so, do 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nothing. This is almost always the case. VG_(extend_stack) 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown calls VG_(am_find_nsegment) twice, so this optimisation -- and 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that's all it is -- more or less halves the number of calls to 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_find_nsegment) required. 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TODO: the test "seg->kind == SkAnonC" is really inadequate, 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because although it tests whether the segment is mapped 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _somehow_, it doesn't check that it has the right permissions 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (r,w, maybe x) ? We could test that here, but it will also be 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown necessary to fix the corresponding test in VG_(extend_stack). 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown All this guff is of course Linux-specific. Hence the ifdef. 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid == 1/*ROOT THREAD*/) { 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr stackMin = VG_(get_SP)(tid) - VG_STACK_REDZONE_SZB; 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg = VG_(am_find_nsegment)(stackMin); 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg && seg->kind == SkAnonC) { 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stackMin is already mapped. Nothing to do. */ 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void)VG_(extend_stack)( stackMin, 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->client_stack_szB ); 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* END ensure root thread's stack is suitably mapped */ 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First off, get the syscall args and number. This is a 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform-dependent action. */ 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci = & syscallInfo[tid]; 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsIdle); 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getSyscallArgsFromGuestState( &sci->orig_args, &tst->arch.vex, trc ); 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy .orig_args to .args. The pre-handler may modify .args, but 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we want to keep the originals too, just in case. */ 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->args = sci->orig_args; 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Save the syscall number in the thread state in case the syscall 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is interrupted by a signal. */ 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sysno = sci->orig_args.sysno; 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* It's sometimes useful, as a crude debugging hack, to get a 1391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov stack trace at each (or selected) syscalls. */ 1392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (0 && sysno == __NR_ioctl) { 1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("\nioctl:\n"); 1394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(get_and_pp_StackTrace)(tid, 10); 1395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("\n"); 1396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Record syscall class. But why? Because the syscall might be 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interrupted by a signal, and in the signal handler (which will 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be m_signals.async_signalhandler) we will need to build a SysRes 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reflecting the syscall return result. In order to do that we 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown need to know the syscall class. Hence stash it in the guest 1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov state of this thread. This madness is not needed on Linux 1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov because it only has a single syscall return convention and so 1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov there is no ambiguity involved in converting the post-signal 1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov machine state into a SysRes. */ 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_SC_CLASS = VG_DARWIN_SYSNO_CLASS(sysno); 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The default what-to-do-next thing is hand the syscall to the 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel, so we pre-set that here. Set .sres to something 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown harmless looking (is irrelevant because .what is not 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SsComplete.) */ 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.what = SsHandToKernel; 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.sres = VG_(mk_SysRes_Error)(0); 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->flags = 0; 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fetch the syscall's handlers. If no handlers exist for this 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, we are given dummy handlers which force an immediate 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return with ENOSYS. */ 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ent = get_syscall_entry(sysno); 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fetch the layout information, which tells us where in the guest 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state the syscall args reside. This is a platform-dependent 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown action. This info is needed so that the scalar syscall argument 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown checks (PRE_REG_READ calls) know which bits of the guest state 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they need to inspect. */ 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getSyscallArgLayout( &layout ); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure the tmp signal mask matches the real signal mask; 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigsuspend may change this. */ 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(iseqsigset)(&tst->sig_mask, &tst->tmp_sig_mask)); 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Right, we're finally ready to Party. Call the pre-handler and 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown see what we get back. At this point: 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.what is Unset (we don't know yet). 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->orig_args contains the original args. 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->args is the same as sci->orig_args. 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->flags is zero. 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("SYSCALL[%d,%d](%s) ", 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno)); 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do any pre-syscall actions */ 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).syscall_wrapper) { 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord tmpv[8]; 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[0] = sci->orig_args.arg1; 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[1] = sci->orig_args.arg2; 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[2] = sci->orig_args.arg3; 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[3] = sci->orig_args.arg4; 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[4] = sci->orig_args.arg5; 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[5] = sci->orig_args.arg6; 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[6] = sci->orig_args.arg7; 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[7] = sci->orig_args.arg8; 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TDICT_CALL(tool_pre_syscall, tid, sysno, 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &tmpv[0], sizeof(tmpv)/sizeof(tmpv[0])); 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ent); 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ent->before); 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ent->before)( tid, 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &layout, 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &sci->args, &sci->status, &sci->flags ); 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The pre-handler may have modified: 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->args 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->flags 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown All else remains unchanged. 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Although the args may be modified, pre handlers are not allowed 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to change the syscall number. 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we proceed according to what the pre-handler decided. */ 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsHandToKernel 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || sci->status.what == SsComplete); 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->args.sysno == sci->orig_args.sysno); 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->status.what == SsComplete && !sr_isError(sci->status.sres)) { 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The pre-handler completed the syscall itself, declaring 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown success. */ 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->flags & SfNoWriteResult) { 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT(" --> [pre-success] NoWriteResult"); 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT(" --> [pre-success] Success(0x%llx:0x%llx)", 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_ResHI(sci->status.sres), 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_Res(sci->status.sres)); 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In this case the allowable flags are to ask for a signal-poll 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and/or a yield after the call. Changing the args isn't 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed. */ 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == (sci->flags 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & ~(SfPollAfter | SfYieldAfter | SfNoWriteResult))); 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->status.what == SsComplete && sr_isError(sci->status.sres)) { 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The pre-handler decided to fail syscall itself. */ 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT(" --> [pre-fail] Failure(0x%llx)", (ULong)sr_Err(sci->status.sres)); 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In this case, the pre-handler is also allowed to ask for the 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown post-handler to be run anyway. Changing the args is not 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed. */ 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter))); 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->status.what != SsHandToKernel) { 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* huh?! */ 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else /* (sci->status.what == HandToKernel) */ { 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, this is the usual case -- and the complicated one. There 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are two subcases: sync and async. async is the general case 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and is to be used when there is any possibility that the 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall might block [a fact that the pre-handler must tell us 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown via the sci->flags field.] Because the tidying-away / 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown context-switch overhead of the async case could be large, if 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we are sure that the syscall will not block, we fast-track it 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by doing it directly in this thread, which is a lot 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simpler. */ 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that the given flags are allowable: MayBlock, PollAfter 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and PostOnFail are ok. */ 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter))); 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->flags & SfMayBlock) { 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Syscall may block, so run it asynchronously */ 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask; 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT(" --> [async] ... \n"); 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mask = tst->sig_mask; 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanitize_client_sigmask(&mask); 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Gack. More impedance matching. Copy the possibly 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modified syscall args back into the guest state. */ 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2009-Mar-16: if the syscall args are possibly modified, 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then this assertion is senseless: 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The case that exposed it was sys_posix_spawn on Darwin, 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which heavily modifies its arguments but then lets the call 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go through anyway, with SfToBlock set, hence we end up here. */ 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown putSyscallArgsIntoGuestState( &sci->args, &tst->arch.vex ); 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Drop the bigLock */ 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock)(tid, VgTs_WaitSys, "VG_(client_syscall)[async]"); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Urr. We're now in a race against other threads trying to 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown acquire the bigLock. I guess that doesn't matter provided 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that do_syscall_for_client only touches thread-local 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state. */ 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do the call, which operates directly on the guest state, 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not on our abstracted copies of the args/result. */ 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_syscall_for_client(sysno, tst, &mask); 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* do_syscall_for_client may not return if the syscall was 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interrupted by a signal. In that case, flow of control is 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown first to m_signals.async_sighandler, which calls 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted), which 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fixes up the guest state, and possibly calls 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall). Once that's done, control drops back 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to the scheduler. */ 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Darwin: do_syscall_for_client may not return if the 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall was workq_ops(WQOPS_THREAD_RETURN) and the kernel 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown responded by starting the thread at wqthread_hijack(reuse=1) 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (to run another workqueue item). In that case, wqthread_hijack 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown calls ML_(wqthread_continue), which is similar to 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted). */ 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Reacquire the lock */ 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "VG_(client_syscall)[async]"); 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Even more impedance matching. Extract the syscall status 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from the guest state. */ 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getSyscallStatusFromGuestState( &sci->status, &tst->arch.vex ); 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsComplete); 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Be decorative, if required. */ 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_syscalls)) { 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool failed = sr_isError(sci->status.sres); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (failed) { 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("SYSCALL[%d,%d](%s) ... [async] --> Failure(0x%llx)", 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno), 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_Err(sci->status.sres)); 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("SYSCALL[%d,%d](%s) ... [async] --> " 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Success(0x%llx:0x%llx)", 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno), 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_ResHI(sci->status.sres), 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_Res(sci->status.sres) ); 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* run the syscall directly */ 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The pre-handler may have modified the syscall args, but 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown since we're passing values in ->args directly to the 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel, there's no point in flushing them back to the 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest state. Indeed doing so could be construed as 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown incorrect. */ 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(do_syscall)(sysno, sci->args.arg1, sci->args.arg2, 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->args.arg3, sci->args.arg4, 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->args.arg5, sci->args.arg6, 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->args.arg7, sci->args.arg8 ); 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status = convert_SysRes_to_SyscallStatus(sres); 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Be decorative, if required. */ 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_syscalls)) { 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool failed = sr_isError(sci->status.sres); 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (failed) { 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("[sync] --> Failure(0x%llx)", 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_Err(sci->status.sres) ); 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("[sync] --> Success(0x%llx:0x%llx)", 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_ResHI(sci->status.sres), 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)sr_Res(sci->status.sres) ); 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsComplete); 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dump the syscall result back in the guest state. This is 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a platform-specific action. */ 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sci->flags & SfNoWriteResult)) 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown putSyscallStatusIntoGuestState( tid, &sci->status, &tst->arch.vex ); 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Situation now: 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - the guest state is now correctly modified following the syscall 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - modified args, original args and syscall status are still 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown available in the syscallInfo[] entry for this syscall. 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Now go on to do the post-syscall actions (read on down ..) 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT(" "); 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("\n"); 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Perform post syscall actions. The expected state on entry is 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown precisely as at the end of VG_(client_syscall), that is: 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - guest state up to date following the syscall 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - modified args, original args and syscall status are still 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown available in the syscallInfo[] entry for this syscall. 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - syscall status matches what's in the guest state. 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There are two ways to get here: the normal way -- being called by 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client_syscall), and the unusual way, from 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted). 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Darwin: there's a third way, ML_(wqthread_continue). 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(post_syscall) (ThreadId tid) 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallInfo* sci; 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const SyscallTableEntry* ent; 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallStatus test_status; 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sysno; 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Preliminaries */ 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 1 && tid < VG_N_THREADS); 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci = & syscallInfo[tid]; 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* m_signals.sigvgkill_handler might call here even when not in 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a syscall. */ 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->status.what == SsIdle || sci->status.what == SsHandToKernel) { 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.what = SsIdle; 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Validate current syscallInfo entry. In particular we require 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the current .status matches what's actually in the guest 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state. At least in the normal case where we have actually 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown previously written the result into the guest state. */ 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsComplete); 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getSyscallStatusFromGuestState( &test_status, &tst->arch.vex ); 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sci->flags & SfNoWriteResult)) 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(eq_SyscallStatus( &sci->status, &test_status )); 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Failure of the above assertion on Darwin can indicate a problem 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the syscall wrappers that pre-fail or pre-succeed the 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, by calling SET_STATUS_Success or SET_STATUS_Failure, 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when they really should call SET_STATUS_from_SysRes. The former 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown create a UNIX-class syscall result on Darwin, which may not be 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown correct for the syscall; if that's the case then this assertion 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fires. See PRE(thread_fast_set_cthread_self) for an example. On 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-Darwin platforms this assertion is should never fail, and this 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown comment is completely irrelevant. */ 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, looks sane */ 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the system call number. Because the pre-handler isn't 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed to mess with it, it should be the same for both the 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown original and potentially-modified args. */ 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->args.sysno == sci->orig_args.sysno); 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sysno = sci->args.sysno; 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ent = get_syscall_entry(sysno); 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pre: status == Complete (asserted above) */ 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Consider either success or failure. Now run the post handler if: 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - it exists, and 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Success or (Failure and PostOnFail is set) 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ent->after 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ((!sr_isError(sci->status.sres)) 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (sr_isError(sci->status.sres) 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (sci->flags & SfPostOnFail) ))) { 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ent->after)( tid, &sci->args, &sci->status ); 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Because the post handler might have changed the status (eg, the 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown post-handler for sys_open can change the result from success to 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown failure if the kernel supplied a fd that it doesn't like), once 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown again dump the syscall result back in the guest state.*/ 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sci->flags & SfNoWriteResult)) 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown putSyscallStatusIntoGuestState( tid, &sci->status, &tst->arch.vex ); 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do any post-syscall actions required by the tool. */ 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).syscall_wrapper) { 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord tmpv[8]; 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[0] = sci->orig_args.arg1; 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[1] = sci->orig_args.arg2; 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[2] = sci->orig_args.arg3; 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[3] = sci->orig_args.arg4; 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[4] = sci->orig_args.arg5; 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[5] = sci->orig_args.arg6; 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[6] = sci->orig_args.arg7; 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpv[7] = sci->orig_args.arg8; 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TDICT_CALL(tool_post_syscall, tid, 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sysno, 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &tmpv[0], sizeof(tmpv)/sizeof(tmpv[0]), 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.sres); 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The syscall is done. */ 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsComplete); 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.what = SsIdle; 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The pre/post wrappers may have concluded that pending signals 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown might have been created, and will have set SfPollAfter to 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown request a poll for them once the syscall is done. */ 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->flags & SfPollAfter) 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals)(tid); 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Similarly, the wrappers might have asked for a yield 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown afterwards. */ 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sci->flags & SfYieldAfter) 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vg_yield)(); 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Dealing with syscalls which get interrupted by a signal: 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Syscalls done on behalf of the client are finally handed off to the 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel in VG_(client_syscall) above, either by calling 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_syscall_for_client (the async case), or by calling 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_syscall6) (the sync case). 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If the syscall is not interrupted by a signal (it may block and 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown later unblock, but that's irrelevant here) then those functions 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eventually return and so control is passed to VG_(post_syscall). 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NB: not sure if the sync case can actually get interrupted, as it 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown operates with all signals masked. 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown However, the syscall may get interrupted by an async-signal. In 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that case do_syscall_for_client/VG_(do_syscall6) do not 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return. Instead we wind up in m_signals.async_sighandler. We need 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to fix up the guest state to make it look like the syscall was 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interrupted for guest. So async_sighandler calls here, and this 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does the fixup. Note that from here we wind up calling 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall) too. 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are addresses within ML_(do_syscall_for_client_WRK). See 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall-$PLAT.S for details. 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_setup); 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_restart); 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_complete); 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_committed); 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_finished); 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Darwin requires extra uglyness */ 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_setup_MACH); 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_restart_MACH); 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_complete_MACH); 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_committed_MACH); 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_finished_MACH); 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_setup_MDEP); 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_restart_MDEP); 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_complete_MDEP); 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_committed_MDEP); 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_finished_MDEP); 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_setup_UNIX); 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_restart_UNIX); 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_complete_UNIX); 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_committed_UNIX); 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern const Addr ML_(blksys_finished_UNIX); 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Back up guest state to restart a system call. */ 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_EIP -= 2; // sizeof(int $0x80) 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure our caller is actually sane, and we're really backing 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back over a syscall. 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int $0x80 == CD 80 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar *p = (UChar *)arch->vex.guest_EIP; 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p[0] != 0xcd || p[1] != 0x80) 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "?! restarting over syscall at %#x %02x %02x\n", 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_EIP, p[0], p[1]); 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(p[0] == 0xcd && p[1] == 0x80); 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_RIP -= 2; // sizeof(syscall) 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure our caller is actually sane, and we're really backing 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back over a syscall. 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall == 0F 05 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar *p = (UChar *)arch->vex.guest_RIP; 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p[0] != 0x0F || p[1] != 0x05) 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "?! restarting over syscall at %#llx %02x %02x\n", 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_RIP, p[0], p[1]); 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(p[0] == 0x0F && p[1] == 0x05); 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_CIA -= 4; // sizeof(ppc32 instr) 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure our caller is actually sane, and we're really backing 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back over a syscall. 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sc == 44 00 00 02 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar *p = (UChar *)arch->vex.guest_CIA; 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p[0] != 0x44 || p[1] != 0x0 || p[2] != 0x0 || p[3] != 0x02) 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "?! restarting over syscall at %#llx %02x %02x %02x %02x\n", 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_CIA + 0ULL, p[0], p[1], p[2], p[3]); 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(p[0] == 0x44 && p[1] == 0x0 && p[2] == 0x0 && p[3] == 0x2); 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arch->vex.guest_R15T & 1) { 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Thumb mode. SVC is a encoded as 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1101 1111 imm8 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // where imm8 is the SVC number, and we only accept 0. 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R15T -= 2; // sizeof(thumb 16 bit insn) 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)(arch->vex.guest_R15T - 1); 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool valid = p[0] == 0 && p[1] == 0xDF; 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!valid) { 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "?! restarting over (Thumb) syscall that is not syscall " 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "at %#llx %02x %02x\n", 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R15T - 1ULL, p[0], p[1]); 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(valid); 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: NOTE, this really isn't right. We need to back up 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ITSTATE to what it was before the SVC instruction, but we 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // don't know what it was. At least assert that it is now 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // zero, because if it is nonzero then it must also have 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // been nonzero for the SVC itself, which means it was 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // conditional. Urk. 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arch->vex.guest_ITSTATE == 0); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ARM mode. SVC is encoded as 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // cond 1111 imm24 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // where imm24 is the SVC number, and we only accept 0. 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R15T -= 4; // sizeof(arm instr) 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)arch->vex.guest_R15T; 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool valid = p[0] == 0 && p[1] == 0 && p[2] == 0 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (p[3] & 0xF) == 0xF; 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!valid) { 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "?! restarting over (ARM) syscall that is not syscall " 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "at %#llx %02x %02x %02x %02x\n", 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R15T + 0ULL, p[0], p[1], p[2], p[3]); 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(valid); 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL; 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure our caller is actually sane, and we're really backing 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back over a syscall. 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int $0x80 == CD 80 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int $0x81 == CD 81 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int $0x82 == CD 82 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sysenter == 0F 34 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar *p = (UChar *)arch->vex.guest_EIP; 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = (p[0] == 0xCD && p[1] == 0x80) 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (p[0] == 0xCD && p[1] == 0x81) 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (p[0] == 0xCD && p[1] == 0x82) 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (p[0] == 0x0F && p[1] == 0x34); 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "?! restarting over syscall at %#x %02x %02x\n", 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_EIP, p[0], p[1]); 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ok); 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: #warning GrP fixme amd64 restart unimplemented 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 1956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arch->vex.guest_IA -= 2; // sizeof(syscall) 1957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Make sure our caller is actually sane, and we're really backing 1959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov back over a syscall. 1960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov syscall == 0A <num> 1962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 1963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { 1964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar *p = (UChar *)arch->vex.guest_IA; 1965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (p[0] != 0x0A) 1966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(message)(Vg_DebugMsg, 1967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "?! restarting over syscall at %#llx %02x %02x\n", 1968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arch->vex.guest_IA, p[0], p[1]); 1969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(p[0] == 0x0A); 1971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux) 1974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_PC -= 4; // sizeof(mips instr) 1976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Make sure our caller is actually sane, and we're really backing 1978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng back over a syscall. 1979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng syscall == 00 00 00 0C 1981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng big endian 1982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng syscall == 0C 00 00 00 1983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */ 1984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 1985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UChar *p = (UChar *)(arch->vex.guest_PC); 1986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined (VG_LITTLEENDIAN) 1987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (p[0] != 0x0c || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x00) 1988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)(Vg_DebugMsg, 1989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "?! restarting over syscall at %#x %02x %02x %02x %02x\n", 1990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_PC, p[0], p[1], p[2], p[3]); 1991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(p[0] == 0x0c && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x00); 1993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined (VG_BIGENDIAN) 1994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x0c) 1995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)(Vg_DebugMsg, 1996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "?! restarting over syscall at %#x %02x %02x %02x %02x\n", 1997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_PC, p[0], p[1], p[2], p[3]); 1998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c); 2000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# else 2001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# error "Unknown endianness" 2002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 2003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 2004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "ML_(fixup_guest_state_to_restart_syscall): unknown plat" 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fix up the guest state when a syscall is interrupted by a signal 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and so has been forced to return 'sysret'. 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown To do this, we determine the precise state of the syscall by 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown looking at the (real) IP at the time the signal happened. The 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall sequence looks like: 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1. unblock signals 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2. perform syscall 2021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3. save result to guest state (EAX, RAX, R3+CR0.SO, R0, V0) 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4. re-block signals 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If a signal 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown happens at Then Why? 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [1-2) restart nothing has happened (restart syscall) 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [2] restart syscall hasn't started, or kernel wants to restart 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [2-3) save syscall complete, but results not saved 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [3-4) syscall complete, results saved 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Sometimes we never want to restart an interrupted syscall (because 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigaction says not to), so we only restart if "restart" is True. 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This will also call VG_(post_syscall) if the syscall has actually 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown completed (either because it was interrupted, or because it 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actually finished). It will not call VG_(post_syscall) if the 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall is set up for restart, which means that the pre-wrapper may 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get called multiple times. 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip, 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres, 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool restart) 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that we don't know the syscall number here, since (1) in 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown general there's no reliable way to get hold of it short of 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stashing it in the guest state before the syscall, and (2) in 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any case we don't need to know it for the actions done by this 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown routine. 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Furthermore, 'sres' is only used in the case where the syscall 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is complete, but the result has not been committed to the guest 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state yet. In any other situation it will be meaningless and 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown therefore ignored. */ 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallStatus canonical; 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadArchState* th_regs; 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallInfo* sci; 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compute some Booleans indicating which range we're in. */ 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool outside_range, 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_setup_to_restart, // [1,2) in the .S files 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown at_restart, // [2] in the .S files 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_complete_to_committed, // [3,4) in the .S files 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_committed_to_finished; // [4,5) in the .S files 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown outside_range 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = ip < ML_(blksys_setup) || ip >= ML_(blksys_finished); 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_setup_to_restart 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = ip >= ML_(blksys_setup) && ip < ML_(blksys_restart); 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown at_restart 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = ip == ML_(blksys_restart); 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_complete_to_committed 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed); 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_committed_to_finished 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = ip >= ML_(blksys_committed) && ip < ML_(blksys_finished); 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown outside_range 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (ip < ML_(blksys_setup_MACH) || ip >= ML_(blksys_finished_MACH)) 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (ip < ML_(blksys_setup_MDEP) || ip >= ML_(blksys_finished_MDEP)) 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (ip < ML_(blksys_setup_UNIX) || ip >= ML_(blksys_finished_UNIX)); 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_setup_to_restart 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (ip >= ML_(blksys_setup_MACH) && ip < ML_(blksys_restart_MACH)) 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip >= ML_(blksys_setup_MDEP) && ip < ML_(blksys_restart_MDEP)) 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip >= ML_(blksys_setup_UNIX) && ip < ML_(blksys_restart_UNIX)); 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown at_restart 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (ip == ML_(blksys_restart_MACH)) 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip == ML_(blksys_restart_MDEP)) 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip == ML_(blksys_restart_UNIX)); 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_complete_to_committed 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (ip >= ML_(blksys_complete_MACH) && ip < ML_(blksys_committed_MACH)) 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip >= ML_(blksys_complete_MDEP) && ip < ML_(blksys_committed_MDEP)) 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip >= ML_(blksys_complete_UNIX) && ip < ML_(blksys_committed_UNIX)); 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in_committed_to_finished 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (ip >= ML_(blksys_committed_MACH) && ip < ML_(blksys_finished_MACH)) 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip >= ML_(blksys_committed_MDEP) && ip < ML_(blksys_finished_MDEP)) 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ip >= ML_(blksys_committed_UNIX) && ip < ML_(blksys_finished_UNIX)); 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Wasn't that just So Much Fun? Does your head hurt yet? Mine does. */ 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "interrupted_syscall: tid=%d, ip=0x%llx, " 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "restart=%s, sres.isErr=%s, sres.val=%lld\n", 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)tid, 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)ip, 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restart ? "True" : "False", 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sr_isError(sres) ? "True" : "False", 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Long)(sr_isError(sres) ? sr_Err(sres) : sr_Res(sres)) ); 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 1 && tid < VG_N_THREADS); 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown th_regs = &tst->arch; 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci = & syscallInfo[tid]; 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out what the state of the syscall was by examining the 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (real) IP at the time of the signal, and act accordingly. */ 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (outside_range) { 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " not in syscall at all: hmm, very suspicious\n" ); 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Looks like we weren't in a syscall at all. Hmm. */ 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what != SsIdle); 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We should not be here unless this thread had first started up 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the machinery for a syscall by calling VG_(client_syscall). 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence: */ 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what != SsIdle); 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* now, do one of four fixup actions, depending on where the IP has 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown got to. */ 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (in_setup_to_restart) { 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* syscall hasn't even started; go around again */ 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, " not started: restarting\n"); 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsHandToKernel); 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(fixup_guest_state_to_restart_syscall)(th_regs); 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (at_restart) { 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We're either about to run the syscall, or it was interrupted 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and the kernel restarted it. Restart if asked, otherwise 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EINTR it. */ 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (restart) { 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, " at syscall instr: restarting\n"); 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(fixup_guest_state_to_restart_syscall)(th_regs); 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, " at syscall instr: returning EINTR\n"); 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical = convert_SysRes_to_SyscallStatus( 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_Error)( VKI_EINTR ) 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sci->flags & SfNoWriteResult)) 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown putSyscallStatusIntoGuestState( tid, &canonical, &th_regs->vex ); 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status = canonical; 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (in_complete_to_committed) { 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Syscall complete, but result hasn't been written back yet. 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Write the SysRes we were supplied with back to the guest 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state. */ 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " completed, but uncommitted: committing\n"); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown canonical = convert_SysRes_to_SyscallStatus( sres ); 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sci->flags & SfNoWriteResult)) 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown putSyscallStatusIntoGuestState( tid, &canonical, &th_regs->vex ); 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status = canonical; 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (in_committed_to_finished) { 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Result committed, but the signal mask has not been restored; 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we expect our caller (the signal handler) will have fixed 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this up. */ 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " completed and committed: nothing to do\n"); 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getSyscallStatusFromGuestState( &sci->status, &th_regs->vex ); 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what == SsComplete); 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("?? strange syscall interrupt state?"); 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In all cases, the syscall is now finished (even if we called 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(fixup_guest_state_to_restart_syscall), since that just 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown re-positions the guest's IP for another go at it). So we need 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to record that fact. */ 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.what = SsIdle; 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Clean up after workq_ops(WQOPS_THREAD_RETURN) jumped to wqthread_hijack. 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is similar to VG_(fixup_guest_state_after_syscall_interrupted). 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This longjmps back to the scheduler. 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(wqthread_continue_NORETURN)(ThreadId tid) 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SyscallInfo* sci; 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "wqthread_continue_NORETURN"); 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("SYSCALL[%d,%d](%s) workq_ops() starting new workqueue item\n", 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getpid)(), tid, VG_SYSNUM_STRING(__NR_workq_ops)); 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 1 && tid < VG_N_THREADS); 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci = & syscallInfo[tid]; 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sci->status.what != SsIdle); 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->os_state.wq_jmpbuf_valid); // check this BEFORE post_syscall 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Pretend the syscall completed normally, but don't touch the thread state. 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status = convert_SysRes_to_SyscallStatus( VG_(mk_SysRes_Success)(0) ); 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->flags |= SfNoWriteResult; 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sci->status.what = SsIdle; 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->sched_jmpbuf_valid); 2244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_MINIMAL_LONGJMP(tst->sched_jmpbuf); 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A place to store the where-to-call-when-really-done pointer 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// When the final thread is done, where shall I call to shutdown the 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// system cleanly? Is set once at startup (in m_main) and never 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// changes after that. Is basically a pointer to the exit 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// continuation. This is all just a nasty hack to avoid calling 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// directly from m_syswrap to m_main at exit, since that would cause 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// m_main to become part of a module cycle, which is silly. 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid (* VG_(address_of_m_main_shutdown_actions_NORETURN) ) 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ThreadId,VgSchedReturnCode) 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = NULL; 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2269