1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stack management. m_stacks.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacks.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The stack 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ~~~~~~~~~ 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The stack's segment seems to be dynamically extended downwards by 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the kernel as the stack pointer moves down. Initially, a 1-page 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (4k) stack is allocated. When SP moves below that for the first 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown time, presumably a page fault occurs. The kernel detects that the 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown faulting address is in the range from SP - VG_STACK_REDZONE_SZB 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown upwards to the current valid stack. It then extends the stack 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment downwards for enough to cover the faulting address, and 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resumes the process (invisibly). The process is unaware of any of 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this. 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That means that Valgrind can't spot when the stack segment is being 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extended. Fortunately, we want to precisely and continuously 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown update stack permissions around SP, so we need to spot all writes 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to SP anyway. 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The deal is: when SP is assigned a lower value, the stack is being 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extended. Create suitably-permissioned pages to fill in any holes 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown between the old stack ptr and this one, if necessary. Then mark 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all bytes in the area just "uncovered" by this SP change as 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown write-only. 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When SP goes back up, mark the area receded over as unreadable and 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unwritable. 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Just to record the SP boundary conditions somewhere convenient: 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP - VG_STACK_REDZONE_SZB always points to the lowest live byte in 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the stack. All addresses below SP - VG_STACK_REDZONE_SZB are not 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown live; those at and above it are. 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We do not concern ourselves here with the VG_STACK_REDZONE_SZB 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bias; that is handled by new_mem_stack/die_mem_stack. 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This structure holds information about the start and end addresses of 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * registered stacks. There's always at least one stack registered: 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the main process stack. It will be the first stack registered and 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * so will have a stack id of 0. The user does not need to register 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * this stack: Valgrind does it automatically right before it starts 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * running the client. No other stacks are automatically registered by 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Valgrind, however. 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct _Stack { 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord id; 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr start; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr end; 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _Stack *next; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Stack; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Stack *stacks; 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UWord next_id; /* Next id we hand out to a newly registered stack */ 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * These are the id, start and end values of the current stack. If the 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * stack pointer falls outside the range of the current stack, we search 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the stacks list above for a matching stack. 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Stack *current_stack; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find 'st' in the stacks_list and move it one step closer the the 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown front of the list, so as to make subsequent searches for it 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cheaper. */ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void move_Stack_one_step_forward ( Stack* st ) 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack *st0, *st1, *st2; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st == stacks) 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* already at head of list */ 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(st != NULL); 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st0 = stacks; 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st1 = NULL; 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st2 = NULL; 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st0 == NULL || st0 == st) break; 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st2 = st1; 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st1 = st0; 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st0 = st0->next; 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(st0 == st); 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st0 != NULL && st1 != NULL && st2 != NULL) { 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack* tmp; 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* st0 points to st, st1 to its predecessor, and st2 to st1's 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown predecessor. Swap st0 and st1, that is, move st0 one step 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown closer to the start of the list. */ 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(st2->next == st1); 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(st1->next == st0); 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = st0->next; 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st2->next = st0; 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st0->next = st1; 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st1->next = tmp; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st0 != NULL && st1 != NULL && st2 == NULL) { 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* it's second in the list. */ 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(stacks == st1); 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(st1->next == st0); 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st1->next = st0->next; 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st0->next = st1; 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stacks = st0; 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find what stack an address falls into. */ 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Stack* find_stack_by_addr(Addr sp) 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_fails = 0; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_searches = 0; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_steps = 0; 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack *i = stacks; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_searches++; 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && 0 == (n_searches % 10000)) 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("(hgdev) %lu searches, %lu steps, %lu fails\n", 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_searches, n_steps+1, n_fails); 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* fast track common case */ 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i && sp >= i->start && sp <= i->end) 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i; 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else search the list */ 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i) { 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_steps++; 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp >= i->start && sp <= i->end) { 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (1 && (n_searches & 0x3F) == 0) { 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move_Stack_one_step_forward( i ); 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = i->next; 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_fails++; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Register a new stack from start - end. This is invoked from the 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * VALGRIND_STACK_REGISTER client request, and is also called just before 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * we start the client running, to register the main process stack. 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord VG_(register_stack)(Addr start, Addr end) 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack *i; 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (start > end) { 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr t = end; 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end = start; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start = t; 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, "stacks.rs.1", sizeof(Stack)); 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->start = start; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->end = end; 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->id = next_id++; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->next = stacks; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stacks = i; 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i->id == 0) { 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_stack = i; 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "stacks", "register %p-%p as stack %lu\n", 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)start, (void*)end, i->id); 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i->id; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Deregister a stack. This is invoked from the VALGRIND_STACK_DEREGISTER 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * client request. 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(deregister_stack)(UWord id) 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack *i = stacks; 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack *prev = NULL; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "stacks", "deregister stack %lu\n", id); 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (current_stack && current_stack->id == id) { 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_stack = NULL; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(i) { 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i->id == id) { 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(prev == NULL) { 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stacks = i->next; 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prev->next = i->next; 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)(VG_AR_CORE, i); 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prev = i; 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = i->next; 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Change a stack. This is invoked from the VALGRIND_STACK_CHANGE client 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * request and from the stack growth stuff the signals module when 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * extending the main process stack. 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(change_stack)(UWord id, Addr start, Addr end) 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack *i = stacks; 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i) { 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i->id == id) { 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "stacks", "change stack %lu from %p-%p to %p-%p\n", 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown id, (void*)i->start, (void*)i->end, 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)start, (void*)end); 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->start = start; 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->end = end; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = i->next; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Find the bounds of the stack (if any) which includes the 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * specified stack pointer. 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(stack_limits)(Addr SP, Addr *start, Addr *end ) 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack* stack = find_stack_by_addr(SP); 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stack) { 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *start = stack->start; 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *end = stack->end; 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This function gets called if new_mem_stack and/or die_mem_stack are 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tracked by the tool, and one of the specialised cases 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (eg. new_mem_stack_4) isn't used in preference. 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(3) 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(unknown_SP_update)( Addr old_SP, Addr new_SP, UInt ecu ) 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Int moans = 3; 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word delta = (Word)new_SP - (Word)old_SP; 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check if the stack pointer is still in the same stack as before. */ 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (current_stack == NULL || 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_SP < current_stack->start || new_SP > current_stack->end) { 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack* new_stack = find_stack_by_addr(new_SP); 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_stack 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (current_stack == NULL || new_stack->id != current_stack->id)) { 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The stack pointer is now in another stack. Update the current 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack information and return without doing anything else. */ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_stack = new_stack; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) { 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SP has changed by more than some threshold amount (by 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default, 2MB). We take this to mean that the application is 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switching to a new stack, for whatever reason. 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown JRS 20021001: following discussions with John Regehr, if a stack 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch happens, it seems best not to mess at all with memory 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown permissions. Seems to work well with Netscape 4.X. Really the 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only remaining difficulty is knowing exactly when a stack switch is 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown happening. */ 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 0 && moans > 0 && !VG_(clo_xml)) { 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown moans--; 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Warning: client switching stacks? " 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "SP change: 0x%lx --> 0x%lx\n", old_SP, new_SP); 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " to suppress, use: --max-stackframe=%ld or greater\n", 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (delta < 0 ? -delta : delta)); 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (moans == 0) 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " further instances of this message " 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "will not be shown.\n"); 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (delta < 0) { 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_stack_w_ECU, new_SP, -delta, ecu ); 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_stack, new_SP, -delta ); 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (delta > 0) { 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_stack, old_SP, delta ); 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 330