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 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 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 Brownstatic const Char *signame(Int sigNo); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Maximum usable signal. */ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(max_signal) = _VKI_NSIG; 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_QUEUED_SIGNALS 8 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct SigQueue { 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int next; 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t sigs[N_QUEUED_SIGNALS]; 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} SigQueue; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Macros for pulling stuff out of ucontexts ------ */ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Q: what does VG_UCONTEXT_SYSCALL_SYSRES do? A: let's suppose the 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown machine context (uc) reflects the situation that a syscall had just 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown completed, quite literally -- that is, that the program counter was 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now at the instruction following the syscall. (or we're slightly 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown downstream, but we're sure no relevant register has yet changed 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value.) Then VG_UCONTEXT_SYSCALL_SYSRES returns a SysRes reflecting 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the result of the syscall; it does this by fishing relevant bits of 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the machine state out of the uc. Of course if the program counter 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown was somewhere else entirely then the result is likely to be 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown meaningless, so the caller of VG_UCONTEXT_SYSCALL_SYSRES has to be 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown very careful to pay attention to the results only when it is sure 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the said constraint on the program counter is indeed valid. */ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.eip) 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.esp) 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the value in uc_mcontext.eax into a SysRes. */ \ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax ) 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (ULong)((uc)->uc_mcontext.eip); \ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (ULong)((uc)->uc_mcontext.esp); \ 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.X86.r_ebp = (uc)->uc_mcontext.ebp; \ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip) 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp) 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the value in uc_mcontext.rax into a SysRes. */ \ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_amd64_linux)( (uc)->uc_mcontext.rax ) 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (uc)->uc_mcontext.rip; \ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (uc)->uc_mcontext.rsp; \ 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.AMD64.r_rbp = (uc)->uc_mcontext.rbp; \ 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Comments from Paul Mackerras 25 Nov 05: 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > I'm tracking down a problem where V's signal handling doesn't 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > work properly on a ppc440gx running 2.4.20. The problem is that 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > the ucontext being presented to V's sighandler seems completely 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > bogus. 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > V's kernel headers and hence ucontext layout are derived from 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > 2.6.9. I compared include/asm-ppc/ucontext.h from 2.4.20 and 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > 2.6.13. 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > Can I just check my interpretation: the 2.4.20 one contains the 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > uc_mcontext field in line, whereas the 2.6.13 one has a pointer 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > to said struct? And so if V is using the 2.6.13 struct then a 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown > 2.4.20 one will make no sense to it. 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Not quite... what is inline in the 2.4.20 version is a 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigcontext_struct, not an mcontext. The sigcontext looks like 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this: 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct sigcontext_struct { 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long _unused[4]; 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int signal; 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long handler; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long oldmask; 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct pt_regs *regs; 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown }; 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The regs pointer of that struct ends up at the same offset as the 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc_regs of the 2.6 struct ucontext, and a struct pt_regs is the 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same as the mc_gregs field of the mcontext. In fact the integer 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs are followed in memory by the floating point regs on 2.4.20. 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thus if you are using the 2.6 definitions, it should work on 2.4.20 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown provided that you go via uc->uc_regs rather than looking in 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_mcontext directly. 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There is another subtlety: 2.4.20 doesn't save the vector regs when 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivering a signal, and 2.6.x only saves the vector regs if the 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process has ever used an altivec instructions. If 2.6.x does save 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the vector regs, it sets the MSR_VEC bit in 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_regs->mc_gregs[PT_MSR], otherwise it clears it. That bit 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will always be clear under 2.4.20. So you can use that bit to tell 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whether uc->uc_regs->mc_vregs is valid. */ 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_regs->mc_gregs[VKI_PT_NIP]) 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_regs->mc_gregs[VKI_PT_R1]) 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the values in uc_mcontext r3,cr into a SysRes. */ \ 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_ppc32_linux)( \ 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (uc)->uc_regs->mc_gregs[VKI_PT_R3], \ 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((uc)->uc_regs->mc_gregs[VKI_PT_CCR] >> 28) & 1) \ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (ULong)((uc)->uc_regs->mc_gregs[VKI_PT_NIP]); \ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (ULong)((uc)->uc_regs->mc_gregs[VKI_PT_R1]); \ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.PPC32.r_lr = (uc)->uc_regs->mc_gregs[VKI_PT_LNK]; \ 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.gp_regs[VKI_PT_NIP]) 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.gp_regs[VKI_PT_R1]) 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dubious hack: if there is an error, only consider the lowest 8 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bits of r3. memcheck/tests/post-syscall shows a case where an 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interrupted syscall should have produced a ucontext with 0x4 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VKI_EINTR) in r3 but is in fact producing 0x204. */ 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Awaiting clarification from PaulM. Evidently 0x204 is 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ERESTART_RESTARTBLOCK, which shouldn't have made it into user 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown space. */ 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline SysRes VG_UCONTEXT_SYSCALL_SYSRES( struct vki_ucontext* uc ) 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong err = (uc->uc_mcontext.gp_regs[VKI_PT_CCR] >> 28) & 1; 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong r3 = uc->uc_mcontext.gp_regs[VKI_PT_R3]; 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (err) r3 &= 0xFF; 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_ppc64_linux)( r3, err ); 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (uc)->uc_mcontext.gp_regs[VKI_PT_NIP]; \ 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (uc)->uc_mcontext.gp_regs[VKI_PT_R1]; \ 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.PPC64.r_lr = (uc)->uc_mcontext.gp_regs[VKI_PT_LNK]; \ 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.arm_pc) 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.arm_sp) 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Convert the value in uc_mcontext.rax into a SysRes. */ \ 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mk_SysRes_arm_linux)( (uc)->uc_mcontext.arm_r0 ) 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { (srP)->r_pc = (uc)->uc_mcontext.arm_pc; \ 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->r_sp = (uc)->uc_mcontext.arm_sp; \ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r14 = (uc)->uc_mcontext.arm_lr; \ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r12 = (uc)->uc_mcontext.arm_ip; \ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r11 = (uc)->uc_mcontext.arm_fp; \ 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (srP)->misc.ARM.r7 = (uc)->uc_mcontext.arm_r7; \ 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_INSTR_PTR( void* ucV ) { 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)ucV; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ss->__eip; 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_STACK_PTR( void* ucV ) { 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)ucV; 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ss->__esp; 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline SysRes VG_UCONTEXT_SYSCALL_SYSRES( void* ucV, 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord scclass ) { 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is complicated by the problem that there are 3 different 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kinds of syscalls, each with its own return convention. 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NB: scclass is a host word, hence UWord is good for both 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64-darwin and x86-darwin */ 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 /* duplicates logic in m_syswrap.getSyscallStatusFromGuestState */ 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt carry = 1 & ss->__eflags; 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt err = 0; 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wLO = 0; 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wHI = 0; 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (scclass) { 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_UNIX: 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = carry; 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = ss->__eax; 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI = ss->__edx; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MACH: 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = ss->__eax; 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_DARWIN_SYSCALL_CLASS_MDEP: 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wLO = ss->__eax; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wHI, wLO ); 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void VG_UCONTEXT_TO_UnwindStartRegs( UnwindStartRegs* srP, 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* ucV ) { 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t* uc = (ucontext_t*)(ucV); 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32* mc = uc->uc_mcontext; 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_i386_thread_state* ss = &mc->__ss; 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srP->r_pc = (ULong)(ss->__eip); 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srP->r_sp = (ULong)(ss->__esp); 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srP->misc.X86.r_ebp = (UInt)(ss->__ebp); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_INSTR_PTR( void* ucV ) { 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline Addr VG_UCONTEXT_STACK_PTR( void* ucV ) { 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline SysRes VG_UCONTEXT_SYSCALL_SYSRES( void* ucV, 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord scclass ) { 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static inline 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void VG_UCONTEXT_TO_UnwindStartRegs( UnwindStartRegs* srP, 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* ucV ) { 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.regs.psw.addr) 470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.regs.gprs[15]) 471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.regs.gprs[11]) 472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ 473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(mk_SysRes_s390x_linux)((uc)->uc_mcontext.regs.gprs[2]) 474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.regs.gprs[14]) 475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ 477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { (srP)->r_pc = (ULong)((uc)->uc_mcontext.regs.psw.addr); \ 478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (srP)->r_sp = (ULong)((uc)->uc_mcontext.regs.gprs[15]); \ 479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (srP)->misc.S390X.r_fp = (uc)->uc_mcontext.regs.gprs[11]; \ 480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (srP)->misc.S390X.r_lr = (uc)->uc_mcontext.regs.gprs[14]; \ 481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Macros for pulling stuff out of siginfos ------ */ 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These macros allow use of uniform names when working with 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both the Linux and AIX vki definitions. */ 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_addr _sifields._sigfault._addr 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_pid _sifields._kill._pid 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_addr si_addr 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_SIGINFO_si_pid si_pid 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HIGH LEVEL STUFF TO DO WITH SIGNALS: POLICY (MOSTLY) 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Signal state for this process. 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Base-ment of these arrays[_VKI_NSIG]. 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valid signal numbers are 1 .. _VKI_NSIG inclusive. 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Rather than subtracting 1 for indexing these arrays, which 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is tedious and error-prone, they are simply dimensioned 1 larger, 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and entry [0] is not used. 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----------------------------------------------------- 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Static client signal state (SCSS). This is the state 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the client thinks it has the kernel in. 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS records verbatim the client's settings. These 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are mashed around only when SKSS is calculated from it. 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -------------------------------------------------- */ 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* scss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN or ptr to 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client's handler */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt scss_flags; 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t scss_mask; 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* scss_restorer; /* where sigreturn goes */ 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* scss_sa_tramp; /* sa_tramp setting, Darwin only */ 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* re _restorer and _sa_tramp, we merely record the values 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown supplied when the client does 'sigaction' and give them back 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when requested. Otherwise they are simply ignored. */ 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS_Per_Signal; 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* per-signal info */ 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS_Per_Signal scss_per_sig[1+_VKI_NSIG]; 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Additional elements to SCSS not stored here: 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - for each thread, the thread's blocking mask 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - for each thread in WaitSIG, the set of waited-on sigs 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS; 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SCSS scss; 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----------------------------------------------------- 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Static kernel signal state (SKSS). This is the state 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that we have the kernel in. It is computed from SCSS. 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -------------------------------------------------- */ 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let's do: 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigprocmask assigns to all thread masks 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so that at least everything is always consistent 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Flags: 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_SIGINFO -- we always set it, and honour it for the client 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_NOCLDSTOP -- passed to kernel 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_ONESHOT or SA_RESETHAND -- pass through 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_RESTART -- we observe this but set our handlers to always restart 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_NOMASK or SA_NODEFER -- we observe this, but our handlers block everything 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_ONSTACK -- pass through 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SA_NOCLDWAIT -- pass through 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* skss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or ptr to our handler */ 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt skss_flags; 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There is no skss_mask, since we know that we will always ask 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for all signals to be blocked in our sighandlers. */ 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also there is no skss_restorer. */ 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS_Per_Signal; 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS_Per_Signal skss_per_sig[1+_VKI_NSIG]; 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS; 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SKSS skss; 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* returns True if signal is to be ignored. 597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov To check this, possibly call gdbserver with tid. */ 598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool is_sig_ign(Int sigNo, ThreadId tid) 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo >= 1 && sigNo <= _VKI_NSIG); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_IGN 603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || !VG_(gdbserver_report_signal) (sigNo, tid); 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Compute the SKSS required by the current SCSS. 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pp_SKSS ( void ) 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sig; 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n\nSKSS:\n"); 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sig = 1; sig <= _VKI_NSIG; sig++) { 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sig %d: handler %p, flags 0x%x\n", sig, 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss.skss_per_sig[sig].skss_handler, 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss.skss_per_sig[sig].skss_flags ); 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the core, clever bit. Computation is as follows: 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For each signal 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler = if client has a handler, then our handler 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if client is DFL, then our handler as well 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else (client must be IGN) 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then hander is IGN 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid calculate_SKSS_from_SCSS ( SKSS* dst ) 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sig; 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt scss_flags; 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt skss_flags; 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sig = 1; sig <= _VKI_NSIG; sig++) { 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *skss_handler; 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *scss_handler; 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss_handler = scss.scss_per_sig[sig].scss_handler; 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss_flags = scss.scss_per_sig[sig].scss_flags; 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sig) { 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTRAP: 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For these, we always want to catch them and report, even 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if the client code doesn't. */ 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = sync_signalhandler; 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCONT: 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Let the kernel handle SIGCONT unless the client is actually 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown catching it. */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCHLD: 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGWINCH: 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGURG: 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For signals which are have a default action of Ignore, 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only set a handler if the client has set a signal handler. 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Otherwise the kernel will interrupt a syscall which 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wouldn't have otherwise been interrupted. */ 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (scss.scss_per_sig[sig].scss_handler == VKI_SIG_DFL) 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = VKI_SIG_DFL; 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (scss.scss_per_sig[sig].scss_handler == VKI_SIG_IGN) 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = VKI_SIG_IGN; 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = async_signalhandler; 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VKI_SIGVG* are runtime variables, so we can't make them 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // cases in the switch, so we handle them in the 'default' case. 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sig == VG_SIGVGKILL) 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = sigvgkill_handler; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (scss_handler == VKI_SIG_IGN) 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = VKI_SIG_IGN; 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_handler = async_signalhandler; 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Flags */ 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags = 0; 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_NOCLDSTOP, SA_NOCLDWAIT: pass to kernel */ 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= scss_flags & (VKI_SA_NOCLDSTOP | VKI_SA_NOCLDWAIT); 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_ONESHOT: ignore client setting */ 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_RESTART: ignore client setting and always set it for us. 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Though we never rely on the kernel to restart a 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, we observe whether it wanted to restart the syscall 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or not, which is needed by 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) */ 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= VKI_SA_RESTART; 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_NOMASK: ignore it */ 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SA_ONSTACK: client setting is irrelevant here */ 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't set a signal stack, so ignore */ 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* always ask for SA_SIGINFO */ 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= VKI_SA_SIGINFO; 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* use our own restorer */ 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_flags |= VKI_SA_RESTORER; 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create SKSS entry for this signal. */ 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP) 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->skss_per_sig[sig].skss_handler = skss_handler; 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->skss_per_sig[sig].skss_handler = VKI_SIG_DFL; 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->skss_per_sig[sig].skss_flags = skss_flags; 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sanity checks. */ 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(dst->skss_per_sig[VKI_SIGKILL].skss_handler == VKI_SIG_DFL); 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(dst->skss_per_sig[VKI_SIGSTOP].skss_handler == VKI_SIG_DFL); 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pp_SKSS(); 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown After a possible SCSS change, update SKSS and the kernel itself. 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We need two levels of macro-expansion here to convert __NR_rt_sigreturn 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to a number before converting it to a string... sigh. 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern void my_sigreturn(void); 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " movl $" #name ", %eax\n" \ 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " int $0x80\n" \ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux) 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " movq $" #name ", %rax\n" \ 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " syscall\n" \ 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux) 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " li 0, " #name "\n" \ 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " sc\n" \ 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux) 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".align 2\n" \ 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".globl my_sigreturn\n" \ 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".section \".opd\",\"aw\"\n" \ 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".align 3\n" \ 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".quad .my_sigreturn,.TOC.@tocbase,0\n" \ 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" \ 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".type .my_sigreturn,@function\n" \ 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".globl .my_sigreturn\n" \ 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".my_sigreturn:\n" \ 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " li 0, " #name "\n" \ 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " sc\n" 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux) 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n\t" \ 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " mov r7, #" #name "\n\t" \ 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " svc 0x00000000\n" \ 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".previous\n" 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin) 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "movl $" VG_STRINGIFY(__NR_DARWIN_FAKE_SIGRETURN) ",%eax\n" \ 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "int $0x80" 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin) 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: todo 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define _MY_SIGRETURN(name) \ 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ".text\n" \ 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "my_sigreturn:\n" \ 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ud2\n" 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux) 803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define _MY_SIGRETURN(name) \ 804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ".text\n" \ 805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "my_sigreturn:\n" \ 806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov " svc " #name "\n" \ 807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ".previous\n" 808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MY_SIGRETURN(name) _MY_SIGRETURN(name) 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm( 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MY_SIGRETURN(__NR_rt_sigreturn) 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown); 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_SCSS_change ( Bool force_update ) 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int res, sig; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SKSS skss_old; 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t ksa; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t ksa_old; 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Remember old SKSS and calculate new one. */ 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown skss_old = skss; 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown calculate_SKSS_from_SCSS ( &skss ); 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compare the new SKSS entries vs the old ones, and update kernel 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown where they differ. */ 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sig = 1; sig <= VG_(max_signal); sig++) { 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Trying to do anything with SIGKILL is pointless; just ignore 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. */ 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP) 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!force_update) { 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((skss_old.skss_per_sig[sig].skss_handler 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss.skss_per_sig[sig].skss_handler) 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (skss_old.skss_per_sig[sig].skss_flags 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss.skss_per_sig[sig].skss_flags)) 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no difference */ 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler; 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if !defined(VGP_ppc32_linux) && \ 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ksa.sa_restorer = my_sigreturn; 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Re above ifdef (also the assertion below), PaulM says: 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The sa_restorer field is not used at all on ppc. Glibc 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown converts the sigaction you give it into a kernel sigaction, 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but it doesn't put anything in the sa_restorer field. 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* block all signals in handler */ 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)( &ksa.sa_mask ); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)( &ksa.sa_mask, VKI_SIGKILL ); 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)( &ksa.sa_mask, VKI_SIGSTOP ); 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2) 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("setting ksig %d to: hdlr %p, flags 0x%lx, " 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "mask(msb..lsb) 0x%llx 0x%llx\n", 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sig, ksa.ksa_handler, 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)ksa.sa_flags, 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VKI_NSIG_WORDS > 1 ? (ULong)ksa.sa_mask.sig[1] : 0, 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)ksa.sa_mask.sig[0]); 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(sigaction)( sig, &ksa, &ksa_old ); 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(res == 0); 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Since we got the old sigaction more or less for free, might 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as well extract the maximum sanity-check value from it. */ 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!force_update) { 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ksa_old.ksa_handler 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss_old.skss_per_sig[sig].skss_handler); 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ksa_old.sa_flags 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == skss_old.skss_per_sig[sig].skss_flags); 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if !defined(VGP_ppc32_linux) && \ 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ksa_old.sa_restorer 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == my_sigreturn); 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL ); 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGSTOP ); 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(isfullsigset)( &ksa_old.sa_mask )); 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Update/query SCSS in accordance with client requests. 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Logic for this alt-stack stuff copied directly from do_sigaltstack 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in kernel/signal.[ch] */ 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* True if we are on the alternate signal stack. */ 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool on_sig_stack ( ThreadId tid, Addr m_SP ) 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (m_SP - (Addr)tst->altstack.ss_sp < (Addr)tst->altstack.ss_size); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int sas_ss_flags ( ThreadId tid, Addr m_SP ) 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (tst->altstack.ss_size == 0 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? VKI_SS_DISABLE 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : on_sig_stack(tid, m_SP) ? VKI_SS_ONSTACK : 0); 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss ) 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr m_SP; 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_SP = VG_(get_SP)(tid); 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sys_sigaltstack: tid %d, " 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ss %p{%p,sz=%llu,flags=0x%llx}, oss %p (current SP %p)\n", 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, (void*)ss, 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ss ? ss->ss_sp : 0, 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)(ss ? ss->ss_size : 0), 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)(ss ? ss->ss_flags : 0), 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)oss, (void*)m_SP); 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (oss != NULL) { 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oss->ss_sp = VG_(threads)[tid].altstack.ss_sp; 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oss->ss_size = VG_(threads)[tid].altstack.ss_size; 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oss->ss_flags = VG_(threads)[tid].altstack.ss_flags 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | sas_ss_flags(tid, m_SP); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss != NULL) { 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (on_sig_stack(tid, VG_(get_SP)(tid))) { 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EPERM ); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss->ss_flags != VKI_SS_DISABLE 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ss->ss_flags != VKI_SS_ONSTACK 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ss->ss_flags != 0) { 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss->ss_flags == VKI_SS_DISABLE) { 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE; 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ss->ss_size < VKI_MINSIGSTKSZ) { 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_ENOMEM ); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_sp = ss->ss_sp; 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_size = ss->ss_size; 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_flags = 0; 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( 0 ); 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_sys_sigaction) ( Int signo, 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigaction_toK_t* new_act, 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t* old_act ) 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sys_sigaction: sigNo %d, " 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "new %#lx, old %#lx, new flags 0x%llx\n", 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signo, (UWord)new_act, (UWord)old_act, 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)(new_act ? new_act->sa_flags : 0)); 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Rule out various error conditions. The aim is to ensure that if 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when the call is passed to the kernel it will definitely 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown succeed. */ 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Reject out-of-range signal numbers. */ 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (signo < 1 || signo > VG_(max_signal)) goto bad_signo; 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* don't let them use our signals */ 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (signo > VG_SIGVGRTUSERMAX) 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && new_act 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && !(new_act->ksa_handler == VKI_SIG_DFL 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || new_act->ksa_handler == VKI_SIG_IGN) ) 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad_signo_reserved; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Reject attempts to set a handler (or set ignore) for SIGKILL. */ 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (signo == VKI_SIGKILL || signo == VKI_SIGSTOP) 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && new_act 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && new_act->ksa_handler != VKI_SIG_DFL) 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad_sigkill_or_sigstop; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the client supplied non-NULL old_act, copy the relevant SCSS 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entry into it. */ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old_act) { 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->ksa_handler = scss.scss_per_sig[signo].scss_handler; 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->sa_flags = scss.scss_per_sig[signo].scss_flags; 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->sa_mask = scss.scss_per_sig[signo].scss_mask; 1005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer; 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* And now copy new SCSS entry from new_act. */ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_act) { 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_handler = new_act->ksa_handler; 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_flags = new_act->sa_flags; 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_mask = new_act->sa_mask; 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_restorer = NULL; 1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer; 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_sa_tramp = NULL; 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[signo].scss_sa_tramp = new_act->sa_tramp; 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGKILL); 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGSTOP); 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All happy bunnies ... */ 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_act) { 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_SCSS_change( False /* lazy update */ ); 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( 0 ); 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad_signo: 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(showing_core_errors)() && !VG_(clo_xml)) { 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: bad signal number %d in sigaction()\n", signo); 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad_signo_reserved: 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(showing_core_errors)() && !VG_(clo_xml)) { 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: ignored attempt to set %s handler in sigaction();\n", 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signame(signo)); 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" the %s signal is used internally by Valgrind\n", 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signame(signo)); 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad_sigkill_or_sigstop: 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(showing_core_errors)() && !VG_(clo_xml)) { 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: ignored attempt to set %s handler in sigaction();\n", 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signame(signo)); 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" the %s signal is uncatchable\n", 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signame(signo)); 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_sigprocmask_bitops ( Int vki_how, 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* orig_set, 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* modifier ) 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (vki_how) { 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_BLOCK: 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset_from_set)( orig_set, modifier ); 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_UNBLOCK: 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset_from_set)( orig_set, modifier ); 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_SETMASK: 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *orig_set = *modifier; 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("do_sigprocmask_bitops"); 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* format_sigset ( const vki_sigset_t* set ) 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static HChar buf[128]; 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int w; 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(buf, ""); 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (w = _VKI_NSIG_WORDS - 1; w >= 0; w--) 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if _VKI_NSIG_BPW == 32 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf + VG_(strlen)(buf), "%08llx", 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set ? (ULong)set->sig[w] : 0); 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif _VKI_NSIG_BPW == 64 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf + VG_(strlen)(buf), "%16llx", 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set ? (ULong)set->sig[w] : 0); 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported value for _VKI_NSIG_BPW" 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This updates the thread's signal mask. There's no such thing as a 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process-wide signal mask. 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that the thread signal masks are an implicit part of SCSS, 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which is why this routine is allowed to mess with them. 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_setmask ( ThreadId tid, 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int how, 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* newset, 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* oldset ) 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("do_setmask: tid = %d how = %d (%s), newset = %p (%s)\n", 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, how, 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown how==VKI_SIG_BLOCK ? "SIG_BLOCK" : ( 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown how==VKI_SIG_UNBLOCK ? "SIG_UNBLOCK" : ( 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown how==VKI_SIG_SETMASK ? "SIG_SETMASK" : "???")), 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newset, newset ? format_sigset(newset) : "NULL" ); 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Just do this thread. */ 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (oldset) { 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *oldset = VG_(threads)[tid].sig_mask; 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("\toldset=%p %s\n", oldset, format_sigset(oldset)); 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newset) { 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_sigprocmask_bitops (how, &VG_(threads)[tid].sig_mask, newset ); 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGKILL); 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGSTOP); 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask; 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_sys_sigprocmask) ( ThreadId tid, 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int how, 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* set, 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t* oldset ) 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(how) { 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_BLOCK: 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_UNBLOCK: 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIG_SETMASK: 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_setmask ( tid, how, set, oldset ); 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( 0 ); 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sigprocmask: unknown 'how' field %d\n", how); 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Handy utilities to block/restore all host signals. 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Block all host signals, dumping the old mask in *saved_mask. */ 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void block_all_host_signals ( /* OUT */ vki_sigset_t* saved_mask ) 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t block_procmask; 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&block_procmask); 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigprocmask) 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VKI_SIG_SETMASK, &block_procmask, saved_mask); 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret == 0); 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Restore the blocking mask using the supplied saved one. */ 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void restore_all_host_signals ( /* IN */ vki_sigset_t* saved_mask ) 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigprocmask)(VKI_SIG_SETMASK, saved_mask, NULL); 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret == 0); 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(clear_out_queued_signals)( ThreadId tid, vki_sigset_t* saved_mask ) 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals(saved_mask); 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].sig_queue != NULL) { 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)(VG_AR_CORE, VG_(threads)[tid].sig_queue); 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].sig_queue = NULL; 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_all_host_signals(saved_mask); 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The signal simulation proper. A simplified version of what the 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux kernel does. 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set up a stack frame (VgSigContext) for the client's signal 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler. */ 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid push_signal_frame ( ThreadId tid, const vki_siginfo_t *siginfo, 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct vki_ucontext *uc ) 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr esp_top_of_frame; 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = siginfo->si_signo; 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal)); 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = & VG_(threads)[tid]; 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("push_signal_frame (thread %d): signal %d\n", tid, sigNo); 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)(tid, 10); 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (/* this signal asked to run on an alt stack */ 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONSTACK ) 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && /* there is a defined and enabled alt stack, which we're not 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown already using. Logic from get_sigframe in 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch/i386/kernel/signal.c. */ 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sas_ss_flags(tid, VG_(get_SP)(tid)) == 0 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) { 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown esp_top_of_frame 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (Addr)(tst->altstack.ss_sp) + tst->altstack.ss_size; 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("delivering signal %d (%s) to thread %d: " 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "on ALT STACK (%p-%p; %ld bytes)\n", 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, signame(sigNo), tid, tst->altstack.ss_sp, 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UChar *)tst->altstack.ss_sp + tst->altstack.ss_size, 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Word)tst->altstack.ss_size ); 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal delivery to tools */ 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/True ); 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown esp_top_of_frame = VG_(get_SP)(tid) - VG_STACK_REDZONE_SZB; 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal delivery to tools */ 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/False ); 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN); 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This may fail if the client stack is busted; if that happens, 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the whole process will exit rather than simply calling the 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal handler. */ 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigframe_create) (tid, esp_top_of_frame, siginfo, uc, 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[sigNo].scss_handler, 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[sigNo].scss_flags, 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &tst->sig_mask, 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[sigNo].scss_restorer); 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const Char *signame(Int sigNo) 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char buf[20]; 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sigNo) { 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGHUP: return "SIGHUP"; 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGINT: return "SIGINT"; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGQUIT: return "SIGQUIT"; 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: return "SIGILL"; 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTRAP: return "SIGTRAP"; 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGABRT: return "SIGABRT"; 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: return "SIGBUS"; 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: return "SIGFPE"; 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGKILL: return "SIGKILL"; 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR1: return "SIGUSR1"; 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR2: return "SIGUSR2"; 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: return "SIGSEGV"; 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPIPE: return "SIGPIPE"; 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGALRM: return "SIGALRM"; 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTERM: return "SIGTERM"; 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGSTKFLT) 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSTKFLT: return "SIGSTKFLT"; 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCHLD: return "SIGCHLD"; 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGCONT: return "SIGCONT"; 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSTOP: return "SIGSTOP"; 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTSTP: return "SIGTSTP"; 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTTIN: return "SIGTTIN"; 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTTOU: return "SIGTTOU"; 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGURG: return "SIGURG"; 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXCPU: return "SIGXCPU"; 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXFSZ: return "SIGXFSZ"; 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGVTALRM: return "SIGVTALRM"; 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPROF: return "SIGPROF"; 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGWINCH: return "SIGWINCH"; 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGIO: return "SIGIO"; 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGPWR) 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPWR: return "SIGPWR"; 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGUNUSED) 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUNUSED: return "SIGUNUSED"; 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGRTMIN ... VKI_SIGRTMAX: 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "SIGRT%d", sigNo-VKI_SIGRTMIN); 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "SIG%d", sigNo); 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Hit ourselves with a signal using the default handler */ 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(kill_self)(Int sigNo) 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int r; 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask, origmask; 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t sa, origsa2; 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t origsa; 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.ksa_handler = VKI_SIG_DFL; 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_flags = 0; 1330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_restorer = 0; 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&sa.sa_mask); 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaction)(sigNo, &sa, &origsa); 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&mask); 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)(&mask, sigNo); 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_UNBLOCK, &mask, &origmask); 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = VG_(kill)(VG_(getpid)(), sigNo); 1342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This sometimes fails with EPERM on Darwin. I don't know why. */ 1344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(r == 0); 1345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(convert_sigaction_fromK_to_toK)( &origsa, &origsa2 ); 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaction)(sigNo, &origsa2, NULL); 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &origmask, NULL); 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The si_code describes where the signal came from. Some come from the 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// kernel, eg.: seg faults, illegal opcodes. Some come from the user, eg.: 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// from kill() (SI_USER), or timer_settime() (SI_TIMER), or an async I/O 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// request (SI_ASYNCIO). There's lots of implementation-defined leeway in 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// POSIX, but the user vs. kernal distinction is what we want here. We also 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pass in some other details that can help when si_code is unreliable. 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_signal_from_kernel(ThreadId tid, int signum, int si_code) 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // On Linux, SI_USER is zero, negative values are from the user, positive 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // values are from the kernel. There are SI_FROMUSER and SI_FROMKERNEL 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // macros but we don't use them here because other platforms don't have 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // them. 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ( si_code > VKI_SI_USER ? True : False ); 1366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGO_darwin) 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // On Darwin 9.6.0, the si_code is completely unreliable. It should be the 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case that 0 means "user", and >0 means "kernel". But: 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGSEGV, it seems quite reliable. 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGBUS, it's always 2. 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGFPE, it's often 0, even for kernel ones (eg. 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // div-by-integer-zero always gives zero). 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGILL, it's unclear. 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - For SIGTRAP, it's always 1. 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // You can see the "NOTIMP" (not implemented) status of a number of the 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // sub-cases in sys/signal.h. Hopefully future versions of Darwin will 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // get this right. 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If we're blocked waiting on a syscall, it must be a user signal, because 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the kernel won't generate sync signals within syscalls. 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_WaitSys) { 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If it's a SIGSEGV, use the proper condition, since it's fairly reliable. 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (SIGSEGV == signum) { 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ( si_code > 0 ? True : False ); 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If it's anything else, assume it's kernel-generated. Reason being that 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // kernel-generated sync signals are more common, and it's probable that 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // misdiagnosing a user signal as a kernel signal is better than the 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // opposite. 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 1397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# error Unknown OS 1398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is an arbitrary si_code that we only use internally. It corresponds 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to the value SI_KERNEL on Linux, but that's not really of any significance 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// as far as I can determine. 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VKI_SEGV_MADE_UP_GPF 0x80 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Perform the default action of a signal. If the signal is fatal, it 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown marks all threads as needing to exit, but it doesn't actually kill 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the process or thread. 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If we're not being quiet, then print out some more detail about 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fatal signals (esp. core dumping signals). 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void default_action(const vki_siginfo_t *info, ThreadId tid) 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = info->si_signo; 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool terminate = False; /* kills process */ 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool core = False; /* kills process w/ core */ 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_rlimit corelim; 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool could_core; 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sigNo) { 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGQUIT: /* core */ 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: /* core */ 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGABRT: /* core */ 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: /* core */ 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: /* core */ 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: /* core */ 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTRAP: /* core */ 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXCPU: /* core */ 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGXFSZ: /* core */ 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminate = True; 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core = True; 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGHUP: /* term */ 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGINT: /* term */ 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGKILL: /* term - we won't see this */ 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPIPE: /* term */ 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGALRM: /* term */ 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGTERM: /* term */ 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR1: /* term */ 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGUSR2: /* term */ 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGIO: /* term */ 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGPWR) 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPWR: /* term */ 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSYS: /* term */ 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGPROF: /* term */ 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGVTALRM: /* term */ 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGRTMIN ... VKI_SIGRTMAX: /* term */ 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminate = True; 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!core || (core && terminate)); 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("delivering %d (code %d) to default handler; action: %s%s\n", 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, info->si_code, terminate ? "terminate" : "ignore", 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core ? "+core" : ""); 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!terminate) 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* nothing to do */ 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown could_core = core; 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (core) { 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If they set the core-size limit to zero, don't generate a 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core file */ 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(getrlimit)(VKI_RLIMIT_CORE, &corelim); 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (corelim.rlim_cur == 0) 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core = False; 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (VG_(clo_verbosity) > 1 || 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (could_core && is_signal_from_kernel(tid, sigNo, info->si_code)) 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) && 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !VG_(clo_xml) ) { 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Process terminating with default action of signal %d (%s)%s\n", 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, signame(sigNo), core ? ": dumping core" : ""); 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Be helpful - decode some more details about this fault */ 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_signal_from_kernel(tid, sigNo, info->si_code)) { 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char *event = NULL; 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool haveaddr = True; 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(sigNo) { 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGSEGV: 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(info->si_code) { 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEGV_MAPERR: event = "Access not within mapped region"; 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEGV_ACCERR: event = "Bad permissions for mapped region"; 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEGV_MADE_UP_GPF: 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* General Protection Fault: The CPU/kernel 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isn't telling us anything useful, but this 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is commonly the result of exceeding a 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment limit. */ 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown event = "General Protection Fault"; 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown haveaddr = False; 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[110]; 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_show_nsegments)(0,"post segfault"); 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "/bin/cat /proc/%d/maps", VG_(getpid)()); 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(system)(buf); 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGILL: 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(info->si_code) { 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLOPC: event = "Illegal opcode"; break; 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLOPN: event = "Illegal operand"; break; 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLADR: event = "Illegal addressing mode"; break; 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_ILLTRP: event = "Illegal trap"; break; 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_PRVOPC: event = "Privileged opcode"; break; 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_PRVREG: event = "Privileged register"; break; 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_COPROC: event = "Coprocessor error"; break; 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_ILL_BADSTK: event = "Internal stack error"; break; 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGFPE: 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (info->si_code) { 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_INTDIV: event = "Integer divide by zero"; break; 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_INTOVF: event = "Integer overflow"; break; 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTDIV: event = "FP divide by zero"; break; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTOVF: event = "FP overflow"; break; 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTUND: event = "FP underflow"; break; 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTRES: event = "FP inexact"; break; 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTINV: event = "FP invalid operation"; break; 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_FPE_FLTSUB: event = "FP subscript out of range"; break; 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SIGBUS: 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (info->si_code) { 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_BUS_ADRALN: event = "Invalid address alignment"; break; 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_BUS_ADRERR: event = "Non-existent physical address"; break; 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_BUS_OBJERR: event = "Hardware error"; break; 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (sigNo) */ 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (event != NULL) { 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (haveaddr) 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" %s at address %p\n", 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown event, info->VKI_SIGINFO_si_addr); 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" %s\n", event); 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print a stack trace. Be cautious if the thread's SP is in an 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obviously stupid place (not mapped readable) that would 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown likely cause a segfault. */ 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_valid_tid)(tid)) { 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* ec = VG_(am_is_valid_for_client) 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_(get_SP)(tid), sizeof(Addr), VKI_PROT_READ) 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ ) 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : VG_(record_depth_1_ExeContext)( tid ); 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ec); 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( ec ); 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sigNo == VKI_SIGSEGV 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && info && is_signal_from_kernel(tid, sigNo, info->si_code) 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && info->si_code == VKI_SEGV_MAPERR) { 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" If you believe this happened as a result of a stack\n" ); 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" overflow in your program's main thread (unlikely but\n"); 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" possible), you can try to increase the size of the\n" ); 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" main thread stack using the --main-stacksize= flag.\n" ); 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: assumes main ThreadId == 1 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_valid_tid)(1)) { 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " The main thread stack size used in this run was %d.\n", 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)VG_(threads)[1].client_stack_szB); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) )) { 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(start_debugger)( tid ); 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (core) { 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const static struct vki_rlimit zero = { 0, 0 }; 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(make_coredump)(tid, info, corelim.rlim_cur); 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure we don't get a confusing kernel-generated 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown coredump when we finally exit */ 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(setrlimit)(VKI_RLIMIT_CORE, &zero); 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stash fatal signal in main thread */ 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // what's this for? 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(threads)[VG_(master_tid)].os_state.fatalsig = sigNo; 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* everyone dies */ 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(nuke_all_threads_except)(tid, VgSrc_FatalSig); 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].exitreason = VgSrc_FatalSig; 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].os_state.fatalsig = sigNo; 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This does the business of delivering a signal to a thread. It may 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be called from either a real signal handler, or from normal code to 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cause the thread to enter the signal handler. 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This updates the thread state, but it does not set it to be 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Runnable. 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deliver_signal ( ThreadId tid, const vki_siginfo_t *info, 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct vki_ucontext *uc ) 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = info->si_signo; 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCSS_Per_Signal *handler = &scss.scss_per_sig[sigNo]; 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *handler_fn; 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("delivering signal %d (%s):%d to thread %d\n", 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, signame(sigNo), info->si_code, tid ); 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sigNo == VG_SIGVGKILL) { 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this is a SIGVGKILL, we're expecting it to interrupt any 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blocked syscall. It doesn't matter whether the VCPU state is 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set to restart or not, because we don't expect it will 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown execute any more client instructions. */ 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_exiting)(tid)); 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the client specifies SIG_IGN, treat it as SIG_DFL. 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If deliver_signal() is being called on a thread, we want 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the signal to get through no matter what; if they're ignoring 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it, then we do this override (this is so we can send it SIGSEGV, 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown etc). */ 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler_fn = handler->scss_handler; 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (handler_fn == VKI_SIG_IGN) 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler_fn = VKI_SIG_DFL; 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(handler_fn != VKI_SIG_IGN); 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (handler_fn == VKI_SIG_DFL) { 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default_action(info, tid); 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create a signal delivery frame, and set the client's %ESP and 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %EIP so that when execution continues, we will enter the 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal handler with the frame on top of the client's stack, 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as it expects. 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Signal delivery can fail if the client stack is too small or 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown missing, and we can't push the frame. If that happens, 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push_signal_frame will cause the whole process to exit when 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we next hit the scheduler. 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push_signal_frame ( tid, info, uc ); 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (handler->scss_flags & VKI_SA_ONESHOT) { 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do the ONESHOT thing. */ 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler->scss_handler = VKI_SIG_DFL; 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_SCSS_change( False /* lazy update */ ); 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At this point: 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_mask is the current signal mask 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tmp_sig_mask is the same as sig_mask, unless we're in sigsuspend 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler->scss_mask is the mask set by the handler 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Handler gets a mask of tmp_sig_mask|handler_mask|signo 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_mask = tst->tmp_sig_mask; 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(handler->scss_flags & VKI_SA_NOMASK)) { 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset_from_set)(&tst->sig_mask, &handler->scss_mask); 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaddset)(&tst->sig_mask, sigNo); 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tmp_sig_mask = tst->sig_mask; 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Thread state is ready to go - just add Runnable */ 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void resume_scheduler(ThreadId tid) 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->os_state.lwpid == VG_(gettid)()); 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tst->sched_jmpbuf_valid) { 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Can't continue; must longjmp back to the scheduler and thus 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enter the sighandler immediately. */ 1708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_MINIMAL_LONGJMP(tst->sched_jmpbuf); 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void synth_fault_common(ThreadId tid, Addr addr, Int si_code) 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGSEGV; 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = si_code; 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.VKI_SIGINFO_si_addr = (void*)addr; 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* even if gdbserver indicates to ignore the signal, we will deliver it */ 1724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdbserver_report_signal) (VKI_SIGSEGV, tid); 1725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If they're trying to block the signal, force it to be delivered */ 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigismember)(&VG_(threads)[tid].sig_mask, VKI_SIGSEGV)) 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(VKI_SIGSEGV); 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, &info, NULL); 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesize a fault where the address is OK, but the page 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// permissions are bad. 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_fault_perms)(ThreadId tid, Addr addr) 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_fault_common(tid, addr, VKI_SEGV_ACCERR); 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesize a fault where the address there's nothing mapped at the address. 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_fault_mapping)(ThreadId tid, Addr addr) 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_fault_common(tid, addr, VKI_SEGV_MAPERR); 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesize a misc memory fault. 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_fault)(ThreadId tid) 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_fault_common(tid, 0, VKI_SEGV_MADE_UP_GPF); 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesise a SIGILL. 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_sigill)(ThreadId tid, Addr addr) 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGILL; 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = VKI_ILL_ILLOPC; /* jrs: no idea what this should be */ 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.VKI_SIGINFO_si_addr = (void*)addr; 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (VKI_SIGILL, tid)) { 1765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, &info, NULL); 1767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesise a SIGBUS. 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_sigbus)(ThreadId tid) 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGBUS; 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There are several meanings to SIGBUS (as per POSIX, presumably), 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the most widely understood is "invalid address alignment", 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so let's use that. */ 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = VKI_BUS_ADRALN; 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we knew the invalid address in question, we could put it 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in .si_addr. Oh well. */ 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* info.VKI_SIGINFO_si_addr = (void*)addr; */ 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (VKI_SIGBUS, tid)) { 1790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, &info, NULL); 1792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Synthesise a SIGTRAP. 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(synth_sigtrap)(ThreadId tid) 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext uc; 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext32 mc; 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct __darwin_mcontext64 mc; 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_Runnable); 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&info, 0, sizeof(info)); 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&uc, 0, sizeof(uc)); 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_signo = VKI_SIGTRAP; 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */ 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext.trapno = 3; /* tjh: this is the x86 trap number 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for a breakpoint trap... */ 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext.err = 0; /* tjh: no error code for x86 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown breakpoint trap... */ 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* the same thing, but using Darwin field/struct names */ 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&mc, 0, sizeof(mc)); 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext = &mc; 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext->__es.__trapno = 3; 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc.uc_mcontext->__es.__err = 0; 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* fixs390: do we need to do anything here for s390 ? */ 1829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (VKI_SIGTRAP, tid)) { 1830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, &info, &uc); 1832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a signal pending for a thread, for later delivery. 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals) will arrange for it to be delivered at the right 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown time. 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid==0 means add it to the process-wide queue, and not sent it to a 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specific thread. 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid queue_signal(ThreadId tid, const vki_siginfo_t *si) 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst; 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SigQueue *sq; 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t savedmask; 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Protect the signal queue against async deliveries */ 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals(&savedmask); 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tst->sig_queue == NULL) { 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_queue = VG_(arena_malloc)(VG_AR_CORE, "signals.qs.1", 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(*tst->sig_queue)); 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(tst->sig_queue, 0, sizeof(*tst->sig_queue)); 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq = tst->sig_queue; 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Queueing signal %d (idx %d) to thread %d\n", 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown si->si_signo, sq->next, tid); 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add signal to the queue. If the queue gets overrun, then old 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queued signals may get lost. 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XXX We should also keep a sigset of pending signals, so that at 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown least a non-siginfo signal gets deliviered. 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sq->sigs[sq->next].si_signo != 0) 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Signal %d being dropped from thread %d's queue\n", 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[sq->next].si_signo, tid); 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[sq->next] = *si; 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->next = (sq->next+1) % N_QUEUED_SIGNALS; 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_all_host_signals(&savedmask); 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns the next queued signal for thread tid which is in "set". 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid==0 means process-wide signal. Set si_signo to 0 when the 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal has been delivered. 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Must be called with all signals blocked, to protect against async 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliveries. 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vki_siginfo_t *next_queued(ThreadId tid, const vki_sigset_t *set) 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SigQueue *sq; 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int idx; 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t *ret = NULL; 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq = tst->sig_queue; 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sq == NULL) 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown idx = sq->next; 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("idx=%d si_signo=%d inset=%d\n", idx, 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[idx].si_signo, 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigismember)(set, sq->sigs[idx].si_signo)); 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sq->sigs[idx].si_signo != 0 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(sigismember)(set, sq->sigs[idx].si_signo)) { 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Returning queued signal %d (idx %d) for thread %d\n", 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sq->sigs[idx].si_signo, idx, tid); 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = &sq->sigs[idx]; 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown idx = (idx + 1) % N_QUEUED_SIGNALS; 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while(idx != sq->next); 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out: 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sanitize_si_code(int si_code) 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The linux kernel uses the top 16 bits of si_code for it's own 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown use and only exports the bottom 16 bits to user space - at least 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that is the theory, but it turns out that there are some kernels 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown around that forget to mask out the top 16 bits so we do it here. 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The kernel treats the bottom 16 bits as signed and (when it does 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mask them off) sign extends them when exporting to user space so 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we do the same thing here. */ 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (Short)si_code; 1936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return si_code; 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Receive an async signal from the kernel. 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This should only happen when the thread is blocked in a syscall, 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown since that's the only time this set of signals is unblocked. 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid async_signalhandler ( Int sigNo, 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t *info, struct vki_ucontext *uc ) 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst = VG_(get_ThreadState)(tid); 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The thread isn't currently running, make it so before going on */ 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->status == VgTs_WaitSys); 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "async_signalhandler"); 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code = sanitize_si_code(info->si_code); 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("async signal handler: signal=%d, tid=%d, si_code=%d\n", 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, tid, info->si_code); 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Update thread state properly. The signal can only have been 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered whilst we were in 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown coregrind/m_syswrap/syscall-<PLAT>.S, and only then in the 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown window between the two sigprocmask calls, since at all other 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown times, we run with async signals on the host blocked. Hence 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown make enquiries on the basis that we were in or very close to a 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall, and attempt to fix up the guest state accordingly. 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (normal async signals occurring during computation are blocked, 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but periodically polled for using VG_(sigtimedwait_zero), and 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered at a point convenient for us. Hence this routine only 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deals with signals that are delivered to a thread during a 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall.) */ 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, extract a SysRes from the ucontext_t* given to this 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler. If it is subsequently established by 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) that the 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall was complete but the results had not been committed yet 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to the guest state, then it'll have to commit the results itself 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "by hand", and so we need to extract the SysRes. Of course if 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the thread was not in that particular window then the 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes will be meaningless, but that's OK too because 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted) will detect 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the thread was not in said window and ignore the SysRes. */ 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* To make matters more complex still, on Darwin we need to know 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the "class" of the syscall under consideration in order to be 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown able to extract the a correct SysRes. The class will have been 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown saved just before the syscall, by VG_(client_syscall), into this 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread's tst->arch.vex.guest_SC_CLASS. Hence: */ 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_UCONTEXT_SYSCALL_SYSRES(uc, tst->arch.vex.guest_SC_CLASS); 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_UCONTEXT_SYSCALL_SYSRES(uc); 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* (1) */ 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fixup_guest_state_after_syscall_interrupted)( 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_INSTR_PTR(uc), 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres, 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART) 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* (2) */ 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up the thread's state to deliver a signal */ 2013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_sig_ign(info->si_signo, tid)) 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, info, uc); 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It's crucial that (1) and (2) happen in the order (1) then (2) 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and not the other way around. (1) fixes up the guest thread 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state to reflect the fact that the syscall was interrupted -- 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either to restart the syscall or to return EINTR. (2) then sets 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown up the thread state to deliver the signal. Then we resume 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown execution. First, the signal handler is run, since that's the 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second adjustment we made to the thread state. If that returns, 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then we resume at the guest state created by (1), viz, either 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the syscall returns EINTR or is restarted. 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If (2) was done before (1) the outcome would be completely 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown different, and wrong. */ 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* longjmp back to the thread's main loop to start executing the 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler. */ 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resume_scheduler(tid); 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("async_signalhandler: got unexpected signal " 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "while outside of scheduler"); 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extend the stack to cover addr. maxsize is the limit the stack can grow to. 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns True on success, False on failure. 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Succeeds without doing anything if addr is already within a segment. 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Failure could be caused by: 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - addr not below a growable segment 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - new stack size would exceed maxsize 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - mmap failed for some other reason 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(extend_stack)(Addr addr, UInt maxsize) 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT udelta; 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find the next Segment above addr */ 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(am_find_nsegment)(addr); 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg_next 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = seg ? VG_(am_next_nsegment)( (NSegment*)seg, True/*fwds*/ ) 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : NULL; 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg && seg->kind == SkAnonC) 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* addr is already mapped. Nothing to do. */ 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that the requested new base is in a shrink-down 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reservation section which abuts an anonymous mapping that 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown belongs to the client. */ 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( ! (seg 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->kind == SkResvn 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->smode == SmUpper 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next->kind == SkAnonC 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->end+1 == seg_next->start)) 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown udelta = VG_PGROUNDUP(seg_next->start - addr); 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "signals", 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "extending a stack base 0x%llx down by %lld\n", 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg_next->start, (ULong)udelta); 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! VG_(am_extend_into_adjacent_reservation_client) 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( (NSegment*)seg_next, -(SSizeT)udelta )) { 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "signals", "extending a stack base: FAILED\n"); 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* When we change the main stack, we have to let the stack handling 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code know about it. */ 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(change_stack)(VG_(clstk_id), addr, VG_(clstk_end)); 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) > 2) 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_general)(False); 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void (*fault_catcher)(Int sig, Addr addr) = NULL; 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(set_fault_catcher)(void (*catcher)(Int, Addr)) 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "signals", "set fault catcher to %p\n", catcher); 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(NULL == catcher || NULL == fault_catcher, 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Fault catcher is already registered"); 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fault_catcher = catcher; 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sync_signalhandler_from_user ( ThreadId tid, 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc ) 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId qtid; 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If some user-process sent us a sync signal (ie. it's not the result 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of a faulting instruction), then how we treat it depends on when it 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arrives... */ 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_WaitSys) { 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal arrived while we're blocked in a syscall. This means that 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the client's signal mask was applied. In other words, so we can't 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get here unless the client wants this signal right now. This means 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we can simply use the async_signalhandler. */ 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Delivering user-sent sync signal %d as async signal\n", 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo); 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown async_signalhandler(sigNo, info, uc); 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("async_signalhandler returned!?\n"); 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Signal arrived while in generated client code, or while running 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valgrind core code. That means that every thread has these signals 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unblocked, so we can't rely on the kernel to route them properly, so 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we need to queue them manually. */ 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Routing user-sent sync signal %d via queue\n", sigNo); 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* On Linux, first we have to do a sanity check of the siginfo. */ 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->VKI_SIGINFO_si_pid == 0) { 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a per-user limit of pending siginfo signals. If 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown you exceed this, by having more than that number of 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pending signals with siginfo, then new signals are 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered without siginfo. This condition can be caused 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by any unrelated program you're running at the same time 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as Valgrind, if it has a large number of pending siginfo 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals which it isn't taking delivery of. 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Since we depend on siginfo to work out why we were sent a 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signal and what we should do about it, we really can't 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue unless we get it. */ 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Signal %d (%s) appears to have lost its siginfo; " 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "I can't go on.\n", sigNo, signame(sigNo)); 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" This may be because one of your programs has consumed your ration of\n" 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" siginfo structures. For more information, see:\n" 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" http://kerneltrap.org/mailarchive/1/message/25599/thread\n" 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" Basically, some program on your system is building up a large queue of\n" 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" pending signals, and this causes the siginfo data for other signals to\n" 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" be dropped because it's exceeding a system limit. However, Valgrind\n" 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" absolutely needs siginfo for SIGSEGV. A workaround is to track down the\n" 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" offending program and avoid running it while using Valgrind, but there\n" 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" is no easy way to do this. Apparently the problem was fixed in kernel\n" 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" 2.6.12.\n"); 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It's a fatal signal, so we force the default handler. */ 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(sigNo); 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, info, uc); 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resume_scheduler(tid); 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(99); /* If we can't resume, then just exit */ 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qtid = 0; /* shared pending by default */ 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->si_code == VKI_SI_TKILL) 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qtid = tid; /* directed to us specifically */ 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queue_signal(qtid, info); 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Returns the reported fault address for an exact address */ 2182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Addr fault_mask(Addr in) 2183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 2184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* We have to use VG_PGROUNDDN because faults on s390x only deliver 2185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the page address but not the address within a page. 2186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 2187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGA_s390x) 2188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return VG_PGROUNDDN(in); 2189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 2190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return in; 2191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 2192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 2193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Returns True if the sync signal was due to the stack requiring extension 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and the extension was successful. 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool extend_stack_if_appropriate(ThreadId tid, vki_siginfo_t* info) 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr fault; 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr esp; 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg; 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg_next; 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->si_signo != VKI_SIGSEGV) 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fault = (Addr)info->VKI_SIGINFO_si_addr; 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown esp = VG_(get_SP)(tid); 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg = VG_(am_find_nsegment)(fault); 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg_next = seg ? VG_(am_next_nsegment)( (NSegment*)seg, True/*fwds*/ ) 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : NULL; 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg == NULL) 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("SIGSEGV: si_code=%d faultaddr=%#lx tid=%d ESP=%#lx " 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "seg=NULL\n", 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code, fault, tid, esp); 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("SIGSEGV: si_code=%d faultaddr=%#lx tid=%d ESP=%#lx " 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "seg=%#lx-%#lx\n", 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code, fault, tid, esp, seg->start, seg->end); 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->si_code == VKI_SEGV_MAPERR 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->kind == SkResvn 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->smode == SmUpper 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg_next->kind == SkAnonC 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->end+1 == seg_next->start 2231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && fault >= fault_mask(esp - VG_STACK_REDZONE_SZB)) { 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the fault address is above esp but below the current known 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack segment base, and it was a fault because there was 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nothing mapped there (as opposed to a permissions fault), 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then extend the stack segment. 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr base = VG_PGROUNDDN(esp - VG_STACK_REDZONE_SZB); 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(extend_stack)(base, VG_(threads)[tid].client_stack_szB)) { 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)(" -> extended stack base to %#lx\n", 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_PGROUNDDN(fault)); 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Stack overflow in thread %d: can't grow stack to %#lx\n", 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, fault); 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sync_signalhandler_from_kernel ( ThreadId tid, 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc ) 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check to see if some part of Valgrind itself is interested in faults. 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The fault catcher should never be set whilst we're in generated code, so 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check for that. AFAIK the only use of the catcher right now is 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memcheck's leak detector. */ 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fault_catcher) { 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == False); 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*fault_catcher)(sigNo, (Addr)info->VKI_SIGINFO_si_addr); 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the catcher returns, then it didn't handle the fault, 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so carry on panicking. */ 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (extend_stack_if_appropriate(tid, info)) { 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Stack extension occurred, so we don't need to do anything else; upon 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown returning from this function, we'll restart the host (hence guest) 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction. */ 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, this is a signal we really have to deal with. If it came 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from the client's code, then we can jump back into the scheduler 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and have it delivered. Otherwise it's a Valgrind bug. */ 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigismember)(&tst->sig_mask, sigNo)) { 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* signal is blocked, but they're not allowed to block faults */ 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(sigNo); 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(in_generated_code)) { 2285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_report_signal) (sigNo, tid) 2286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || VG_(sigismember)(&tst->sig_mask, sigNo)) { 2287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Can't continue; must longjmp back to the scheduler and thus 2288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov enter the sighandler immediately. */ 2289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deliver_signal(tid, info, uc); 2290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 2291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 2293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resume_scheduler(tid); 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If resume_scheduler returns or its our fault, it means we 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown don't have longjmp set up, implying that we weren't running 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client code, and therefore it was actually generated by 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valgrind internally. 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("VALGRIND INTERNAL ERROR: Valgrind received " 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a signal %d (%s) - exiting\n", 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, signame(sigNo)); 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("si_code=%x; Faulting address: %p; sp: %#lx\n", 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code, info->VKI_SIGINFO_si_addr, 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_STACK_PTR(uc)); 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(kill_self)(sigNo); /* generate a core dump */ 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //if (tid == 0) /* could happen after everyone has exited */ 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // tid = VG_(master_tid); 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid != 0); 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UnwindStartRegs startRegs; 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&startRegs, 0, sizeof(startRegs)); 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_TO_UnwindStartRegs(&startRegs, uc); 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic_at)("Killed by fatal signal", &startRegs); 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Receive a sync signal from the host. 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sync_signalhandler ( Int sigNo, 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t *info, struct vki_ucontext *uc ) 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); 2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool from_user; 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sync_sighandler(%d, %p, %p)\n", sigNo, info, uc); 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(info != NULL); 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(info->si_signo == sigNo); 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo == VKI_SIGSEGV || 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGBUS || 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGFPE || 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGILL || 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo == VKI_SIGTRAP); 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->si_code = sanitize_si_code(info->si_code); 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from_user = !is_signal_from_kernel(tid, sigNo, info->si_code); 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sync signal handler: " 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "signal=%d, si_code=%d, EIP=%#lx, eip=%#lx, from %s\n", 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigNo, info->si_code, VG_(get_IP)(tid), 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_UCONTEXT_INSTR_PTR(uc), 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( from_user ? "user" : "kernel" )); 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal)); 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* // debug code: 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_signo %d\n", info->si_signo); 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_errno %d\n", info->si_errno); 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_code %d\n", info->si_code); 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_pid %d\n", info->si_pid); 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_uid %d\n", info->si_uid); 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_status %d\n", info->si_status); 2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("info->si_addr %p\n", info->si_addr); 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out if the signal is being sent from outside the process. 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Why do we care?) If the signal is from the user rather than the 2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel, then treat it more like an async signal than a sync signal -- 2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that is, merely queue it for later delivery. */ 2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (from_user) { 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sync_signalhandler_from_user( tid, sigNo, info, uc); 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sync_signalhandler_from_kernel(tid, sigNo, info, uc); 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Kill this thread. Makes it leave any syscall it might be currently 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blocked in, and return to the scheduler. This doesn't mark the thread 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as exiting; that's the caller's job. 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sigvgkill_handler(int signo, vki_siginfo_t *si, 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext *uc) 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadStatus at_signal = VG_(threads)[tid].status; 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("sigvgkill for lwp %d tid %d\n", VG_(gettid)(), tid); 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "sigvgkill_handler"); 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(signo == VG_SIGVGKILL); 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(si->si_signo == signo); 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* jrs 2006 August 3: the following assertion seems incorrect to 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown me, and fails on AIX. sigvgkill could be sent to a thread which 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is runnable - see VG_(nuke_all_threads_except) in the scheduler. 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence comment these out .. 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].status == VgTs_WaitSys); 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and instead do: 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (at_signal == VgTs_WaitSys) 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(post_syscall)(tid); 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* jrs 2006 August 3 ends */ 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resume_scheduler(tid); 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("sigvgkill_handler couldn't return to the scheduler\n"); 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __attribute((unused)) 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pp_ksigaction ( vki_sigaction_toK_t* sa ) 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n", 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa->ksa_handler, 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UInt)sa->sa_flags, 2427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa->sa_restorer 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)0 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("pp_ksigaction: { "); 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i <= VG_(max_signal); i++) 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigismember(&(sa->sa_mask),i))) 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%d ", i); 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("}\n"); 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Force signal handler to default 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(set_default_handler)(Int signo) 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t sa; 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.ksa_handler = VKI_SIG_DFL; 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_flags = 0; 2449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_restorer = 0; 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&sa.sa_mask); 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_sys_sigaction)(signo, &sa, NULL); 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Poll for pending signals, and set the next one up for delivery. 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(poll_signals)(ThreadId tid) 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t si, *sip; 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t pollset; 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t saved_mask; 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* look for all the signals this thread isn't blocking */ 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pollset = ~tst->sig_mask */ 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigcomplementset)( &pollset, &tst->sig_mask ); 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals(&saved_mask); // protect signal queue 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First look for any queued pending signals */ 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip = next_queued(tid, &pollset); /* this thread */ 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sip == NULL) 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip = next_queued(0, &pollset); /* process-wide */ 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If there was nothing queued, ask the kernel for a pending signal */ 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sip == NULL && VG_(sigtimedwait_zero)(&pollset, &si) > 0) { 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("poll_signals: got signal %d for thread %d\n", 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown si.si_signo, tid); 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip = &si; 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sip != NULL) { 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, something to do; deliver it */ 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Polling found signal %d for tid %d\n", sip->si_signo, tid); 2491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_sig_ign(sip->si_signo, tid)) 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deliver_signal(tid, sip, NULL); 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (VG_(clo_trace_signals)) 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)(" signal %d ignored\n", sip->si_signo); 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sip->si_signo = 0; /* remove from signal queue, if that's 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown where it came from */ 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_all_host_signals(&saved_mask); 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* At startup, copy the process' real signal state to the SCSS. 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Whilst doing this, block all real signals. Then calculate SKSS and 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set the kernel to that. Also initialise DCSS. 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigstartup_actions) ( void ) 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, ret, vKI_SIGRTMIN; 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t saved_procmask; 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t sa; 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&scss, 0, sizeof(scss)); 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&skss, 0, sizeof(skss)); 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_SIGRTMIN) 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vKI_SIGRTMIN = VKI_SIGRTMIN; 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vKI_SIGRTMIN = 0; /* eg Darwin */ 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(printf)("SIGSTARTUP\n"); */ 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Block all signals. saved_procmask remembers the previous mask, 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which the first thread inherits. 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_all_host_signals( &saved_procmask ); 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy per-signal settings to SCSS. */ 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i <= _VKI_NSIG; i++) { 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the old host action */ 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigaction)(i, NULL, &sa); 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* apparently we may not even ask about the disposition of these 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signals, let alone change them */ 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0 && (i == VKI_SIGKILL || i == VKI_SIGSTOP)) 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try setting it back to see if this signal is really 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown available */ 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vKI_SIGRTMIN > 0 /* it actually exists on this platform */ 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && i >= vKI_SIGRTMIN) { 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t tsa, sa2; 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsa.ksa_handler = (void *)sync_signalhandler; 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsa.sa_flags = VKI_SA_SIGINFO; 2551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsa.sa_restorer = 0; 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&tsa.sa_mask); 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* try setting it to some arbitrary handler */ 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sigaction)(i, &tsa, NULL) != 0) { 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* failed - not really usable */ 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(convert_sigaction_fromK_to_toK)( &sa, &sa2 ); 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(sigaction)(i, &sa2, NULL); 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret == 0); 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(max_signal) = i; 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2) 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("snaffling handler 0x%lx for signal %d\n", 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(sa.ksa_handler), i ); 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_handler = sa.ksa_handler; 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_flags = sa.sa_flags; 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_mask = sa.sa_mask; 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_restorer = NULL; 2578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_restorer = sa.sa_restorer; 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_sa_tramp = NULL; 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[i].scss_sa_tramp = NULL; 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*sa.sa_tramp;*/ 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We can't know what it was, because Darwin's sys_sigaction 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doesn't tell us. */ 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dmsg)("Max kernel-supported signal is %d\n", VG_(max_signal)); 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our private internal signals are treated as ignored */ 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[VG_SIGVGKILL].scss_handler = VKI_SIG_IGN; 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scss.scss_per_sig[VG_SIGVGKILL].scss_flags = VKI_SA_SIGINFO; 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&scss.scss_per_sig[VG_SIGVGKILL].scss_mask); 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy the process' signal mask into the root thread. */ 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[1].status == VgTs_Init); 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 2; i < VG_N_THREADS; i++) 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[i].status == VgTs_Empty); 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[1].sig_mask = saved_procmask; 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[1].tmp_sig_mask = saved_procmask; 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Calculate SKSS and apply it. This also sets the initial kernel 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mask we need to run with. */ 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_SCSS_change( True /* forced update */ ); 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Leave with all signals still blocked; the thread scheduler loop 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will set the appropriate mask at the appropriate time. */ 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2618