1945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
2945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--------------------------------------------------------------------*/
3945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--- Stack management.                                 m_stacks.c ---*/
4945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--------------------------------------------------------------------*/
5945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
6945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
7945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   This file is part of Valgrind, a dynamic binary instrumentation
8945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   framework.
9945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
100f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 Julian Seward
11945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      jseward@acm.org
12945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
13945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   This program is free software; you can redistribute it and/or
14945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   modify it under the terms of the GNU General Public License as
15945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   published by the Free Software Foundation; either version 2 of the
16945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   License, or (at your option) any later version.
17945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
18945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   This program is distributed in the hope that it will be useful, but
19945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   WITHOUT ANY WARRANTY; without even the implied warranty of
20945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   General Public License for more details.
22945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
23945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   You should have received a copy of the GNU General Public License
24945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   along with this program; if not, write to the Free Software
25945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   02111-1307, USA.
27945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
28945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   The GNU General Public License is contained in the file COPYING.
29945ed2e53f6bbe9c84a8173b63881158132d9ca8njn*/
30945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
31945ed2e53f6bbe9c84a8173b63881158132d9ca8njn#include "pub_core_basics.h"
32de3cf139fb17c01ff6121e7997e4063f4e3bd55btom#include "pub_core_debuglog.h"
3325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj#include "pub_core_libcassert.h"
34945ed2e53f6bbe9c84a8173b63881158132d9ca8njn#include "pub_core_libcprint.h"
35945ed2e53f6bbe9c84a8173b63881158132d9ca8njn#include "pub_core_mallocfree.h"
363a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe#include "pub_core_aspacemgr.h"
37945ed2e53f6bbe9c84a8173b63881158132d9ca8njn#include "pub_core_options.h"
38945ed2e53f6bbe9c84a8173b63881158132d9ca8njn#include "pub_core_stacks.h"
39945ed2e53f6bbe9c84a8173b63881158132d9ca8njn#include "pub_core_tooliface.h"
40945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
414fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe// For expensive debugging
424fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe#define EDEBUG(fmt, args...) //VG_(debugLog)(2, "stacks", fmt, ## args)
434fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe
44945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
45945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   The stack
46945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   ~~~~~~~~~
47945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   The stack's segment seems to be dynamically extended downwards by
48945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   the kernel as the stack pointer moves down.  Initially, a 1-page
49945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   (4k) stack is allocated.  When SP moves below that for the first
50945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   time, presumably a page fault occurs.  The kernel detects that the
51945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   faulting address is in the range from SP - VG_STACK_REDZONE_SZB
52945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   upwards to the current valid stack.  It then extends the stack
53945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   segment downwards for enough to cover the faulting address, and
54945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   resumes the process (invisibly).  The process is unaware of any of
55945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   this.
56945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
57945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   That means that Valgrind can't spot when the stack segment is being
58945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   extended.  Fortunately, we want to precisely and continuously
59945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   update stack permissions around SP, so we need to spot all writes
60945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   to SP anyway.
61945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
62945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   The deal is: when SP is assigned a lower value, the stack is being
63945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   extended.  Create suitably-permissioned pages to fill in any holes
64945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   between the old stack ptr and this one, if necessary.  Then mark
65945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   all bytes in the area just "uncovered" by this SP change as
66945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   write-only.
67945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
68945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   When SP goes back up, mark the area receded over as unreadable and
69945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   unwritable.
70945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
71945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Just to record the SP boundary conditions somewhere convenient:
72945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   SP - VG_STACK_REDZONE_SZB always points to the lowest live byte in
73945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   the stack.  All addresses below SP - VG_STACK_REDZONE_SZB are not
74945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   live; those at and above it are.
75945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
76945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   We do not concern ourselves here with the VG_STACK_REDZONE_SZB
77945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   bias; that is handled by new_mem_stack/die_mem_stack.
78945ed2e53f6bbe9c84a8173b63881158132d9ca8njn*/
79945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
80945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
81945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * This structure holds information about the start and end addresses of
82945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * registered stacks.  There's always at least one stack registered:
83945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * the main process stack.  It will be the first stack registered and
84945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * so will have a stack id of 0.  The user does not need to register
85945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * this stack: Valgrind does it automatically right before it starts
86945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * running the client.  No other stacks are automatically registered by
87945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * Valgrind, however.
88945ed2e53f6bbe9c84a8173b63881158132d9ca8njn */
89945ed2e53f6bbe9c84a8173b63881158132d9ca8njntypedef struct _Stack {
90945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   UWord id;
9138a74d2cc4670e3eb559adff51a376cd6ec98005philippe   Addr start; // Lowest stack byte, included.
9238a74d2cc4670e3eb559adff51a376cd6ec98005philippe   Addr end;   // Highest stack byte, included.
93945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   struct _Stack *next;
94945ed2e53f6bbe9c84a8173b63881158132d9ca8njn} Stack;
95945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
96945ed2e53f6bbe9c84a8173b63881158132d9ca8njnstatic Stack *stacks;
97945ed2e53f6bbe9c84a8173b63881158132d9ca8njnstatic UWord next_id;  /* Next id we hand out to a newly registered stack */
98945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
99945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
100945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * These are the id, start and end values of the current stack.  If the
101945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * stack pointer falls outside the range of the current stack, we search
102945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * the stacks list above for a matching stack.
103945ed2e53f6bbe9c84a8173b63881158132d9ca8njn */
104de3cf139fb17c01ff6121e7997e4063f4e3bd55btomstatic Stack *current_stack;
105945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
10625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj/* Find 'st' in the stacks_list and move it one step closer the the
10725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   front of the list, so as to make subsequent searches for it
10825b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   cheaper. */
10925b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardjstatic void move_Stack_one_step_forward ( Stack* st )
11025b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj{
11125b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   Stack *st0, *st1, *st2;
11225b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   if (st == stacks)
11325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      return; /* already at head of list */
11425b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   vg_assert(st != NULL);
11525b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   st0 = stacks;
11625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   st1 = NULL;
11725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   st2 = NULL;
11825b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   while (True) {
11925b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      if (st0 == NULL || st0 == st) break;
12025b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st2 = st1;
12125b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st1 = st0;
12225b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st0 = st0->next;
12325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   }
12425b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   vg_assert(st0 == st);
12525b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   if (st0 != NULL && st1 != NULL && st2 != NULL) {
12625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      Stack* tmp;
12725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      /* st0 points to st, st1 to its predecessor, and st2 to st1's
12825b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj         predecessor.  Swap st0 and st1, that is, move st0 one step
12925b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj         closer to the start of the list. */
13025b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      vg_assert(st2->next == st1);
13125b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      vg_assert(st1->next == st0);
13225b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      tmp = st0->next;
13325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st2->next = st0;
13425b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st0->next = st1;
13525b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st1->next = tmp;
13625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   }
13725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   else
13825b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   if (st0 != NULL && st1 != NULL && st2 == NULL) {
13925b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      /* it's second in the list. */
14025b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      vg_assert(stacks == st1);
14125b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      vg_assert(st1->next == st0);
14225b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st1->next = st0->next;
14325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      st0->next = st1;
14425b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      stacks = st0;
14525b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   }
14625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj}
14725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj
148945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/* Find what stack an address falls into. */
1494e72d20f223193fafd7c615f25e4c929ff479741njnstatic Stack* find_stack_by_addr(Addr sp)
150945ed2e53f6bbe9c84a8173b63881158132d9ca8njn{
15125b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   static UWord n_fails = 0;
15225b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   static UWord n_searches = 0;
15325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   static UWord n_steps = 0;
154945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Stack *i = stacks;
15525b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   n_searches++;
15625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   if (0 && 0 == (n_searches % 10000))
15725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      VG_(printf)("(hgdev) %lu searches, %lu steps, %lu fails\n",
15825b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj                  n_searches, n_steps+1, n_fails);
15925b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   /* fast track common case */
16025b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   if (i && sp >= i->start && sp <= i->end)
16125b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      return i;
16225b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   /* else search the list */
1634e72d20f223193fafd7c615f25e4c929ff479741njn   while (i) {
16425b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj      n_steps++;
1654e72d20f223193fafd7c615f25e4c929ff479741njn      if (sp >= i->start && sp <= i->end) {
16625b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj         if (1 && (n_searches & 0x3F) == 0) {
16725b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj            move_Stack_one_step_forward( i );
16825b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj         }
1694e72d20f223193fafd7c615f25e4c929ff479741njn         return i;
170945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      }
171945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      i = i->next;
172945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
17325b079cf1bb1da8eaaff6ce0a1f7a9fca4955d48sewardj   n_fails++;
1744e72d20f223193fafd7c615f25e4c929ff479741njn   return NULL;
175945ed2e53f6bbe9c84a8173b63881158132d9ca8njn}
176945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
177945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
178945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * Register a new stack from start - end.  This is invoked from the
179945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * VALGRIND_STACK_REGISTER client request, and is also called just before
180945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * we start the client running, to register the main process stack.
181945ed2e53f6bbe9c84a8173b63881158132d9ca8njn */
182945ed2e53f6bbe9c84a8173b63881158132d9ca8njnUWord VG_(register_stack)(Addr start, Addr end)
183945ed2e53f6bbe9c84a8173b63881158132d9ca8njn{
184945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Stack *i;
18545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
186945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   if (start > end) {
18738a74d2cc4670e3eb559adff51a376cd6ec98005philippe      /* If caller provides addresses in reverse order, swap them.
18838a74d2cc4670e3eb559adff51a376cd6ec98005philippe         Ugly but not doing that breaks backward compatibility with
18938a74d2cc4670e3eb559adff51a376cd6ec98005philippe         (user) code registering stacks with start/end inverted . */
190945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      Addr t = end;
191945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      end = start;
192945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      start = t;
193945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
194945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
19577eb20b3865e7b17c7695c7e7a526b52935f593eflorian   i = VG_(malloc)("stacks.rs.1", sizeof(Stack));
196945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   i->start = start;
197945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   i->end = end;
198945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   i->id = next_id++;
199945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   i->next = stacks;
200945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   stacks = i;
201945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
2024e72d20f223193fafd7c615f25e4c929ff479741njn   if (i->id == 0) {
203de3cf139fb17c01ff6121e7997e4063f4e3bd55btom      current_stack = i;
204945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
205945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
2063a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe   VG_(debugLog)(2, "stacks", "register [start-end] [%p-%p] as stack %lu\n",
2074818d73a255b7b474b670feeb37f83a2c17c401bnjn                    (void*)start, (void*)end, i->id);
208de3cf139fb17c01ff6121e7997e4063f4e3bd55btom
209945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   return i->id;
210945ed2e53f6bbe9c84a8173b63881158132d9ca8njn}
211945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
212945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
213945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * Deregister a stack.  This is invoked from the VALGRIND_STACK_DEREGISTER
214945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * client request.
215945ed2e53f6bbe9c84a8173b63881158132d9ca8njn */
216945ed2e53f6bbe9c84a8173b63881158132d9ca8njnvoid VG_(deregister_stack)(UWord id)
217945ed2e53f6bbe9c84a8173b63881158132d9ca8njn{
218945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Stack *i = stacks;
219945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Stack *prev = NULL;
220945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
2214818d73a255b7b474b670feeb37f83a2c17c401bnjn   VG_(debugLog)(2, "stacks", "deregister stack %lu\n", id);
222de3cf139fb17c01ff6121e7997e4063f4e3bd55btom
2230edccddc1511cd2479d963adcd1fb4c98247580bsewardj   if (current_stack && current_stack->id == id) {
224de3cf139fb17c01ff6121e7997e4063f4e3bd55btom      current_stack = NULL;
225945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
226945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
227945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   while(i) {
228945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      if (i->id == id) {
229945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         if(prev == NULL) {
230945ed2e53f6bbe9c84a8173b63881158132d9ca8njn            stacks = i->next;
231945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         } else {
232945ed2e53f6bbe9c84a8173b63881158132d9ca8njn            prev->next = i->next;
233945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         }
23477eb20b3865e7b17c7695c7e7a526b52935f593eflorian         VG_(free)(i);
235945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         return;
236945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      }
237945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      prev = i;
238945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      i = i->next;
239945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
240945ed2e53f6bbe9c84a8173b63881158132d9ca8njn}
241945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
242945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*
243945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * Change a stack.  This is invoked from the VALGRIND_STACK_CHANGE client
244945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * request and from the stack growth stuff the signals module when
245945ed2e53f6bbe9c84a8173b63881158132d9ca8njn * extending the main process stack.
246945ed2e53f6bbe9c84a8173b63881158132d9ca8njn */
247945ed2e53f6bbe9c84a8173b63881158132d9ca8njnvoid VG_(change_stack)(UWord id, Addr start, Addr end)
248945ed2e53f6bbe9c84a8173b63881158132d9ca8njn{
249945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   Stack *i = stacks;
250945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
2514e72d20f223193fafd7c615f25e4c929ff479741njn   while (i) {
252945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      if (i->id == id) {
25338a74d2cc4670e3eb559adff51a376cd6ec98005philippe         VG_(debugLog)(2, "stacks",
25438a74d2cc4670e3eb559adff51a376cd6ec98005philippe                       "change stack %lu from [%p-%p] to [%p-%p]\n",
2554818d73a255b7b474b670feeb37f83a2c17c401bnjn                       id, (void*)i->start, (void*)i->end,
2564818d73a255b7b474b670feeb37f83a2c17c401bnjn                           (void*)start,    (void*)end);
25738a74d2cc4670e3eb559adff51a376cd6ec98005philippe         /* FIXME : swap start/end like VG_(register_stack) ??? */
258945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         i->start = start;
259945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         i->end = end;
260945ed2e53f6bbe9c84a8173b63881158132d9ca8njn         return;
261945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      }
262945ed2e53f6bbe9c84a8173b63881158132d9ca8njn      i = i->next;
263945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
264945ed2e53f6bbe9c84a8173b63881158132d9ca8njn}
265945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
266690c3c807be3571951400b98d5136437dd957b65tom/*
267690c3c807be3571951400b98d5136437dd957b65tom * Find the bounds of the stack (if any) which includes the
268690c3c807be3571951400b98d5136437dd957b65tom * specified stack pointer.
269690c3c807be3571951400b98d5136437dd957b65tom */
270690c3c807be3571951400b98d5136437dd957b65tomvoid VG_(stack_limits)(Addr SP, Addr *start, Addr *end )
271690c3c807be3571951400b98d5136437dd957b65tom{
272690c3c807be3571951400b98d5136437dd957b65tom   Stack* stack = find_stack_by_addr(SP);
2733a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe   NSegment const *stackseg = VG_(am_find_nsegment) (SP);
274690c3c807be3571951400b98d5136437dd957b65tom
27593d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (LIKELY(stack)) {
276690c3c807be3571951400b98d5136437dd957b65tom      *start = stack->start;
277690c3c807be3571951400b98d5136437dd957b65tom      *end = stack->end;
278690c3c807be3571951400b98d5136437dd957b65tom   }
2793a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe
280cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   /* SP is assumed to be in a RW segment or in the SkResvn segment of an
281cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      extensible stack (normally, only the main thread has an extensible
282cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      stack segment).
2833a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      If no such segment is found, assume we have no valid
2843a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      stack for SP, and set *start and *end to 0.
285cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      Otherwise, possibly reduce the stack limits using the boundaries of
286cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      the RW segment/SkResvn segments containing SP. */
28793d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (UNLIKELY(stackseg == NULL)) {
2883a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      VG_(debugLog)(2, "stacks",
2893a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe                    "no addressable segment for SP %p\n",
2903a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe                    (void*)SP);
2913a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      *start = 0;
2923a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      *end = 0;
293cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      return;
294cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   }
295cda0c2cf073a7fba19e1fb2576446506894facbaphilippe
29693d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (UNLIKELY((!stackseg->hasR || !stackseg->hasW)
29793d127f02c9abb9e6373585ee4529ece6dee0503philippe                && (stackseg->kind != SkResvn || stackseg->smode != SmUpper))) {
2983a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      VG_(debugLog)(2, "stacks",
299cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    "segment for SP %p is not RW or not a SmUpper Resvn\n",
3003a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe                    (void*)SP);
3013a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      *start = 0;
3023a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      *end = 0;
303cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      return;
304cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   }
3053a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe
30693d127f02c9abb9e6373585ee4529ece6dee0503philippe   /* SP is in a RW segment, or in the SkResvn of an extensible stack.
30793d127f02c9abb9e6373585ee4529ece6dee0503philippe      We can use the seg start as the stack start limit. */
30893d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (UNLIKELY(*start < stackseg->start)) {
309cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      VG_(debugLog)(2, "stacks",
310cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    "segment for SP %p changed stack start limit"
311cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    " from %p to %p\n",
312cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    (void*)SP, (void*)*start, (void*)stackseg->start);
313cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      *start = stackseg->start;
314cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   }
315cda0c2cf073a7fba19e1fb2576446506894facbaphilippe
31693d127f02c9abb9e6373585ee4529ece6dee0503philippe   /* Now, determine the stack end limit. If the stackseg is SkResvn,
31793d127f02c9abb9e6373585ee4529ece6dee0503philippe      we need to get the neighbour segment (towards higher addresses).
31893d127f02c9abb9e6373585ee4529ece6dee0503philippe      This segment must be anonymous and RW. */
31993d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (UNLIKELY(stackseg->kind == SkResvn)) {
320cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      stackseg = VG_(am_next_nsegment)(stackseg, /*forward*/ True);
321cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      if (!stackseg || !stackseg->hasR || !stackseg->hasW
322cda0c2cf073a7fba19e1fb2576446506894facbaphilippe          || stackseg->kind != SkAnonC) {
3233a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe         VG_(debugLog)(2, "stacks",
324cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                       "Next forward segment for SP %p Resvn segment"
325cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                       " is not RW or not AnonC\n",
326cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                       (void*)SP);
3273a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe         *start = 0;
3283a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe         *end = 0;
329cda0c2cf073a7fba19e1fb2576446506894facbaphilippe         return;
3303a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe      }
3313a75d2e7a6b8e8d28024b7444228097ae1504ca2philippe   }
332cda0c2cf073a7fba19e1fb2576446506894facbaphilippe
33393d127f02c9abb9e6373585ee4529ece6dee0503philippe   /* Limit the stack end limit, using the found segment. */
33493d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (UNLIKELY(*end > stackseg->end)) {
335cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      VG_(debugLog)(2, "stacks",
336cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    "segment for SP %p changed stack end limit"
337cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    " from %p to %p\n",
338cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    (void*)SP, (void*)*end, (void*)stackseg->end);
339cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      *end = stackseg->end;
340cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   }
341cda0c2cf073a7fba19e1fb2576446506894facbaphilippe
342cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   /* If reducing start and/or end to the SP segment gives an
343cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      empty range, return 'empty' limits */
34493d127f02c9abb9e6373585ee4529ece6dee0503philippe   if (UNLIKELY(*start > *end)) {
345cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      VG_(debugLog)(2, "stacks",
346cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    "stack for SP %p start %p after end %p\n",
347cda0c2cf073a7fba19e1fb2576446506894facbaphilippe                    (void*)SP, (void*)*start, (void*)end);
348cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      *start = 0;
349cda0c2cf073a7fba19e1fb2576446506894facbaphilippe      *end = 0;
350cda0c2cf073a7fba19e1fb2576446506894facbaphilippe   }
351690c3c807be3571951400b98d5136437dd957b65tom}
352690c3c807be3571951400b98d5136437dd957b65tom
353d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe/* complaints_stack_switch reports that SP has changed by more than some
354d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   threshold amount (by default, 2MB).  We take this to mean that the
355d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   application is switching to a new stack, for whatever reason.
356d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
357d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   JRS 20021001: following discussions with John Regehr, if a stack
358d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   switch happens, it seems best not to mess at all with memory
359d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   permissions.  Seems to work well with Netscape 4.X.  Really the
360d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   only remaining difficulty is knowing exactly when a stack switch is
361d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   happening. */
362d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe__attribute__((noinline))
363d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippestatic void complaints_stack_switch (Addr old_SP, Addr new_SP)
364d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe{
365d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   static Int complaints = 3;
366d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   if (VG_(clo_verbosity) > 0 && complaints > 0 && !VG_(clo_xml)) {
367d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      Word delta  = (Word)new_SP - (Word)old_SP;
368d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      complaints--;
369d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      VG_(message)(Vg_UserMsg,
370d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                   "Warning: client switching stacks?  "
371d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                   "SP change: 0x%lx --> 0x%lx\n", old_SP, new_SP);
372d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      VG_(message)(Vg_UserMsg,
373d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                   "         to suppress, use: --max-stackframe=%ld "
374d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                   "or greater\n",
375d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                   (delta < 0 ? -delta : delta));
376d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      if (complaints == 0)
377d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe         VG_(message)(Vg_UserMsg,
378d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                      "         further instances of this message "
379d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                      "will not be shown.\n");
380d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   }
381d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe}
382d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
383d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe/* The functions VG_(unknown_SP_update) and VG_(unknown_SP_update_w_ECU)
384d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   get called if new_mem_stack and/or die_mem_stack are
385945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   tracked by the tool, and one of the specialised cases
386945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   (eg. new_mem_stack_4) isn't used in preference.
387d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
388d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   These functions are performance critical, so are built with macros. */
389d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
390d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe// preamble + check if stack has switched.
3919cbe9d79d72020e7f69b4cd3fc9ac312e7aa4037philippe#define IF_STACK_SWITCH_SET_current_stack_AND_RETURN                    \
392d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   Word delta  = (Word)new_SP - (Word)old_SP;                           \
393d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                                                                        \
3944fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe   EDEBUG("current_stack  %p-%p %lu new_SP %p old_SP %p\n",             \
3954fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe          (void *) (current_stack ? current_stack->start : 0x0),        \
3964fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe          (void *) (current_stack ? current_stack->end : 0x0),          \
3974fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe          current_stack ? current_stack->id : 0,                        \
3984fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe          (void *)new_SP, (void *)old_SP);                              \
3994fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe                                                                        \
400d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   /* Check if the stack pointer is still in the same stack as before. */ \
401d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   if (UNLIKELY(current_stack == NULL ||                                \
402d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      new_SP < current_stack->start || new_SP > current_stack->end)) {  \
403d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      Stack* new_stack = find_stack_by_addr(new_SP);                    \
404d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      if (new_stack                                                     \
405d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe          && (current_stack == NULL || new_stack->id != current_stack->id)) { \
406d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe         /* The stack pointer is now in another stack.  Update the current */ \
407d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe         /* stack information and return without doing anything else. */ \
408d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe         current_stack = new_stack;                                     \
4094fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe         EDEBUG("new current_stack  %p-%p %lu \n",                      \
4104fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe                (void *) current_stack->start,                          \
4114fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe                (void *) current_stack->end,                            \
4124fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe                current_stack->id);                                     \
413d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe         return;                                                        \
4144fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe      } else                                                            \
4154fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe         EDEBUG("new current_stack not found\n");                       \
416945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
417945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
418d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe#define IF_BIG_DELTA_complaints_AND_RETURN                              \
419d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   if (UNLIKELY(delta < -VG_(clo_max_stackframe)                        \
420d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe                || VG_(clo_max_stackframe) < delta)) {                  \
421d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      complaints_stack_switch(old_SP, new_SP);                          \
422d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      return;                                                           \
423d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   }
424d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
425d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe#define IF_SMALLER_STACK_die_mem_stack_AND_RETURN                       \
426d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   if (delta > 0) {                                                     \
427d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      VG_TRACK( die_mem_stack, old_SP,  delta );                        \
428d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      return;                                                           \
429d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   }
430d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
431d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe
432d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippeVG_REGPARM(3)
433d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippevoid VG_(unknown_SP_update_w_ECU)( Addr old_SP, Addr new_SP, UInt ecu ) {
4349cbe9d79d72020e7f69b4cd3fc9ac312e7aa4037philippe   IF_STACK_SWITCH_SET_current_stack_AND_RETURN;
435d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   IF_BIG_DELTA_complaints_AND_RETURN;
436d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   IF_SMALLER_STACK_die_mem_stack_AND_RETURN;
437d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   if (delta < 0) { // IF_BIGGER_STACK
4387cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      VG_TRACK( new_mem_stack_w_ECU, new_SP, -delta, ecu );
439d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      return;
440d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   }
441d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   // SAME_STACK. nothing to do.
442d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe}
443945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
444d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippeVG_REGPARM(2)
445d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippevoid VG_(unknown_SP_update)( Addr old_SP, Addr new_SP ) {
4469cbe9d79d72020e7f69b4cd3fc9ac312e7aa4037philippe   IF_STACK_SWITCH_SET_current_stack_AND_RETURN;
447d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   IF_BIG_DELTA_complaints_AND_RETURN;
448d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   IF_SMALLER_STACK_die_mem_stack_AND_RETURN;
449d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   if (delta < 0) { // IF_BIGGER_STACK
450d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      VG_TRACK( new_mem_stack,      new_SP, -delta );
451d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe      return;
452945ed2e53f6bbe9c84a8173b63881158132d9ca8njn   }
453d5fb89de7477f1ffc6dd4f511f268ce226ed7d13philippe   // SAME_STACK. nothing to do.
454945ed2e53f6bbe9c84a8173b63881158132d9ca8njn}
455945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
456945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--------------------------------------------------------------------*/
457945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--- end                                                          ---*/
458945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--------------------------------------------------------------------*/
459945ed2e53f6bbe9c84a8173b63881158132d9ca8njn
460