blob: 0aa44176ab9ad3cbaf6b32d2e4c8bbee85a5fb47 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njned6b8242005-06-01 00:03:17 +00003/*--- Implementation of POSIX signals. m_signals.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
njned6b8242005-06-01 00:03:17 +00005
sewardjde4a1d02002-03-22 01:27:54 +00006/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
jsgf855d93d2003-10-13 22:26:55 +000031/*
sewardjb5f6f512005-03-10 23:59:00 +000032 Signal handling.
jsgf855d93d2003-10-13 22:26:55 +000033
sewardjb5f6f512005-03-10 23:59:00 +000034 There are 4 distinct classes of signal:
jsgf855d93d2003-10-13 22:26:55 +000035
sewardjb5f6f512005-03-10 23:59:00 +000036 1. Synchronous, instruction-generated (SIGILL, FPE, BUS, SEGV and
37 TRAP): these are signals as a result of an instruction fault. If
38 we get one while running client code, then we just do the
39 appropriate thing. If it happens while running Valgrind code, then
40 it indicates a Valgrind bug. Note that we "manually" implement
41 automatic stack growth, such that if a fault happens near the
42 client process stack, it is extended in the same way the kernel
43 would, and the fault is never reported to the client program.
jsgf855d93d2003-10-13 22:26:55 +000044
sewardjb5f6f512005-03-10 23:59:00 +000045 2. Asynchronous varients of the above signals: If the kernel tries
46 to deliver a sync signal while it is blocked, it just kills the
47 process. Therefore, we can't block those signals if we want to be
48 able to report on bugs in Valgrind. This means that we're also
49 open to receiving those signals from other processes, sent with
50 kill. We could get away with just dropping them, since they aren't
51 really signals that processes send to each other.
jsgf855d93d2003-10-13 22:26:55 +000052
sewardjb5f6f512005-03-10 23:59:00 +000053 3. Synchronous, general signals. If a thread/process sends itself
54 a signal with kill, its expected to be synchronous: ie, the signal
55 will have been delivered by the time the syscall finishes.
56
57 4. Asyncronous, general signals. All other signals, sent by
58 another process with kill. These are generally blocked, except for
59 two special cases: we poll for them each time we're about to run a
60 thread for a time quanta, and while running blocking syscalls.
jsgf855d93d2003-10-13 22:26:55 +000061
jsgf855d93d2003-10-13 22:26:55 +000062
sewardjb5f6f512005-03-10 23:59:00 +000063 In addition, we define two signals for internal use: SIGVGCHLD and
64 SIGVGKILL. SIGVGCHLD is used to indicate thread death to any
65 reaping thread (the master thread). It is always blocked and never
66 delivered as a signal; it is always polled with sigtimedwait.
67
68 SIGVGKILL is used to terminate threads. When one thread wants
69 another to exit, it will set its exitreason and send it SIGVGKILL
70 if it appears to be blocked in a syscall.
71
72
73 We use a kernel thread for each application thread. When the
74 thread allows itself to be open to signals, it sets the thread
75 signal mask to what the client application set it to. This means
76 that we get the kernel to do all signal routing: under Valgrind,
77 signals get delivered in the same way as in the non-Valgrind case
78 (the exception being for the sync signal set, since they're almost
79 always unblocked).
jsgf855d93d2003-10-13 22:26:55 +000080 */
sewardjde4a1d02002-03-22 01:27:54 +000081
njnc7561b92005-06-19 01:24:32 +000082#include "pub_core_basics.h"
83#include "pub_core_threadstate.h"
njn899ce732005-06-21 00:28:11 +000084#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
njn2521d322005-05-08 14:45:13 +000085#include "pub_core_aspacemgr.h"
njn634a6522005-07-02 01:59:28 +000086#include "pub_core_debugger.h" // For VG_(start_debugger)
njnd2b17112005-04-19 04:10:25 +000087#include "pub_core_errormgr.h"
njn97405b22005-06-02 03:39:33 +000088#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000089#include "pub_core_libcassert.h"
njne9befc62005-06-11 15:51:30 +000090#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000091#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000092#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000093#include "pub_core_libcsignal.h"
njnf536bbb2005-06-13 04:21:38 +000094#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000095#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000096#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000097#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000098#include "pub_core_signals.h"
njn24a6efb2005-06-20 03:36:51 +000099#include "pub_core_sigframe.h" // For VG_(sigframe_create)()
njn945ed2e2005-06-24 03:28:30 +0000100#include "pub_core_stacks.h" // For VG_(change_stack)()
njn24a6efb2005-06-20 03:36:51 +0000101#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
njn9abd6082005-06-17 21:31:45 +0000102#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +0000103#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +0000104#include "pub_core_tooliface.h"
njn9abd6082005-06-17 21:31:45 +0000105#include "vki_unistd.h"
sewardj985fabb2005-04-24 14:18:14 +0000106
njnd2b17112005-04-19 04:10:25 +0000107
sewardj018f7622002-05-15 21:13:39 +0000108/* Define to give more sanity checking for signals. */
109#define DEBUG_SIGNALS
110
111
112/* ---------------------------------------------------------------------
113 Forwards decls.
114 ------------------------------------------------------------------ */
115
njn695c16e2005-03-27 03:40:28 +0000116static void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext * );
117static void async_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext * );
sewardjb5f6f512005-03-10 23:59:00 +0000118static void sigvgkill_handler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext * );
sewardj018f7622002-05-15 21:13:39 +0000119
jsgf855d93d2003-10-13 22:26:55 +0000120static const Char *signame(Int sigNo);
sewardj018f7622002-05-15 21:13:39 +0000121
sewardjb5f6f512005-03-10 23:59:00 +0000122/* Maximum usable signal. */
123Int VG_(max_signal) = _VKI_NSIG;
nethercote759dda32004-08-07 18:16:56 +0000124
sewardjb5f6f512005-03-10 23:59:00 +0000125#define N_QUEUED_SIGNALS 8
nethercote759dda32004-08-07 18:16:56 +0000126
sewardjb5f6f512005-03-10 23:59:00 +0000127typedef struct SigQueue {
128 Int next;
129 vki_siginfo_t sigs[N_QUEUED_SIGNALS];
130} SigQueue;
nethercote759dda32004-08-07 18:16:56 +0000131
njn605f4882005-05-29 17:50:40 +0000132#if defined(VGP_x86_linux)
njnaf839f52005-06-23 03:27:57 +0000133# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.eip)
134# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.esp)
135# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.ebp)
136# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.eax)
sewardjacaec5f2005-08-19 16:02:59 +0000137# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
sewardja8d8e232005-06-07 20:04:56 +0000138 /* Convert the value in uc_mcontext.eax into a SysRes. */ \
cerion85665ca2005-06-20 15:51:07 +0000139 VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax )
sewardjacaec5f2005-08-19 16:02:59 +0000140# define VG_UCONTEXT_LINK_REG(uc) 0 /* Dude, where's my LR? */
sewardje7aa4ae2005-06-09 12:43:42 +0000141
njn605f4882005-05-29 17:50:40 +0000142#elif defined(VGP_amd64_linux)
njnaf839f52005-06-23 03:27:57 +0000143# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip)
144# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp)
145# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.rbp)
146# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.rax)
sewardjacaec5f2005-08-19 16:02:59 +0000147# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
sewardje7aa4ae2005-06-09 12:43:42 +0000148 /* Convert the value in uc_mcontext.rax into a SysRes. */ \
cerion85665ca2005-06-20 15:51:07 +0000149 VG_(mk_SysRes_amd64_linux)( (uc)->uc_mcontext.rax )
sewardjacaec5f2005-08-19 16:02:59 +0000150# define VG_UCONTEXT_LINK_REG(uc) 0 /* No LR on amd64 either */
sewardje7aa4ae2005-06-09 12:43:42 +0000151
cerion85665ca2005-06-20 15:51:07 +0000152#elif defined(VGP_ppc32_linux)
njnaf839f52005-06-23 03:27:57 +0000153# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.mc_gregs[VKI_PT_NIP])
154# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.mc_gregs[1])
155# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.mc_gregs[1])
156# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.mc_gregs[0])
sewardjacaec5f2005-08-19 16:02:59 +0000157# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
cerion85665ca2005-06-20 15:51:07 +0000158 /* Convert the values in uc_mcontext r3,cr into a SysRes. */ \
159 VG_(mk_SysRes_ppc32_linux)( (uc)->uc_mcontext.mc_gregs[3], \
160 (uc)->uc_mcontext.mc_gregs[VKI_PT_CCR] )
sewardjacaec5f2005-08-19 16:02:59 +0000161# define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.mc_gregs[VKI_PT_LNK])
cerion85665ca2005-06-20 15:51:07 +0000162
njn605f4882005-05-29 17:50:40 +0000163#else
164# error Unknown platform
165#endif
166
nethercote759dda32004-08-07 18:16:56 +0000167/* ---------------------------------------------------------------------
sewardj018f7622002-05-15 21:13:39 +0000168 HIGH LEVEL STUFF TO DO WITH SIGNALS: POLICY (MOSTLY)
169 ------------------------------------------------------------------ */
170
sewardjde4a1d02002-03-22 01:27:54 +0000171/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000172 Signal state for this process.
173 ------------------------------------------------------------------ */
174
sewardj018f7622002-05-15 21:13:39 +0000175
nethercote73b526f2004-10-31 18:48:21 +0000176/* Base-ment of these arrays[_VKI_NSIG].
sewardjb48e5002002-05-13 00:16:03 +0000177
nethercote73b526f2004-10-31 18:48:21 +0000178 Valid signal numbers are 1 .. _VKI_NSIG inclusive.
sewardjb48e5002002-05-13 00:16:03 +0000179 Rather than subtracting 1 for indexing these arrays, which
180 is tedious and error-prone, they are simply dimensioned 1 larger,
181 and entry [0] is not used.
182 */
183
sewardjb48e5002002-05-13 00:16:03 +0000184
sewardj018f7622002-05-15 21:13:39 +0000185/* -----------------------------------------------------
186 Static client signal state (SCSS). This is the state
187 that the client thinks it has the kernel in.
188 SCSS records verbatim the client's settings. These
189 are mashed around only when SKSS is calculated from it.
190 -------------------------------------------------- */
sewardjb48e5002002-05-13 00:16:03 +0000191
sewardj018f7622002-05-15 21:13:39 +0000192typedef
193 struct {
194 void* scss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN or ptr to
195 client's handler */
196 UInt scss_flags;
nethercote73b526f2004-10-31 18:48:21 +0000197 vki_sigset_t scss_mask;
sewardjb5f6f512005-03-10 23:59:00 +0000198 void* scss_restorer; /* where sigreturn goes */
sewardj018f7622002-05-15 21:13:39 +0000199 }
200 SCSS_Per_Signal;
sewardjb48e5002002-05-13 00:16:03 +0000201
sewardj018f7622002-05-15 21:13:39 +0000202typedef
203 struct {
sewardj2342c972002-05-22 23:34:20 +0000204 /* per-signal info */
nethercote73b526f2004-10-31 18:48:21 +0000205 SCSS_Per_Signal scss_per_sig[1+_VKI_NSIG];
sewardj2342c972002-05-22 23:34:20 +0000206
sewardj018f7622002-05-15 21:13:39 +0000207 /* Additional elements to SCSS not stored here:
208 - for each thread, the thread's blocking mask
209 - for each thread in WaitSIG, the set of waited-on sigs
210 */
211 }
212 SCSS;
sewardjb48e5002002-05-13 00:16:03 +0000213
njn695c16e2005-03-27 03:40:28 +0000214static SCSS scss;
sewardj018f7622002-05-15 21:13:39 +0000215
216
217/* -----------------------------------------------------
218 Static kernel signal state (SKSS). This is the state
219 that we have the kernel in. It is computed from SCSS.
220 -------------------------------------------------- */
221
222/* Let's do:
223 sigprocmask assigns to all thread masks
224 so that at least everything is always consistent
225 Flags:
jsgf855d93d2003-10-13 22:26:55 +0000226 SA_SIGINFO -- we always set it, and honour it for the client
sewardj018f7622002-05-15 21:13:39 +0000227 SA_NOCLDSTOP -- passed to kernel
sewardjb5f6f512005-03-10 23:59:00 +0000228 SA_ONESHOT or SA_RESETHAND -- pass through
jsgf855d93d2003-10-13 22:26:55 +0000229 SA_RESTART -- we observe this but set our handlers to always restart
230 SA_NOMASK or SA_NODEFER -- we observe this, but our handlers block everything
sewardjb5f6f512005-03-10 23:59:00 +0000231 SA_ONSTACK -- pass through
232 SA_NOCLDWAIT -- pass through
sewardjb48e5002002-05-13 00:16:03 +0000233*/
sewardjde4a1d02002-03-22 01:27:54 +0000234
sewardj77e466c2002-04-14 02:29:29 +0000235
sewardj018f7622002-05-15 21:13:39 +0000236typedef
237 struct {
238 void* skss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN
239 or ptr to our handler */
240 UInt skss_flags;
241 /* There is no skss_mask, since we know that we will always ask
jsgf855d93d2003-10-13 22:26:55 +0000242 for all signals to be blocked in our sighandlers. */
sewardj018f7622002-05-15 21:13:39 +0000243 /* Also there is no skss_restorer. */
244 }
245 SKSS_Per_Signal;
sewardjde4a1d02002-03-22 01:27:54 +0000246
sewardj018f7622002-05-15 21:13:39 +0000247typedef
248 struct {
nethercote73b526f2004-10-31 18:48:21 +0000249 SKSS_Per_Signal skss_per_sig[1+_VKI_NSIG];
sewardj018f7622002-05-15 21:13:39 +0000250 }
251 SKSS;
252
njn695c16e2005-03-27 03:40:28 +0000253static SKSS skss;
sewardjde4a1d02002-03-22 01:27:54 +0000254
njn07ef6c02005-05-18 19:43:09 +0000255static Bool is_sig_ign(Int sigNo)
jsgf855d93d2003-10-13 22:26:55 +0000256{
nethercote73b526f2004-10-31 18:48:21 +0000257 vg_assert(sigNo >= 1 && sigNo <= _VKI_NSIG);
sewardj2e93c502002-04-12 11:12:52 +0000258
njn695c16e2005-03-27 03:40:28 +0000259 return scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_IGN;
jsgf855d93d2003-10-13 22:26:55 +0000260}
sewardjb48e5002002-05-13 00:16:03 +0000261
sewardj018f7622002-05-15 21:13:39 +0000262/* ---------------------------------------------------------------------
263 Compute the SKSS required by the current SCSS.
264 ------------------------------------------------------------------ */
265
sewardj4f29ddf2002-05-03 22:29:04 +0000266static
sewardj018f7622002-05-15 21:13:39 +0000267void pp_SKSS ( void )
268{
269 Int sig;
270 VG_(printf)("\n\nSKSS:\n");
nethercote73b526f2004-10-31 18:48:21 +0000271 for (sig = 1; sig <= _VKI_NSIG; sig++) {
sewardj018f7622002-05-15 21:13:39 +0000272 VG_(printf)("sig %d: handler 0x%x, flags 0x%x\n", sig,
njn695c16e2005-03-27 03:40:28 +0000273 skss.skss_per_sig[sig].skss_handler,
274 skss.skss_per_sig[sig].skss_flags );
sewardj77e466c2002-04-14 02:29:29 +0000275
sewardj018f7622002-05-15 21:13:39 +0000276 }
sewardj018f7622002-05-15 21:13:39 +0000277}
278
sewardj018f7622002-05-15 21:13:39 +0000279/* This is the core, clever bit. Computation is as follows:
280
281 For each signal
282 handler = if client has a handler, then our handler
jsgf855d93d2003-10-13 22:26:55 +0000283 else if client is DFL, then our handler as well
284 else (client must be IGN)
sewardjb5f6f512005-03-10 23:59:00 +0000285 then hander is IGN
sewardj018f7622002-05-15 21:13:39 +0000286*/
287static
288void calculate_SKSS_from_SCSS ( SKSS* dst )
289{
290 Int sig;
sewardj018f7622002-05-15 21:13:39 +0000291 UInt scss_flags;
292 UInt skss_flags;
293
nethercote73b526f2004-10-31 18:48:21 +0000294 for (sig = 1; sig <= _VKI_NSIG; sig++) {
jsgf855d93d2003-10-13 22:26:55 +0000295 void *skss_handler;
296 void *scss_handler;
297
njn695c16e2005-03-27 03:40:28 +0000298 scss_handler = scss.scss_per_sig[sig].scss_handler;
299 scss_flags = scss.scss_per_sig[sig].scss_flags;
sewardj018f7622002-05-15 21:13:39 +0000300
jsgf855d93d2003-10-13 22:26:55 +0000301 switch(sig) {
302 case VKI_SIGSEGV:
303 case VKI_SIGBUS:
304 case VKI_SIGFPE:
305 case VKI_SIGILL:
sewardjb5f6f512005-03-10 23:59:00 +0000306 case VKI_SIGTRAP:
jsgf855d93d2003-10-13 22:26:55 +0000307 /* For these, we always want to catch them and report, even
308 if the client code doesn't. */
njn695c16e2005-03-27 03:40:28 +0000309 skss_handler = sync_signalhandler;
jsgf855d93d2003-10-13 22:26:55 +0000310 break;
311
sewardjb5f6f512005-03-10 23:59:00 +0000312 case VKI_SIGCONT:
313 /* Let the kernel handle SIGCONT unless the client is actually
314 catching it. */
njna530fc62005-03-13 04:46:36 +0000315 case VKI_SIGCHLD:
316 case VKI_SIGWINCH:
317 case VKI_SIGURG:
318 /* For signals which are have a default action of Ignore,
319 only set a handler if the client has set a signal handler.
320 Otherwise the kernel will interrupt a syscall which
321 wouldn't have otherwise been interrupted. */
njn695c16e2005-03-27 03:40:28 +0000322 if (scss.scss_per_sig[sig].scss_handler == VKI_SIG_DFL)
sewardjb5f6f512005-03-10 23:59:00 +0000323 skss_handler = VKI_SIG_DFL;
njn695c16e2005-03-27 03:40:28 +0000324 else if (scss.scss_per_sig[sig].scss_handler == VKI_SIG_IGN)
jsgf855d93d2003-10-13 22:26:55 +0000325 skss_handler = VKI_SIG_IGN;
sewardjb5f6f512005-03-10 23:59:00 +0000326 else
njn695c16e2005-03-27 03:40:28 +0000327 skss_handler = async_signalhandler;
jsgf855d93d2003-10-13 22:26:55 +0000328 break;
jsgf855d93d2003-10-13 22:26:55 +0000329
sewardjb5f6f512005-03-10 23:59:00 +0000330 default:
njna530fc62005-03-13 04:46:36 +0000331 // VKI_SIGVG* are runtime variables, so we can't make them
332 // cases in the switch, so we handle them in the 'default' case.
njn351d0062005-06-21 22:23:59 +0000333 if (sig == VG_SIGVGKILL)
sewardjb5f6f512005-03-10 23:59:00 +0000334 skss_handler = sigvgkill_handler;
sewardjb5f6f512005-03-10 23:59:00 +0000335 else {
336 if (scss_handler == VKI_SIG_IGN)
337 skss_handler = VKI_SIG_IGN;
338 else
njn695c16e2005-03-27 03:40:28 +0000339 skss_handler = async_signalhandler;
sewardjb5f6f512005-03-10 23:59:00 +0000340 }
341 break;
342 }
sewardj018f7622002-05-15 21:13:39 +0000343
sewardj018f7622002-05-15 21:13:39 +0000344 /* Flags */
345
346 skss_flags = 0;
jsgf855d93d2003-10-13 22:26:55 +0000347
sewardjb5f6f512005-03-10 23:59:00 +0000348 /* SA_NOCLDSTOP, SA_NOCLDWAIT: pass to kernel */
349 skss_flags |= scss_flags & (VKI_SA_NOCLDSTOP | VKI_SA_NOCLDWAIT);
jsgf855d93d2003-10-13 22:26:55 +0000350
sewardj018f7622002-05-15 21:13:39 +0000351 /* SA_ONESHOT: ignore client setting */
sewardjb5f6f512005-03-10 23:59:00 +0000352
sewardja8d8e232005-06-07 20:04:56 +0000353 /* SA_RESTART: ignore client setting and always set it for us.
354 Though we never rely on the kernel to restart a
jsgf855d93d2003-10-13 22:26:55 +0000355 syscall, we observe whether it wanted to restart the syscall
sewardja8d8e232005-06-07 20:04:56 +0000356 or not, which is needed by
357 VG_(fixup_guest_state_after_syscall_interrupted) */
sewardj018f7622002-05-15 21:13:39 +0000358 skss_flags |= VKI_SA_RESTART;
jsgf855d93d2003-10-13 22:26:55 +0000359
360 /* SA_NOMASK: ignore it */
361
sewardj2342c972002-05-22 23:34:20 +0000362 /* SA_ONSTACK: client setting is irrelevant here */
sewardjb5f6f512005-03-10 23:59:00 +0000363 /* We don't set a signal stack, so ignore */
sewardj018f7622002-05-15 21:13:39 +0000364
jsgf855d93d2003-10-13 22:26:55 +0000365 /* always ask for SA_SIGINFO */
366 skss_flags |= VKI_SA_SIGINFO;
sewardj018f7622002-05-15 21:13:39 +0000367
fitzhardinge4f10ada2004-06-03 10:00:42 +0000368 /* use our own restorer */
369 skss_flags |= VKI_SA_RESTORER;
370
jsgf855d93d2003-10-13 22:26:55 +0000371 /* Create SKSS entry for this signal. */
sewardj6a3c26e2002-05-23 17:09:43 +0000372 if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
373 dst->skss_per_sig[sig].skss_handler = skss_handler;
374 else
375 dst->skss_per_sig[sig].skss_handler = VKI_SIG_DFL;
376
sewardj018f7622002-05-15 21:13:39 +0000377 dst->skss_per_sig[sig].skss_flags = skss_flags;
378 }
379
380 /* Sanity checks. */
nethercote5fd72bb2004-11-04 19:28:38 +0000381 vg_assert(dst->skss_per_sig[VKI_SIGKILL].skss_handler == VKI_SIG_DFL);
382 vg_assert(dst->skss_per_sig[VKI_SIGSTOP].skss_handler == VKI_SIG_DFL);
sewardj018f7622002-05-15 21:13:39 +0000383
384 if (0)
385 pp_SKSS();
386}
387
388
389/* ---------------------------------------------------------------------
390 After a possible SCSS change, update SKSS and the kernel itself.
391 ------------------------------------------------------------------ */
392
njn9abd6082005-06-17 21:31:45 +0000393// We need two levels of macro-expansion here to convert __NR_rt_sigreturn
394// to a number before converting it to a string... sigh.
tom3a088152005-06-22 12:11:42 +0000395static void my_sigreturn(void);
njn9abd6082005-06-17 21:31:45 +0000396
397#if defined(VGP_x86_linux)
398# define _MYSIG(name) \
399 "my_sigreturn:\n" \
400 " movl $" #name ", %eax\n" \
401 " int $0x80\n"
402#elif defined(VGP_amd64_linux)
403# define _MYSIG(name) \
404 "my_sigreturn:\n" \
405 " movq $" #name ", %rax\n" \
406 " syscall\n"
cerion85665ca2005-06-20 15:51:07 +0000407#elif defined(VGP_ppc32_linux)
408# define _MYSIG(name) \
409 "my_sigreturn:\n" \
410 " li 0, " #name "\n" \
411 " sc\n"
njn9abd6082005-06-17 21:31:45 +0000412#else
413# error Unknown platform
414#endif
415
416#define MYSIG(name) _MYSIG(name)
417asm(
418 MYSIG(__NR_rt_sigreturn)
419);
420
421
nethercote9dd11512004-08-04 15:31:30 +0000422static void handle_SCSS_change ( Bool force_update )
sewardj018f7622002-05-15 21:13:39 +0000423{
nethercote73b526f2004-10-31 18:48:21 +0000424 Int res, sig;
425 SKSS skss_old;
426 struct vki_sigaction ksa, ksa_old;
sewardj018f7622002-05-15 21:13:39 +0000427
sewardj018f7622002-05-15 21:13:39 +0000428 /* Remember old SKSS and calculate new one. */
njn695c16e2005-03-27 03:40:28 +0000429 skss_old = skss;
430 calculate_SKSS_from_SCSS ( &skss );
sewardj018f7622002-05-15 21:13:39 +0000431
432 /* Compare the new SKSS entries vs the old ones, and update kernel
433 where they differ. */
sewardjb5f6f512005-03-10 23:59:00 +0000434 for (sig = 1; sig <= VG_(max_signal); sig++) {
sewardj018f7622002-05-15 21:13:39 +0000435
436 /* Trying to do anything with SIGKILL is pointless; just ignore
437 it. */
438 if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP)
439 continue;
440
sewardj018f7622002-05-15 21:13:39 +0000441 if (!force_update) {
442 if ((skss_old.skss_per_sig[sig].skss_handler
njn695c16e2005-03-27 03:40:28 +0000443 == skss.skss_per_sig[sig].skss_handler)
sewardj018f7622002-05-15 21:13:39 +0000444 && (skss_old.skss_per_sig[sig].skss_flags
njn695c16e2005-03-27 03:40:28 +0000445 == skss.skss_per_sig[sig].skss_flags))
sewardj018f7622002-05-15 21:13:39 +0000446 /* no difference */
447 continue;
448 }
449
njn695c16e2005-03-27 03:40:28 +0000450 ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler;
451 ksa.sa_flags = skss.skss_per_sig[sig].skss_flags;
sewardjce2a6152005-07-08 18:25:13 +0000452# if !defined(VGP_ppc32_linux)
njn9abd6082005-06-17 21:31:45 +0000453 ksa.sa_restorer = my_sigreturn;
sewardjce2a6152005-07-08 18:25:13 +0000454# endif
sewardj162bebd2005-07-09 10:43:45 +0000455 /* Re above ifdef (also the assertion below), PaulM says:
456 The sa_restorer field is not used at all on ppc. Glibc
457 converts the sigaction you give it into a kernel sigaction,
458 but it doesn't put anything in the sa_restorer field.
459 */
fitzhardinge4f10ada2004-06-03 10:00:42 +0000460
sewardjb5f6f512005-03-10 23:59:00 +0000461 /* block all signals in handler */
nethercote73b526f2004-10-31 18:48:21 +0000462 VG_(sigfillset)( &ksa.sa_mask );
463 VG_(sigdelset)( &ksa.sa_mask, VKI_SIGKILL );
464 VG_(sigdelset)( &ksa.sa_mask, VKI_SIGSTOP );
sewardj018f7622002-05-15 21:13:39 +0000465
sewardjb5f6f512005-03-10 23:59:00 +0000466 if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2)
sewardj018f7622002-05-15 21:13:39 +0000467 VG_(message)(Vg_DebugMsg,
468 "setting ksig %d to: hdlr 0x%x, flags 0x%x, "
469 "mask(63..0) 0x%x 0x%x",
470 sig, ksa.ksa_handler,
nethercote73b526f2004-10-31 18:48:21 +0000471 ksa.sa_flags,
472 ksa.sa_mask.sig[1],
473 ksa.sa_mask.sig[0]
sewardj018f7622002-05-15 21:13:39 +0000474 );
475
nethercote73b526f2004-10-31 18:48:21 +0000476 res = VG_(sigaction)( sig, &ksa, &ksa_old );
sewardj018f7622002-05-15 21:13:39 +0000477 vg_assert(res == 0);
478
479 /* Since we got the old sigaction more or less for free, might
480 as well extract the maximum sanity-check value from it. */
481 if (!force_update) {
482 vg_assert(ksa_old.ksa_handler
483 == skss_old.skss_per_sig[sig].skss_handler);
nethercote73b526f2004-10-31 18:48:21 +0000484 vg_assert(ksa_old.sa_flags
sewardj018f7622002-05-15 21:13:39 +0000485 == skss_old.skss_per_sig[sig].skss_flags);
sewardjce2a6152005-07-08 18:25:13 +0000486# if !defined(VGP_ppc32_linux)
nethercote73b526f2004-10-31 18:48:21 +0000487 vg_assert(ksa_old.sa_restorer
njn9abd6082005-06-17 21:31:45 +0000488 == my_sigreturn);
sewardjce2a6152005-07-08 18:25:13 +0000489# endif
nethercote73b526f2004-10-31 18:48:21 +0000490 VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL );
491 VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGSTOP );
492 vg_assert(VG_(isfullsigset)( &ksa_old.sa_mask ));
sewardj018f7622002-05-15 21:13:39 +0000493 }
494 }
sewardj018f7622002-05-15 21:13:39 +0000495}
496
497
498/* ---------------------------------------------------------------------
499 Update/query SCSS in accordance with client requests.
500 ------------------------------------------------------------------ */
501
sewardj2342c972002-05-22 23:34:20 +0000502/* Logic for this alt-stack stuff copied directly from do_sigaltstack
503 in kernel/signal.[ch] */
504
505/* True if we are on the alternate signal stack. */
sewardjb5f6f512005-03-10 23:59:00 +0000506static Bool on_sig_stack ( ThreadId tid, Addr m_SP )
sewardj2342c972002-05-22 23:34:20 +0000507{
fitzhardinge98c4dc02004-03-16 08:27:29 +0000508 ThreadState *tst = VG_(get_ThreadState)(tid);
509
nethercote511e4062004-09-11 13:34:08 +0000510 return (m_SP - (Addr)tst->altstack.ss_sp < tst->altstack.ss_size);
sewardj2342c972002-05-22 23:34:20 +0000511}
512
nethercote511e4062004-09-11 13:34:08 +0000513static Int sas_ss_flags ( ThreadId tid, Addr m_SP )
sewardj2342c972002-05-22 23:34:20 +0000514{
fitzhardinge98c4dc02004-03-16 08:27:29 +0000515 ThreadState *tst = VG_(get_ThreadState)(tid);
516
517 return (tst->altstack.ss_size == 0
sewardj2342c972002-05-22 23:34:20 +0000518 ? VKI_SS_DISABLE
nethercote511e4062004-09-11 13:34:08 +0000519 : on_sig_stack(tid, m_SP) ? VKI_SS_ONSTACK : 0);
sewardj2342c972002-05-22 23:34:20 +0000520}
521
522
sewardja8d8e232005-06-07 20:04:56 +0000523SysRes VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss )
sewardj2342c972002-05-22 23:34:20 +0000524{
njn502badb2005-05-08 02:04:49 +0000525 Addr m_SP;
sewardj2342c972002-05-22 23:34:20 +0000526
527 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000528 m_SP = VG_(get_SP)(tid);
sewardj2342c972002-05-22 23:34:20 +0000529
530 if (VG_(clo_trace_signals))
531 VG_(message)(Vg_DebugExtraMsg,
nethercote04d3a802004-11-16 18:26:11 +0000532 "sys_sigaltstack: tid %d, "
nethercote511e4062004-09-11 13:34:08 +0000533 "ss %p, oss %p (current SP %p)",
534 tid, (void*)ss, (void*)oss, (void*)m_SP );
sewardj2342c972002-05-22 23:34:20 +0000535
536 if (oss != NULL) {
fitzhardinge98c4dc02004-03-16 08:27:29 +0000537 oss->ss_sp = VG_(threads)[tid].altstack.ss_sp;
538 oss->ss_size = VG_(threads)[tid].altstack.ss_size;
nethercote511e4062004-09-11 13:34:08 +0000539 oss->ss_flags = VG_(threads)[tid].altstack.ss_flags | sas_ss_flags(tid, m_SP);
sewardj2342c972002-05-22 23:34:20 +0000540 }
541
542 if (ss != NULL) {
njnf536bbb2005-06-13 04:21:38 +0000543 if (on_sig_stack(tid, VG_(get_SP)(tid))) {
sewardja8d8e232005-06-07 20:04:56 +0000544 return VG_(mk_SysRes_Error)( VKI_EPERM );
sewardj2342c972002-05-22 23:34:20 +0000545 }
546 if (ss->ss_flags != VKI_SS_DISABLE
547 && ss->ss_flags != VKI_SS_ONSTACK
548 && ss->ss_flags != 0) {
sewardja8d8e232005-06-07 20:04:56 +0000549 return VG_(mk_SysRes_Error)( VKI_EINVAL );
sewardj2342c972002-05-22 23:34:20 +0000550 }
551 if (ss->ss_flags == VKI_SS_DISABLE) {
fitzhardinge98c4dc02004-03-16 08:27:29 +0000552 VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE;
sewardj2342c972002-05-22 23:34:20 +0000553 } else {
554 if (ss->ss_size < VKI_MINSIGSTKSZ) {
sewardja8d8e232005-06-07 20:04:56 +0000555 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
sewardj2342c972002-05-22 23:34:20 +0000556 }
jsgf855d93d2003-10-13 22:26:55 +0000557
nethercote20283c62004-11-04 19:43:22 +0000558 VG_(threads)[tid].altstack.ss_sp = ss->ss_sp;
559 VG_(threads)[tid].altstack.ss_size = ss->ss_size;
fitzhardinge98c4dc02004-03-16 08:27:29 +0000560 VG_(threads)[tid].altstack.ss_flags = 0;
sewardj2342c972002-05-22 23:34:20 +0000561 }
sewardj2342c972002-05-22 23:34:20 +0000562 }
sewardja8d8e232005-06-07 20:04:56 +0000563 return VG_(mk_SysRes_Success)( 0 );
sewardj2342c972002-05-22 23:34:20 +0000564}
565
566
sewardja8d8e232005-06-07 20:04:56 +0000567SysRes VG_(do_sys_sigaction) ( Int signo,
568 const struct vki_sigaction *new_act,
569 struct vki_sigaction *old_act )
sewardj018f7622002-05-15 21:13:39 +0000570{
sewardj018f7622002-05-15 21:13:39 +0000571 if (VG_(clo_trace_signals))
572 VG_(message)(Vg_DebugExtraMsg,
sewardjb5f6f512005-03-10 23:59:00 +0000573 "sys_sigaction: sigNo %d, "
nethercote93246cf2004-11-04 18:56:47 +0000574 "new %p, old %p, new flags 0x%llx",
sewardjb5f6f512005-03-10 23:59:00 +0000575 signo, (UWord)new_act, (UWord)old_act,
nethercote93246cf2004-11-04 18:56:47 +0000576 (ULong)(new_act ? new_act->sa_flags : 0) );
sewardj018f7622002-05-15 21:13:39 +0000577
578 /* Rule out various error conditions. The aim is to ensure that if
579 when the call is passed to the kernel it will definitely
580 succeed. */
581
582 /* Reject out-of-range signal numbers. */
sewardjb5f6f512005-03-10 23:59:00 +0000583 if (signo < 1 || signo > VG_(max_signal)) goto bad_signo;
sewardj018f7622002-05-15 21:13:39 +0000584
jsgf855d93d2003-10-13 22:26:55 +0000585 /* don't let them use our signals */
njn351d0062005-06-21 22:23:59 +0000586 if ( (signo > VG_SIGVGRTUSERMAX)
jsgf855d93d2003-10-13 22:26:55 +0000587 && new_act
sewardja8d8e232005-06-07 20:04:56 +0000588 && !(new_act->ksa_handler == VKI_SIG_DFL
589 || new_act->ksa_handler == VKI_SIG_IGN) )
nethercote9c42a0f2003-11-17 10:37:19 +0000590 goto bad_signo_reserved;
jsgf855d93d2003-10-13 22:26:55 +0000591
sewardj018f7622002-05-15 21:13:39 +0000592 /* Reject attempts to set a handler (or set ignore) for SIGKILL. */
593 if ( (signo == VKI_SIGKILL || signo == VKI_SIGSTOP)
594 && new_act
595 && new_act->ksa_handler != VKI_SIG_DFL)
596 goto bad_sigkill_or_sigstop;
597
598 /* If the client supplied non-NULL old_act, copy the relevant SCSS
599 entry into it. */
600 if (old_act) {
njn695c16e2005-03-27 03:40:28 +0000601 old_act->ksa_handler = scss.scss_per_sig[signo].scss_handler;
602 old_act->sa_flags = scss.scss_per_sig[signo].scss_flags;
603 old_act->sa_mask = scss.scss_per_sig[signo].scss_mask;
604 old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer;
sewardj018f7622002-05-15 21:13:39 +0000605 }
606
607 /* And now copy new SCSS entry from new_act. */
608 if (new_act) {
njn695c16e2005-03-27 03:40:28 +0000609 scss.scss_per_sig[signo].scss_handler = new_act->ksa_handler;
610 scss.scss_per_sig[signo].scss_flags = new_act->sa_flags;
611 scss.scss_per_sig[signo].scss_mask = new_act->sa_mask;
612 scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer;
sewardjb5f6f512005-03-10 23:59:00 +0000613
njn695c16e2005-03-27 03:40:28 +0000614 VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGKILL);
615 VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGSTOP);
sewardj018f7622002-05-15 21:13:39 +0000616 }
617
618 /* All happy bunnies ... */
619 if (new_act) {
nethercote9dd11512004-08-04 15:31:30 +0000620 handle_SCSS_change( False /* lazy update */ );
sewardj018f7622002-05-15 21:13:39 +0000621 }
sewardja8d8e232005-06-07 20:04:56 +0000622 return VG_(mk_SysRes_Success)( 0 );
sewardj018f7622002-05-15 21:13:39 +0000623
624 bad_signo:
njn0087c502005-07-01 04:15:36 +0000625 if (VG_(showing_core_errors)()) {
njn25e49d8e72002-09-23 09:36:25 +0000626 VG_(message)(Vg_UserMsg,
nethercote9c42a0f2003-11-17 10:37:19 +0000627 "Warning: bad signal number %d in sigaction()",
njn25e49d8e72002-09-23 09:36:25 +0000628 signo);
sewardj9a3d8bd2005-05-23 14:47:52 +0000629 }
sewardja8d8e232005-06-07 20:04:56 +0000630 return VG_(mk_SysRes_Error)( VKI_EINVAL );
sewardj018f7622002-05-15 21:13:39 +0000631
nethercote9c42a0f2003-11-17 10:37:19 +0000632 bad_signo_reserved:
njn0087c502005-07-01 04:15:36 +0000633 if (VG_(showing_core_errors)()) {
nethercote9c42a0f2003-11-17 10:37:19 +0000634 VG_(message)(Vg_UserMsg,
635 "Warning: ignored attempt to set %s handler in sigaction();",
636 signame(signo));
637 VG_(message)(Vg_UserMsg,
638 " the %s signal is used internally by Valgrind",
639 signame(signo));
fitzhardingebf459872003-11-18 16:55:33 +0000640 }
sewardja8d8e232005-06-07 20:04:56 +0000641 return VG_(mk_SysRes_Error)( VKI_EINVAL );
nethercote9c42a0f2003-11-17 10:37:19 +0000642
sewardj018f7622002-05-15 21:13:39 +0000643 bad_sigkill_or_sigstop:
njn0087c502005-07-01 04:15:36 +0000644 if (VG_(showing_core_errors)()) {
njn25e49d8e72002-09-23 09:36:25 +0000645 VG_(message)(Vg_UserMsg,
nethercote9c42a0f2003-11-17 10:37:19 +0000646 "Warning: ignored attempt to set %s handler in sigaction();",
jsgf855d93d2003-10-13 22:26:55 +0000647 signame(signo));
nethercote9c42a0f2003-11-17 10:37:19 +0000648 VG_(message)(Vg_UserMsg,
649 " the %s signal is uncatchable",
650 signame(signo));
sewardj9a3d8bd2005-05-23 14:47:52 +0000651 }
sewardja8d8e232005-06-07 20:04:56 +0000652 return VG_(mk_SysRes_Error)( VKI_EINVAL );
sewardj018f7622002-05-15 21:13:39 +0000653}
654
655
656static
657void do_sigprocmask_bitops ( Int vki_how,
nethercote73b526f2004-10-31 18:48:21 +0000658 vki_sigset_t* orig_set,
659 vki_sigset_t* modifier )
sewardj018f7622002-05-15 21:13:39 +0000660{
661 switch (vki_how) {
662 case VKI_SIG_BLOCK:
nethercote73b526f2004-10-31 18:48:21 +0000663 VG_(sigaddset_from_set)( orig_set, modifier );
sewardj018f7622002-05-15 21:13:39 +0000664 break;
665 case VKI_SIG_UNBLOCK:
nethercote73b526f2004-10-31 18:48:21 +0000666 VG_(sigdelset_from_set)( orig_set, modifier );
sewardj018f7622002-05-15 21:13:39 +0000667 break;
668 case VKI_SIG_SETMASK:
669 *orig_set = *modifier;
670 break;
671 default:
njne427a662002-10-02 11:08:25 +0000672 VG_(core_panic)("do_sigprocmask_bitops");
sewardj018f7622002-05-15 21:13:39 +0000673 break;
674 }
675}
676
jsgf855d93d2003-10-13 22:26:55 +0000677/*
678 This updates the thread's signal mask. There's no such thing as a
679 process-wide signal mask.
sewardj018f7622002-05-15 21:13:39 +0000680
681 Note that the thread signal masks are an implicit part of SCSS,
682 which is why this routine is allowed to mess with them.
683*/
684static
685void do_setmask ( ThreadId tid,
686 Int how,
nethercote73b526f2004-10-31 18:48:21 +0000687 vki_sigset_t* newset,
688 vki_sigset_t* oldset )
sewardj018f7622002-05-15 21:13:39 +0000689{
sewardj018f7622002-05-15 21:13:39 +0000690 if (VG_(clo_trace_signals))
sewardja464e5c2002-05-23 17:34:49 +0000691 VG_(message)(Vg_DebugExtraMsg,
jsgf855d93d2003-10-13 22:26:55 +0000692 "do_setmask: tid = %d how = %d (%s), set = %p %08x%08x",
693 tid, how,
694 how==VKI_SIG_BLOCK ? "SIG_BLOCK" : (
695 how==VKI_SIG_UNBLOCK ? "SIG_UNBLOCK" : (
696 how==VKI_SIG_SETMASK ? "SIG_SETMASK" : "???")),
nethercote73b526f2004-10-31 18:48:21 +0000697 newset, newset ? newset->sig[1] : 0, newset ? newset->sig[0] : 0
jsgf855d93d2003-10-13 22:26:55 +0000698 );
sewardj018f7622002-05-15 21:13:39 +0000699
jsgf855d93d2003-10-13 22:26:55 +0000700 /* Just do this thread. */
701 vg_assert(VG_(is_valid_tid)(tid));
702 if (oldset) {
sewardjb5f6f512005-03-10 23:59:00 +0000703 *oldset = VG_(threads)[tid].sig_mask;
jsgf855d93d2003-10-13 22:26:55 +0000704 if (VG_(clo_trace_signals))
705 VG_(message)(Vg_DebugExtraMsg,
706 "\toldset=%p %08x%08x",
nethercote73b526f2004-10-31 18:48:21 +0000707 oldset, oldset->sig[1], oldset->sig[0]);
sewardj018f7622002-05-15 21:13:39 +0000708 }
sewardj018f7622002-05-15 21:13:39 +0000709 if (newset) {
jsgf855d93d2003-10-13 22:26:55 +0000710 do_sigprocmask_bitops (how, &VG_(threads)[tid].sig_mask, newset );
nethercote73b526f2004-10-31 18:48:21 +0000711 VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGKILL);
712 VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGSTOP);
sewardjb5f6f512005-03-10 23:59:00 +0000713 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
sewardj018f7622002-05-15 21:13:39 +0000714 }
715}
716
717
sewardja8d8e232005-06-07 20:04:56 +0000718SysRes VG_(do_sys_sigprocmask) ( ThreadId tid,
719 Int how,
720 vki_sigset_t* set,
721 vki_sigset_t* oldset )
sewardj018f7622002-05-15 21:13:39 +0000722{
jsgf855d93d2003-10-13 22:26:55 +0000723 switch(how) {
724 case VKI_SIG_BLOCK:
725 case VKI_SIG_UNBLOCK:
726 case VKI_SIG_SETMASK:
sewardj018f7622002-05-15 21:13:39 +0000727 vg_assert(VG_(is_valid_tid)(tid));
jsgf855d93d2003-10-13 22:26:55 +0000728 do_setmask ( tid, how, set, oldset );
sewardja8d8e232005-06-07 20:04:56 +0000729 return VG_(mk_SysRes_Success)( 0 );
jsgf855d93d2003-10-13 22:26:55 +0000730
731 default:
sewardj018f7622002-05-15 21:13:39 +0000732 VG_(message)(Vg_DebugMsg,
njn02bc4b82005-05-15 17:28:26 +0000733 "sigprocmask: unknown 'how' field %d", how);
sewardja8d8e232005-06-07 20:04:56 +0000734 return VG_(mk_SysRes_Error)( VKI_EINVAL );
sewardj018f7622002-05-15 21:13:39 +0000735 }
736}
737
738
sewardj018f7622002-05-15 21:13:39 +0000739/* ---------------------------------------------------------------------
740 LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION
741 ------------------------------------------------------------------ */
sewardj77e466c2002-04-14 02:29:29 +0000742
sewardj2e93c502002-04-12 11:12:52 +0000743/* ---------------------------------------------------------------------
744 Handy utilities to block/restore all host signals.
745 ------------------------------------------------------------------ */
746
747/* Block all host signals, dumping the old mask in *saved_mask. */
njn444eba12005-05-12 03:47:31 +0000748static void block_all_host_signals ( /* OUT */ vki_sigset_t* saved_mask )
sewardj2e93c502002-04-12 11:12:52 +0000749{
750 Int ret;
nethercote73b526f2004-10-31 18:48:21 +0000751 vki_sigset_t block_procmask;
752 VG_(sigfillset)(&block_procmask);
753 ret = VG_(sigprocmask)
sewardj2e93c502002-04-12 11:12:52 +0000754 (VKI_SIG_SETMASK, &block_procmask, saved_mask);
755 vg_assert(ret == 0);
756}
757
758/* Restore the blocking mask using the supplied saved one. */
njn444eba12005-05-12 03:47:31 +0000759static void restore_all_host_signals ( /* IN */ vki_sigset_t* saved_mask )
sewardj2e93c502002-04-12 11:12:52 +0000760{
761 Int ret;
nethercote73b526f2004-10-31 18:48:21 +0000762 ret = VG_(sigprocmask)(VKI_SIG_SETMASK, saved_mask, NULL);
sewardj2e93c502002-04-12 11:12:52 +0000763 vg_assert(ret == 0);
764}
sewardjde4a1d02002-03-22 01:27:54 +0000765
njn444eba12005-05-12 03:47:31 +0000766void VG_(clear_out_queued_signals)( ThreadId tid, vki_sigset_t* saved_mask )
767{
768 block_all_host_signals(saved_mask);
769 if (VG_(threads)[tid].sig_queue != NULL) {
770 VG_(arena_free)(VG_AR_CORE, VG_(threads)[tid].sig_queue);
771 VG_(threads)[tid].sig_queue = NULL;
772 }
773 restore_all_host_signals(saved_mask);
774}
775
sewardjde4a1d02002-03-22 01:27:54 +0000776/* ---------------------------------------------------------------------
777 The signal simulation proper. A simplified version of what the
778 Linux kernel does.
779 ------------------------------------------------------------------ */
780
sewardjde4a1d02002-03-22 01:27:54 +0000781/* Set up a stack frame (VgSigContext) for the client's signal
nethercotefedd8102004-09-13 15:19:34 +0000782 handler. */
sewardj2c5ffbe2005-03-12 13:32:06 +0000783static
njn695c16e2005-03-27 03:40:28 +0000784void push_signal_frame ( ThreadId tid, const vki_siginfo_t *siginfo )
sewardjde4a1d02002-03-22 01:27:54 +0000785{
nethercote6eec4602004-09-13 14:15:36 +0000786 Addr esp_top_of_frame;
sewardj2e93c502002-04-12 11:12:52 +0000787 ThreadState* tst;
jsgf855d93d2003-10-13 22:26:55 +0000788 Int sigNo = siginfo->si_signo;
sewardj2e93c502002-04-12 11:12:52 +0000789
sewardjb5f6f512005-03-10 23:59:00 +0000790 vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal));
sewardj018f7622002-05-15 21:13:39 +0000791 vg_assert(VG_(is_valid_tid)(tid));
792 tst = & VG_(threads)[tid];
sewardj2e93c502002-04-12 11:12:52 +0000793
jsgf855d93d2003-10-13 22:26:55 +0000794 if (VG_(clo_trace_signals))
795 VG_(message)(Vg_DebugMsg,
njn695c16e2005-03-27 03:40:28 +0000796 "push_signal_frame (thread %d): signal %d", tid, sigNo);
jsgf855d93d2003-10-13 22:26:55 +0000797
sewardj2342c972002-05-22 23:34:20 +0000798 if (/* this signal asked to run on an alt stack */
njn695c16e2005-03-27 03:40:28 +0000799 (scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONSTACK )
sewardj2342c972002-05-22 23:34:20 +0000800 && /* there is a defined and enabled alt stack, which we're not
801 already using. Logic from get_sigframe in
802 arch/i386/kernel/signal.c. */
njnf536bbb2005-06-13 04:21:38 +0000803 sas_ss_flags(tid, VG_(get_SP)(tid)) == 0
sewardj2342c972002-05-22 23:34:20 +0000804 ) {
805 esp_top_of_frame
fitzhardinge98c4dc02004-03-16 08:27:29 +0000806 = (Addr)(tst->altstack.ss_sp) + tst->altstack.ss_size;
sewardj2342c972002-05-22 23:34:20 +0000807 if (VG_(clo_trace_signals))
808 VG_(message)(Vg_DebugMsg,
sewardjb5f6f512005-03-10 23:59:00 +0000809 "delivering signal %d (%s) to thread %d: on ALT STACK (%p-%p; %d bytes)",
810 sigNo, signame(sigNo), tid,
811 tst->altstack.ss_sp,
812 tst->altstack.ss_sp + tst->altstack.ss_size,
813 tst->altstack.ss_size );
njnfdc28af2003-02-24 10:36:48 +0000814
nethercote7cc9c232004-01-21 15:08:04 +0000815 /* Signal delivery to tools */
fitzhardinge98c4dc02004-03-16 08:27:29 +0000816 VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/True );
njnfdc28af2003-02-24 10:36:48 +0000817
sewardj2342c972002-05-22 23:34:20 +0000818 } else {
njnaf839f52005-06-23 03:27:57 +0000819 esp_top_of_frame = VG_(get_SP)(tid) - VG_STACK_REDZONE_SZB;
njnfdc28af2003-02-24 10:36:48 +0000820
nethercote7cc9c232004-01-21 15:08:04 +0000821 /* Signal delivery to tools */
fitzhardinge98c4dc02004-03-16 08:27:29 +0000822 VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/False );
sewardj2342c972002-05-22 23:34:20 +0000823 }
sewardjb5f6f512005-03-10 23:59:00 +0000824
njn695c16e2005-03-27 03:40:28 +0000825 vg_assert(scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN);
826 vg_assert(scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL);
sewardjb5f6f512005-03-10 23:59:00 +0000827
828 /* This may fail if the client stack is busted; if that happens,
829 the whole process will exit rather than simply calling the
830 signal handler. */
sewardj985fabb2005-04-24 14:18:14 +0000831 VG_(sigframe_create) (tid, esp_top_of_frame, siginfo,
832 scss.scss_per_sig[sigNo].scss_handler,
833 scss.scss_per_sig[sigNo].scss_flags,
834 &tst->sig_mask,
835 scss.scss_per_sig[sigNo].scss_restorer);
sewardjde4a1d02002-03-22 01:27:54 +0000836}
837
sewardjde4a1d02002-03-22 01:27:54 +0000838
jsgf855d93d2003-10-13 22:26:55 +0000839static const Char *signame(Int sigNo)
sewardjde4a1d02002-03-22 01:27:54 +0000840{
jsgf855d93d2003-10-13 22:26:55 +0000841 static Char buf[10];
sewardjb48e5002002-05-13 00:16:03 +0000842
jsgf855d93d2003-10-13 22:26:55 +0000843 switch(sigNo) {
844#define S(x) case VKI_##x: return #x
845 S(SIGHUP);
846 S(SIGINT);
847 S(SIGQUIT);
848 S(SIGILL);
849 S(SIGTRAP);
850 S(SIGABRT);
851 S(SIGBUS);
852 S(SIGFPE);
853 S(SIGKILL);
854 S(SIGUSR1);
855 S(SIGUSR2);
856 S(SIGSEGV);
857 S(SIGPIPE);
858 S(SIGALRM);
859 S(SIGTERM);
860 S(SIGSTKFLT);
861 S(SIGCHLD);
862 S(SIGCONT);
863 S(SIGSTOP);
864 S(SIGTSTP);
865 S(SIGTTIN);
866 S(SIGTTOU);
867 S(SIGURG);
868 S(SIGXCPU);
869 S(SIGXFSZ);
870 S(SIGVTALRM);
871 S(SIGPROF);
872 S(SIGWINCH);
873 S(SIGIO);
874 S(SIGPWR);
875 S(SIGUNUSED);
876#undef S
sewardjde4a1d02002-03-22 01:27:54 +0000877
jsgf855d93d2003-10-13 22:26:55 +0000878 case VKI_SIGRTMIN ... VKI_SIGRTMAX:
sewardjb5f6f512005-03-10 23:59:00 +0000879 VG_(sprintf)(buf, "SIGRT%d", sigNo-VKI_SIGRTMIN);
jsgf855d93d2003-10-13 22:26:55 +0000880 return buf;
sewardjde4a1d02002-03-22 01:27:54 +0000881
jsgf855d93d2003-10-13 22:26:55 +0000882 default:
883 VG_(sprintf)(buf, "SIG%d", sigNo);
884 return buf;
885 }
886}
sewardjde4a1d02002-03-22 01:27:54 +0000887
jsgf855d93d2003-10-13 22:26:55 +0000888/* Hit ourselves with a signal using the default handler */
889void VG_(kill_self)(Int sigNo)
890{
nethercote73b526f2004-10-31 18:48:21 +0000891 vki_sigset_t mask, origmask;
892 struct vki_sigaction sa, origsa;
sewardj018f7622002-05-15 21:13:39 +0000893
jsgf855d93d2003-10-13 22:26:55 +0000894 sa.ksa_handler = VKI_SIG_DFL;
nethercote73b526f2004-10-31 18:48:21 +0000895 sa.sa_flags = 0;
896 sa.sa_restorer = 0;
897 VG_(sigemptyset)(&sa.sa_mask);
sewardj2e93c502002-04-12 11:12:52 +0000898
nethercote73b526f2004-10-31 18:48:21 +0000899 VG_(sigaction)(sigNo, &sa, &origsa);
sewardj018f7622002-05-15 21:13:39 +0000900
sewardjb5f6f512005-03-10 23:59:00 +0000901 VG_(sigemptyset)(&mask);
902 VG_(sigaddset)(&mask, sigNo);
903 VG_(sigprocmask)(VKI_SIG_UNBLOCK, &mask, &origmask);
jsgf855d93d2003-10-13 22:26:55 +0000904
tomb9b10c72005-07-20 16:05:28 +0000905 VG_(kill)(VG_(getpid)(), sigNo);
jsgf855d93d2003-10-13 22:26:55 +0000906
nethercote73b526f2004-10-31 18:48:21 +0000907 VG_(sigaction)(sigNo, &origsa, NULL);
908 VG_(sigprocmask)(VKI_SIG_SETMASK, &origmask, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000909}
910
njn277a6d62004-11-26 14:07:24 +0000911// Core dumping is disabled until someone can work out how to abstract out
912// the arch-specific and word-size-specific parts neatly.
njnbde30272004-11-29 15:45:31 +0000913//
914// Note that the code below is not 64-bit clean!
915//
njn277a6d62004-11-26 14:07:24 +0000916#if 0
fitzhardinged65dcad2004-03-13 02:06:58 +0000917/*
918 Dump core
919
920 Generate a standard ELF core file corresponding to the client state
921 at the time of a crash.
922 */
923#include <elf.h>
924#ifndef NT_PRXFPREG
925#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
926#endif /* NT_PRXFPREG */
927
928/* If true, then this Segment may be mentioned in the core */
929static Bool may_dump(const Segment *seg)
930{
njn0ae787c2005-06-28 22:14:53 +0000931 return (seg->flags & SF_VALGRIND) == 0 && VG_(is_client_addr)(seg->addr);
fitzhardinged65dcad2004-03-13 02:06:58 +0000932}
933
934/* If true, then this Segment's contents will be in the core */
935static Bool should_dump(const Segment *seg)
936{
937 return may_dump(seg); // && (seg->prot & VKI_PROT_WRITE);
938}
939
940static void fill_ehdr(Elf32_Ehdr *ehdr, Int num_phdrs)
941{
njne1d981a2005-03-11 04:47:23 +0000942 VG_(memset)(ehdr, 0, sizeof(*ehdr));
fitzhardinged65dcad2004-03-13 02:06:58 +0000943
944 VG_(memcpy)(ehdr->e_ident, ELFMAG, SELFMAG);
njnaf839f52005-06-23 03:27:57 +0000945 ehdr->e_ident[EI_CLASS] = VG_ELF_CLASS;
946 ehdr->e_ident[EI_DATA] = VG_ELF_ENDIANNESS;
fitzhardinged65dcad2004-03-13 02:06:58 +0000947 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
fitzhardinged65dcad2004-03-13 02:06:58 +0000948
949 ehdr->e_type = ET_CORE;
njnaf839f52005-06-23 03:27:57 +0000950 ehdr->e_machine = VG_ELF_MACHINE;
fitzhardinged65dcad2004-03-13 02:06:58 +0000951 ehdr->e_version = EV_CURRENT;
952 ehdr->e_entry = 0;
953 ehdr->e_phoff = sizeof(Elf32_Ehdr);
954 ehdr->e_shoff = 0;
955 ehdr->e_flags = 0;
956 ehdr->e_ehsize = sizeof(Elf32_Ehdr);
957 ehdr->e_phentsize = sizeof(Elf32_Phdr);
958 ehdr->e_phnum = num_phdrs;
959 ehdr->e_shentsize = 0;
960 ehdr->e_shnum = 0;
961 ehdr->e_shstrndx = 0;
962
963}
964
965static void fill_phdr(Elf32_Phdr *phdr, const Segment *seg, UInt off, Bool write)
966{
967 write = write && should_dump(seg);
968
969 VG_(memset)(phdr, 0, sizeof(*phdr));
970
971 phdr->p_type = PT_LOAD;
972 phdr->p_offset = off;
973 phdr->p_vaddr = seg->addr;
974 phdr->p_paddr = 0;
975 phdr->p_filesz = write ? seg->len : 0;
976 phdr->p_memsz = seg->len;
977 phdr->p_flags = 0;
978
979 if (seg->prot & VKI_PROT_READ)
980 phdr->p_flags |= PF_R;
981 if (seg->prot & VKI_PROT_WRITE)
982 phdr->p_flags |= PF_W;
983 if (seg->prot & VKI_PROT_EXEC)
984 phdr->p_flags |= PF_X;
985
nethercote73b526f2004-10-31 18:48:21 +0000986 phdr->p_align = VKI_PAGE_SIZE;
fitzhardinged65dcad2004-03-13 02:06:58 +0000987}
988
989struct note {
990 struct note *next;
991 Elf32_Nhdr note;
992 Char name[0];
993};
994
995static UInt note_size(const struct note *n)
996{
njn13bfd852005-06-02 03:52:53 +0000997 return sizeof(Elf32_Nhdr) + VG_ROUNDUP(VG_(strlen)(n->name)+1, 4) + VG_ROUNDUP(n->note.n_descsz, 4);
fitzhardinged65dcad2004-03-13 02:06:58 +0000998}
999
1000static void add_note(struct note **list, const Char *name, UInt type, const void *data, UInt datasz)
1001{
1002 Int namelen = VG_(strlen)(name)+1;
1003 Int notelen = sizeof(struct note) +
njn13bfd852005-06-02 03:52:53 +00001004 VG_ROUNDUP(namelen, 4) +
1005 VG_ROUNDUP(datasz, 4);
fitzhardinged65dcad2004-03-13 02:06:58 +00001006 struct note *n = VG_(arena_malloc)(VG_AR_CORE, notelen);
1007
1008 VG_(memset)(n, 0, notelen);
1009
1010 n->next = *list;
1011 *list = n;
1012
1013 n->note.n_type = type;
1014 n->note.n_namesz = namelen;
1015 n->note.n_descsz = datasz;
1016
1017 VG_(memcpy)(n->name, name, namelen);
njn13bfd852005-06-02 03:52:53 +00001018 VG_(memcpy)(n->name+VG_ROUNDUP(namelen,4), data, datasz);
fitzhardinged65dcad2004-03-13 02:06:58 +00001019}
1020
1021static void write_note(Int fd, const struct note *n)
1022{
1023 VG_(write)(fd, &n->note, note_size(n));
1024}
1025
nethercote73b526f2004-10-31 18:48:21 +00001026static void fill_prpsinfo(const ThreadState *tst, struct vki_elf_prpsinfo *prpsinfo)
fitzhardinged65dcad2004-03-13 02:06:58 +00001027{
njnf845f8f2005-06-23 02:26:47 +00001028 static Char name[VKI_PATH_MAX];
1029 Bool res;
fitzhardinged65dcad2004-03-13 02:06:58 +00001030
1031 VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo));
1032
1033 switch(tst->status) {
1034 case VgTs_Runnable:
sewardjb5f6f512005-03-10 23:59:00 +00001035 case VgTs_Yielding:
fitzhardinged65dcad2004-03-13 02:06:58 +00001036 prpsinfo->pr_sname = 'R';
1037 break;
1038
fitzhardinged65dcad2004-03-13 02:06:58 +00001039 case VgTs_WaitSys:
fitzhardinged65dcad2004-03-13 02:06:58 +00001040 prpsinfo->pr_sname = 'S';
1041 break;
1042
sewardjb5f6f512005-03-10 23:59:00 +00001043 case VgTs_Zombie:
1044 prpsinfo->pr_sname = 'Z';
1045 break;
1046
fitzhardinged65dcad2004-03-13 02:06:58 +00001047 case VgTs_Empty:
sewardjb5f6f512005-03-10 23:59:00 +00001048 case VgTs_Init:
1049 prpsinfo->pr_sname = '?';
fitzhardinged65dcad2004-03-13 02:06:58 +00001050 break;
1051 }
1052
1053 prpsinfo->pr_uid = 0;
1054 prpsinfo->pr_gid = 0;
1055
njnf845f8f2005-06-23 02:26:47 +00001056 if (VG_(resolve_filename)(VG_(clexecfd), name, VKI_PATH_MAX)) {
fitzhardinged65dcad2004-03-13 02:06:58 +00001057 Char *n = name+VG_(strlen)(name)-1;
1058
njnf845f8f2005-06-23 02:26:47 +00001059 while (n > name && *n != '/')
fitzhardinged65dcad2004-03-13 02:06:58 +00001060 n--;
1061 if (n != name)
1062 n++;
1063
1064 VG_(strncpy)(prpsinfo->pr_fname, n, sizeof(prpsinfo->pr_fname));
1065 }
1066}
1067
sewardjb5f6f512005-03-10 23:59:00 +00001068static void fill_prstatus(const ThreadState *tst,
1069 struct vki_elf_prstatus *prs,
1070 const vki_siginfo_t *si)
fitzhardinged65dcad2004-03-13 02:06:58 +00001071{
nethercote73b526f2004-10-31 18:48:21 +00001072 struct vki_user_regs_struct *regs;
fitzhardinged65dcad2004-03-13 02:06:58 +00001073
1074 VG_(memset)(prs, 0, sizeof(*prs));
1075
1076 prs->pr_info.si_signo = si->si_signo;
1077 prs->pr_info.si_code = si->si_code;
1078 prs->pr_info.si_errno = 0;
1079
1080 prs->pr_cursig = si->si_signo;
1081
sewardjb5f6f512005-03-10 23:59:00 +00001082 prs->pr_pid = tst->os_state.lwpid;
fitzhardinged65dcad2004-03-13 02:06:58 +00001083 prs->pr_ppid = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001084 prs->pr_pgrp = VG_(getpgrp)();
1085 prs->pr_sid = VG_(getpgrp)();
fitzhardinged65dcad2004-03-13 02:06:58 +00001086
nethercote73b526f2004-10-31 18:48:21 +00001087 regs = (struct vki_user_regs_struct *)prs->pr_reg;
fitzhardinged65dcad2004-03-13 02:06:58 +00001088
1089 vg_assert(sizeof(*regs) == sizeof(prs->pr_reg));
1090
njnaf839f52005-06-23 03:27:57 +00001091 VG_(fill_elfregs_from_tst)(regs, &tst->arch);
fitzhardinged65dcad2004-03-13 02:06:58 +00001092}
1093
nethercote73b526f2004-10-31 18:48:21 +00001094static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
fitzhardinged65dcad2004-03-13 02:06:58 +00001095{
njnaf839f52005-06-23 03:27:57 +00001096 VG_(fill_elffpregs_from_tst)(fpu, &tst->arch);
fitzhardinged65dcad2004-03-13 02:06:58 +00001097}
1098
nethercote73b526f2004-10-31 18:48:21 +00001099static void fill_xfpu(const ThreadState *tst, vki_elf_fpxregset_t *xfpu)
fitzhardinged65dcad2004-03-13 02:06:58 +00001100{
njnaf839f52005-06-23 03:27:57 +00001101 VG_(fill_elffpxregs_from_tst)(xfpu, &tst->arch);
fitzhardinged65dcad2004-03-13 02:06:58 +00001102}
1103
nethercote73b526f2004-10-31 18:48:21 +00001104static void make_coredump(ThreadId tid, const vki_siginfo_t *si, UInt max_size)
fitzhardinged65dcad2004-03-13 02:06:58 +00001105{
1106 Char buf[1000];
1107 Char *basename = "vgcore";
1108 Char *coreext = "";
1109 Int seq = 0;
1110 Int core_fd;
1111 Segment *seg;
1112 Elf32_Ehdr ehdr;
1113 Elf32_Phdr *phdrs;
1114 Int num_phdrs;
sewardjb5f6f512005-03-10 23:59:00 +00001115 Int i, idx;
fitzhardinged65dcad2004-03-13 02:06:58 +00001116 UInt off;
1117 struct note *notelist, *note;
1118 UInt notesz;
nethercote73b526f2004-10-31 18:48:21 +00001119 struct vki_elf_prpsinfo prpsinfo;
1120 struct vki_elf_prstatus prstatus;
fitzhardinged65dcad2004-03-13 02:06:58 +00001121
nethercotef8548672004-06-21 12:42:35 +00001122 if (VG_(clo_log_name) != NULL) {
fitzhardinged65dcad2004-03-13 02:06:58 +00001123 coreext = ".core";
nethercotef8548672004-06-21 12:42:35 +00001124 basename = VG_(clo_log_name);
fitzhardinged65dcad2004-03-13 02:06:58 +00001125 }
1126
1127 for(;;) {
1128 if (seq == 0)
1129 VG_(sprintf)(buf, "%s%s.pid%d",
sewardjb5f6f512005-03-10 23:59:00 +00001130 basename, coreext, VG_(getpid)());
fitzhardinged65dcad2004-03-13 02:06:58 +00001131 else
1132 VG_(sprintf)(buf, "%s%s.pid%d.%d",
sewardjb5f6f512005-03-10 23:59:00 +00001133 basename, coreext, VG_(getpid)(), seq);
fitzhardinged65dcad2004-03-13 02:06:58 +00001134 seq++;
1135
1136 core_fd = VG_(open)(buf,
1137 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1138 VKI_S_IRUSR|VKI_S_IWUSR);
1139 if (core_fd >= 0)
1140 break;
1141
1142 if (core_fd != -VKI_EEXIST)
1143 return; /* can't create file */
1144 }
1145
1146 /* First, count how many memory segments to dump */
1147 num_phdrs = 1; /* start with notes */
1148 for(seg = VG_(first_segment)();
1149 seg != NULL;
1150 seg = VG_(next_segment)(seg)) {
1151 if (!may_dump(seg))
1152 continue;
1153
1154 num_phdrs++;
1155 }
1156
1157 fill_ehdr(&ehdr, num_phdrs);
1158
sewardjb5f6f512005-03-10 23:59:00 +00001159 notelist = NULL;
1160
fitzhardinged65dcad2004-03-13 02:06:58 +00001161 /* Second, work out their layout */
1162 phdrs = VG_(arena_malloc)(VG_AR_CORE, sizeof(*phdrs) * num_phdrs);
1163
1164 for(i = 1; i < VG_N_THREADS; i++) {
sewardj51ac0872004-12-21 01:20:49 +00001165 vki_elf_fpregset_t fpu;
1166 vki_elf_fpxregset_t xfpu;
fitzhardinged65dcad2004-03-13 02:06:58 +00001167
1168 if (VG_(threads)[i].status == VgTs_Empty)
1169 continue;
1170
sewardj51ac0872004-12-21 01:20:49 +00001171 fill_xfpu(&VG_(threads)[i], &xfpu);
1172 add_note(&notelist, "LINUX", NT_PRXFPREG, &xfpu, sizeof(xfpu));
fitzhardinged65dcad2004-03-13 02:06:58 +00001173
1174 fill_fpu(&VG_(threads)[i], &fpu);
1175 add_note(&notelist, "CORE", NT_FPREGSET, &fpu, sizeof(fpu));
1176
1177 fill_prstatus(&VG_(threads)[i], &prstatus, si);
1178 add_note(&notelist, "CORE", NT_PRSTATUS, &prstatus, sizeof(prstatus));
1179 }
1180
1181 fill_prpsinfo(&VG_(threads)[tid], &prpsinfo);
1182 add_note(&notelist, "CORE", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo));
1183
1184 for(note = notelist, notesz = 0; note != NULL; note = note->next)
1185 notesz += note_size(note);
1186
1187 off = sizeof(ehdr) + sizeof(*phdrs) * num_phdrs;
1188
1189 phdrs[0].p_type = PT_NOTE;
1190 phdrs[0].p_offset = off;
1191 phdrs[0].p_vaddr = 0;
1192 phdrs[0].p_paddr = 0;
1193 phdrs[0].p_filesz = notesz;
1194 phdrs[0].p_memsz = 0;
1195 phdrs[0].p_flags = 0;
1196 phdrs[0].p_align = 0;
1197
1198 off += notesz;
1199
njn13bfd852005-06-02 03:52:53 +00001200 off = VG_PGROUNDUP(off);
fitzhardinged65dcad2004-03-13 02:06:58 +00001201
sewardjb5f6f512005-03-10 23:59:00 +00001202 for(seg = VG_(first_segment)(), idx = 1;
fitzhardinged65dcad2004-03-13 02:06:58 +00001203 seg != NULL;
sewardjb5f6f512005-03-10 23:59:00 +00001204 seg = VG_(next_segment)(seg)) {
fitzhardinged65dcad2004-03-13 02:06:58 +00001205 if (!may_dump(seg))
1206 continue;
1207
sewardjb5f6f512005-03-10 23:59:00 +00001208 fill_phdr(&phdrs[idx], seg, off, (seg->len + off) < max_size);
fitzhardinged65dcad2004-03-13 02:06:58 +00001209
sewardjb5f6f512005-03-10 23:59:00 +00001210 off += phdrs[idx].p_filesz;
1211
1212 idx++;
fitzhardinged65dcad2004-03-13 02:06:58 +00001213 }
1214
1215 /* write everything out */
1216 VG_(write)(core_fd, &ehdr, sizeof(ehdr));
1217 VG_(write)(core_fd, phdrs, sizeof(*phdrs) * num_phdrs);
1218
1219 for(note = notelist; note != NULL; note = note->next)
1220 write_note(core_fd, note);
1221
1222 VG_(lseek)(core_fd, phdrs[1].p_offset, VKI_SEEK_SET);
1223
sewardjb5f6f512005-03-10 23:59:00 +00001224 for(seg = VG_(first_segment)(), idx = 1;
fitzhardinged65dcad2004-03-13 02:06:58 +00001225 seg != NULL;
sewardjb5f6f512005-03-10 23:59:00 +00001226 seg = VG_(next_segment)(seg)) {
fitzhardinged65dcad2004-03-13 02:06:58 +00001227 if (!should_dump(seg))
1228 continue;
1229
sewardjb5f6f512005-03-10 23:59:00 +00001230 if (phdrs[idx].p_filesz > 0) {
1231 Int ret;
1232
1233 vg_assert(VG_(lseek)(core_fd, phdrs[idx].p_offset, VKI_SEEK_SET) == phdrs[idx].p_offset);
1234 vg_assert(seg->len >= phdrs[idx].p_filesz);
1235
1236 ret = VG_(write)(core_fd, (void *)seg->addr, phdrs[idx].p_filesz);
1237 }
1238 idx++;
fitzhardinged65dcad2004-03-13 02:06:58 +00001239 }
1240
1241 VG_(close)(core_fd);
1242}
njn277a6d62004-11-26 14:07:24 +00001243#endif
fitzhardinged65dcad2004-03-13 02:06:58 +00001244
jsgf855d93d2003-10-13 22:26:55 +00001245/*
sewardjb5f6f512005-03-10 23:59:00 +00001246 Perform the default action of a signal. If the signal is fatal, it
1247 marks all threads as needing to exit, but it doesn't actually kill
1248 the process or thread.
jsgf855d93d2003-10-13 22:26:55 +00001249
1250 If we're not being quiet, then print out some more detail about
1251 fatal signals (esp. core dumping signals).
1252 */
njn695c16e2005-03-27 03:40:28 +00001253static void default_action(const vki_siginfo_t *info, ThreadId tid)
jsgf855d93d2003-10-13 22:26:55 +00001254{
1255 Int sigNo = info->si_signo;
sewardjb5f6f512005-03-10 23:59:00 +00001256 Bool terminate = False; /* kills process */
1257 Bool core = False; /* kills process w/ core */
1258 struct vki_rlimit corelim;
1259 Bool could_core;
jsgf855d93d2003-10-13 22:26:55 +00001260
sewardjb5f6f512005-03-10 23:59:00 +00001261 vg_assert(VG_(is_running_thread)(tid));
1262
jsgf855d93d2003-10-13 22:26:55 +00001263 switch(sigNo) {
1264 case VKI_SIGQUIT: /* core */
1265 case VKI_SIGILL: /* core */
1266 case VKI_SIGABRT: /* core */
1267 case VKI_SIGFPE: /* core */
1268 case VKI_SIGSEGV: /* core */
1269 case VKI_SIGBUS: /* core */
1270 case VKI_SIGTRAP: /* core */
1271 case VKI_SIGXCPU: /* core */
1272 case VKI_SIGXFSZ: /* core */
1273 terminate = True;
1274 core = True;
1275 break;
1276
1277 case VKI_SIGHUP: /* term */
1278 case VKI_SIGINT: /* term */
1279 case VKI_SIGKILL: /* term - we won't see this */
1280 case VKI_SIGPIPE: /* term */
1281 case VKI_SIGALRM: /* term */
1282 case VKI_SIGTERM: /* term */
1283 case VKI_SIGUSR1: /* term */
1284 case VKI_SIGUSR2: /* term */
1285 case VKI_SIGIO: /* term */
1286 case VKI_SIGPWR: /* term */
1287 case VKI_SIGSYS: /* term */
1288 case VKI_SIGPROF: /* term */
1289 case VKI_SIGVTALRM: /* term */
1290 case VKI_SIGRTMIN ... VKI_SIGRTMAX: /* term */
1291 terminate = True;
1292 break;
1293 }
1294
1295 vg_assert(!core || (core && terminate));
1296
fitzhardinge98abfc72003-12-16 02:05:15 +00001297 if (VG_(clo_trace_signals))
sewardjb5f6f512005-03-10 23:59:00 +00001298 VG_(message)(Vg_DebugMsg, "delivering %d (code %d) to default handler; action: %s%s",
1299 sigNo, info->si_code, terminate ? "terminate" : "ignore", core ? "+core" : "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001300
sewardjb5f6f512005-03-10 23:59:00 +00001301 if (!terminate)
1302 return; /* nothing to do */
fitzhardinge4a4d1082004-03-15 23:46:54 +00001303
sewardjb5f6f512005-03-10 23:59:00 +00001304 could_core = core;
1305
1306 if (core) {
1307 /* If they set the core-size limit to zero, don't generate a
1308 core file */
fitzhardinge61a53412004-03-15 23:44:11 +00001309
sewardjb5f6f512005-03-10 23:59:00 +00001310 VG_(getrlimit)(VKI_RLIMIT_CORE, &corelim);
fitzhardinge61a53412004-03-15 23:44:11 +00001311
sewardjb5f6f512005-03-10 23:59:00 +00001312 if (corelim.rlim_cur == 0)
1313 core = False;
1314 }
fitzhardinge61a53412004-03-15 23:44:11 +00001315
sewardjb5f6f512005-03-10 23:59:00 +00001316 if (VG_(clo_verbosity) > 1 || (could_core && info->si_code > VKI_SI_USER)) {
1317 VG_(message)(Vg_UserMsg, "");
1318 VG_(message)(Vg_UserMsg, "Process terminating with default action of signal %d (%s)%s",
1319 sigNo, signame(sigNo), core ? ": dumping core" : "");
jsgf855d93d2003-10-13 22:26:55 +00001320
sewardjb5f6f512005-03-10 23:59:00 +00001321 /* Be helpful - decode some more details about this fault */
1322 if (info->si_code > VKI_SI_USER) {
1323 const Char *event = NULL;
1324 Bool haveaddr = True;
jsgf855d93d2003-10-13 22:26:55 +00001325
sewardjb5f6f512005-03-10 23:59:00 +00001326 switch(sigNo) {
1327 case VKI_SIGSEGV:
1328 switch(info->si_code) {
1329 case 1: event = "Access not within mapped region"; break;
1330 case 2: event = "Bad permissions for mapped region"; break;
1331 case 128:
1332 /* General Protection Fault: The CPU/kernel
1333 isn't telling us anything useful, but this
1334 is commonly the result of exceeding a
1335 segment limit, such as the one imposed by
1336 --pointercheck=yes. */
1337 if (VG_(clo_pointercheck))
1338 event = "GPF (Pointer out of bounds?)";
1339 else
1340 event = "General Protection Fault";
1341 haveaddr = False;
jsgf855d93d2003-10-13 22:26:55 +00001342 break;
1343 }
sewardjb5f6f512005-03-10 23:59:00 +00001344 break;
jsgf855d93d2003-10-13 22:26:55 +00001345
sewardjb5f6f512005-03-10 23:59:00 +00001346 case VKI_SIGILL:
1347 switch(info->si_code) {
1348 case 1: event = "Illegal opcode"; break;
1349 case 2: event = "Illegal operand"; break;
1350 case 3: event = "Illegal addressing mode"; break;
1351 case 4: event = "Illegal trap"; break;
1352 case 5: event = "Privileged opcode"; break;
1353 case 6: event = "Privileged register"; break;
1354 case 7: event = "Coprocessor error"; break;
1355 case 8: event = "Internal stack error"; break;
1356 }
1357 break;
1358
1359 case VKI_SIGFPE:
1360 switch (info->si_code) {
1361 case 1: event = "Integer divide by zero"; break;
1362 case 2: event = "Integer overflow"; break;
1363 case 3: event = "FP divide by zero"; break;
1364 case 4: event = "FP overflow"; break;
1365 case 5: event = "FP underflow"; break;
1366 case 6: event = "FP inexact"; break;
1367 case 7: event = "FP invalid operation"; break;
1368 case 8: event = "FP subscript out of range"; break;
1369 }
1370 break;
1371
1372 case VKI_SIGBUS:
1373 switch (info->si_code) {
1374 case 1: event = "Invalid address alignment"; break;
1375 case 2: event = "Non-existent physical address"; break;
1376 case 3: event = "Hardware error"; break;
1377 }
1378 break;
1379 }
1380
1381 if (event != NULL) {
1382 if (haveaddr)
nethercote3b390c72003-11-13 17:53:43 +00001383 VG_(message)(Vg_UserMsg, " %s at address %p",
jsgf855d93d2003-10-13 22:26:55 +00001384 event, info->_sifields._sigfault._addr);
sewardjb5f6f512005-03-10 23:59:00 +00001385 else
1386 VG_(message)(Vg_UserMsg, " %s", event);
jsgf855d93d2003-10-13 22:26:55 +00001387 }
1388 }
fitzhardinge126c64f2003-12-08 21:58:37 +00001389
sewardjb5f6f512005-03-10 23:59:00 +00001390 if (tid != VG_INVALID_THREADID) {
njnd01fef72005-03-25 23:35:48 +00001391 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
fitzhardinge126c64f2003-12-08 21:58:37 +00001392 }
sewardjb5f6f512005-03-10 23:59:00 +00001393 }
1394
1395 if (VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) )) {
1396 VG_(start_debugger)( tid );
1397 }
fitzhardinge126c64f2003-12-08 21:58:37 +00001398
njn277a6d62004-11-26 14:07:24 +00001399 // See comment above about this temporary disabling of core dumps.
1400 #if 0
sewardjb5f6f512005-03-10 23:59:00 +00001401 if (core) {
1402 const static struct vki_rlimit zero = { 0, 0 };
fitzhardinge4a4d1082004-03-15 23:46:54 +00001403
sewardjb5f6f512005-03-10 23:59:00 +00001404 make_coredump(tid, info, corelim.rlim_cur);
fitzhardinged65dcad2004-03-13 02:06:58 +00001405
sewardjb5f6f512005-03-10 23:59:00 +00001406 /* Make sure we don't get a confusing kernel-generated
1407 coredump when we finally exit */
1408 VG_(setrlimit)(VKI_RLIMIT_CORE, &zero);
1409 }
njn277a6d62004-11-26 14:07:24 +00001410 #endif
fitzhardinged65dcad2004-03-13 02:06:58 +00001411
sewardjb5f6f512005-03-10 23:59:00 +00001412 /* stash fatal signal in main thread */
sewardj1d887112005-05-30 21:44:08 +00001413 // what's this for?
1414 //VG_(threads)[VG_(master_tid)].os_state.fatalsig = sigNo;
sewardjde4a1d02002-03-22 01:27:54 +00001415
sewardjb5f6f512005-03-10 23:59:00 +00001416 /* everyone dies */
1417 VG_(nuke_all_threads_except)(tid, VgSrc_FatalSig);
1418 VG_(threads)[tid].exitreason = VgSrc_FatalSig;
1419 VG_(threads)[tid].os_state.fatalsig = sigNo;
sewardjb48e5002002-05-13 00:16:03 +00001420}
1421
sewardjb5f6f512005-03-10 23:59:00 +00001422/*
1423 This does the business of delivering a signal to a thread. It may
1424 be called from either a real signal handler, or from normal code to
1425 cause the thread to enter the signal handler.
sewardj5e2f0012004-12-13 14:10:34 +00001426
sewardjb5f6f512005-03-10 23:59:00 +00001427 This updates the thread state, but it does not set it to be
1428 Runnable.
1429*/
njn9ec0f3e2005-03-13 06:00:47 +00001430static void deliver_signal ( ThreadId tid, const vki_siginfo_t *info )
sewardjde4a1d02002-03-22 01:27:54 +00001431{
jsgf855d93d2003-10-13 22:26:55 +00001432 Int sigNo = info->si_signo;
njn695c16e2005-03-27 03:40:28 +00001433 SCSS_Per_Signal *handler = &scss.scss_per_sig[sigNo];
fitzhardinge98abfc72003-12-16 02:05:15 +00001434 void *handler_fn;
jsgf855d93d2003-10-13 22:26:55 +00001435 ThreadState *tst = VG_(get_ThreadState)(tid);
1436
1437 if (VG_(clo_trace_signals))
sewardjb5f6f512005-03-10 23:59:00 +00001438 VG_(message)(Vg_DebugMsg,"delivering signal %d (%s):%d to thread %d",
1439 sigNo, signame(sigNo), info->si_code, tid );
jsgf855d93d2003-10-13 22:26:55 +00001440
njn351d0062005-06-21 22:23:59 +00001441 if (sigNo == VG_SIGVGKILL) {
sewardjb5f6f512005-03-10 23:59:00 +00001442 /* If this is a SIGVGKILL, we're expecting it to interrupt any
1443 blocked syscall. It doesn't matter whether the VCPU state is
1444 set to restart or not, because we don't expect it will
1445 execute any more client instructions. */
1446 vg_assert(VG_(is_exiting)(tid));
jsgf855d93d2003-10-13 22:26:55 +00001447 return;
1448 }
1449
sewardjb5f6f512005-03-10 23:59:00 +00001450 /* If the client specifies SIG_IGN, treat it as SIG_DFL.
jsgf855d93d2003-10-13 22:26:55 +00001451
njn9ec0f3e2005-03-13 06:00:47 +00001452 If deliver_signal() is being called on a thread, we want
sewardjb5f6f512005-03-10 23:59:00 +00001453 the signal to get through no matter what; if they're ignoring
1454 it, then we do this override (this is so we can send it SIGSEGV,
1455 etc). */
fitzhardinge98abfc72003-12-16 02:05:15 +00001456 handler_fn = handler->scss_handler;
sewardjb5f6f512005-03-10 23:59:00 +00001457 if (handler_fn == VKI_SIG_IGN)
fitzhardinge98abfc72003-12-16 02:05:15 +00001458 handler_fn = VKI_SIG_DFL;
1459
1460 vg_assert(handler_fn != VKI_SIG_IGN);
jsgf855d93d2003-10-13 22:26:55 +00001461
fitzhardinge98abfc72003-12-16 02:05:15 +00001462 if (handler_fn == VKI_SIG_DFL) {
njn695c16e2005-03-27 03:40:28 +00001463 default_action(info, tid);
jsgf855d93d2003-10-13 22:26:55 +00001464 } else {
1465 /* Create a signal delivery frame, and set the client's %ESP and
1466 %EIP so that when execution continues, we will enter the
1467 signal handler with the frame on top of the client's stack,
sewardjb5f6f512005-03-10 23:59:00 +00001468 as it expects.
1469
1470 Signal delivery can fail if the client stack is too small or
1471 missing, and we can't push the frame. If that happens,
1472 push_signal_frame will cause the whole process to exit when
1473 we next hit the scheduler.
1474 */
jsgf855d93d2003-10-13 22:26:55 +00001475 vg_assert(VG_(is_valid_tid)(tid));
sewardjb5f6f512005-03-10 23:59:00 +00001476
njn695c16e2005-03-27 03:40:28 +00001477 push_signal_frame ( tid, info );
jsgf855d93d2003-10-13 22:26:55 +00001478
1479 if (handler->scss_flags & VKI_SA_ONESHOT) {
1480 /* Do the ONESHOT thing. */
1481 handler->scss_handler = VKI_SIG_DFL;
1482
nethercote9dd11512004-08-04 15:31:30 +00001483 handle_SCSS_change( False /* lazy update */ );
jsgf855d93d2003-10-13 22:26:55 +00001484 }
sewardjb5f6f512005-03-10 23:59:00 +00001485
1486 /* At this point:
1487 tst->sig_mask is the current signal mask
1488 tst->tmp_sig_mask is the same as sig_mask, unless we're in sigsuspend
1489 handler->scss_mask is the mask set by the handler
1490
1491 Handler gets a mask of tmp_sig_mask|handler_mask|signo
1492 */
1493 tst->sig_mask = tst->tmp_sig_mask;
1494 if (!(handler->scss_flags & VKI_SA_NOMASK)) {
1495 VG_(sigaddset_from_set)(&tst->sig_mask, &handler->scss_mask);
1496 VG_(sigaddset)(&tst->sig_mask, sigNo);
1497
1498 tst->tmp_sig_mask = tst->sig_mask;
1499 }
1500 }
1501
1502 /* Thread state is ready to go - just add Runnable */
1503}
1504
njn06244e72005-06-21 22:27:19 +00001505static void resume_scheduler(ThreadId tid)
1506{
1507 ThreadState *tst = VG_(get_ThreadState)(tid);
1508
1509 vg_assert(tst->os_state.lwpid == VG_(gettid)());
1510
1511 if (tst->sched_jmpbuf_valid) {
1512 /* Can't continue; must longjmp back to the scheduler and thus
1513 enter the sighandler immediately. */
1514 longjmp(tst->sched_jmpbuf, True);
1515 }
1516}
1517
njn9ec0f3e2005-03-13 06:00:47 +00001518static void synth_fault_common(ThreadId tid, Addr addr, Int si_code)
1519{
1520 vki_siginfo_t info;
1521
1522 vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
1523
1524 info.si_signo = VKI_SIGSEGV;
1525 info.si_code = si_code;
1526 info._sifields._sigfault._addr = (void*)addr;
1527
1528 /* If they're trying to block the signal, force it to be delivered */
1529 if (VG_(sigismember)(&VG_(threads)[tid].sig_mask, VKI_SIGSEGV))
1530 VG_(set_default_handler)(VKI_SIGSEGV);
1531
1532 deliver_signal(tid, &info);
1533}
1534
1535// Synthesize a fault where the address is OK, but the page
1536// permissions are bad.
1537void VG_(synth_fault_perms)(ThreadId tid, Addr addr)
1538{
1539 synth_fault_common(tid, addr, 2);
1540}
1541
1542// Synthesize a fault where the address there's nothing mapped at the address.
1543void VG_(synth_fault_mapping)(ThreadId tid, Addr addr)
1544{
1545 synth_fault_common(tid, addr, 1);
1546}
1547
1548// Synthesize a misc memory fault.
1549void VG_(synth_fault)(ThreadId tid)
1550{
1551 synth_fault_common(tid, 0, 0x80);
1552}
1553
1554// Synthesise a SIGILL.
1555void VG_(synth_sigill)(ThreadId tid, Addr addr)
1556{
1557 vki_siginfo_t info;
1558
1559 vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
1560
1561 info.si_signo = VKI_SIGILL;
1562 info.si_code = 1; /* jrs: no idea what this should be */
1563 info._sifields._sigfault._addr = (void*)addr;
1564
njn06244e72005-06-21 22:27:19 +00001565 resume_scheduler(tid);
njn9ec0f3e2005-03-13 06:00:47 +00001566 deliver_signal(tid, &info);
1567}
1568
sewardjb5f6f512005-03-10 23:59:00 +00001569/* Make a signal pending for a thread, for later delivery.
1570 VG_(poll_signals) will arrange for it to be delivered at the right
1571 time.
1572
1573 tid==0 means add it to the process-wide queue, and not sent it to a
1574 specific thread.
1575*/
sewardj2c5ffbe2005-03-12 13:32:06 +00001576static
sewardjb5f6f512005-03-10 23:59:00 +00001577void queue_signal(ThreadId tid, const vki_siginfo_t *si)
1578{
1579 ThreadState *tst;
1580 SigQueue *sq;
1581 vki_sigset_t savedmask;
1582
1583 tst = VG_(get_ThreadState)(tid);
1584
1585 /* Protect the signal queue against async deliveries */
njn444eba12005-05-12 03:47:31 +00001586 block_all_host_signals(&savedmask);
sewardjb5f6f512005-03-10 23:59:00 +00001587
1588 if (tst->sig_queue == NULL) {
1589 tst->sig_queue = VG_(arena_malloc)(VG_AR_CORE, sizeof(*tst->sig_queue));
1590 VG_(memset)(tst->sig_queue, 0, sizeof(*tst->sig_queue));
1591 }
1592 sq = tst->sig_queue;
1593
1594 if (VG_(clo_trace_signals))
1595 VG_(message)(Vg_DebugMsg, "Queueing signal %d (idx %d) to thread %d",
1596 si->si_signo, sq->next, tid);
1597
1598 /* Add signal to the queue. If the queue gets overrun, then old
1599 queued signals may get lost.
1600
1601 XXX We should also keep a sigset of pending signals, so that at
1602 least a non-siginfo signal gets deliviered.
1603 */
1604 if (sq->sigs[sq->next].si_signo != 0)
1605 VG_(message)(Vg_UserMsg, "Signal %d being dropped from thread %d's queue",
1606 sq->sigs[sq->next].si_signo, tid);
1607
1608 sq->sigs[sq->next] = *si;
1609 sq->next = (sq->next+1) % N_QUEUED_SIGNALS;
1610
njn444eba12005-05-12 03:47:31 +00001611 restore_all_host_signals(&savedmask);
sewardjb5f6f512005-03-10 23:59:00 +00001612}
1613
1614/*
1615 Returns the next queued signal for thread tid which is in "set".
1616 tid==0 means process-wide signal. Set si_signo to 0 when the
1617 signal has been delivered.
1618
1619 Must be called with all signals blocked, to protect against async
1620 deliveries.
1621*/
1622static vki_siginfo_t *next_queued(ThreadId tid, const vki_sigset_t *set)
1623{
1624 ThreadState *tst = VG_(get_ThreadState)(tid);
1625 SigQueue *sq;
1626 Int idx;
1627 vki_siginfo_t *ret = NULL;
1628
1629 sq = tst->sig_queue;
1630 if (sq == NULL)
1631 goto out;
jsgf855d93d2003-10-13 22:26:55 +00001632
sewardjb5f6f512005-03-10 23:59:00 +00001633 idx = sq->next;
1634 do {
1635 if (0)
1636 VG_(printf)("idx=%d si_signo=%d inset=%d\n", idx,
1637 sq->sigs[idx].si_signo, VG_(sigismember)(set, sq->sigs[idx].si_signo));
jsgf855d93d2003-10-13 22:26:55 +00001638
sewardjb5f6f512005-03-10 23:59:00 +00001639 if (sq->sigs[idx].si_signo != 0 && VG_(sigismember)(set, sq->sigs[idx].si_signo)) {
1640 if (VG_(clo_trace_signals))
1641 VG_(message)(Vg_DebugMsg, "Returning queued signal %d (idx %d) for thread %d",
1642 sq->sigs[idx].si_signo, idx, tid);
1643 ret = &sq->sigs[idx];
1644 goto out;
jsgf855d93d2003-10-13 22:26:55 +00001645 }
1646
sewardjb5f6f512005-03-10 23:59:00 +00001647 idx = (idx + 1) % N_QUEUED_SIGNALS;
1648 } while(idx != sq->next);
1649 out:
1650 return ret;
jsgf855d93d2003-10-13 22:26:55 +00001651}
1652
1653/*
sewardjb5f6f512005-03-10 23:59:00 +00001654 Receive an async signal from the kernel.
jsgf855d93d2003-10-13 22:26:55 +00001655
sewardjb5f6f512005-03-10 23:59:00 +00001656 This should only happen when the thread is blocked in a syscall,
1657 since that's the only time this set of signals is unblocked.
jsgf855d93d2003-10-13 22:26:55 +00001658*/
1659static
njn695c16e2005-03-27 03:40:28 +00001660void async_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc )
jsgf855d93d2003-10-13 22:26:55 +00001661{
sewardjb5f6f512005-03-10 23:59:00 +00001662 ThreadId tid = VG_(get_lwp_tid)(VG_(gettid)());
1663 ThreadState *tst = VG_(get_ThreadState)(tid);
jsgf855d93d2003-10-13 22:26:55 +00001664
sewardjb5f6f512005-03-10 23:59:00 +00001665 vg_assert(tst->status == VgTs_WaitSys);
jsgf855d93d2003-10-13 22:26:55 +00001666
sewardjb5f6f512005-03-10 23:59:00 +00001667 /* The thread isn't currently running, make it so before going on */
1668 VG_(set_running)(tid);
1669
1670 if (VG_(clo_trace_signals))
1671 VG_(message)(Vg_DebugMsg, "Async handler got signal %d for tid %d info %d",
1672 sigNo, tid, info->si_code);
1673
1674 /* Update thread state properly */
sewardja8d8e232005-06-07 20:04:56 +00001675 VG_(fixup_guest_state_after_syscall_interrupted)(
1676 tid,
njnaf839f52005-06-23 03:27:57 +00001677 VG_UCONTEXT_INSTR_PTR(uc),
1678 VG_UCONTEXT_SYSCALL_NUM(uc),
1679 VG_UCONTEXT_SYSCALL_SYSRES(uc),
sewardja8d8e232005-06-07 20:04:56 +00001680 !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART)
1681 );
sewardjb5f6f512005-03-10 23:59:00 +00001682
1683 /* Set up the thread's state to deliver a signal */
njn07ef6c02005-05-18 19:43:09 +00001684 if (!is_sig_ign(info->si_signo))
njn9ec0f3e2005-03-13 06:00:47 +00001685 deliver_signal(tid, info);
sewardjb5f6f512005-03-10 23:59:00 +00001686
1687 /* longjmp back to the thread's main loop to start executing the
1688 handler. */
njn06244e72005-06-21 22:27:19 +00001689 resume_scheduler(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001690
njn695c16e2005-03-27 03:40:28 +00001691 VG_(core_panic)("async_signalhandler: got unexpected signal while outside of scheduler");
jsgf855d93d2003-10-13 22:26:55 +00001692}
1693
sewardjb5f6f512005-03-10 23:59:00 +00001694/* Extend the stack to cover addr. maxsize is the limit the stack can grow to.
1695
1696 Returns True on success, False on failure.
1697
1698 Succeeds without doing anything if addr is already within a segment.
1699
1700 Failure could be caused by:
1701 - addr not below a growable segment
1702 - new stack size would exceed maxsize
1703 - mmap failed for some other reason
1704 */
1705Bool VG_(extend_stack)(Addr addr, UInt maxsize)
1706{
1707 Segment *seg;
1708 Addr base;
1709 UInt newsize;
1710
1711 /* Find the next Segment above addr */
1712 seg = VG_(find_segment)(addr);
1713 if (seg)
1714 return True;
1715
1716 /* now we know addr is definitely unmapped */
1717 seg = VG_(find_segment_above_unmapped)(addr);
1718
1719 /* If there isn't one, or it isn't growable, fail */
1720 if (seg == NULL ||
1721 !(seg->flags & SF_GROWDOWN) ||
1722 VG_(seg_contains)(seg, addr, sizeof(void *)))
1723 return False;
1724
1725 vg_assert(seg->addr > addr);
1726
1727 /* Create the mapping */
njn13bfd852005-06-02 03:52:53 +00001728 base = VG_PGROUNDDN(addr);
sewardjb5f6f512005-03-10 23:59:00 +00001729 newsize = seg->addr - base;
1730
1731 if (seg->len + newsize >= maxsize)
1732 return False;
1733
sewardj50b8f772005-08-02 13:35:21 +00001734 /* Nasty Hack. The new segment will have SF_MMAP set because
1735 that's what VG_(mmap) does. But the existing stack segment
1736 won't necessarily have it set, because the initial segment list
1737 entry for the main thread's stack doesn't have it set. That
1738 means that the segment list preener won't merge the segments
1739 together (because they have different flags). That means the
1740 segment list will in fact list two adjacent segments for the
1741 main stack, which is wrong. This means that the tests which
1742 check if a translation is from a stack-like area and therefore
1743 in need of a self-check will not work right. Sigh.
1744
1745 So .. in lieu of fixing this properly (viz, rationalising all
1746 the SF_ flags), just mark the original stack segment as having
1747 SF_MMAP. Then the preener will merge it into the new area.
1748 This is a hack. */
1749 seg->flags |= SF_MMAP;
1750 /* end of Nasty Hack */
1751
sewardjb5f6f512005-03-10 23:59:00 +00001752 if (VG_(mmap)((Char *)base, newsize,
1753 seg->prot,
1754 VKI_MAP_PRIVATE | VKI_MAP_FIXED | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1755 seg->flags,
1756 -1, 0) == (void *)-1)
1757 return False;
1758
rjwalsh0140af52005-06-04 20:42:33 +00001759 /* When we change the main stack, we have to let the stack handling
1760 code know about it. */
njn945ed2e2005-06-24 03:28:30 +00001761 VG_(change_stack)(VG_(clstk_id), base, VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00001762
sewardjb5f6f512005-03-10 23:59:00 +00001763 if (0)
1764 VG_(printf)("extended stack: %p %d\n",
1765 base, newsize);
1766
1767 if (VG_(clo_sanity_level) > 2)
1768 VG_(sanity_check_general)(False);
1769
1770 return True;
1771}
1772
1773static void (*fault_catcher)(Int sig, Addr addr);
1774
1775void VG_(set_fault_catcher)(void (*catcher)(Int, Addr))
1776{
njn50ae1a72005-04-08 23:28:23 +00001777 vg_assert2(NULL == catcher || NULL == fault_catcher,
1778 "Fault catcher is already registered");
sewardjb5f6f512005-03-10 23:59:00 +00001779
1780 fault_catcher = catcher;
1781}
1782
1783
jsgf855d93d2003-10-13 22:26:55 +00001784/*
sewardj2a99cf62004-11-24 10:44:19 +00001785 Receive a sync signal from the host.
jsgf855d93d2003-10-13 22:26:55 +00001786*/
1787static
njn695c16e2005-03-27 03:40:28 +00001788void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc )
jsgf855d93d2003-10-13 22:26:55 +00001789{
sewardjb5f6f512005-03-10 23:59:00 +00001790 ThreadId tid = VG_(get_lwp_tid)(VG_(gettid)());
jsgf855d93d2003-10-13 22:26:55 +00001791
1792 vg_assert(info != NULL);
1793 vg_assert(info->si_signo == sigNo);
1794 vg_assert(sigNo == VKI_SIGSEGV ||
1795 sigNo == VKI_SIGBUS ||
1796 sigNo == VKI_SIGFPE ||
sewardjb5f6f512005-03-10 23:59:00 +00001797 sigNo == VKI_SIGILL ||
1798 sigNo == VKI_SIGTRAP);
jsgf855d93d2003-10-13 22:26:55 +00001799
sewardjb5f6f512005-03-10 23:59:00 +00001800 if (info->si_code <= VKI_SI_USER) {
1801 /* If some user-process sent us one of these signals (ie,
1802 they're not the result of a faulting instruction), then treat
1803 it as an async signal. This is tricky because we could get
1804 this almost anywhere:
1805 - while generated client code
1806 Action: queue signal and return
1807 - while running Valgrind code
1808 Action: queue signal and return
1809 - while blocked in a syscall
1810 Action: make thread runnable, queue signal, resume scheduler
1811 */
1812 if (VG_(threads)[tid].status == VgTs_WaitSys) {
1813 /* Since this signal interrupted a syscall, it means the
1814 client's signal mask was applied, so we can't get here
1815 unless the client wants this signal right now. This means
1816 we can simply use the async_signalhandler. */
njn695c16e2005-03-27 03:40:28 +00001817 async_signalhandler(sigNo, info, uc);
1818 VG_(core_panic)("async_signalhandler returned!?\n");
sewardjb5f6f512005-03-10 23:59:00 +00001819 }
jsgf855d93d2003-10-13 22:26:55 +00001820
sewardjb5f6f512005-03-10 23:59:00 +00001821 if (info->_sifields._kill._pid == 0) {
1822 /* There's a per-user limit of pending siginfo signals. If
1823 you exceed this, by having more than that number of
1824 pending signals with siginfo, then new signals are
1825 delivered without siginfo. This condition can be caused
1826 by any unrelated program you're running at the same time
1827 as Valgrind, if it has a large number of pending siginfo
1828 signals which it isn't taking delivery of.
1829
1830 Since we depend on siginfo to work out why we were sent a
1831 signal and what we should do about it, we really can't
1832 continue unless we get it. */
1833 VG_(message)(Vg_UserMsg, "Signal %d (%s) appears to have lost its siginfo; I can't go on.",
1834 sigNo, signame(sigNo));
1835 VG_(message)(Vg_UserMsg, " This may be because one of your programs has consumed your");
1836 VG_(message)(Vg_UserMsg, " ration of siginfo structures.");
njn504b72b2005-08-16 01:39:34 +00001837 VG_(printf)(
1838" For more information, see:\n"
1839" http://kerneltrap.org/mailarchive/1/message/25599/thread\n"
1840" Basically, some program on your system is building up a large queue of\n"
1841" pending signals, and this causes the siginfo data for other signals to\n"
1842" be dropped because it's exceeding a system limit. However, Valgrind\n"
1843" absolutely needs siginfo for SIGSEGV. A workaround is to track down the\n"
1844" offending program and avoid running it while using Valgrind, but there\n"
1845" is no easy way to do this. Apparently the problem was fixed in kernel\n"
1846" 2.6.12.\n");
sewardjb5f6f512005-03-10 23:59:00 +00001847
1848 /* It's a fatal signal, so we force the default handler. */
1849 VG_(set_default_handler)(sigNo);
njn9ec0f3e2005-03-13 06:00:47 +00001850 deliver_signal(tid, info);
njn06244e72005-06-21 22:27:19 +00001851 resume_scheduler(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001852 VG_(exit)(99); /* If we can't resume, then just exit */
1853 }
1854
1855 if (VG_(clo_trace_signals))
1856 VG_(message)(Vg_DebugMsg, "Routing user-sent sync signal %d via queue",
1857 sigNo);
1858
1859 /* Since every thread has these signals unblocked, we can't rely
1860 on the kernel to route them properly, so we need to queue
1861 them manually. */
1862 if (info->si_code == VKI_SI_TKILL)
1863 queue_signal(tid, info); /* directed to us specifically */
1864 else
1865 queue_signal(0, info); /* shared pending */
1866
jsgf855d93d2003-10-13 22:26:55 +00001867 return;
sewardjb5f6f512005-03-10 23:59:00 +00001868 }
1869
1870 if (VG_(clo_trace_signals)) {
1871 VG_(message)(Vg_DebugMsg, "signal %d arrived ... si_code=%d, EIP=%p, eip=%p",
njnf536bbb2005-06-13 04:21:38 +00001872 sigNo, info->si_code, VG_(get_IP)(tid),
njnaf839f52005-06-23 03:27:57 +00001873 VG_UCONTEXT_INSTR_PTR(uc) );
jsgf855d93d2003-10-13 22:26:55 +00001874 }
sewardjb5f6f512005-03-10 23:59:00 +00001875 vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal));
sewardjde4a1d02002-03-22 01:27:54 +00001876
fitzhardinge98abfc72003-12-16 02:05:15 +00001877 /* Special fault-handling case. We can now get signals which can
1878 act upon and immediately restart the faulting instruction.
1879 */
1880 if (info->si_signo == VKI_SIGSEGV) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001881 Addr fault = (Addr)info->_sifields._sigfault._addr;
njnf536bbb2005-06-13 04:21:38 +00001882 Addr esp = VG_(get_SP)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001883 Segment* seg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001884
1885 seg = VG_(find_segment)(fault);
sewardj548be6d2005-02-16 01:31:37 +00001886 if (seg == NULL)
1887 seg = VG_(find_segment_above_unmapped)(fault);
1888
fitzhardinge98abfc72003-12-16 02:05:15 +00001889 if (VG_(clo_trace_signals)) {
1890 if (seg == NULL)
1891 VG_(message)(Vg_DebugMsg,
sewardjb5f6f512005-03-10 23:59:00 +00001892 "SIGSEGV: si_code=%d faultaddr=%p tid=%d ESP=%p seg=NULL shad=%p-%p",
fitzhardinge98abfc72003-12-16 02:05:15 +00001893 info->si_code, fault, tid, esp,
1894 VG_(shadow_base), VG_(shadow_end));
1895 else
1896 VG_(message)(Vg_DebugMsg,
sewardjb5f6f512005-03-10 23:59:00 +00001897 "SIGSEGV: si_code=%d faultaddr=%p tid=%d ESP=%p seg=%p-%p fl=%x shad=%p-%p",
fitzhardinge98abfc72003-12-16 02:05:15 +00001898 info->si_code, fault, tid, esp, seg->addr, seg->addr+seg->len, seg->flags,
1899 VG_(shadow_base), VG_(shadow_end));
1900 }
sewardjb5f6f512005-03-10 23:59:00 +00001901 if (info->si_code == 1 /* SEGV_MAPERR */
njnaf839f52005-06-23 03:27:57 +00001902 && fault >= (esp - VG_STACK_REDZONE_SZB)
njncafca7b2005-03-13 04:39:28 +00001903 && fault < VG_(client_end)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001904 /* If the fault address is above esp but below the current known
1905 stack segment base, and it was a fault because there was
1906 nothing mapped there (as opposed to a permissions fault),
1907 then extend the stack segment.
1908 */
njnaf839f52005-06-23 03:27:57 +00001909 Addr base = VG_PGROUNDDN(esp - VG_STACK_REDZONE_SZB);
njn50ba34e2005-04-04 02:41:42 +00001910 if (VG_(extend_stack)(base, VG_(threads)[tid].client_stack_szB)) {
sewardjb5f6f512005-03-10 23:59:00 +00001911 if (VG_(clo_trace_signals))
1912 VG_(message)(Vg_DebugMsg,
njn13bfd852005-06-02 03:52:53 +00001913 " -> extended stack base to %p", VG_PGROUNDDN(fault));
sewardjb5f6f512005-03-10 23:59:00 +00001914 return; // extension succeeded, restart instruction
1915 } else
1916 VG_(message)(Vg_UserMsg, "Stack overflow in thread %d: can't grow stack to %p",
1917 tid, fault);
fitzhardinge98abfc72003-12-16 02:05:15 +00001918 }
njnb69f7c12005-06-24 22:17:38 +00001919 /* Fall into normal signal handling for all other cases */
fitzhardinge98abfc72003-12-16 02:05:15 +00001920 }
1921
sewardjb5f6f512005-03-10 23:59:00 +00001922 /* OK, this is a signal we really have to deal with. If it came
1923 from the client's code, then we can jump back into the scheduler
1924 and have it delivered. Otherwise it's a Valgrind bug. */
1925 {
sewardjb5f6f512005-03-10 23:59:00 +00001926 ThreadState *tst = VG_(get_ThreadState)(VG_(get_lwp_tid)(VG_(gettid)()));
jsgf855d93d2003-10-13 22:26:55 +00001927
sewardjb5f6f512005-03-10 23:59:00 +00001928 if (VG_(sigismember)(&tst->sig_mask, sigNo)) {
1929 /* signal is blocked, but they're not allowed to block faults */
1930 VG_(set_default_handler)(sigNo);
1931 }
1932
1933 if (!VG_(my_fault)) {
1934 /* Can't continue; must longjmp back to the scheduler and thus
1935 enter the sighandler immediately. */
njn9ec0f3e2005-03-13 06:00:47 +00001936 deliver_signal(tid, info);
njn06244e72005-06-21 22:27:19 +00001937 resume_scheduler(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001938 }
1939
1940 /* Check to see if someone is interested in faults. */
1941 if (fault_catcher) {
1942 (*fault_catcher)(sigNo, (Addr)info->_sifields._sigfault._addr);
1943
1944 /* If the catcher returns, then it didn't handle the fault,
1945 so carry on panicing. */
1946 }
1947
1948 /* If resume_scheduler returns or its our fault, it means we
1949 don't have longjmp set up, implying that we weren't running
1950 client code, and therefore it was actually generated by
1951 Valgrind internally.
1952 */
jsgf855d93d2003-10-13 22:26:55 +00001953 VG_(message)(Vg_DebugMsg,
1954 "INTERNAL ERROR: Valgrind received a signal %d (%s) - exiting",
1955 sigNo, signame(sigNo));
fitzhardinge98abfc72003-12-16 02:05:15 +00001956
jsgf855d93d2003-10-13 22:26:55 +00001957 VG_(message)(Vg_DebugMsg,
njnd0073f42005-05-14 17:00:25 +00001958 "si_code=%x; Faulting address: %p; sp: %p",
1959 info->si_code, info->_sifields._sigfault._addr,
njnaf839f52005-06-23 03:27:57 +00001960 VG_UCONTEXT_STACK_PTR(uc));
jsgf855d93d2003-10-13 22:26:55 +00001961
1962 if (0)
1963 VG_(kill_self)(sigNo); /* generate a core dump */
sewardjb5f6f512005-03-10 23:59:00 +00001964
sewardj1d887112005-05-30 21:44:08 +00001965 //if (tid == 0) /* could happen after everyone has exited */
1966 // tid = VG_(master_tid);
1967 vg_assert(tid != 0);
1968
njndb13c4f2005-06-01 00:00:46 +00001969 VG_(core_panic_at)("Killed by fatal signal",
njnaf839f52005-06-23 03:27:57 +00001970 VG_UCONTEXT_INSTR_PTR(uc),
1971 VG_UCONTEXT_STACK_PTR(uc),
sewardjacaec5f2005-08-19 16:02:59 +00001972 VG_UCONTEXT_FRAME_PTR(uc),
1973 VG_UCONTEXT_LINK_REG(uc));
jsgf855d93d2003-10-13 22:26:55 +00001974 }
1975}
1976
1977
1978/*
sewardjb5f6f512005-03-10 23:59:00 +00001979 Kill this thread. Makes it leave any syscall it might be currently
1980 blocked in, and return to the scheduler. This doesn't mark the thread
1981 as exiting; that's the caller's job.
jsgf855d93d2003-10-13 22:26:55 +00001982 */
sewardjb5f6f512005-03-10 23:59:00 +00001983static void sigvgkill_handler(int signo, vki_siginfo_t *si, struct vki_ucontext *uc)
jsgf855d93d2003-10-13 22:26:55 +00001984{
sewardjb5f6f512005-03-10 23:59:00 +00001985 ThreadId tid = VG_(get_lwp_tid)(VG_(gettid)());
1986
1987 if (VG_(clo_trace_signals))
1988 VG_(message)(Vg_DebugMsg, "sigvgkill for lwp %d tid %d", VG_(gettid)(), tid);
1989
njn351d0062005-06-21 22:23:59 +00001990 vg_assert(signo == VG_SIGVGKILL);
jsgf855d93d2003-10-13 22:26:55 +00001991 vg_assert(si->si_signo == signo);
sewardjb5f6f512005-03-10 23:59:00 +00001992 vg_assert(VG_(threads)[tid].status == VgTs_WaitSys);
jsgf855d93d2003-10-13 22:26:55 +00001993
sewardjb5f6f512005-03-10 23:59:00 +00001994 VG_(set_running)(tid);
1995 VG_(post_syscall)(tid);
1996
njn06244e72005-06-21 22:27:19 +00001997 resume_scheduler(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001998
1999 VG_(core_panic)("sigvgkill_handler couldn't return to the scheduler\n");
sewardjde4a1d02002-03-22 01:27:54 +00002000}
2001
sewardjde4a1d02002-03-22 01:27:54 +00002002static __attribute((unused))
njn695c16e2005-03-27 03:40:28 +00002003void pp_ksigaction ( struct vki_sigaction* sa )
sewardjde4a1d02002-03-22 01:27:54 +00002004{
2005 Int i;
njn695c16e2005-03-27 03:40:28 +00002006 VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n",
nethercote73b526f2004-10-31 18:48:21 +00002007 sa->ksa_handler, (UInt)sa->sa_flags, sa->sa_restorer);
njn695c16e2005-03-27 03:40:28 +00002008 VG_(printf)("pp_ksigaction: { ");
sewardjb5f6f512005-03-10 23:59:00 +00002009 for (i = 1; i <= VG_(max_signal); i++)
nethercote73b526f2004-10-31 18:48:21 +00002010 if (VG_(sigismember(&(sa->sa_mask),i)))
sewardjde4a1d02002-03-22 01:27:54 +00002011 VG_(printf)("%d ", i);
2012 VG_(printf)("}\n");
2013}
2014
jsgf855d93d2003-10-13 22:26:55 +00002015/*
sewardjb5f6f512005-03-10 23:59:00 +00002016 Force signal handler to default
jsgf855d93d2003-10-13 22:26:55 +00002017 */
sewardjb5f6f512005-03-10 23:59:00 +00002018void VG_(set_default_handler)(Int signo)
2019{
2020 struct vki_sigaction sa;
2021
2022 sa.ksa_handler = VKI_SIG_DFL;
2023 sa.sa_flags = 0;
2024 sa.sa_restorer = 0;
2025 VG_(sigemptyset)(&sa.sa_mask);
2026
2027 VG_(do_sys_sigaction)(signo, &sa, NULL);
2028}
2029
2030/*
2031 Poll for pending signals, and set the next one up for delivery.
2032 */
2033void VG_(poll_signals)(ThreadId tid)
jsgf855d93d2003-10-13 22:26:55 +00002034{
2035 static const struct vki_timespec zero = { 0, 0 };
sewardjb5f6f512005-03-10 23:59:00 +00002036 vki_siginfo_t si, *sip;
2037 vki_sigset_t pollset;
2038 ThreadState *tst = VG_(get_ThreadState)(tid);
2039 Int i;
2040 vki_sigset_t saved_mask;
jsgf855d93d2003-10-13 22:26:55 +00002041
sewardjb5f6f512005-03-10 23:59:00 +00002042 /* look for all the signals this thread isn't blocking */
2043 for(i = 0; i < _VKI_NSIG_WORDS; i++)
2044 pollset.sig[i] = ~tst->sig_mask.sig[i];
jsgf855d93d2003-10-13 22:26:55 +00002045
sewardjb5f6f512005-03-10 23:59:00 +00002046 //VG_(printf)("tid %d pollset=%08x%08x\n", tid, pollset.sig[1], pollset.sig[0]);
jsgf855d93d2003-10-13 22:26:55 +00002047
njn444eba12005-05-12 03:47:31 +00002048 block_all_host_signals(&saved_mask); // protect signal queue
sewardjb5f6f512005-03-10 23:59:00 +00002049
2050 /* First look for any queued pending signals */
2051 sip = next_queued(tid, &pollset); /* this thread */
2052
2053 if (sip == NULL)
2054 sip = next_queued(0, &pollset); /* process-wide */
2055
2056 /* If there was nothing queued, ask the kernel for a pending signal */
2057 if (sip == NULL && VG_(sigtimedwait)(&pollset, &si, &zero) > 0) {
2058 if (VG_(clo_trace_signals))
sewardja8d8e232005-06-07 20:04:56 +00002059 VG_(message)(Vg_DebugMsg, "poll_signals: got signal %d "
2060 "for thread %d", si.si_signo, tid);
sewardjb5f6f512005-03-10 23:59:00 +00002061 sip = &si;
thughes8abf3922004-10-16 10:59:49 +00002062 }
fitzhardingee1c06d82003-10-30 07:21:44 +00002063
sewardjb5f6f512005-03-10 23:59:00 +00002064 if (sip != NULL) {
2065 /* OK, something to do; deliver it */
2066 if (VG_(clo_trace_signals))
2067 VG_(message)(Vg_DebugMsg, "Polling found signal %d for tid %d",
2068 sip->si_signo, tid);
njn07ef6c02005-05-18 19:43:09 +00002069 if (!is_sig_ign(sip->si_signo))
njn9ec0f3e2005-03-13 06:00:47 +00002070 deliver_signal(tid, sip);
sewardjb5f6f512005-03-10 23:59:00 +00002071 else if (VG_(clo_trace_signals))
2072 VG_(message)(Vg_DebugMsg, " signal %d ignored", sip->si_signo);
2073
2074 sip->si_signo = 0; /* remove from signal queue, if that's
2075 where it came from */
jsgf855d93d2003-10-13 22:26:55 +00002076 }
2077
njn444eba12005-05-12 03:47:31 +00002078 restore_all_host_signals(&saved_mask);
sewardjb5f6f512005-03-10 23:59:00 +00002079}
2080
sewardj018f7622002-05-15 21:13:39 +00002081/* At startup, copy the process' real signal state to the SCSS.
2082 Whilst doing this, block all real signals. Then calculate SKSS and
2083 set the kernel to that. Also initialise DCSS.
sewardjde4a1d02002-03-22 01:27:54 +00002084*/
2085void VG_(sigstartup_actions) ( void )
2086{
2087 Int i, ret;
nethercote73b526f2004-10-31 18:48:21 +00002088 vki_sigset_t saved_procmask;
nethercote73b526f2004-10-31 18:48:21 +00002089 struct vki_sigaction sa;
sewardjde4a1d02002-03-22 01:27:54 +00002090
sewardj2e93c502002-04-12 11:12:52 +00002091 /* VG_(printf)("SIGSTARTUP\n"); */
jsgf855d93d2003-10-13 22:26:55 +00002092 /* Block all signals. saved_procmask remembers the previous mask,
2093 which the first thread inherits.
2094 */
njn444eba12005-05-12 03:47:31 +00002095 block_all_host_signals( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00002096
sewardj018f7622002-05-15 21:13:39 +00002097 /* Copy per-signal settings to SCSS. */
nethercote73b526f2004-10-31 18:48:21 +00002098 for (i = 1; i <= _VKI_NSIG; i++) {
sewardj018f7622002-05-15 21:13:39 +00002099 /* Get the old host action */
nethercote73b526f2004-10-31 18:48:21 +00002100 ret = VG_(sigaction)(i, NULL, &sa);
sewardj018f7622002-05-15 21:13:39 +00002101
sewardjb5f6f512005-03-10 23:59:00 +00002102 if (ret != 0)
2103 break;
2104
2105 /* Try setting it back to see if this signal is really
2106 available */
2107 if (i >= VKI_SIGRTMIN) {
2108 struct vki_sigaction tsa;
2109
njn695c16e2005-03-27 03:40:28 +00002110 tsa.ksa_handler = (void *)sync_signalhandler;
sewardjb5f6f512005-03-10 23:59:00 +00002111 tsa.sa_flags = VKI_SA_SIGINFO;
2112 tsa.sa_restorer = 0;
2113 VG_(sigfillset)(&tsa.sa_mask);
2114
2115 /* try setting it to some arbitrary handler */
2116 if (VG_(sigaction)(i, &tsa, NULL) != 0) {
2117 /* failed - not really usable */
2118 break;
2119 }
2120
2121 ret = VG_(sigaction)(i, &sa, NULL);
2122 vg_assert(ret == 0);
2123 }
2124
2125 VG_(max_signal) = i;
2126
2127 if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2)
sewardj018f7622002-05-15 21:13:39 +00002128 VG_(printf)("snaffling handler 0x%x for signal %d\n",
2129 (Addr)(sa.ksa_handler), i );
2130
njn695c16e2005-03-27 03:40:28 +00002131 scss.scss_per_sig[i].scss_handler = sa.ksa_handler;
2132 scss.scss_per_sig[i].scss_flags = sa.sa_flags;
2133 scss.scss_per_sig[i].scss_mask = sa.sa_mask;
2134 scss.scss_per_sig[i].scss_restorer = sa.sa_restorer;
sewardj018f7622002-05-15 21:13:39 +00002135 }
2136
sewardjb5f6f512005-03-10 23:59:00 +00002137 if (VG_(clo_trace_signals))
2138 VG_(message)(Vg_DebugMsg, "Max kernel-supported signal is %d", VG_(max_signal));
2139
jsgf855d93d2003-10-13 22:26:55 +00002140 /* Our private internal signals are treated as ignored */
njn351d0062005-06-21 22:23:59 +00002141 scss.scss_per_sig[VG_SIGVGKILL].scss_handler = VKI_SIG_IGN;
2142 scss.scss_per_sig[VG_SIGVGKILL].scss_flags = VKI_SA_SIGINFO;
2143 VG_(sigfillset)(&scss.scss_per_sig[VG_SIGVGKILL].scss_mask);
jsgf855d93d2003-10-13 22:26:55 +00002144
sewardj018f7622002-05-15 21:13:39 +00002145 /* Copy the process' signal mask into the root thread. */
sewardj1d887112005-05-30 21:44:08 +00002146 vg_assert(VG_(threads)[1].status == VgTs_Init);
2147 for (i = 2; i < VG_N_THREADS; i++)
2148 vg_assert(VG_(threads)[i].status == VgTs_Empty);
2149
2150 VG_(threads)[1].sig_mask = saved_procmask;
2151 VG_(threads)[1].tmp_sig_mask = saved_procmask;
sewardj7a61d912002-04-25 01:27:35 +00002152
sewardj018f7622002-05-15 21:13:39 +00002153 /* Calculate SKSS and apply it. This also sets the initial kernel
2154 mask we need to run with. */
nethercote9dd11512004-08-04 15:31:30 +00002155 handle_SCSS_change( True /* forced update */ );
jsgf855d93d2003-10-13 22:26:55 +00002156
sewardjb5f6f512005-03-10 23:59:00 +00002157 /* Leave with all signals still blocked; the thread scheduler loop
2158 will set the appropriate mask at the appropriate time. */
sewardjde4a1d02002-03-22 01:27:54 +00002159}
2160
sewardjde4a1d02002-03-22 01:27:54 +00002161/*--------------------------------------------------------------------*/
njned6b8242005-06-01 00:03:17 +00002162/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002163/*--------------------------------------------------------------------*/