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@valgrind.org
15   Copyright (C) 2006-2015 OpenWorks Ltd
16      info@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. */
47static 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. */
57Bool 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. */
112Bool 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