Home | History | Annotate | Download | only in coregrind
      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-2011 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