1 2 /*--------------------------------------------------------------------*/ 3 /*--- Signal-related libc stuff. m_libcsignal.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2012 Julian Seward 11 jseward (at) acm.org 12 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 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #include "pub_core_basics.h" 32 #include "pub_core_debuglog.h" 33 #include "pub_core_vki.h" 34 #include "pub_core_vkiscnums.h" 35 #include "pub_core_libcbase.h" 36 #include "pub_core_libcassert.h" 37 #include "pub_core_syscall.h" 38 #include "pub_core_libcsignal.h" /* self */ 39 40 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions 41 of syscalls rather than the vanilla version, if a _nocancel version 42 is available. See docs/internals/Darwin-notes.txt for the reason 43 why. */ 44 45 /* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on 46 success and -1 on error. */ 47 /* In the sigset routines below, be aware that _VKI_NSIG_BPW can be 48 either 32 or 64, and hence the sig[] words can either be 32- or 49 64-bits. And which they are it doesn't necessarily follow from the 50 host word size. */ 51 52 Int VG_(sigfillset)( vki_sigset_t* set ) 53 { 54 Int i; 55 if (set == NULL) 56 return -1; 57 for (i = 0; i < _VKI_NSIG_WORDS; i++) 58 set->sig[i] = ~0; 59 return 0; 60 } 61 62 Int VG_(sigemptyset)( vki_sigset_t* set ) 63 { 64 Int i; 65 if (set == NULL) 66 return -1; 67 for (i = 0; i < _VKI_NSIG_WORDS; i++) 68 set->sig[i] = 0; 69 return 0; 70 } 71 72 Bool VG_(isemptysigset)( const vki_sigset_t* set ) 73 { 74 Int i; 75 vg_assert(set != NULL); 76 for (i = 0; i < _VKI_NSIG_WORDS; i++) 77 if (set->sig[i] != 0) return False; 78 return True; 79 } 80 81 Bool VG_(isfullsigset)( const vki_sigset_t* set ) 82 { 83 Int i; 84 vg_assert(set != NULL); 85 for (i = 0; i < _VKI_NSIG_WORDS; i++) 86 if (set->sig[i] != ~0) return False; 87 return True; 88 } 89 90 Bool VG_(iseqsigset)( const vki_sigset_t* set1, const vki_sigset_t* set2 ) 91 { 92 Int i; 93 vg_assert(set1 != NULL && set2 != NULL); 94 for (i = 0; i < _VKI_NSIG_WORDS; i++) 95 if (set1->sig[i] != set2->sig[i]) return False; 96 return True; 97 } 98 99 100 Int VG_(sigaddset)( vki_sigset_t* set, Int signum ) 101 { 102 if (set == NULL) 103 return -1; 104 if (signum < 1 || signum > _VKI_NSIG) 105 return -1; 106 signum--; 107 set->sig[signum / _VKI_NSIG_BPW] |= (1ULL << (signum % _VKI_NSIG_BPW)); 108 return 0; 109 } 110 111 Int VG_(sigdelset)( vki_sigset_t* set, Int signum ) 112 { 113 if (set == NULL) 114 return -1; 115 if (signum < 1 || signum > _VKI_NSIG) 116 return -1; 117 signum--; 118 set->sig[signum / _VKI_NSIG_BPW] &= ~(1ULL << (signum % _VKI_NSIG_BPW)); 119 return 0; 120 } 121 122 Int VG_(sigismember) ( const vki_sigset_t* set, Int signum ) 123 { 124 if (set == NULL) 125 return 0; 126 if (signum < 1 || signum > _VKI_NSIG) 127 return 0; 128 signum--; 129 if (1 & ((set->sig[signum / _VKI_NSIG_BPW]) >> (signum % _VKI_NSIG_BPW))) 130 return 1; 131 else 132 return 0; 133 } 134 135 /* Add all signals in src to dst. */ 136 void VG_(sigaddset_from_set)( vki_sigset_t* dst, vki_sigset_t* src ) 137 { 138 Int i; 139 vg_assert(dst != NULL && src != NULL); 140 for (i = 0; i < _VKI_NSIG_WORDS; i++) 141 dst->sig[i] |= src->sig[i]; 142 } 143 144 /* Remove all signals in src from dst. */ 145 void VG_(sigdelset_from_set)( vki_sigset_t* dst, vki_sigset_t* src ) 146 { 147 Int i; 148 vg_assert(dst != NULL && src != NULL); 149 for (i = 0; i < _VKI_NSIG_WORDS; i++) 150 dst->sig[i] &= ~(src->sig[i]); 151 } 152 153 /* dst = dst `intersect` src. */ 154 void VG_(sigintersectset)( vki_sigset_t* dst, vki_sigset_t* src ) 155 { 156 Int i; 157 vg_assert(dst != NULL && src != NULL); 158 for (i = 0; i < _VKI_NSIG_WORDS; i++) 159 dst->sig[i] &= src->sig[i]; 160 } 161 162 /* dst = ~src */ 163 void VG_(sigcomplementset)( vki_sigset_t* dst, vki_sigset_t* src ) 164 { 165 Int i; 166 vg_assert(dst != NULL && src != NULL); 167 for (i = 0; i < _VKI_NSIG_WORDS; i++) 168 dst->sig[i] = ~ src->sig[i]; 169 } 170 171 172 /* The functions sigaction, sigprocmask, sigpending and sigsuspend 173 return 0 on success and -1 on error. 174 */ 175 Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset) 176 { 177 # if defined(VGO_linux) 178 # if defined(__NR_rt_sigprocmask) 179 SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask, 180 how, (UWord)set, (UWord)oldset, 181 _VKI_NSIG_WORDS * sizeof(UWord)); 182 # else 183 SysRes res = VG_(do_syscall3)(__NR_sigprocmask, 184 how, (UWord)set, (UWord)oldset); 185 # endif 186 187 # elif defined(VGO_darwin) 188 /* On Darwin, __NR_sigprocmask appears to affect the entire 189 process, not just this thread. Hence need to use 190 __NR___pthread_sigmask instead. */ 191 SysRes res = VG_(do_syscall3)(__NR___pthread_sigmask, 192 how, (UWord)set, (UWord)oldset); 193 # else 194 # error "Unknown OS" 195 # endif 196 return sr_isError(res) ? -1 : 0; 197 } 198 199 200 #if defined(VGO_darwin) 201 /* A helper function for sigaction on Darwin. */ 202 static 203 void darwin_signal_demux(void* a1, UWord a2, UWord a3, void* a4, void* a5) { 204 VG_(debugLog)(2, "libcsignal", 205 "PRE demux sig, a2 = %lu, signo = %lu\n", a2, a3); 206 if (a2 == 1) 207 ((void(*)(int))a1) (a3); 208 else 209 ((void(*)(int,void*,void*))a1) (a3,a4,a5); 210 VG_(debugLog)(2, "libcsignal", 211 "POST demux sig, a2 = %lu, signo = %lu\n", a2, a3); 212 VG_(do_syscall2)(__NR_sigreturn, (UWord)a5, 0x1E); 213 /* NOTREACHED */ 214 __asm__ __volatile__("ud2"); 215 } 216 #endif 217 218 Int VG_(sigaction) ( Int signum, 219 const vki_sigaction_toK_t* act, 220 vki_sigaction_fromK_t* oldact) 221 { 222 # if defined(VGO_linux) 223 /* Normal case: vki_sigaction_toK_t and vki_sigaction_fromK_t are 224 identical types. */ 225 SysRes res = VG_(do_syscall4)(__NR_rt_sigaction, 226 signum, (UWord)act, (UWord)oldact, 227 _VKI_NSIG_WORDS * sizeof(UWord)); 228 return sr_isError(res) ? -1 : 0; 229 230 # elif defined(VGO_darwin) 231 /* If we're passing a new action to the kernel, make a copy of the 232 new action, install our own sa_tramp field in it, and ignore 233 whatever we were provided with. This is OK because all the 234 sigaction requests come from m_signals, and are not directly 235 what the client program requested, so there is no chance that we 236 will inadvertantly ignore the sa_tramp field requested by the 237 client. (In fact m_signals does ignore it when building signal 238 frames for the client, but that's a completely different 239 matter). 240 241 If we're receiving an old action from the kernel, be very 242 paranoid and make sure the kernel doesn't trash bits of memory 243 that we don't expect it to. */ 244 SysRes res; 245 246 vki_sigaction_toK_t actCopy; 247 struct { 248 ULong before[2]; 249 vki_sigaction_fromK_t oa; 250 ULong after[2]; 251 } 252 oldactCopy; 253 254 vki_sigaction_toK_t* real_act; 255 vki_sigaction_fromK_t* real_oldact; 256 257 real_act = act ? &actCopy : NULL; 258 real_oldact = oldact ? &oldactCopy.oa : NULL; 259 VG_(memset)(&oldactCopy, 0x55, sizeof(oldactCopy)); 260 if (real_act) { 261 *real_act = *act; 262 real_act->sa_tramp = (void*)&darwin_signal_demux; 263 } 264 res = VG_(do_syscall3)(__NR_sigaction, 265 signum, (UWord)real_act, (UWord)real_oldact); 266 if (real_oldact) { 267 vg_assert(oldactCopy.before[0] == 0x5555555555555555ULL); 268 vg_assert(oldactCopy.before[1] == 0x5555555555555555ULL); 269 vg_assert(oldactCopy.after[0] == 0x5555555555555555ULL); 270 vg_assert(oldactCopy.after[1] == 0x5555555555555555ULL); 271 *oldact = *real_oldact; 272 } 273 return sr_isError(res) ? -1 : 0; 274 275 # else 276 # error "Unsupported OS" 277 # endif 278 } 279 280 281 /* See explanation in pub_core_libcsignal.h. */ 282 void 283 VG_(convert_sigaction_fromK_to_toK)( vki_sigaction_fromK_t* fromK, 284 /*OUT*/vki_sigaction_toK_t* toK ) 285 { 286 # if defined(VGO_linux) 287 *toK = *fromK; 288 # elif defined(VGO_darwin) 289 toK->ksa_handler = fromK->ksa_handler; 290 toK->sa_tramp = NULL; /* the cause of all the difficulty */ 291 toK->sa_mask = fromK->sa_mask; 292 toK->sa_flags = fromK->sa_flags; 293 # else 294 # error "Unsupported OS" 295 # endif 296 } 297 298 299 Int VG_(kill)( Int pid, Int signo ) 300 { 301 # if defined(VGO_linux) 302 SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo); 303 # elif defined(VGO_darwin) 304 SysRes res = VG_(do_syscall3)(__NR_kill, 305 pid, signo, 1/*posix-compliant*/); 306 # else 307 # error "Unsupported OS" 308 # endif 309 return sr_isError(res) ? -1 : 0; 310 } 311 312 Int VG_(tkill)( Int lwpid, Int signo ) 313 { 314 # if defined(__NR_tkill) 315 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); 316 res = VG_(do_syscall2)(__NR_tkill, lwpid, signo); 317 if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS) 318 res = VG_(do_syscall2)(__NR_kill, lwpid, signo); 319 return sr_isError(res) ? -1 : 0; 320 321 # elif defined(VGO_darwin) 322 // Note that the __pthread_kill syscall takes a Mach thread, not a pthread. 323 SysRes res; 324 res = VG_(do_syscall2)(__NR___pthread_kill, lwpid, signo); 325 return sr_isError(res) ? -1 : 0; 326 327 # else 328 # error "Unsupported plat" 329 # endif 330 } 331 332 /* ---------------------- sigtimedwait_zero ----------------------- */ 333 334 /* A cut-down version of POSIX sigtimedwait: poll for pending signals 335 mentioned in the sigset_t, and if any are present, select one 336 arbitrarily, return its number (which must be > 0), and put 337 auxiliary info about it in the siginfo_t, and make it 338 not-pending-any-more. If none are pending, return zero. The _zero 339 refers to the fact that there is zero timeout, so if no signals are 340 pending it returns immediately. Perhaps a better name would be 341 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0 342 if signal n was selected. 343 344 The Linux implementation is trivial: do the corresponding syscall. 345 346 The Darwin implementation is horrible and probably broken in a dozen 347 obscure ways. I suspect it's only thread-safe because V forces 348 single-threadedness. */ 349 350 /* ---------- sigtimedwait_zero: Linux ----------- */ 351 352 #if defined(VGO_linux) 353 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, 354 vki_siginfo_t *info ) 355 { 356 static const struct vki_timespec zero = { 0, 0 }; 357 SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info, 358 (UWord)&zero, sizeof(*set)); 359 return sr_isError(res) ? -1 : sr_Res(res); 360 } 361 362 /* ---------- sigtimedwait_zero: Darwin ----------- */ 363 364 #elif defined(VGO_darwin) 365 366 //static void show_set ( HChar* str, const vki_sigset_t* set ) { 367 // Int i; 368 // VG_(printf)("%s { ", str); 369 // for (i = 1; i <= _VKI_NSIG; i++) { 370 // if (VG_(sigismember)(set, i)) 371 // VG_(printf)("%u ", i); 372 // } 373 // VG_(printf)("}\n"); 374 //} 375 376 /* The general idea is: 377 - use sigpending to find out which signals are pending 378 - choose one 379 - temporarily set its handler to sigtimedwait_zero_handler 380 - use sigsuspend atomically unblock it and wait for the signal. 381 Upon return, sigsuspend restores the signal mask to what it 382 was to start with. 383 - Restore the handler for the signal to whatever it was before. 384 */ 385 386 /* A signal handler which does nothing (it doesn't need to). It does 387 however check that it's not handing a sync signal for which 388 returning is meaningless. */ 389 static void sigtimedwait_zero_handler ( Int sig ) 390 { 391 /* XXX this is wrong -- get rid of these. We could 392 get _any_ signal here */ 393 vg_assert(sig != VKI_SIGILL); 394 vg_assert(sig != VKI_SIGSEGV); 395 vg_assert(sig != VKI_SIGBUS); 396 vg_assert(sig != VKI_SIGTRAP); 397 /* do nothing */ 398 } 399 400 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, 401 vki_siginfo_t *info ) 402 { 403 const Bool debug = False; 404 Int i, ir; 405 SysRes sr; 406 vki_sigset_t pending, blocked, allbutone; 407 vki_sigaction_toK_t sa, saved_sa2; 408 vki_sigaction_fromK_t saved_sa; 409 410 //show_set("STWZ: looking for", set); 411 412 /* Find out what's pending: Darwin sigpending */ 413 sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending); 414 vg_assert(!sr_isError(sr)); 415 416 /* don't try for signals not in 'set' */ 417 /* pending = pending `intersect` set */ 418 VG_(sigintersectset)(&pending, (vki_sigset_t*)set); 419 420 /* don't try for signals not blocked at the moment */ 421 ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked); 422 vg_assert(ir == 0); 423 424 /* pending = pending `intersect` blocked */ 425 VG_(sigintersectset)(&pending, &blocked); 426 427 /* decide which signal we're going to snarf */ 428 for (i = 1; i < _VKI_NSIG; i++) 429 if (VG_(sigismember)(&pending,i)) 430 break; 431 432 if (i == _VKI_NSIG) 433 return 0; 434 435 if (debug) 436 VG_(debugLog)(0, "libcsignal", 437 "sigtimedwait_zero: snarfing signal %d\n", i ); 438 439 /* fetch signal i. 440 pre: i is blocked and pending 441 pre: we are the only thread running 442 */ 443 /* Set up alternative signal handler */ 444 VG_(sigfillset)(&sa.sa_mask); 445 sa.ksa_handler = &sigtimedwait_zero_handler; 446 sa.sa_flags = 0; 447 ir = VG_(sigaction)(i, &sa, &saved_sa); 448 vg_assert(ir == 0); 449 450 /* Switch signal masks and wait for the signal. This should happen 451 immediately, since we've already established it is pending and 452 blocked. */ 453 VG_(sigfillset)(&allbutone); 454 VG_(sigdelset)(&allbutone, i); 455 /* Note: pass the sig mask by value here, not reference (!) */ 456 vg_assert(_VKI_NSIG_WORDS == 1); 457 sr = VG_(do_syscall3)(__NR_sigsuspend_nocancel, 458 (UWord)allbutone.sig[0], 0,0); 459 if (debug) 460 VG_(debugLog)(0, "libcsignal", 461 "sigtimedwait_zero: sigsuspend got " 462 "res: %s %#lx\n", 463 sr_isError(sr) ? "FAIL" : "SUCCESS", 464 sr_isError(sr) ? sr_Err(sr) : sr_Res(sr)); 465 vg_assert(sr_isError(sr)); 466 vg_assert(sr_Err(sr) == VKI_EINTR); 467 468 /* Restore signal's handler to whatever it was before */ 469 VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &saved_sa2 ); 470 ir = VG_(sigaction)(i, &saved_sa2, NULL); 471 vg_assert(ir == 0); 472 473 /* This is bogus - we could get more info from the sighandler. */ 474 VG_(memset)( info, 0, sizeof(*info) ); 475 info->si_signo = i; 476 477 return i; 478 } 479 480 #else 481 # error "Unknown OS" 482 #endif 483 484 /*--------------------------------------------------------------------*/ 485 /*--- end ---*/ 486 /*--------------------------------------------------------------------*/ 487