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