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