blob: 549348e8e8739c6b8876bc48d564358993008af0 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003/*--- Memory-related stuff: segment initialisation and tracking, ---*/
4/*--- stack operations ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--- vg_memory.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
njnc9539842002-10-02 13:26:35 +00009 This file is part of Valgrind, an extensible x86 protected-mode
10 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000011
njn0e1b5142003-04-15 14:58:06 +000012 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
32
33#include "vg_include.h"
34
sewardja4495682002-10-21 07:29:59 +000035/* Define to debug the memory-leak-detector. */
36/* #define VG_DEBUG_LEAKCHECK */
37
sewardjde4a1d02002-03-22 01:27:54 +000038
njn25e49d8e72002-09-23 09:36:25 +000039/*--------------------------------------------------------------*/
40/*--- Initialise program data/text etc on program startup. ---*/
41/*--------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +000042
njn25e49d8e72002-09-23 09:36:25 +000043typedef
44 struct _ExeSeg {
45 Addr start;
46 UInt size;
47 struct _ExeSeg* next;
sewardjde4a1d02002-03-22 01:27:54 +000048 }
njn25e49d8e72002-09-23 09:36:25 +000049 ExeSeg;
sewardjde4a1d02002-03-22 01:27:54 +000050
njn25e49d8e72002-09-23 09:36:25 +000051/* The list of current executable segments loaded. Required so that when a
52 segment is munmap'd, if it's executable we can recognise it as such and
53 invalidate translations for it, and drop any basic-block specific
54 information being stored. If symbols are being used, this list will have
55 the same segments recorded in it as the SegInfo symbols list (but much
56 less information about each segment).
57*/
58static ExeSeg* exeSegsHead = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000059
njn25e49d8e72002-09-23 09:36:25 +000060/* Prepend it -- mmaps/munmaps likely to follow a stack pattern(?) so this
61 is good.
62 Also check no segments overlap, which would be very bad. Check is linear
63 for each seg added (quadratic overall) but the total number should be
64 small (konqueror has around 50 --njn). */
njn20c25d52003-05-14 09:08:49 +000065static void add_exe_segment_to_list( Addr a, UInt len )
njn25e49d8e72002-09-23 09:36:25 +000066{
67 Addr lo = a;
68 Addr hi = a + len - 1;
69 ExeSeg* es;
70 ExeSeg* es2;
sewardjde4a1d02002-03-22 01:27:54 +000071
njn25e49d8e72002-09-23 09:36:25 +000072 /* Prepend it */
73 es = (ExeSeg*)VG_(arena_malloc)(VG_AR_CORE, sizeof(ExeSeg));
74 es->start = a;
75 es->size = len;
76 es->next = exeSegsHead;
77 exeSegsHead = es;
sewardjde4a1d02002-03-22 01:27:54 +000078
njn25e49d8e72002-09-23 09:36:25 +000079 /* Check there's no overlap with the rest of the list */
80 for (es2 = es->next; es2 != NULL; es2 = es2->next) {
81 Addr lo2 = es2->start;
82 Addr hi2 = es2->start + es2->size - 1;
83 Bool overlap;
84 vg_assert(lo < hi);
85 vg_assert(lo2 < hi2);
86 /* the main assertion */
87 overlap = (lo <= lo2 && lo2 <= hi)
88 || (lo <= hi2 && hi2 <= hi);
89 if (overlap) {
90 VG_(printf)("\n\nOVERLAPPING EXE SEGMENTS\n"
91 " new: start %p, size %d\n"
92 " old: start %p, size %d\n\n",
93 es->start, es->size, es2->start, es2->size );
94 vg_assert(! overlap);
sewardjde4a1d02002-03-22 01:27:54 +000095 }
sewardjde4a1d02002-03-22 01:27:54 +000096 }
njn25e49d8e72002-09-23 09:36:25 +000097}
98
njnfa1016e2003-09-25 17:54:11 +000099static Bool remove_if_exeseg_from_list( Addr a )
njn25e49d8e72002-09-23 09:36:25 +0000100{
101 ExeSeg **prev_next_ptr = & exeSegsHead,
102 *curr = exeSegsHead;
103
104 while (True) {
105 if (curr == NULL) break;
106 if (a == curr->start) break;
107 prev_next_ptr = &curr->next;
108 curr = curr->next;
109 }
110 if (curr == NULL)
111 return False;
112
113 vg_assert(*prev_next_ptr == curr);
114
115 *prev_next_ptr = curr->next;
116
117 VG_(arena_free)(VG_AR_CORE, curr);
sewardjde4a1d02002-03-22 01:27:54 +0000118 return True;
119}
120
njn25e49d8e72002-09-23 09:36:25 +0000121/* Records the exe segment in the ExeSeg list (checking for overlaps), and
122 reads debug info if required. Note the entire /proc/pid/maps file is
123 read for the debug info, but it just reads symbols for newly added exe
njnfa1016e2003-09-25 17:54:11 +0000124 segments. This is required to find out their names if they have one,
125 because with mmap() we only have the file descriptor, not the name. We
126 don't use this at startup because we do have the names then. */
127void VG_(new_exeseg_mmap) ( Addr a, UInt len )
sewardjde4a1d02002-03-22 01:27:54 +0000128{
njn25e49d8e72002-09-23 09:36:25 +0000129 add_exe_segment_to_list( a, len );
njnfa1016e2003-09-25 17:54:11 +0000130 VG_(read_all_symbols)();
131}
132
133/* Like VG_(new_exeseg_mmap)(), but here we do have the name, so we don't
134 need to grovel through /proc/self/maps to find it. */
135void VG_(new_exeseg_startup) ( Addr a, UInt len, Char rr, Char ww, Char xx,
136 UInt foffset, UChar* filename )
137{
138 add_exe_segment_to_list( a, len );
139 VG_(read_seg_symbols)( a, len, rr, ww, xx, foffset, filename);
sewardjde4a1d02002-03-22 01:27:54 +0000140}
141
njn25e49d8e72002-09-23 09:36:25 +0000142/* Invalidate translations as necessary (also discarding any basic
143 block-specific info retained by the skin) and unload any debug
144 symbols. */
njnfa1016e2003-09-25 17:54:11 +0000145// Nb: remove_if_exeseg_from_list() and VG_(maybe_unload_symbols)()
njn25e49d8e72002-09-23 09:36:25 +0000146// both ignore 'len', but that seems that's ok for most programs... see
147// comment above vg_syscalls.c:mmap_segment() et al for more details.
njnfa1016e2003-09-25 17:54:11 +0000148void VG_(remove_if_exeseg) ( Addr a, UInt len )
sewardjde4a1d02002-03-22 01:27:54 +0000149{
njnfa1016e2003-09-25 17:54:11 +0000150 if (remove_if_exeseg_from_list( a )) {
sewardj97ad5522003-05-04 12:32:56 +0000151 VG_(invalidate_translations) ( a, len, False );
sewardj8a77ffb2003-07-10 23:31:27 +0000152 VG_(unload_symbols) ( a, len );
sewardjde4a1d02002-03-22 01:27:54 +0000153 }
154}
155
156
njn25e49d8e72002-09-23 09:36:25 +0000157static
158void startup_segment_callback ( Addr start, UInt size,
159 Char rr, Char ww, Char xx,
160 UInt foffset, UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +0000161{
njn25e49d8e72002-09-23 09:36:25 +0000162 UInt r_esp;
163 Bool is_stack_segment;
sewardjecf8e102003-07-12 12:11:39 +0000164 Bool verbose = False; /* set to True for debugging */
sewardjde4a1d02002-03-22 01:27:54 +0000165
sewardjecf8e102003-07-12 12:11:39 +0000166 if (verbose)
njn25e49d8e72002-09-23 09:36:25 +0000167 VG_(message)(Vg_DebugMsg,
168 "initial map %8x-%8x %c%c%c? %8x (%d) (%s)",
169 start,start+size,rr,ww,xx,foffset,
170 size, filename?filename:(UChar*)"NULL");
171
172 if (rr != 'r' && xx != 'x' && ww != 'w') {
sewardj6e4234e2002-10-06 00:28:21 +0000173 /* Implausible as it seems, R H 6.2 generates such segments:
174 40067000-400ac000 r-xp 00000000 08:05 320686 /usr/X11R6/lib/libXt.so.6.0
175 400ac000-400ad000 ---p 00045000 08:05 320686 /usr/X11R6/lib/libXt.so.6.0
176 400ad000-400b0000 rw-p 00045000 08:05 320686 /usr/X11R6/lib/libXt.so.6.0
177 when running xedit. So just ignore them. */
178 if (0)
179 VG_(printf)("No permissions on a segment mapped from %s\n",
180 filename?filename:(UChar*)"NULL");
181 return;
sewardjde4a1d02002-03-22 01:27:54 +0000182 }
njn25e49d8e72002-09-23 09:36:25 +0000183
sewardjecf8e102003-07-12 12:11:39 +0000184 /* If this segment corresponds to something mmap'd /dev/zero by the
185 low-level memory manager (vg_malloc2.c), skip it. Clients
186 should never have access to the segments which hold valgrind
187 internal data. And access to client data in the VG_AR_CLIENT
188 arena is mediated by the skin, so we don't want make it
189 accessible at this stage. */
190 if (VG_(is_inside_segment_mmapd_by_low_level_MM)( start )) {
191 if (verbose)
192 VG_(message)(Vg_DebugMsg,
193 " skipping %8x-%8x (owned by our MM)",
194 start, start+size );
195 /* Don't announce it to the skin. */
196 return;
197 }
198
njnfa1016e2003-09-25 17:54:11 +0000199 /* This is similar to what happens when we mmap some new memory */
njn25e49d8e72002-09-23 09:36:25 +0000200 if (filename != NULL && xx == 'x') {
njnfa1016e2003-09-25 17:54:11 +0000201 VG_(new_exeseg_startup)( start, size, rr, ww, xx, foffset, filename );
njn25e49d8e72002-09-23 09:36:25 +0000202 }
sewardjecf8e102003-07-12 12:11:39 +0000203
njn25e49d8e72002-09-23 09:36:25 +0000204 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
205
206 /* If this is the stack segment mark all below %esp as noaccess. */
207 r_esp = VG_(baseBlock)[VGOFF_(m_esp)];
208 is_stack_segment = start <= r_esp && r_esp < start+size;
209 if (is_stack_segment) {
210 if (0)
211 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
212 start,r_esp);
213 VG_TRACK( die_mem_stack, start, r_esp-start );
214 }
215}
216
217
njn3e884182003-04-15 13:03:23 +0000218/* 1. Records startup segments from /proc/pid/maps. Takes special note
219 of the executable ones, because if they're munmap()ed we need to
220 discard translations. Also checks there's no exe segment overlaps.
njn25e49d8e72002-09-23 09:36:25 +0000221
njn3e884182003-04-15 13:03:23 +0000222 Note that `read_from_file' is false; we read /proc/self/maps into a
223 buffer at the start of VG_(main) so that any superblocks mmap'd by
224 calls to VG_(malloc)() by SK_({pre,post}_clo_init) aren't erroneously
225 thought of as being owned by the client.
njn25e49d8e72002-09-23 09:36:25 +0000226
njn3e884182003-04-15 13:03:23 +0000227 2. Sets up the end of the data segment so that vg_syscalls.c can make
njn25e49d8e72002-09-23 09:36:25 +0000228 sense of calls to brk().
229 */
230void VG_(init_memory) ( void )
231{
njn3e884182003-04-15 13:03:23 +0000232 /* 1 */
njnfa1016e2003-09-25 17:54:11 +0000233 VG_(parse_procselfmaps) ( startup_segment_callback );
njn25e49d8e72002-09-23 09:36:25 +0000234
njn3e884182003-04-15 13:03:23 +0000235 /* 2 */
njn25e49d8e72002-09-23 09:36:25 +0000236 VG_(init_dataseg_end_for_brk)();
sewardjd5815ec2003-04-06 12:23:27 +0000237
238 /* kludge: some newer kernels place a "sysinfo" page up high, with
239 vsyscalls in it, and possibly some other stuff in the future. */
240 if (VG_(sysinfo_page_exists)) {
njnfa1016e2003-09-25 17:54:11 +0000241 // 2003-Sep-25, njn: Jeremy thinks the sysinfo page probably doesn't
242 // have any symbols that need to be loaded. So just treat it like
243 // a non-executable page.
244 //VG_(new_exeseg_mmap)( VG_(sysinfo_page_addr), 4096 );
sewardjd5815ec2003-04-06 12:23:27 +0000245 VG_TRACK( new_mem_startup, VG_(sysinfo_page_addr), 4096,
246 True, True, True );
247 }
sewardjde4a1d02002-03-22 01:27:54 +0000248}
249
sewardjde4a1d02002-03-22 01:27:54 +0000250/*------------------------------------------------------------*/
251/*--- Tracking permissions around %esp changes. ---*/
252/*------------------------------------------------------------*/
253
254/*
255 The stack
256 ~~~~~~~~~
257 The stack's segment seems to be dynamically extended downwards
258 by the kernel as the stack pointer moves down. Initially, a
259 1-page (4k) stack is allocated. When %esp moves below that for
260 the first time, presumably a page fault occurs. The kernel
261 detects that the faulting address is in the range from %esp upwards
262 to the current valid stack. It then extends the stack segment
263 downwards for enough to cover the faulting address, and resumes
264 the process (invisibly). The process is unaware of any of this.
265
266 That means that Valgrind can't spot when the stack segment is
267 being extended. Fortunately, we want to precisely and continuously
268 update stack permissions around %esp, so we need to spot all
269 writes to %esp anyway.
270
271 The deal is: when %esp is assigned a lower value, the stack is
272 being extended. Create a secondary maps to fill in any holes
273 between the old stack ptr and this one, if necessary. Then
274 mark all bytes in the area just "uncovered" by this %esp change
275 as write-only.
276
277 When %esp goes back up, mark the area receded over as unreadable
278 and unwritable.
279
280 Just to record the %esp boundary conditions somewhere convenient:
281 %esp always points to the lowest live byte in the stack. All
282 addresses below %esp are not live; those at and above it are.
283*/
284
sewardjde4a1d02002-03-22 01:27:54 +0000285/* Kludgey ... how much does %esp have to change before we reckon that
286 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +0000287#define VG_PLAUSIBLE_STACK_SIZE 8000000
288#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +0000289
njn9b007f62003-04-07 14:40:25 +0000290/* This function gets called if new_mem_stack and/or die_mem_stack are
291 tracked by the skin, and one of the specialised cases (eg. new_mem_stack_4)
292 isn't used in preference */
293__attribute__((regparm(1)))
294void VG_(unknown_esp_update)(Addr new_ESP)
sewardjde4a1d02002-03-22 01:27:54 +0000295{
njn9b007f62003-04-07 14:40:25 +0000296 Addr old_ESP = VG_(get_archreg)(R_ESP);
297 Int delta = (Int)new_ESP - (Int)old_ESP;
sewardjde4a1d02002-03-22 01:27:54 +0000298
njn9b007f62003-04-07 14:40:25 +0000299 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
300 /* %esp has changed by more than HUGE_DELTA. We take this to mean
301 that the application is switching to a new stack, for whatever
302 reason.
303
304 JRS 20021001: following discussions with John Regehr, if a stack
305 switch happens, it seems best not to mess at all with memory
306 permissions. Seems to work well with Netscape 4.X. Really the
307 only remaining difficulty is knowing exactly when a stack switch is
308 happening. */
309 if (VG_(clo_verbosity) > 1)
310 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
311 "%%esp: %p --> %p", old_ESP, new_ESP);
312 } else if (delta < 0) {
313 VG_TRACK( new_mem_stack, new_ESP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +0000314
njn9b007f62003-04-07 14:40:25 +0000315 } else if (delta > 0) {
316 VG_TRACK( die_mem_stack, old_ESP, delta );
sewardjde4a1d02002-03-22 01:27:54 +0000317 }
318}
319
jsgf855d93d2003-10-13 22:26:55 +0000320static jmp_buf segv_jmpbuf;
321
322static void segv_handler(Int seg)
323{
324 __builtin_longjmp(segv_jmpbuf, 1);
325 VG_(core_panic)("longjmp failed");
326}
327
328/*
329 Test if a piece of memory is addressable by setting up a temporary
330 SIGSEGV handler, then try to touch the memory. No signal = good,
331 signal = bad.
332 */
333Bool VG_(is_addressable)(Addr p, Int size)
334{
335 volatile Char * volatile cp = (volatile Char *)p;
336 volatile Bool ret;
337 vki_ksigaction sa, origsa;
338 vki_ksigset_t mask;
339
340 vg_assert(size > 0);
341
342 sa.ksa_handler = segv_handler;
343 sa.ksa_flags = 0;
344 VG_(ksigfillset)(&sa.ksa_mask);
345 VG_(ksigaction)(VKI_SIGSEGV, &sa, &origsa);
346 VG_(ksigprocmask)(VKI_SIG_SETMASK, NULL, &mask);
347
348 if (__builtin_setjmp(&segv_jmpbuf) == 0) {
349 while(size--)
350 *cp++;
351 ret = True;
352 } else
353 ret = False;
354
355 VG_(ksigaction)(VKI_SIGSEGV, &origsa, NULL);
356 VG_(ksigprocmask)(VKI_SIG_SETMASK, &mask, NULL);
357
358 return ret;
359}
360
sewardjde4a1d02002-03-22 01:27:54 +0000361/*--------------------------------------------------------------------*/
362/*--- end vg_memory.c ---*/
363/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000364