1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Implementation of POSIX signals. m_signals.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2000-2013 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/* 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Signal handling. 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There are 4 distinct classes of signal: 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1. Synchronous, instruction-generated (SIGILL, FPE, BUS, SEGV and 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRAP): these are signals as a result of an instruction fault. If 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we get one while running client code, then we just do the 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appropriate thing. If it happens while running Valgrind code, then 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it indicates a Valgrind bug. Note that we "manually" implement 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown automatic stack growth, such that if a fault happens near the 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client process stack, it is extended in the same way the kernel 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would, and the fault is never reported to the client program. 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2. Asynchronous variants of the above signals: If the kernel tries 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to deliver a sync signal while it is blocked, it just kills the 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process. Therefore, we can't block those signals if we want to be 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown able to report on bugs in Valgrind. This means that we're also 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown open to receiving those signals from other processes, sent with 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kill. We could get away with just dropping them, since they aren't 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown really signals that processes send to each other. 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3. Synchronous, general signals. If a thread/process sends itself 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a signal with kill, its expected to be synchronous: ie, the signal 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will have been delivered by the time the syscall finishes. 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4. Asynchronous, general signals. All other signals, sent by 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown another process with kill. These are generally blocked, except for 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown two special cases: we poll for them each time we're about to run a 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread for a time quanta, and while running blocking syscalls. 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In addition, we reserve one signal for internal use: SIGVGKILL. 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SIGVGKILL is used to terminate threads. When one thread wants 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown another to exit, it will set its exitreason and send it SIGVGKILL 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if it appears to be blocked in a syscall. 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We use a kernel thread for each application thread. When the 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread allows itself to be open to signals, it sets the thread 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal mask to what the client application set it to. This means 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that we get the kernel to do all signal routing: under Valgrind, 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals get delivered in the same way as in the non-Valgrind case 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (the exception being for the sync signal set, since they're almost 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown always unblocked). 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Some more details... 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown First off, we take note of the client's requests (via sys_sigaction 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and sys_sigprocmask) to set the signal state (handlers for each 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal, which are process-wide, + a mask for each signal, which is 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown per-thread). This info is duly recorded in the SCSS (static Client 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal state) in m_signals.c, and if the client later queries what 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the state is, we merely fish the relevant info out of SCSS and give 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it back. 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown However, we set the real signal state in the kernel to something 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entirely different. This is recorded in SKSS, the static Kernel 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal state. What's nice (to the extent that anything is nice w.r.t 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals) is that there's a pure function to calculate SKSS from SCSS, 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown calculate_SKSS_from_SCSS. So when the client changes SCSS then we 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown recompute the associated SKSS and apply any changes from the previous 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS through to the kernel. 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Now, that said, the general scheme we have now is, that regardless of 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what the client puts into the SCSS (viz, asks for), what we would 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown like to do is as follows: 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) run code on the virtual CPU with all signals blocked 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (2) at convenient moments for us (that is, when the VCPU stops, and 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown control is back with the scheduler), ask the kernel "do you have 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any signals for me?" and if it does, collect up the info, and 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver them to the client (by building sigframes). 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown And that's almost what we do. The signal polling is done by 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals), which calls through to VG_(sigtimedwait_zero) to 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do the dirty work. (of which more later). 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown By polling signals, rather than catching them, we get to deal with 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown them only at convenient moments, rather than having to recover from 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown taking a signal while generated code is running. 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Now unfortunately .. the above scheme only works for so-called async 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals. An async signal is one which isn't associated with any 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown particular instruction, eg Control-C (SIGINT). For those, it doesn't 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown matter if we don't deliver the signal to the client immediately; it 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only matters that we deliver it eventually. Hence polling is OK. 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown But the other group -- sync signals -- are all related by the fact 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that they are various ways for the host CPU to fail to execute an 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction: SIGILL, SIGSEGV, SIGFPU. And they can't be deferred, 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because obviously if a host instruction can't execute, well then we 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have to immediately do Plan B, whatever that is. 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown So the next approximation of what happens is: 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) run code on vcpu with all async signals blocked 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (2) at convenient moments (when NOT running the vcpu), poll for async 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals. 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) and (2) together imply that if the host does deliver a signal to 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown async_signalhandler while the VCPU is running, something's 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seriously wrong. 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (3) when running code on vcpu, don't block sync signals. Instead 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register sync_signalhandler and catch any such via that. Of 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown course, that means an ugly recovery path if we do -- the 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sync_signalhandler has to longjump, exiting out of the generated 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code, and the assembly-dispatcher thingy that runs it, and gets 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caught in m_scheduler, which then tells m_signals to deliver the 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal. 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Now naturally (ha ha) even that might be tolerable, but there's 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown something worse: dealing with signals delivered to threads in 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscalls. 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Obviously from the above, SKSS's signal mask (viz, what we really run 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with) is way different from SCSS's signal mask (viz, what the client 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread thought it asked for). (eg) It may well be that the client 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown did not block control-C, so that it just expects to drop dead if it 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown receives ^C whilst blocked in a syscall, but by default we are 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown running with all async signals blocked, and so that signal could be 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arbitrarily delayed, or perhaps even lost (not sure). 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown So what we have to do, when doing any syscall which SfMayBlock, is to 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown quickly switch in the SCSS-specified signal mask just before the 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, and switch it back just afterwards, and hope that we don't 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get caught up in some wierd race condition. This is the primary 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown purpose of the ultra-magical pieces of assembly code in 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown coregrind/m_syswrap/syscall-<plat>.S 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ----------- 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The ways in which V can come to hear of signals that need to be 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown forwarded to the client as are follows: 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sync signals: can arrive at any time whatsoever. These are caught 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by sync_signalhandler 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown async signals: 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if running generated code 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then these are blocked, so we don't expect to catch them in 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown async_signalhandler 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if thread is blocked in a syscall marked SfMayBlock 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then signals may be delivered to async_sighandler, since we 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temporarily unblocked them for the duration of the syscall, 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by using the real (SCSS) mask for this thread 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else we're doing misc housekeeping activities (eg, making a translation, 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown washing our hair, etc). As in the normal case, these signals are 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blocked, but we can and do poll for them using VG_(poll_signals). 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Now, re VG_(poll_signals), it polls the kernel by doing 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigtimedwait_zero). This is trivial on Linux, since it's just a 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall. But on Darwin and AIX, we have to cobble together the 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown functionality in a tedious, longwinded and probably error-prone way. 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Finally, if a gdb is debugging the process under valgrind, 196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the signal can be ignored if gdb tells this. So, before resuming the 197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov scheduler/delivering the signal, a call to VG_(gdbserver_report_signal) 198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov is done. If this returns True, the signal is delivered. 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debugger.h" // For VG_(start_debugger) 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_errormgr.h" 212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_gdbserver.h" 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h" 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_sigframe.h" // For VG_(sigframe_create)() 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacks.h" // For VG_(change_stack)() 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h" 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_coredump.h" 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Forwards decls. 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext * ); 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void async_signalhandler ( Int sigNo, vki_siginfo_t *info, 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext * ); 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sigvgkill_handler ( Int sigNo, vki_siginfo_t *info, 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext * ); 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Maximum usable signal. */ 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(max_signal) = _VKI_NSIG; 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_QUEUED_SIGNALS 8 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct SigQueue { 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int next; 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t sigs[N_QUEUED_SIGNALS]; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} SigQueue; 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Macros for pulling stuff out of ucontexts ------ */ 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Q: what does VG_UCONTEXT_SYSCALL_SYSRES do? A: let's suppose the 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown machine context (uc) reflects the situation that a syscall had just 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown completed, quite literally -- that is, that the program counter was 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now at the instruction following the syscall. (or we're slightly 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown downstream, but we're sure no relevant register has yet changed 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value.) Then VG_UCONTEXT_SYSCALL_SYSRES returns a SysRes reflecting 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the result of the syscall; it does this by fishing relevant bits of 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the machine state out of the uc. Of course if the program counter 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown was somewhere else entirely then the result is likely to be 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown meaningless, so the caller of VG_UCONTEXT_SYSCALL_SYSRES has to be 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown very careful to pay attention to the results only when it is sure 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the said constraint on the program counter is indeed valid. */ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.eip) 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.esp) 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the value in uc_mcontext.eax into a SysRes. */ \ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax ) 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (ULong)((uc)->uc_mcontext.eip); \ 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (ULong)((uc)->uc_mcontext.esp); \ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.X86.r_ebp = (uc)->uc_mcontext.ebp; \ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip) 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp) 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the value in uc_mcontext.rax into a SysRes. */ \ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_amd64_linux)( (uc)->uc_mcontext.rax ) 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (uc)->uc_mcontext.rip; \ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (uc)->uc_mcontext.rsp; \ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.AMD64.r_rbp = (uc)->uc_mcontext.rbp; \ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Comments from Paul Mackerras 25 Nov 05: 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > I'm tracking down a problem where V's signal handling doesn't 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > work properly on a ppc440gx running 2.4.20. The problem is that 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > the ucontext being presented to V's sighandler seems completely 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > bogus. 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > V's kernel headers and hence ucontext layout are derived from 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > 2.6.9. I compared include/asm-ppc/ucontext.h from 2.4.20 and 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > 2.6.13. 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > Can I just check my interpretation: the 2.4.20 one contains the 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > uc_mcontext field in line, whereas the 2.6.13 one has a pointer 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > to said struct? And so if V is using the 2.6.13 struct then a 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > 2.4.20 one will make no sense to it. 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Not quite... what is inline in the 2.4.20 version is a 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigcontext_struct, not an mcontext. The sigcontext looks like 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this: 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct sigcontext_struct { 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long _unused[4]; 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int signal; 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long handler; 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long oldmask; 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct pt_regs *regs; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown }; 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The regs pointer of that struct ends up at the same offset as the 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc_regs of the 2.6 struct ucontext, and a struct pt_regs is the 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same as the mc_gregs field of the mcontext. In fact the integer 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs are followed in memory by the floating point regs on 2.4.20. 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thus if you are using the 2.6 definitions, it should work on 2.4.20 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown provided that you go via uc->uc_regs rather than looking in 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_mcontext directly. 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There is another subtlety: 2.4.20 doesn't save the vector regs when 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivering a signal, and 2.6.x only saves the vector regs if the 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process has ever used an altivec instructions. If 2.6.x does save 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the vector regs, it sets the MSR_VEC bit in 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_regs->mc_gregs[PT_MSR], otherwise it clears it. That bit 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will always be clear under 2.4.20. So you can use that bit to tell 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whether uc->uc_regs->mc_vregs is valid. */ 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_regs->mc_gregs[VKI_PT_NIP]) 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_regs->mc_gregs[VKI_PT_R1]) 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the values in uc_mcontext r3,cr into a SysRes. */ \ 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_ppc32_linux)( \ 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (uc)->uc_regs->mc_gregs[VKI_PT_R3], \ 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((uc)->uc_regs->mc_gregs[VKI_PT_CCR] >> 28) & 1) \ 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (ULong)((uc)->uc_regs->mc_gregs[VKI_PT_NIP]); \ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (ULong)((uc)->uc_regs->mc_gregs[VKI_PT_R1]); \ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.PPC32.r_lr = (uc)->uc_regs->mc_gregs[VKI_PT_LNK]; \ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.gp_regs[VKI_PT_NIP]) 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.gp_regs[VKI_PT_R1]) 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dubious hack: if there is an error, only consider the lowest 8 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bits of r3. memcheck/tests/post-syscall shows a case where an 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interrupted syscall should have produced a ucontext with 0x4 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VKI_EINTR) in r3 but is in fact producing 0x204. */ 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Awaiting clarification from PaulM. Evidently 0x204 is 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ERESTART_RESTARTBLOCK, which shouldn't have made it into user 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown space. */ 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline SysRes VG_UCONTEXT_SYSCALL_SYSRES( struct vki_ucontext* uc ) 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong err = (uc->uc_mcontext.gp_regs[VKI_PT_CCR] >> 28) & 1; 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong r3 = uc->uc_mcontext.gp_regs[VKI_PT_R3]; 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (err) r3 &= 0xFF; 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_ppc64_linux)( r3, err ); 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (uc)->uc_mcontext.gp_regs[VKI_PT_NIP]; \ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (uc)->uc_mcontext.gp_regs[VKI_PT_R1]; \ 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.PPC64.r_lr = (uc)->uc_mcontext.gp_regs[VKI_PT_LNK]; \ 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.arm_pc) 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.arm_sp) 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the value in uc_mcontext.rax into a SysRes. */ \ 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_arm_linux)( (uc)->uc_mcontext.arm_r0 ) 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (uc)->uc_mcontext.arm_pc; \ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (uc)->uc_mcontext.arm_sp; \ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r14 = (uc)->uc_mcontext.arm_lr; \ 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r12 = (uc)->uc_mcontext.arm_ip; \ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r11 = (uc)->uc_mcontext.arm_fp; \ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r7 = (uc)->uc_mcontext.arm_r7; \ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_arm64_linux) 390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)((uc)->uc_mcontext.pc)) 391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_STACK_PTR(uc) ((UWord)((uc)->uc_mcontext.sp)) 392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Convert the value in uc_mcontext.regs[0] into a SysRes. */ \ 394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(mk_SysRes_arm64_linux)( (uc)->uc_mcontext.regs[0] ) 395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { (srP)->r_pc = (uc)->uc_mcontext.pc; \ 397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->r_sp = (uc)->uc_mcontext.sp; \ 398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->misc.ARM64.x29 = (uc)->uc_mcontext.regs[29]; \ 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->misc.ARM64.x30 = (uc)->uc_mcontext.regs[30]; \ 400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_INSTR_PTR( void* ucV ) { 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)ucV; 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ss->__eip; 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_STACK_PTR( void* ucV ) { 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)ucV; 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ss->__esp; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline SysRes VG_UCONTEXT_SYSCALL_SYSRES( void* ucV, 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord scclass ) { 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is complicated by the problem that there are 3 different 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kinds of syscalls, each with its own return convention. 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NB: scclass is a host word, hence UWord is good for both 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64-darwin and x86-darwin */ 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)ucV; 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* duplicates logic in m_syswrap.getSyscallStatusFromGuestState */ 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt carry = 1 & ss->__eflags; 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt err = 0; 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wLO = 0; 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wHI = 0; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (scclass) { 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_UNIX: 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = carry; 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = ss->__eax; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI = ss->__edx; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MACH: 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = ss->__eax; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MDEP: 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = ss->__eax; 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI, wLO ); 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void VG_UCONTEXT_TO_UnwindStartRegs( UnwindStartRegs* srP, 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* ucV ) { 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)(ucV); 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srP->r_pc = (ULong)(ss->__eip); 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srP->r_sp = (ULong)(ss->__esp); 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srP->misc.X86.r_ebp = (UInt)(ss->__ebp); 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_INSTR_PTR( void* ucV ) { 463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ucontext_t* uc = (ucontext_t*)ucV; 464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_mcontext64* mc = uc->uc_mcontext; 465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_x86_thread_state64* ss = &mc->__ss; 466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return ss->__rip; 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_STACK_PTR( void* ucV ) { 469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ucontext_t* uc = (ucontext_t*)ucV; 470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_mcontext64* mc = uc->uc_mcontext; 471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_x86_thread_state64* ss = &mc->__ss; 472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return ss->__rsp; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline SysRes VG_UCONTEXT_SYSCALL_SYSRES( void* ucV, 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord scclass ) { 476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* This is copied from the x86-darwin case. I'm not sure if it 477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is correct. */ 478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ucontext_t* uc = (ucontext_t*)ucV; 479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_mcontext64* mc = uc->uc_mcontext; 480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_x86_thread_state64* ss = &mc->__ss; 481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* duplicates logic in m_syswrap.getSyscallStatusFromGuestState */ 482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ULong carry = 1 & ss->__rflags; 483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ULong err = 0; 484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ULong wLO = 0; 485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ULong wHI = 0; 486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (scclass) { 487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_DARWIN_SYSCALL_CLASS_UNIX: 488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng err = carry; 489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng wLO = ss->__rax; 490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng wHI = ss->__rdx; 491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_DARWIN_SYSCALL_CLASS_MACH: 493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng wLO = ss->__rax; 494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_DARWIN_SYSCALL_CLASS_MDEP: 496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng wLO = ss->__rax; 497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(0); 500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, 503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng wHI, wLO ); 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void VG_UCONTEXT_TO_UnwindStartRegs( UnwindStartRegs* srP, 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* ucV ) { 508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ucontext_t* uc = (ucontext_t*)ucV; 509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_mcontext64* mc = uc->uc_mcontext; 510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct __darwin_x86_thread_state64* ss = &mc->__ss; 511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng srP->r_pc = (ULong)(ss->__rip); 512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng srP->r_sp = (ULong)(ss->__rsp); 513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng srP->misc.AMD64.r_rbp = (ULong)(ss->__rbp); 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.regs.psw.addr) 519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.regs.gprs[15]) 520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.regs.gprs[11]) 521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(mk_SysRes_s390x_linux)((uc)->uc_mcontext.regs.gprs[2]) 523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.regs.gprs[14]) 524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { (srP)->r_pc = (ULong)((uc)->uc_mcontext.regs.psw.addr); \ 527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (srP)->r_sp = (ULong)((uc)->uc_mcontext.regs.gprs[15]); \ 528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (srP)->misc.S390X.r_fp = (uc)->uc_mcontext.regs.gprs[11]; \ 529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (srP)->misc.S390X.r_lr = (uc)->uc_mcontext.regs.gprs[14]; \ 530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux) 533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)(((uc)->uc_mcontext.sc_pc))) 534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_UCONTEXT_STACK_PTR(uc) ((UWord)((uc)->uc_mcontext.sc_regs[29])) 535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.sc_regs[30]) 536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.sc_regs[2]) 537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Convert the value in uc_mcontext.rax into a SysRes. */ \ 539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(mk_SysRes_mips32_linux)( (uc)->uc_mcontext.sc_regs[2], \ 540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (uc)->uc_mcontext.sc_regs[3], \ 541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (uc)->uc_mcontext.sc_regs[7]) 542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { (srP)->r_pc = (uc)->uc_mcontext.sc_pc; \ 545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (srP)->r_sp = (uc)->uc_mcontext.sc_regs[29]; \ 546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (srP)->misc.MIPS32.r30 = (uc)->uc_mcontext.sc_regs[30]; \ 547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (srP)->misc.MIPS32.r31 = (uc)->uc_mcontext.sc_regs[31]; \ 548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \ 549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_mips64_linux) 552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_INSTR_PTR(uc) (((uc)->uc_mcontext.sc_pc)) 553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.sc_regs[29]) 554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.sc_regs[30]) 555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.sc_regs[2]) 556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Convert the value in uc_mcontext.rax into a SysRes. */ \ 558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(mk_SysRes_mips64_linux)((uc)->uc_mcontext.sc_regs[2], \ 559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (uc)->uc_mcontext.sc_regs[3], \ 560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (uc)->uc_mcontext.sc_regs[7]) 561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { (srP)->r_pc = (uc)->uc_mcontext.sc_pc; \ 564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->r_sp = (uc)->uc_mcontext.sc_regs[29]; \ 565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->misc.MIPS64.r30 = (uc)->uc_mcontext.sc_regs[30]; \ 566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->misc.MIPS64.r31 = (uc)->uc_mcontext.sc_regs[31]; \ 567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (srP)->misc.MIPS64.r28 = (uc)->uc_mcontext.sc_regs[28]; \ 568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Macros for pulling stuff out of siginfos ------ */ 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These macros allow use of uniform names when working with 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both the Linux and AIX vki definitions. */ 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_addr _sifields._sigfault._addr 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_pid _sifields._kill._pid 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_addr si_addr 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_pid si_pid 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HIGH LEVEL STUFF TO DO WITH SIGNALS: POLICY (MOSTLY) 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Signal state for this process. 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Base-ment of these arrays[_VKI_NSIG]. 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valid signal numbers are 1 .. _VKI_NSIG inclusive. 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Rather than subtracting 1 for indexing these arrays, which 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is tedious and error-prone, they are simply dimensioned 1 larger, 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and entry [0] is not used. 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----------------------------------------------------- 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Static client signal state (SCSS). This is the state 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the client thinks it has the kernel in. 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS records verbatim the client's settings. These 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are mashed around only when SKSS is calculated from it. 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -------------------------------------------------- */ 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* scss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN or ptr to 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client's handler */ 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt scss_flags; 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t scss_mask; 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* scss_restorer; /* where sigreturn goes */ 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* scss_sa_tramp; /* sa_tramp setting, Darwin only */ 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* re _restorer and _sa_tramp, we merely record the values 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown supplied when the client does 'sigaction' and give them back 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when requested. Otherwise they are simply ignored. */ 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS_Per_Signal; 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* per-signal info */ 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS_Per_Signal scss_per_sig[1+_VKI_NSIG]; 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Additional elements to SCSS not stored here: 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - for each thread, the thread's blocking mask 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - for each thread in WaitSIG, the set of waited-on sigs 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS; 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SCSS scss; 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----------------------------------------------------- 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Static kernel signal state (SKSS). This is the state 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that we have the kernel in. It is computed from SCSS. 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -------------------------------------------------- */ 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let's do: 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigprocmask assigns to all thread masks 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so that at least everything is always consistent 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Flags: 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_SIGINFO -- we always set it, and honour it for the client 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_NOCLDSTOP -- passed to kernel 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_ONESHOT or SA_RESETHAND -- pass through 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_RESTART -- we observe this but set our handlers to always restart 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_NOMASK or SA_NODEFER -- we observe this, but our handlers block everything 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_ONSTACK -- pass through 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_NOCLDWAIT -- pass through 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* skss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or ptr to our handler */ 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt skss_flags; 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There is no skss_mask, since we know that we will always ask 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for all signals to be blocked in our sighandlers. */ 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also there is no skss_restorer. */ 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS_Per_Signal; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS_Per_Signal skss_per_sig[1+_VKI_NSIG]; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SKSS skss; 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* returns True if signal is to be ignored. 683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov To check this, possibly call gdbserver with tid. */ 684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool is_sig_ign(Int sigNo, ThreadId tid) 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo >= 1 && sigNo <= _VKI_NSIG); 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_IGN 689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || !VG_(gdbserver_report_signal) (sigNo, tid); 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Compute the SKSS required by the current SCSS. 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pp_SKSS ( void ) 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sig; 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n\nSKSS:\n"); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sig = 1; sig <= _VKI_NSIG; sig++) { 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sig %d: handler %p, flags 0x%x\n", sig, 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss.skss_per_sig[sig].skss_handler, 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss.skss_per_sig[sig].skss_flags ); 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the core, clever bit. Computation is as follows: 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For each signal 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler = if client has a handler, then our handler 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if client is DFL, then our handler as well 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else (client must be IGN) 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then hander is IGN 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid calculate_SKSS_from_SCSS ( SKSS* dst ) 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sig; 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt scss_flags; 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt skss_flags; 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sig = 1; sig <= _VKI_NSIG; sig++) { 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *skss_handler; 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *scss_handler; 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss_handler = scss.scss_per_sig[sig].scss_handler; 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss_flags = scss.scss_per_sig[sig].scss_flags; 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sig) { 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTRAP: 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For these, we always want to catch them and report, even 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if the client code doesn't. */ 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = sync_signalhandler; 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCONT: 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Let the kernel handle SIGCONT unless the client is actually 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown catching it. */ 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCHLD: 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGWINCH: 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGURG: 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For signals which are have a default action of Ignore, 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only set a handler if the client has set a signal handler. 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Otherwise the kernel will interrupt a syscall which 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wouldn't have otherwise been interrupted. */ 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (scss.scss_per_sig[sig].scss_handler == VKI_SIG_DFL) 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = VKI_SIG_DFL; 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (scss.scss_per_sig[sig].scss_handler == VKI_SIG_IGN) 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = VKI_SIG_IGN; 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = async_signalhandler; 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VKI_SIGVG* are runtime variables, so we can't make them 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // cases in the switch, so we handle them in the 'default' case. 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sig == VG_SIGVGKILL) 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = sigvgkill_handler; 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (scss_handler == VKI_SIG_IGN) 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = VKI_SIG_IGN; 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = async_signalhandler; 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Flags */ 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags = 0; 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_NOCLDSTOP, SA_NOCLDWAIT: pass to kernel */ 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= scss_flags & (VKI_SA_NOCLDSTOP | VKI_SA_NOCLDWAIT); 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_ONESHOT: ignore client setting */ 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_RESTART: ignore client setting and always set it for us. 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Though we never rely on the kernel to restart a 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, we observe whether it wanted to restart the syscall 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or not, which is needed by 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) */ 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= VKI_SA_RESTART; 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_NOMASK: ignore it */ 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_ONSTACK: client setting is irrelevant here */ 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't set a signal stack, so ignore */ 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* always ask for SA_SIGINFO */ 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= VKI_SA_SIGINFO; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* use our own restorer */ 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= VKI_SA_RESTORER; 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create SKSS entry for this signal. */ 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP) 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->skss_per_sig[sig].skss_handler = skss_handler; 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->skss_per_sig[sig].skss_handler = VKI_SIG_DFL; 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->skss_per_sig[sig].skss_flags = skss_flags; 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sanity checks. */ 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(dst->skss_per_sig[VKI_SIGKILL].skss_handler == VKI_SIG_DFL); 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(dst->skss_per_sig[VKI_SIGSTOP].skss_handler == VKI_SIG_DFL); 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pp_SKSS(); 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown After a possible SCSS change, update SKSS and the kernel itself. 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We need two levels of macro-expansion here to convert __NR_rt_sigreturn 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to a number before converting it to a string... sigh. 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern void my_sigreturn(void); 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " movl $" #name ", %eax\n" \ 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " int $0x80\n" \ 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " movq $" #name ", %rax\n" \ 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " syscall\n" \ 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " li 0, " #name "\n" \ 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " sc\n" \ 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".align 2\n" \ 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".globl my_sigreturn\n" \ 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".section \".opd\",\"aw\"\n" \ 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".align 3\n" \ 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".quad .my_sigreturn,.TOC.@tocbase,0\n" \ 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" \ 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".type .my_sigreturn,@function\n" \ 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".globl .my_sigreturn\n" \ 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".my_sigreturn:\n" \ 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " li 0, " #name "\n" \ 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " sc\n" 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n\t" \ 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " mov r7, #" #name "\n\t" \ 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " svc 0x00000000\n" \ 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_arm64_linux) 879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define _MY_SIGRETURN(name) \ 880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ".text\n" \ 881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ".globl my_sigreturn\n" \ 882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "my_sigreturn:\n\t" \ 883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov " mov x8, #" #name "\n\t" \ 884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov " svc 0x0\n" \ 885436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ".previous\n" 886436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "movl $" VG_STRINGIFY(__NR_DARWIN_FAKE_SIGRETURN) ",%eax\n" \ 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "int $0x80" 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: todo 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ud2\n" 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define _MY_SIGRETURN(name) \ 905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ".text\n" \ 906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".globl my_sigreturn\n" \ 907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "my_sigreturn:\n" \ 908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov " svc " #name "\n" \ 909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ".previous\n" 910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux) 912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define _MY_SIGRETURN(name) \ 913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".text\n" \ 914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "my_sigreturn:\n" \ 915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " li $2, " #name "\n" /* apparently $2 is v0 */ \ 916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " syscall\n" \ 917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ".previous\n" 918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_mips64_linux) 920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define _MY_SIGRETURN(name) \ 921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ".text\n" \ 922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "my_sigreturn:\n" \ 923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov " li $2, " #name "\n" \ 924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov " syscall\n" \ 925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ".previous\n" 926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MY_SIGRETURN(name) _MY_SIGRETURN(name) 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm( 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MY_SIGRETURN(__NR_rt_sigreturn) 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_SCSS_change ( Bool force_update ) 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int res, sig; 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS skss_old; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t ksa; 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t ksa_old; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Remember old SKSS and calculate new one. */ 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_old = skss; 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown calculate_SKSS_from_SCSS ( &skss ); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compare the new SKSS entries vs the old ones, and update kernel 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown where they differ. */ 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sig = 1; sig <= VG_(max_signal); sig++) { 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Trying to do anything with SIGKILL is pointless; just ignore 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. */ 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP) 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!force_update) { 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((skss_old.skss_per_sig[sig].skss_handler 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss.skss_per_sig[sig].skss_handler) 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (skss_old.skss_per_sig[sig].skss_flags 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss.skss_per_sig[sig].skss_flags)) 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no difference */ 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if !defined(VGP_ppc32_linux) && \ 969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ 970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng !defined(VGP_mips32_linux) 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ksa.sa_restorer = my_sigreturn; 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Re above ifdef (also the assertion below), PaulM says: 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The sa_restorer field is not used at all on ppc. Glibc 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown converts the sigaction you give it into a kernel sigaction, 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but it doesn't put anything in the sa_restorer field. 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* block all signals in handler */ 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)( &ksa.sa_mask ); 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)( &ksa.sa_mask, VKI_SIGKILL ); 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)( &ksa.sa_mask, VKI_SIGSTOP ); 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2) 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("setting ksig %d to: hdlr %p, flags 0x%lx, " 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "mask(msb..lsb) 0x%llx 0x%llx\n", 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sig, ksa.ksa_handler, 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)ksa.sa_flags, 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VKI_NSIG_WORDS > 1 ? (ULong)ksa.sa_mask.sig[1] : 0, 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)ksa.sa_mask.sig[0]); 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(sigaction)( sig, &ksa, &ksa_old ); 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(res == 0); 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Since we got the old sigaction more or less for free, might 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as well extract the maximum sanity-check value from it. */ 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!force_update) { 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ksa_old.ksa_handler 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss_old.skss_per_sig[sig].skss_handler); 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ksa_old.sa_flags 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss_old.skss_per_sig[sig].skss_flags); 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if !defined(VGP_ppc32_linux) && \ 1003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ 1004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) 1005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(ksa_old.sa_restorer == my_sigreturn); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL ); 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGSTOP ); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(isfullsigset)( &ksa_old.sa_mask )); 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Update/query SCSS in accordance with client requests. 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Logic for this alt-stack stuff copied directly from do_sigaltstack 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in kernel/signal.[ch] */ 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* True if we are on the alternate signal stack. */ 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool on_sig_stack ( ThreadId tid, Addr m_SP ) 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (m_SP - (Addr)tst->altstack.ss_sp < (Addr)tst->altstack.ss_size); 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int sas_ss_flags ( ThreadId tid, Addr m_SP ) 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (tst->altstack.ss_size == 0 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? VKI_SS_DISABLE 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : on_sig_stack(tid, m_SP) ? VKI_SS_ONSTACK : 0); 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss ) 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr m_SP; 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_SP = VG_(get_SP)(tid); 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sys_sigaltstack: tid %d, " 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ss %p{%p,sz=%llu,flags=0x%llx}, oss %p (current SP %p)\n", 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, (void*)ss, 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ss ? ss->ss_sp : 0, 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)(ss ? ss->ss_size : 0), 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)(ss ? ss->ss_flags : 0), 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)oss, (void*)m_SP); 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (oss != NULL) { 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oss->ss_sp = VG_(threads)[tid].altstack.ss_sp; 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oss->ss_size = VG_(threads)[tid].altstack.ss_size; 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oss->ss_flags = VG_(threads)[tid].altstack.ss_flags 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | sas_ss_flags(tid, m_SP); 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss != NULL) { 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (on_sig_stack(tid, VG_(get_SP)(tid))) { 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EPERM ); 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss->ss_flags != VKI_SS_DISABLE 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ss->ss_flags != VKI_SS_ONSTACK 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ss->ss_flags != 0) { 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss->ss_flags == VKI_SS_DISABLE) { 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE; 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss->ss_size < VKI_MINSIGSTKSZ) { 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_ENOMEM ); 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_sp = ss->ss_sp; 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_size = ss->ss_size; 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_flags = 0; 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( 0 ); 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_sys_sigaction) ( Int signo, 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigaction_toK_t* new_act, 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t* old_act ) 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sys_sigaction: sigNo %d, " 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "new %#lx, old %#lx, new flags 0x%llx\n", 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signo, (UWord)new_act, (UWord)old_act, 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)(new_act ? new_act->sa_flags : 0)); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Rule out various error conditions. The aim is to ensure that if 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when the call is passed to the kernel it will definitely 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown succeed. */ 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Reject out-of-range signal numbers. */ 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (signo < 1 || signo > VG_(max_signal)) goto bad_signo; 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* don't let them use our signals */ 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (signo > VG_SIGVGRTUSERMAX) 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && new_act 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && !(new_act->ksa_handler == VKI_SIG_DFL 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || new_act->ksa_handler == VKI_SIG_IGN) ) 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad_signo_reserved; 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Reject attempts to set a handler (or set ignore) for SIGKILL. */ 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (signo == VKI_SIGKILL || signo == VKI_SIGSTOP) 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && new_act 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && new_act->ksa_handler != VKI_SIG_DFL) 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad_sigkill_or_sigstop; 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the client supplied non-NULL old_act, copy the relevant SCSS 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entry into it. */ 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old_act) { 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->ksa_handler = scss.scss_per_sig[signo].scss_handler; 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->sa_flags = scss.scss_per_sig[signo].scss_flags; 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->sa_mask = scss.scss_per_sig[signo].scss_mask; 1124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer; 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* And now copy new SCSS entry from new_act. */ 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_act) { 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_handler = new_act->ksa_handler; 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_flags = new_act->sa_flags; 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_mask = new_act->sa_mask; 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_restorer = NULL; 1136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer; 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_sa_tramp = NULL; 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_sa_tramp = new_act->sa_tramp; 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGKILL); 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGSTOP); 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All happy bunnies ... */ 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_act) { 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_SCSS_change( False /* lazy update */ ); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( 0 ); 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad_signo: 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(showing_core_errors)() && !VG_(clo_xml)) { 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: bad signal number %d in sigaction()\n", signo); 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad_signo_reserved: 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(showing_core_errors)() && !VG_(clo_xml)) { 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: ignored attempt to set %s handler in sigaction();\n", 1164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(signame)(signo)); 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" the %s signal is used internally by Valgrind\n", 1166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(signame)(signo)); 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad_sigkill_or_sigstop: 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(showing_core_errors)() && !VG_(clo_xml)) { 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: ignored attempt to set %s handler in sigaction();\n", 1173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(signame)(signo)); 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" the %s signal is uncatchable\n", 1175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(signame)(signo)); 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_sigprocmask_bitops ( Int vki_how, 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* orig_set, 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* modifier ) 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (vki_how) { 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_BLOCK: 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset_from_set)( orig_set, modifier ); 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_UNBLOCK: 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset_from_set)( orig_set, modifier ); 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_SETMASK: 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *orig_set = *modifier; 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("do_sigprocmask_bitops"); 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* format_sigset ( const vki_sigset_t* set ) 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static HChar buf[128]; 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int w; 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(buf, ""); 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (w = _VKI_NSIG_WORDS - 1; w >= 0; w--) 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if _VKI_NSIG_BPW == 32 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf + VG_(strlen)(buf), "%08llx", 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set ? (ULong)set->sig[w] : 0); 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif _VKI_NSIG_BPW == 64 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf + VG_(strlen)(buf), "%16llx", 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set ? (ULong)set->sig[w] : 0); 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported value for _VKI_NSIG_BPW" 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This updates the thread's signal mask. There's no such thing as a 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process-wide signal mask. 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that the thread signal masks are an implicit part of SCSS, 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which is why this routine is allowed to mess with them. 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_setmask ( ThreadId tid, 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int how, 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* newset, 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* oldset ) 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("do_setmask: tid = %d how = %d (%s), newset = %p (%s)\n", 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, how, 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown how==VKI_SIG_BLOCK ? "SIG_BLOCK" : ( 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown how==VKI_SIG_UNBLOCK ? "SIG_UNBLOCK" : ( 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown how==VKI_SIG_SETMASK ? "SIG_SETMASK" : "???")), 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newset, newset ? format_sigset(newset) : "NULL" ); 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Just do this thread. */ 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (oldset) { 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *oldset = VG_(threads)[tid].sig_mask; 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("\toldset=%p %s\n", oldset, format_sigset(oldset)); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newset) { 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_sigprocmask_bitops (how, &VG_(threads)[tid].sig_mask, newset ); 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGKILL); 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGSTOP); 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask; 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_sys_sigprocmask) ( ThreadId tid, 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int how, 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* set, 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* oldset ) 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(how) { 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_BLOCK: 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_UNBLOCK: 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_SETMASK: 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_setmask ( tid, how, set, oldset ); 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( 0 ); 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sigprocmask: unknown 'how' field %d\n", how); 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Handy utilities to block/restore all host signals. 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Block all host signals, dumping the old mask in *saved_mask. */ 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void block_all_host_signals ( /* OUT */ vki_sigset_t* saved_mask ) 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t block_procmask; 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&block_procmask); 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigprocmask) 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VKI_SIG_SETMASK, &block_procmask, saved_mask); 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret == 0); 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Restore the blocking mask using the supplied saved one. */ 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void restore_all_host_signals ( /* IN */ vki_sigset_t* saved_mask ) 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigprocmask)(VKI_SIG_SETMASK, saved_mask, NULL); 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret == 0); 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(clear_out_queued_signals)( ThreadId tid, vki_sigset_t* saved_mask ) 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals(saved_mask); 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].sig_queue != NULL) { 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)(VG_AR_CORE, VG_(threads)[tid].sig_queue); 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].sig_queue = NULL; 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_all_host_signals(saved_mask); 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The signal simulation proper. A simplified version of what the 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux kernel does. 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set up a stack frame (VgSigContext) for the client's signal 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler. */ 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid push_signal_frame ( ThreadId tid, const vki_siginfo_t *siginfo, 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct vki_ucontext *uc ) 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr esp_top_of_frame; 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = siginfo->si_signo; 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal)); 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = & VG_(threads)[tid]; 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("push_signal_frame (thread %d): signal %d\n", tid, sigNo); 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)(tid, 10); 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (/* this signal asked to run on an alt stack */ 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONSTACK ) 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && /* there is a defined and enabled alt stack, which we're not 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown already using. Logic from get_sigframe in 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch/i386/kernel/signal.c. */ 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sas_ss_flags(tid, VG_(get_SP)(tid)) == 0 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) { 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown esp_top_of_frame 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (Addr)(tst->altstack.ss_sp) + tst->altstack.ss_size; 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("delivering signal %d (%s) to thread %d: " 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "on ALT STACK (%p-%p; %ld bytes)\n", 1356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sigNo, VG_(signame)(sigNo), tid, tst->altstack.ss_sp, 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UChar *)tst->altstack.ss_sp + tst->altstack.ss_size, 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Word)tst->altstack.ss_size ); 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal delivery to tools */ 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/True ); 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown esp_top_of_frame = VG_(get_SP)(tid) - VG_STACK_REDZONE_SZB; 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal delivery to tools */ 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/False ); 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN); 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL); 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This may fail if the client stack is busted; if that happens, 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the whole process will exit rather than simply calling the 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal handler. */ 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigframe_create) (tid, esp_top_of_frame, siginfo, uc, 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[sigNo].scss_handler, 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[sigNo].scss_flags, 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &tst->sig_mask, 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[sigNo].scss_restorer); 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst HChar *VG_(signame)(Int sigNo) 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static HChar buf[20]; 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sigNo) { 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGHUP: return "SIGHUP"; 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGINT: return "SIGINT"; 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGQUIT: return "SIGQUIT"; 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: return "SIGILL"; 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTRAP: return "SIGTRAP"; 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGABRT: return "SIGABRT"; 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: return "SIGBUS"; 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: return "SIGFPE"; 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGKILL: return "SIGKILL"; 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR1: return "SIGUSR1"; 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR2: return "SIGUSR2"; 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: return "SIGSEGV"; 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPIPE: return "SIGPIPE"; 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGALRM: return "SIGALRM"; 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTERM: return "SIGTERM"; 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGSTKFLT) 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSTKFLT: return "SIGSTKFLT"; 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCHLD: return "SIGCHLD"; 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCONT: return "SIGCONT"; 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSTOP: return "SIGSTOP"; 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTSTP: return "SIGTSTP"; 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTTIN: return "SIGTTIN"; 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTTOU: return "SIGTTOU"; 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGURG: return "SIGURG"; 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXCPU: return "SIGXCPU"; 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXFSZ: return "SIGXFSZ"; 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGVTALRM: return "SIGVTALRM"; 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPROF: return "SIGPROF"; 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGWINCH: return "SIGWINCH"; 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGIO: return "SIGIO"; 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGPWR) 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPWR: return "SIGPWR"; 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGUNUSED) 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUNUSED: return "SIGUNUSED"; 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGRTMIN ... VKI_SIGRTMAX: 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "SIGRT%d", sigNo-VKI_SIGRTMIN); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "SIG%d", sigNo); 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Hit ourselves with a signal using the default handler */ 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(kill_self)(Int sigNo) 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int r; 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask, origmask; 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t sa, origsa2; 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t origsa; 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.ksa_handler = VKI_SIG_DFL; 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_flags = 0; 1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_restorer = 0; 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&sa.sa_mask); 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaction)(sigNo, &sa, &origsa); 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&mask); 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)(&mask, sigNo); 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_UNBLOCK, &mask, &origmask); 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = VG_(kill)(VG_(getpid)(), sigNo); 1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This sometimes fails with EPERM on Darwin. I don't know why. */ 1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(r == 0); 1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(convert_sigaction_fromK_to_toK)( &origsa, &origsa2 ); 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaction)(sigNo, &origsa2, NULL); 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &origmask, NULL); 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The si_code describes where the signal came from. Some come from the 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// kernel, eg.: seg faults, illegal opcodes. Some come from the user, eg.: 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// from kill() (SI_USER), or timer_settime() (SI_TIMER), or an async I/O 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// request (SI_ASYNCIO). There's lots of implementation-defined leeway in 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// POSIX, but the user vs. kernal distinction is what we want here. We also 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pass in some other details that can help when si_code is unreliable. 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_signal_from_kernel(ThreadId tid, int signum, int si_code) 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // On Linux, SI_USER is zero, negative values are from the user, positive 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // values are from the kernel. There are SI_FROMUSER and SI_FROMKERNEL 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // macros but we don't use them here because other platforms don't have 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // them. 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ( si_code > VKI_SI_USER ? True : False ); 1485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGO_darwin) 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // On Darwin 9.6.0, the si_code is completely unreliable. It should be the 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case that 0 means "user", and >0 means "kernel". But: 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGSEGV, it seems quite reliable. 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGBUS, it's always 2. 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGFPE, it's often 0, even for kernel ones (eg. 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // div-by-integer-zero always gives zero). 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGILL, it's unclear. 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGTRAP, it's always 1. 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // You can see the "NOTIMP" (not implemented) status of a number of the 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // sub-cases in sys/signal.h. Hopefully future versions of Darwin will 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // get this right. 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If we're blocked waiting on a syscall, it must be a user signal, because 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the kernel won't generate sync signals within syscalls. 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_WaitSys) { 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If it's a SIGSEGV, use the proper condition, since it's fairly reliable. 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (SIGSEGV == signum) { 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ( si_code > 0 ? True : False ); 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If it's anything else, assume it's kernel-generated. Reason being that 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // kernel-generated sync signals are more common, and it's probable that 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // misdiagnosing a user signal as a kernel signal is better than the 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // opposite. 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# error Unknown OS 1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is an arbitrary si_code that we only use internally. It corresponds 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to the value SI_KERNEL on Linux, but that's not really of any significance 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// as far as I can determine. 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VKI_SEGV_MADE_UP_GPF 0x80 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Perform the default action of a signal. If the signal is fatal, it 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown marks all threads as needing to exit, but it doesn't actually kill 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the process or thread. 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If we're not being quiet, then print out some more detail about 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fatal signals (esp. core dumping signals). 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void default_action(const vki_siginfo_t *info, ThreadId tid) 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = info->si_signo; 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool terminate = False; /* kills process */ 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool core = False; /* kills process w/ core */ 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_rlimit corelim; 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool could_core; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sigNo) { 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGQUIT: /* core */ 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: /* core */ 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGABRT: /* core */ 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: /* core */ 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: /* core */ 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: /* core */ 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTRAP: /* core */ 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXCPU: /* core */ 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXFSZ: /* core */ 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminate = True; 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core = True; 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGHUP: /* term */ 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGINT: /* term */ 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGKILL: /* term - we won't see this */ 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPIPE: /* term */ 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGALRM: /* term */ 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTERM: /* term */ 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR1: /* term */ 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR2: /* term */ 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGIO: /* term */ 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGPWR) 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPWR: /* term */ 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSYS: /* term */ 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPROF: /* term */ 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGVTALRM: /* term */ 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGRTMIN ... VKI_SIGRTMAX: /* term */ 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminate = True; 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!core || (core && terminate)); 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("delivering %d (code %d) to default handler; action: %s%s\n", 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, info->si_code, terminate ? "terminate" : "ignore", 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core ? "+core" : ""); 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!terminate) 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* nothing to do */ 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown could_core = core; 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (core) { 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If they set the core-size limit to zero, don't generate a 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core file */ 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getrlimit)(VKI_RLIMIT_CORE, &corelim); 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (corelim.rlim_cur == 0) 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core = False; 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (VG_(clo_verbosity) > 1 || 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (could_core && is_signal_from_kernel(tid, sigNo, info->si_code)) 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) && 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !VG_(clo_xml) ) { 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Process terminating with default action of signal %d (%s)%s\n", 1608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sigNo, VG_(signame)(sigNo), core ? ": dumping core" : ""); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Be helpful - decode some more details about this fault */ 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_signal_from_kernel(tid, sigNo, info->si_code)) { 1612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar *event = NULL; 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool haveaddr = True; 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sigNo) { 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(info->si_code) { 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEGV_MAPERR: event = "Access not within mapped region"; 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEGV_ACCERR: event = "Bad permissions for mapped region"; 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEGV_MADE_UP_GPF: 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* General Protection Fault: The CPU/kernel 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isn't telling us anything useful, but this 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is commonly the result of exceeding a 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment limit. */ 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown event = "General Protection Fault"; 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown haveaddr = False; 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[110]; 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_show_nsegments)(0,"post segfault"); 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "/bin/cat /proc/%d/maps", VG_(getpid)()); 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(system)(buf); 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(info->si_code) { 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLOPC: event = "Illegal opcode"; break; 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLOPN: event = "Illegal operand"; break; 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLADR: event = "Illegal addressing mode"; break; 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLTRP: event = "Illegal trap"; break; 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_PRVOPC: event = "Privileged opcode"; break; 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_PRVREG: event = "Privileged register"; break; 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_COPROC: event = "Coprocessor error"; break; 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_BADSTK: event = "Internal stack error"; break; 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (info->si_code) { 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_INTDIV: event = "Integer divide by zero"; break; 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_INTOVF: event = "Integer overflow"; break; 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTDIV: event = "FP divide by zero"; break; 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTOVF: event = "FP overflow"; break; 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTUND: event = "FP underflow"; break; 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTRES: event = "FP inexact"; break; 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTINV: event = "FP invalid operation"; break; 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTSUB: event = "FP subscript out of range"; break; 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (info->si_code) { 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_BUS_ADRALN: event = "Invalid address alignment"; break; 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_BUS_ADRERR: event = "Non-existent physical address"; break; 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_BUS_OBJERR: event = "Hardware error"; break; 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (sigNo) */ 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (event != NULL) { 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (haveaddr) 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" %s at address %p\n", 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown event, info->VKI_SIGINFO_si_addr); 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" %s\n", event); 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print a stack trace. Be cautious if the thread's SP is in an 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obviously stupid place (not mapped readable) that would 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown likely cause a segfault. */ 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_valid_tid)(tid)) { 1688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Word first_ip_delta = 0; 1689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGO_linux) 1690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Make sure that the address stored in the stack pointer is 1691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng located in a mapped page. That is not necessarily so. E.g. 1692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng consider the scenario where the stack pointer was decreased 1693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng and now has a value that is just below the end of a page that has 1694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng not been mapped yet. In that case VG_(am_is_valid_for_client) 1695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng will consider the address of the stack pointer invalid and that 1696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng would cause a back-trace of depth 1 to be printed, instead of a 1697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng full back-trace. */ 1698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (tid == 1) { // main thread 1699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr esp = VG_(get_SP)(tid); 1700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr base = VG_PGROUNDDN(esp - VG_STACK_REDZONE_SZB); 1701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(extend_stack)(base, VG_(threads)[tid].client_stack_szB)) { 1702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(clo_trace_signals)) 1703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(dmsg)(" -> extended stack base to %#lx\n", 1704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_PGROUNDDN(esp)); 1705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif 1708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGA_s390x) 1709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (sigNo == VKI_SIGILL) { 1710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The guest instruction address has been adjusted earlier to 1711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng point to the insn following the one that could not be decoded. 1712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng When printing the back-trace here we need to undo that 1713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng adjustment so the first line in the back-trace reports the 1714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng correct address. */ 1715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr addr = (Addr)info->VKI_SIGINFO_si_addr; 1716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UChar byte = ((UChar *)addr)[0]; 1717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int insn_length = ((((byte >> 6) + 1) >> 1) + 1) << 1; 1718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng first_ip_delta = -insn_length; 1720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* ec = VG_(am_is_valid_for_client) 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_(get_SP)(tid), sizeof(Addr), VKI_PROT_READ) 1724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ? VG_(record_ExeContext)( tid, first_ip_delta ) 1725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng : VG_(record_depth_1_ExeContext)( tid, 1726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng first_ip_delta ); 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ec); 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( ec ); 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sigNo == VKI_SIGSEGV 1731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && is_signal_from_kernel(tid, sigNo, info->si_code) 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && info->si_code == VKI_SEGV_MAPERR) { 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" If you believe this happened as a result of a stack\n" ); 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" overflow in your program's main thread (unlikely but\n"); 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" possible), you can try to increase the size of the\n" ); 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" main thread stack using the --main-stacksize= flag.\n" ); 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: assumes main ThreadId == 1 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_valid_tid)(1)) { 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 1740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov " The main thread stack size used in this run was %lu.\n", 1741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(threads)[1].client_stack_szB); 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) )) { 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(start_debugger)( tid ); 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (core) { 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const static struct vki_rlimit zero = { 0, 0 }; 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(make_coredump)(tid, info, corelim.rlim_cur); 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure we don't get a confusing kernel-generated 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown coredump when we finally exit */ 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(setrlimit)(VKI_RLIMIT_CORE, &zero); 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stash fatal signal in main thread */ 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // what's this for? 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(threads)[VG_(master_tid)].os_state.fatalsig = sigNo; 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* everyone dies */ 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(nuke_all_threads_except)(tid, VgSrc_FatalSig); 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].exitreason = VgSrc_FatalSig; 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].os_state.fatalsig = sigNo; 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This does the business of delivering a signal to a thread. It may 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be called from either a real signal handler, or from normal code to 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cause the thread to enter the signal handler. 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This updates the thread state, but it does not set it to be 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Runnable. 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deliver_signal ( ThreadId tid, const vki_siginfo_t *info, 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct vki_ucontext *uc ) 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = info->si_signo; 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS_Per_Signal *handler = &scss.scss_per_sig[sigNo]; 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *handler_fn; 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("delivering signal %d (%s):%d to thread %d\n", 1788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sigNo, VG_(signame)(sigNo), info->si_code, tid ); 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sigNo == VG_SIGVGKILL) { 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this is a SIGVGKILL, we're expecting it to interrupt any 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blocked syscall. It doesn't matter whether the VCPU state is 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set to restart or not, because we don't expect it will 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown execute any more client instructions. */ 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_exiting)(tid)); 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the client specifies SIG_IGN, treat it as SIG_DFL. 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If deliver_signal() is being called on a thread, we want 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the signal to get through no matter what; if they're ignoring 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it, then we do this override (this is so we can send it SIGSEGV, 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown etc). */ 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler_fn = handler->scss_handler; 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (handler_fn == VKI_SIG_IGN) 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler_fn = VKI_SIG_DFL; 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(handler_fn != VKI_SIG_IGN); 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (handler_fn == VKI_SIG_DFL) { 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default_action(info, tid); 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create a signal delivery frame, and set the client's %ESP and 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %EIP so that when execution continues, we will enter the 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal handler with the frame on top of the client's stack, 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as it expects. 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Signal delivery can fail if the client stack is too small or 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown missing, and we can't push the frame. If that happens, 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push_signal_frame will cause the whole process to exit when 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we next hit the scheduler. 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push_signal_frame ( tid, info, uc ); 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (handler->scss_flags & VKI_SA_ONESHOT) { 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do the ONESHOT thing. */ 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler->scss_handler = VKI_SIG_DFL; 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_SCSS_change( False /* lazy update */ ); 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At this point: 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_mask is the current signal mask 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tmp_sig_mask is the same as sig_mask, unless we're in sigsuspend 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler->scss_mask is the mask set by the handler 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Handler gets a mask of tmp_sig_mask|handler_mask|signo 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_mask = tst->tmp_sig_mask; 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(handler->scss_flags & VKI_SA_NOMASK)) { 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset_from_set)(&tst->sig_mask, &handler->scss_mask); 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)(&tst->sig_mask, sigNo); 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tmp_sig_mask = tst->sig_mask; 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Thread state is ready to go - just add Runnable */ 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void resume_scheduler(ThreadId tid) 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->os_state.lwpid == VG_(gettid)()); 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tst->sched_jmpbuf_valid) { 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Can't continue; must longjmp back to the scheduler and thus 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enter the sighandler immediately. */ 1862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_MINIMAL_LONGJMP(tst->sched_jmpbuf); 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void synth_fault_common(ThreadId tid, Addr addr, Int si_code) 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGSEGV; 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = si_code; 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.VKI_SIGINFO_si_addr = (void*)addr; 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Even if gdbserver indicates to ignore the signal, we must deliver it. 1878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov So ignore the return value of VG_(gdbserver_report_signal). */ 1879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (void) VG_(gdbserver_report_signal) (VKI_SIGSEGV, tid); 1880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If they're trying to block the signal, force it to be delivered */ 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigismember)(&VG_(threads)[tid].sig_mask, VKI_SIGSEGV)) 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(VKI_SIGSEGV); 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, &info, NULL); 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesize a fault where the address is OK, but the page 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// permissions are bad. 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_fault_perms)(ThreadId tid, Addr addr) 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_fault_common(tid, addr, VKI_SEGV_ACCERR); 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesize a fault where the address there's nothing mapped at the address. 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_fault_mapping)(ThreadId tid, Addr addr) 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_fault_common(tid, addr, VKI_SEGV_MAPERR); 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesize a misc memory fault. 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_fault)(ThreadId tid) 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_fault_common(tid, 0, VKI_SEGV_MADE_UP_GPF); 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesise a SIGILL. 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_sigill)(ThreadId tid, Addr addr) 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGILL; 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = VKI_ILL_ILLOPC; /* jrs: no idea what this should be */ 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.VKI_SIGINFO_si_addr = (void*)addr; 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (VKI_SIGILL, tid)) { 1920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, &info, NULL); 1922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesise a SIGBUS. 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_sigbus)(ThreadId tid) 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGBUS; 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There are several meanings to SIGBUS (as per POSIX, presumably), 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the most widely understood is "invalid address alignment", 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so let's use that. */ 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = VKI_BUS_ADRALN; 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we knew the invalid address in question, we could put it 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in .si_addr. Oh well. */ 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* info.VKI_SIGINFO_si_addr = (void*)addr; */ 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (VKI_SIGBUS, tid)) { 1945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, &info, NULL); 1947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesise a SIGTRAP. 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_sigtrap)(ThreadId tid) 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext uc; 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32 mc; 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext64 mc; 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&uc, 0, sizeof(uc)); 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGTRAP; 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */ 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext.trapno = 3; /* tjh: this is the x86 trap number 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for a breakpoint trap... */ 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext.err = 0; /* tjh: no error code for x86 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown breakpoint trap... */ 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* the same thing, but using Darwin field/struct names */ 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&mc, 0, sizeof(mc)); 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext = &mc; 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext->__es.__trapno = 3; 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext->__es.__err = 0; 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* fixs390: do we need to do anything here for s390 ? */ 1984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (VKI_SIGTRAP, tid)) { 1985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, &info, &uc); 1987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Synthesise a SIGFPE. 1993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(synth_sigfpe)(ThreadId tid, UInt code) 1994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 1995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Only tested on mips32 and mips64 1996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if !defined(VGA_mips32) && !defined(VGA_mips64) 1997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(0); 1998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else 1999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vki_siginfo_t info; 2000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct vki_ucontext uc; 2001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 2003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memset)(&info, 0, sizeof(info)); 2005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memset)(&uc, 0, sizeof(uc)); 2006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov info.si_signo = VKI_SIGFPE; 2007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov info.si_code = code; 2008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(gdbserver_report_signal) (VKI_SIGFPE, tid)) { 2010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov resume_scheduler(tid); 2011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov deliver_signal(tid, &info, &uc); 2012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 2014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov resume_scheduler(tid); 2015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif 2016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a signal pending for a thread, for later delivery. 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals) will arrange for it to be delivered at the right 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown time. 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid==0 means add it to the process-wide queue, and not sent it to a 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specific thread. 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid queue_signal(ThreadId tid, const vki_siginfo_t *si) 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst; 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SigQueue *sq; 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t savedmask; 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Protect the signal queue against async deliveries */ 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals(&savedmask); 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tst->sig_queue == NULL) { 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_queue = VG_(arena_malloc)(VG_AR_CORE, "signals.qs.1", 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(*tst->sig_queue)); 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(tst->sig_queue, 0, sizeof(*tst->sig_queue)); 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq = tst->sig_queue; 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Queueing signal %d (idx %d) to thread %d\n", 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown si->si_signo, sq->next, tid); 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add signal to the queue. If the queue gets overrun, then old 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queued signals may get lost. 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XXX We should also keep a sigset of pending signals, so that at 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown least a non-siginfo signal gets deliviered. 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sq->sigs[sq->next].si_signo != 0) 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Signal %d being dropped from thread %d's queue\n", 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[sq->next].si_signo, tid); 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[sq->next] = *si; 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->next = (sq->next+1) % N_QUEUED_SIGNALS; 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_all_host_signals(&savedmask); 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns the next queued signal for thread tid which is in "set". 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid==0 means process-wide signal. Set si_signo to 0 when the 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal has been delivered. 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Must be called with all signals blocked, to protect against async 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliveries. 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vki_siginfo_t *next_queued(ThreadId tid, const vki_sigset_t *set) 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SigQueue *sq; 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int idx; 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t *ret = NULL; 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq = tst->sig_queue; 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sq == NULL) 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown idx = sq->next; 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("idx=%d si_signo=%d inset=%d\n", idx, 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[idx].si_signo, 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigismember)(set, sq->sigs[idx].si_signo)); 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sq->sigs[idx].si_signo != 0 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(sigismember)(set, sq->sigs[idx].si_signo)) { 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Returning queued signal %d (idx %d) for thread %d\n", 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[idx].si_signo, idx, tid); 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = &sq->sigs[idx]; 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown idx = (idx + 1) % N_QUEUED_SIGNALS; 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while(idx != sq->next); 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out: 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sanitize_si_code(int si_code) 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The linux kernel uses the top 16 bits of si_code for it's own 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown use and only exports the bottom 16 bits to user space - at least 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that is the theory, but it turns out that there are some kernels 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown around that forget to mask out the top 16 bits so we do it here. 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The kernel treats the bottom 16 bits as signed and (when it does 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mask them off) sign extends them when exporting to user space so 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we do the same thing here. */ 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (Short)si_code; 2117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return si_code; 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Receive an async signal from the kernel. 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This should only happen when the thread is blocked in a syscall, 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown since that's the only time this set of signals is unblocked. 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid async_signalhandler ( Int sigNo, 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t *info, struct vki_ucontext *uc ) 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst = VG_(get_ThreadState)(tid); 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The thread isn't currently running, make it so before going on */ 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->status == VgTs_WaitSys); 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "async_signalhandler"); 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code = sanitize_si_code(info->si_code); 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("async signal handler: signal=%d, tid=%d, si_code=%d\n", 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, tid, info->si_code); 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Update thread state properly. The signal can only have been 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered whilst we were in 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown coregrind/m_syswrap/syscall-<PLAT>.S, and only then in the 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown window between the two sigprocmask calls, since at all other 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown times, we run with async signals on the host blocked. Hence 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown make enquiries on the basis that we were in or very close to a 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, and attempt to fix up the guest state accordingly. 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (normal async signals occurring during computation are blocked, 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but periodically polled for using VG_(sigtimedwait_zero), and 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered at a point convenient for us. Hence this routine only 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deals with signals that are delivered to a thread during a 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall.) */ 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, extract a SysRes from the ucontext_t* given to this 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler. If it is subsequently established by 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) that the 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall was complete but the results had not been committed yet 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to the guest state, then it'll have to commit the results itself 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "by hand", and so we need to extract the SysRes. Of course if 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the thread was not in that particular window then the 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes will be meaningless, but that's OK too because 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) will detect 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the thread was not in said window and ignore the SysRes. */ 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* To make matters more complex still, on Darwin we need to know 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the "class" of the syscall under consideration in order to be 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown able to extract the a correct SysRes. The class will have been 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown saved just before the syscall, by VG_(client_syscall), into this 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread's tst->arch.vex.guest_SC_CLASS. Hence: */ 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_UCONTEXT_SYSCALL_SYSRES(uc, tst->arch.vex.guest_SC_CLASS); 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_UCONTEXT_SYSCALL_SYSRES(uc); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* (1) */ 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted)( 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_INSTR_PTR(uc), 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres, 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART) 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* (2) */ 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up the thread's state to deliver a signal */ 2194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_sig_ign(info->si_signo, tid)) 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, info, uc); 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It's crucial that (1) and (2) happen in the order (1) then (2) 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and not the other way around. (1) fixes up the guest thread 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state to reflect the fact that the syscall was interrupted -- 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either to restart the syscall or to return EINTR. (2) then sets 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown up the thread state to deliver the signal. Then we resume 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown execution. First, the signal handler is run, since that's the 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second adjustment we made to the thread state. If that returns, 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then we resume at the guest state created by (1), viz, either 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the syscall returns EINTR or is restarted. 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If (2) was done before (1) the outcome would be completely 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown different, and wrong. */ 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* longjmp back to the thread's main loop to start executing the 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler. */ 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resume_scheduler(tid); 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("async_signalhandler: got unexpected signal " 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "while outside of scheduler"); 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extend the stack to cover addr. maxsize is the limit the stack can grow to. 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns True on success, False on failure. 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Succeeds without doing anything if addr is already within a segment. 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Failure could be caused by: 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - addr not below a growable segment 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - new stack size would exceed maxsize 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - mmap failed for some other reason 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(extend_stack)(Addr addr, UInt maxsize) 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT udelta; 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find the next Segment above addr */ 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(am_find_nsegment)(addr); 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg_next 2237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov = seg ? VG_(am_next_nsegment)( seg, True/*fwds*/ ) 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : NULL; 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg && seg->kind == SkAnonC) 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* addr is already mapped. Nothing to do. */ 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that the requested new base is in a shrink-down 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reservation section which abuts an anonymous mapping that 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown belongs to the client. */ 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( ! (seg 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->kind == SkResvn 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->smode == SmUpper 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next->kind == SkAnonC 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->end+1 == seg_next->start)) 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown udelta = VG_PGROUNDUP(seg_next->start - addr); 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "signals", 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "extending a stack base 0x%llx down by %lld\n", 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg_next->start, (ULong)udelta); 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! VG_(am_extend_into_adjacent_reservation_client) 2260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ( seg_next, -(SSizeT)udelta )) { 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "signals", "extending a stack base: FAILED\n"); 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* When we change the main stack, we have to let the stack handling 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code know about it. */ 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(change_stack)(VG_(clstk_id), addr, VG_(clstk_end)); 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) > 2) 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_general)(False); 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void (*fault_catcher)(Int sig, Addr addr) = NULL; 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(set_fault_catcher)(void (*catcher)(Int, Addr)) 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "signals", "set fault catcher to %p\n", catcher); 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(NULL == catcher || NULL == fault_catcher, 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Fault catcher is already registered"); 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fault_catcher = catcher; 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sync_signalhandler_from_user ( ThreadId tid, 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc ) 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId qtid; 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If some user-process sent us a sync signal (ie. it's not the result 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of a faulting instruction), then how we treat it depends on when it 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arrives... */ 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_WaitSys) { 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal arrived while we're blocked in a syscall. This means that 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the client's signal mask was applied. In other words, so we can't 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get here unless the client wants this signal right now. This means 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we can simply use the async_signalhandler. */ 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Delivering user-sent sync signal %d as async signal\n", 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo); 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown async_signalhandler(sigNo, info, uc); 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("async_signalhandler returned!?\n"); 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal arrived while in generated client code, or while running 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valgrind core code. That means that every thread has these signals 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unblocked, so we can't rely on the kernel to route them properly, so 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we need to queue them manually. */ 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Routing user-sent sync signal %d via queue\n", sigNo); 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* On Linux, first we have to do a sanity check of the siginfo. */ 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->VKI_SIGINFO_si_pid == 0) { 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a per-user limit of pending siginfo signals. If 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown you exceed this, by having more than that number of 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pending signals with siginfo, then new signals are 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered without siginfo. This condition can be caused 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by any unrelated program you're running at the same time 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as Valgrind, if it has a large number of pending siginfo 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals which it isn't taking delivery of. 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Since we depend on siginfo to work out why we were sent a 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal and what we should do about it, we really can't 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue unless we get it. */ 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Signal %d (%s) appears to have lost its siginfo; " 2332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "I can't go on.\n", sigNo, VG_(signame)(sigNo)); 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" This may be because one of your programs has consumed your ration of\n" 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" siginfo structures. For more information, see:\n" 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" http://kerneltrap.org/mailarchive/1/message/25599/thread\n" 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" Basically, some program on your system is building up a large queue of\n" 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" pending signals, and this causes the siginfo data for other signals to\n" 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" be dropped because it's exceeding a system limit. However, Valgrind\n" 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" absolutely needs siginfo for SIGSEGV. A workaround is to track down the\n" 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" offending program and avoid running it while using Valgrind, but there\n" 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" is no easy way to do this. Apparently the problem was fixed in kernel\n" 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" 2.6.12.\n"); 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It's a fatal signal, so we force the default handler. */ 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(sigNo); 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, info, uc); 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resume_scheduler(tid); 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(99); /* If we can't resume, then just exit */ 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qtid = 0; /* shared pending by default */ 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->si_code == VKI_SI_TKILL) 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qtid = tid; /* directed to us specifically */ 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queue_signal(qtid, info); 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Returns the reported fault address for an exact address */ 2363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Addr fault_mask(Addr in) 2364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 2365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* We have to use VG_PGROUNDDN because faults on s390x only deliver 2366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the page address but not the address within a page. 2367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 2368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGA_s390x) 2369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return VG_PGROUNDDN(in); 2370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 2371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return in; 2372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 2373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 2374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Returns True if the sync signal was due to the stack requiring extension 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and the extension was successful. 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool extend_stack_if_appropriate(ThreadId tid, vki_siginfo_t* info) 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr fault; 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr esp; 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg; 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg_next; 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->si_signo != VKI_SIGSEGV) 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fault = (Addr)info->VKI_SIGINFO_si_addr; 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown esp = VG_(get_SP)(tid); 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg = VG_(am_find_nsegment)(fault); 2391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov seg_next = seg ? VG_(am_next_nsegment)( seg, True/*fwds*/ ) 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : NULL; 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg == NULL) 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("SIGSEGV: si_code=%d faultaddr=%#lx tid=%d ESP=%#lx " 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "seg=NULL\n", 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code, fault, tid, esp); 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("SIGSEGV: si_code=%d faultaddr=%#lx tid=%d ESP=%#lx " 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "seg=%#lx-%#lx\n", 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code, fault, tid, esp, seg->start, seg->end); 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->si_code == VKI_SEGV_MAPERR 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->kind == SkResvn 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->smode == SmUpper 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next->kind == SkAnonC 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->end+1 == seg_next->start 2412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && fault >= fault_mask(esp - VG_STACK_REDZONE_SZB)) { 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the fault address is above esp but below the current known 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack segment base, and it was a fault because there was 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nothing mapped there (as opposed to a permissions fault), 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then extend the stack segment. 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr base = VG_PGROUNDDN(esp - VG_STACK_REDZONE_SZB); 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(extend_stack)(base, VG_(threads)[tid].client_stack_szB)) { 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)(" -> extended stack base to %#lx\n", 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_PGROUNDDN(fault)); 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Stack overflow in thread %d: can't grow stack to %#lx\n", 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, fault); 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sync_signalhandler_from_kernel ( ThreadId tid, 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc ) 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check to see if some part of Valgrind itself is interested in faults. 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The fault catcher should never be set whilst we're in generated code, so 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check for that. AFAIK the only use of the catcher right now is 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memcheck's leak detector. */ 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fault_catcher) { 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == False); 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*fault_catcher)(sigNo, (Addr)info->VKI_SIGINFO_si_addr); 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the catcher returns, then it didn't handle the fault, 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so carry on panicking. */ 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (extend_stack_if_appropriate(tid, info)) { 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Stack extension occurred, so we don't need to do anything else; upon 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown returning from this function, we'll restart the host (hence guest) 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction. */ 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, this is a signal we really have to deal with. If it came 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from the client's code, then we can jump back into the scheduler 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and have it delivered. Otherwise it's a Valgrind bug. */ 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigismember)(&tst->sig_mask, sigNo)) { 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* signal is blocked, but they're not allowed to block faults */ 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(sigNo); 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(in_generated_code)) { 2466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (sigNo, tid) 2467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || VG_(sigismember)(&tst->sig_mask, sigNo)) { 2468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Can't continue; must longjmp back to the scheduler and thus 2469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov enter the sighandler immediately. */ 2470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, info, uc); 2471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 2472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 2474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If resume_scheduler returns or its our fault, it means we 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown don't have longjmp set up, implying that we weren't running 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client code, and therefore it was actually generated by 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valgrind internally. 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("VALGRIND INTERNAL ERROR: Valgrind received " 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a signal %d (%s) - exiting\n", 2484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sigNo, VG_(signame)(sigNo)); 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("si_code=%x; Faulting address: %p; sp: %#lx\n", 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code, info->VKI_SIGINFO_si_addr, 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_STACK_PTR(uc)); 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(kill_self)(sigNo); /* generate a core dump */ 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //if (tid == 0) /* could happen after everyone has exited */ 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // tid = VG_(master_tid); 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid != 0); 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UnwindStartRegs startRegs; 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&startRegs, 0, sizeof(startRegs)); 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_TO_UnwindStartRegs(&startRegs, uc); 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic_at)("Killed by fatal signal", &startRegs); 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Receive a sync signal from the host. 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sync_signalhandler ( Int sigNo, 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t *info, struct vki_ucontext *uc ) 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool from_user; 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sync_sighandler(%d, %p, %p)\n", sigNo, info, uc); 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(info != NULL); 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(info->si_signo == sigNo); 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo == VKI_SIGSEGV || 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGBUS || 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGFPE || 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGILL || 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGTRAP); 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code = sanitize_si_code(info->si_code); 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from_user = !is_signal_from_kernel(tid, sigNo, info->si_code); 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sync signal handler: " 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "signal=%d, si_code=%d, EIP=%#lx, eip=%#lx, from %s\n", 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, info->si_code, VG_(get_IP)(tid), 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_INSTR_PTR(uc), 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( from_user ? "user" : "kernel" )); 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal)); 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* // debug code: 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_signo %d\n", info->si_signo); 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_errno %d\n", info->si_errno); 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_code %d\n", info->si_code); 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_pid %d\n", info->si_pid); 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_uid %d\n", info->si_uid); 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_status %d\n", info->si_status); 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_addr %p\n", info->si_addr); 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out if the signal is being sent from outside the process. 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Why do we care?) If the signal is from the user rather than the 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel, then treat it more like an async signal than a sync signal -- 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that is, merely queue it for later delivery. */ 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (from_user) { 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sync_signalhandler_from_user( tid, sigNo, info, uc); 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sync_signalhandler_from_kernel(tid, sigNo, info, uc); 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Kill this thread. Makes it leave any syscall it might be currently 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blocked in, and return to the scheduler. This doesn't mark the thread 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as exiting; that's the caller's job. 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sigvgkill_handler(int signo, vki_siginfo_t *si, 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext *uc) 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadStatus at_signal = VG_(threads)[tid].status; 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sigvgkill for lwp %d tid %d\n", VG_(gettid)(), tid); 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "sigvgkill_handler"); 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(signo == VG_SIGVGKILL); 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(si->si_signo == signo); 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* jrs 2006 August 3: the following assertion seems incorrect to 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown me, and fails on AIX. sigvgkill could be sent to a thread which 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is runnable - see VG_(nuke_all_threads_except) in the scheduler. 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence comment these out .. 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_WaitSys); 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and instead do: 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (at_signal == VgTs_WaitSys) 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* jrs 2006 August 3 ends */ 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resume_scheduler(tid); 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("sigvgkill_handler couldn't return to the scheduler\n"); 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __attribute((unused)) 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pp_ksigaction ( vki_sigaction_toK_t* sa ) 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n", 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa->ksa_handler, 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UInt)sa->sa_flags, 2608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa->sa_restorer 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)0 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("pp_ksigaction: { "); 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i <= VG_(max_signal); i++) 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigismember(&(sa->sa_mask),i))) 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%d ", i); 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("}\n"); 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Force signal handler to default 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(set_default_handler)(Int signo) 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t sa; 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.ksa_handler = VKI_SIG_DFL; 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_flags = 0; 2630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_restorer = 0; 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&sa.sa_mask); 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_sys_sigaction)(signo, &sa, NULL); 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Poll for pending signals, and set the next one up for delivery. 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(poll_signals)(ThreadId tid) 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t si, *sip; 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t pollset; 2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t saved_mask; 2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* look for all the signals this thread isn't blocking */ 2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pollset = ~tst->sig_mask */ 2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigcomplementset)( &pollset, &tst->sig_mask ); 2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals(&saved_mask); // protect signal queue 2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First look for any queued pending signals */ 2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip = next_queued(tid, &pollset); /* this thread */ 2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sip == NULL) 2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip = next_queued(0, &pollset); /* process-wide */ 2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If there was nothing queued, ask the kernel for a pending signal */ 2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sip == NULL && VG_(sigtimedwait_zero)(&pollset, &si) > 0) { 2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("poll_signals: got signal %d for thread %d\n", 2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown si.si_signo, tid); 2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip = &si; 2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sip != NULL) { 2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, something to do; deliver it */ 2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Polling found signal %d for tid %d\n", sip->si_signo, tid); 2672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_sig_ign(sip->si_signo, tid)) 2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, sip, NULL); 2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (VG_(clo_trace_signals)) 2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)(" signal %d ignored\n", sip->si_signo); 2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip->si_signo = 0; /* remove from signal queue, if that's 2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown where it came from */ 2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_all_host_signals(&saved_mask); 2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* At startup, copy the process' real signal state to the SCSS. 2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Whilst doing this, block all real signals. Then calculate SKSS and 2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set the kernel to that. Also initialise DCSS. 2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigstartup_actions) ( void ) 2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, ret, vKI_SIGRTMIN; 2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t saved_procmask; 2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t sa; 2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&scss, 0, sizeof(scss)); 2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&skss, 0, sizeof(skss)); 2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGRTMIN) 2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vKI_SIGRTMIN = VKI_SIGRTMIN; 2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vKI_SIGRTMIN = 0; /* eg Darwin */ 2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(printf)("SIGSTARTUP\n"); */ 2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Block all signals. saved_procmask remembers the previous mask, 2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which the first thread inherits. 2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals( &saved_procmask ); 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy per-signal settings to SCSS. */ 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i <= _VKI_NSIG; i++) { 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the old host action */ 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigaction)(i, NULL, &sa); 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* apparently we may not even ask about the disposition of these 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals, let alone change them */ 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0 && (i == VKI_SIGKILL || i == VKI_SIGSTOP)) 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try setting it back to see if this signal is really 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown available */ 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vKI_SIGRTMIN > 0 /* it actually exists on this platform */ 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && i >= vKI_SIGRTMIN) { 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t tsa, sa2; 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsa.ksa_handler = (void *)sync_signalhandler; 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsa.sa_flags = VKI_SA_SIGINFO; 2732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsa.sa_restorer = 0; 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&tsa.sa_mask); 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* try setting it to some arbitrary handler */ 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigaction)(i, &tsa, NULL) != 0) { 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* failed - not really usable */ 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(convert_sigaction_fromK_to_toK)( &sa, &sa2 ); 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigaction)(i, &sa2, NULL); 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret == 0); 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(max_signal) = i; 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2) 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("snaffling handler 0x%lx for signal %d\n", 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(sa.ksa_handler), i ); 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_handler = sa.ksa_handler; 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_flags = sa.sa_flags; 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_mask = sa.sa_mask; 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_restorer = NULL; 2759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_restorer = sa.sa_restorer; 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_sa_tramp = NULL; 2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_sa_tramp = NULL; 2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*sa.sa_tramp;*/ 2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We can't know what it was, because Darwin's sys_sigaction 2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doesn't tell us. */ 2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Max kernel-supported signal is %d\n", VG_(max_signal)); 2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our private internal signals are treated as ignored */ 2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[VG_SIGVGKILL].scss_handler = VKI_SIG_IGN; 2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[VG_SIGVGKILL].scss_flags = VKI_SA_SIGINFO; 2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&scss.scss_per_sig[VG_SIGVGKILL].scss_mask); 2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy the process' signal mask into the root thread. */ 2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[1].status == VgTs_Init); 2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 2; i < VG_N_THREADS; i++) 2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[i].status == VgTs_Empty); 2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[1].sig_mask = saved_procmask; 2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[1].tmp_sig_mask = saved_procmask; 2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Calculate SKSS and apply it. This also sets the initial kernel 2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mask we need to run with. */ 2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_SCSS_change( True /* forced update */ ); 2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Leave with all signals still blocked; the thread scheduler loop 2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will set the appropriate mask at the appropriate time. */ 2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2799