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