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-2015 Nicholas Nethercote 14 njn (at) valgrind.org 15 Copyright (C) 2006-2015 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