Home | History | Annotate | Download | only in m_sigframe
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 
      3 /*--------------------------------------------------------------------*/
      4 /*--- Signal frames handling: stuff common to most/all platforms   ---*/
      5 /*---                                                              ---*/
      6 /*---                                            sigframe-common.c ---*/
      7 /*--------------------------------------------------------------------*/
      8 
      9 /*
     10    This file is part of Valgrind, a dynamic binary instrumentation
     11    framework.
     12 
     13    Copyright (C) 2000-2017 Nicholas Nethercote
     14       njn (at) valgrind.org
     15    Copyright (C) 2006-2017 OpenWorks Ltd
     16       info (at) open-works.co.uk
     17 
     18    This program is free software; you can redistribute it and/or
     19    modify it under the terms of the GNU General Public License as
     20    published by the Free Software Foundation; either version 2 of the
     21    License, or (at your option) any later version.
     22 
     23    This program is distributed in the hope that it will be useful, but
     24    WITHOUT ANY WARRANTY; without even the implied warranty of
     25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     26    General Public License for more details.
     27 
     28    You should have received a copy of the GNU General Public License
     29    along with this program; if not, write to the Free Software
     30    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     31    02111-1307, USA.
     32 
     33    The GNU General Public License is contained in the file COPYING.
     34 */
     35 
     36 #include "pub_core_aspacemgr.h"      // VG_(am_find_nsegment)
     37 #include "pub_core_signals.h"        // VG_(extend_stack)
     38 #include "pub_core_libcprint.h"      // VG_(umsg)
     39 #include "pub_core_tooliface.h"      // VG_TRACK
     40 #include "pub_core_machine.h"        // VG_STACK_REDZONE_SZB
     41 #include "priv_sigframe.h"           // self
     42 
     43 
     44 /* For tracking memory events, indicate the entire frame has been
     45    allocated.  Except, don't mess with the area which
     46    overlaps the previous frame's redzone. */
     47 static void track_frame_memory ( Addr addr, SizeT size, ThreadId tid )
     48 {
     49    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, size, tid );
     50 }
     51 
     52 #if defined(VGO_linux) || defined(VGO_solaris)
     53 
     54 /* Extend the stack segment downwards if needed so as to ensure the
     55    new signal frames are mapped to something.  Return a Bool
     56    indicating whether or not the operation was successful. */
     57 Bool ML_(sf_maybe_extend_stack) ( const ThreadState *tst, Addr addr,
     58                                   SizeT size, UInt flags )
     59 {
     60    ThreadId        tid = tst->tid;
     61    const NSegment *stackseg = NULL;
     62 
     63    if (flags & VKI_SA_ONSTACK) {
     64       /* If the sigframe is allocated on an alternate stack, then we cannot
     65          extend that stack. Nothing to do here. */
     66       stackseg = VG_(am_find_nsegment)(addr);
     67    } else if (VG_(am_addr_is_in_extensible_client_stack)(addr)) {
     68       if (VG_(extend_stack)(tid, addr)) {
     69          stackseg = VG_(am_find_nsegment)(addr);
     70          if (0 && stackseg)
     71             VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
     72                         addr, stackseg->start, stackseg->end);
     73       }
     74    } else if ((stackseg = VG_(am_find_nsegment)(addr)) &&
     75               VG_(am_is_valid_for_client)(addr, 1,
     76                                           VKI_PROT_READ | VKI_PROT_WRITE)) {
     77       /* We come here for explicitly defined pthread-stacks which can be
     78          located in any client segment. */
     79    } else {
     80       /* Something unexpected */
     81       stackseg = NULL;
     82    }
     83 
     84    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
     85       VG_(umsg)("Can't extend stack to %#lx during signal delivery for "
     86                 "thread %u:\n", addr, tid);
     87       if (stackseg == NULL)
     88          VG_(umsg)("  no stack segment\n");
     89       else
     90          VG_(umsg)("  too small or bad protection modes\n");
     91 
     92       /* set SIGSEGV to default handler */
     93       VG_(set_default_handler)(VKI_SIGSEGV);
     94       VG_(synth_fault_mapping)(tid, addr);
     95 
     96       /* The whole process should be about to die, since the default
     97 	 action of SIGSEGV to kill the whole process. */
     98       return False;
     99    }
    100 
    101    /* Tell the tool about the new memory */
    102    track_frame_memory(addr, size, tid);
    103 
    104    return True;
    105 }
    106 
    107 #elif defined(VGO_darwin)
    108 
    109 /* Extend the stack segment downwards if needed so as to ensure the
    110    new signal frames are mapped to something.  Return a Bool
    111    indicating whether or not the operation was successful. */
    112 Bool ML_(sf_maybe_extend_stack) ( const ThreadState *tst, Addr addr,
    113                                   SizeT size, UInt flags )
    114 {
    115    /* Tell the tool about the new memory */
    116    track_frame_memory(addr, size, tst->tid);
    117    return True;
    118 }
    119 
    120 #else
    121 #error unknown OS
    122 #endif
    123 
    124 /*--------------------------------------------------------------------*/
    125 /*--- end                                                          ---*/
    126 /*--------------------------------------------------------------------*/
    127