blob: 85eebc174eb92a0cefe1d47710f6cc4f916ae790 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- C startup stuff, reached from vg_startup.S. ---*/
4/*--- vg_main.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32#include "vg_include.h"
sewardjde4a1d02002-03-22 01:27:54 +000033
34/* ---------------------------------------------------------------------
35 Compute offsets into baseBlock. See comments in vg_include.h.
36 ------------------------------------------------------------------ */
37
38/* The variables storing offsets. */
39
40#define INVALID_OFFSET (-1)
41
42Int VGOFF_(m_eax) = INVALID_OFFSET;
43Int VGOFF_(m_ecx) = INVALID_OFFSET;
44Int VGOFF_(m_edx) = INVALID_OFFSET;
45Int VGOFF_(m_ebx) = INVALID_OFFSET;
46Int VGOFF_(m_esp) = INVALID_OFFSET;
47Int VGOFF_(m_ebp) = INVALID_OFFSET;
48Int VGOFF_(m_esi) = INVALID_OFFSET;
49Int VGOFF_(m_edi) = INVALID_OFFSET;
50Int VGOFF_(m_eflags) = INVALID_OFFSET;
51Int VGOFF_(m_fpustate) = INVALID_OFFSET;
sewardj92a59562002-09-30 00:53:10 +000052Int VGOFF_(ldt) = INVALID_OFFSET;
53Int VGOFF_(m_cs) = INVALID_OFFSET;
54Int VGOFF_(m_ss) = INVALID_OFFSET;
55Int VGOFF_(m_ds) = INVALID_OFFSET;
56Int VGOFF_(m_es) = INVALID_OFFSET;
57Int VGOFF_(m_fs) = INVALID_OFFSET;
58Int VGOFF_(m_gs) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000059Int VGOFF_(m_eip) = INVALID_OFFSET;
60Int VGOFF_(spillslots) = INVALID_OFFSET;
61Int VGOFF_(sh_eax) = INVALID_OFFSET;
62Int VGOFF_(sh_ecx) = INVALID_OFFSET;
63Int VGOFF_(sh_edx) = INVALID_OFFSET;
64Int VGOFF_(sh_ebx) = INVALID_OFFSET;
65Int VGOFF_(sh_esp) = INVALID_OFFSET;
66Int VGOFF_(sh_ebp) = INVALID_OFFSET;
67Int VGOFF_(sh_esi) = INVALID_OFFSET;
68Int VGOFF_(sh_edi) = INVALID_OFFSET;
69Int VGOFF_(sh_eflags) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +000070
sewardjde4a1d02002-03-22 01:27:54 +000071Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
72Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
73Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
74Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
75Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
76Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
77Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
78Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
79Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
80Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
81Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
82Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
83Int VGOFF_(helper_CLD) = INVALID_OFFSET;
84Int VGOFF_(helper_STD) = INVALID_OFFSET;
85Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
sewardj7d78e782002-06-02 00:04:00 +000086Int VGOFF_(helper_CLC) = INVALID_OFFSET;
87Int VGOFF_(helper_STC) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000088Int VGOFF_(helper_shldl) = INVALID_OFFSET;
89Int VGOFF_(helper_shldw) = INVALID_OFFSET;
90Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
91Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
92Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
93Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
94Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000095Int VGOFF_(helper_bsf) = INVALID_OFFSET;
96Int VGOFF_(helper_bsr) = INVALID_OFFSET;
97Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
98Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +000099Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +0000100Int VGOFF_(helper_DAA) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +0000101Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +0000102
103/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
104 * increased too much, they won't really be compact any more... */
105#define MAX_COMPACT_HELPERS 8
106#define MAX_NONCOMPACT_HELPERS 8
107
108UInt VG_(n_compact_helpers) = 0;
109UInt VG_(n_noncompact_helpers) = 0;
110
111Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
112Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
113Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
114Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
sewardjde4a1d02002-03-22 01:27:54 +0000115
116/* This is the actual defn of baseblock. */
117UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
118
njn25e49d8e72002-09-23 09:36:25 +0000119
sewardjde4a1d02002-03-22 01:27:54 +0000120/* Words. */
121static Int baB_off = 0;
122
123/* Returns the offset, in words. */
124static Int alloc_BaB ( Int words )
125{
126 Int off = baB_off;
127 baB_off += words;
128 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000129 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000130
131 return off;
132}
133
134/* Allocate 1 word in baseBlock and set it to the given value. */
135static Int alloc_BaB_1_set ( Addr a )
136{
137 Int off = alloc_BaB(1);
138 VG_(baseBlock)[off] = (UInt)a;
139 return off;
140}
141
njn25e49d8e72002-09-23 09:36:25 +0000142/* Registers a function in compact_helper_addrs; compact_helper_offsets is
143 * filled in later.
144 */
145void VG_(register_compact_helper)(Addr a)
146{
147 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
148 VG_(printf)("Can only register %d compact helpers\n",
149 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000150 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000151 }
152 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
153 VG_(n_compact_helpers)++;
154}
155
156/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
157 * is filled in later.
158 */
159void VG_(register_noncompact_helper)(Addr a)
160{
161 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
162 VG_(printf)("Can only register %d non-compact helpers\n",
163 MAX_NONCOMPACT_HELPERS);
164 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000165 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000166 }
167 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
168 VG_(n_noncompact_helpers)++;
169}
170
171/* Allocate offsets in baseBlock for the skin helpers */
172static void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
173{
174 Int i;
175 for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
176}
sewardjde4a1d02002-03-22 01:27:54 +0000177
178/* Here we assign actual offsets. It's important to get the most
179 popular referents within 128 bytes of the start, so we can take
180 advantage of short addressing modes relative to %ebp. Popularity
181 of offsets was measured on 22 Feb 02 running a KDE application, and
182 the slots rearranged accordingly, with a 1.5% reduction in total
183 size of translations. */
184
185static void vg_init_baseBlock ( void )
186{
sewardjde4a1d02002-03-22 01:27:54 +0000187 /* Those with offsets under 128 are carefully chosen. */
188
189 /* WORD offsets in this column */
190 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
191 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
192 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
193 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
194 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
195 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
196 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
197 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
198 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
199
njn25e49d8e72002-09-23 09:36:25 +0000200 if (VG_(needs).shadow_regs) {
201 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
202 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
203 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
204 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
205 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
206 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
207 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
208 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
209 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
210 }
sewardjde4a1d02002-03-22 01:27:54 +0000211
njn25e49d8e72002-09-23 09:36:25 +0000212 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
213 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000214
njn25e49d8e72002-09-23 09:36:25 +0000215 /* (9 or 18) + n_compact_helpers */
216 /* Register VG_(handle_esp_assignment) if needed. */
217 if (VG_(track_events).new_mem_stack_aligned ||
218 VG_(track_events).die_mem_stack_aligned)
219 VG_(register_compact_helper)( (Addr) & VG_(handle_esp_assignment) );
sewardjde4a1d02002-03-22 01:27:54 +0000220
njn25e49d8e72002-09-23 09:36:25 +0000221 /* Allocate slots for compact helpers */
222 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
223 VG_(compact_helper_offsets),
224 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000225
njn25e49d8e72002-09-23 09:36:25 +0000226 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000227 VGOFF_(m_eip) = alloc_BaB(1);
228
229 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000230 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
231 * boundary at >= 32 words, but most spills are to low numbered spill
232 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000233 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
234
njn25e49d8e72002-09-23 09:36:25 +0000235 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000236 short-amode-boundary, there's no point. */
237
238 VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
239
sewardj92a59562002-09-30 00:53:10 +0000240 /* This thread's LDT pointer, and segment registers. */
241 VGOFF_(ldt) = alloc_BaB(1);
242 VGOFF_(m_cs) = alloc_BaB(1);
243 VGOFF_(m_ss) = alloc_BaB(1);
244 VGOFF_(m_ds) = alloc_BaB(1);
245 VGOFF_(m_es) = alloc_BaB(1);
246 VGOFF_(m_fs) = alloc_BaB(1);
247 VGOFF_(m_gs) = alloc_BaB(1);
248
sewardje1042472002-09-30 12:33:11 +0000249 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
250
sewardj92a59562002-09-30 00:53:10 +0000251 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000252 VGOFF_(helper_idiv_64_32)
253 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
254 VGOFF_(helper_div_64_32)
255 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
256 VGOFF_(helper_idiv_32_16)
257 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
258 VGOFF_(helper_div_32_16)
259 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
260 VGOFF_(helper_idiv_16_8)
261 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
262 VGOFF_(helper_div_16_8)
263 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
264
265 VGOFF_(helper_imul_32_64)
266 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
267 VGOFF_(helper_mul_32_64)
268 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
269 VGOFF_(helper_imul_16_32)
270 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
271 VGOFF_(helper_mul_16_32)
272 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
273 VGOFF_(helper_imul_8_16)
274 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
275 VGOFF_(helper_mul_8_16)
276 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
277
278 VGOFF_(helper_CLD)
279 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
280 VGOFF_(helper_STD)
281 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
282 VGOFF_(helper_get_dirflag)
283 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
284
sewardj7d78e782002-06-02 00:04:00 +0000285 VGOFF_(helper_CLC)
286 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000287 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000288 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
289
sewardjde4a1d02002-03-22 01:27:54 +0000290 VGOFF_(helper_shldl)
291 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
292 VGOFF_(helper_shldw)
293 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
294 VGOFF_(helper_shrdl)
295 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
296 VGOFF_(helper_shrdw)
297 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
298
299 VGOFF_(helper_RDTSC)
300 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
301 VGOFF_(helper_CPUID)
302 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
303
sewardjde4a1d02002-03-22 01:27:54 +0000304 VGOFF_(helper_bsf)
305 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
306 VGOFF_(helper_bsr)
307 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
308
309 VGOFF_(helper_fstsw_AX)
310 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
311 VGOFF_(helper_SAHF)
312 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000313 VGOFF_(helper_DAS)
314 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000315 VGOFF_(helper_DAA)
316 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000317
sewardj92a59562002-09-30 00:53:10 +0000318 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000319 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
320 VG_(noncompact_helper_offsets),
321 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000322
njncc7bb472002-10-14 09:25:19 +0000323
324 /* Initialise slots that require it */
325 VG_(copy_m_state_static_to_baseBlock)();
326
327 /* Pretend the root thread has a completely empty LDT to start with. */
328 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
329
330 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000331 if (VG_(needs).shadow_regs) {
332 UInt eflags;
333
334 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
335 VG_(baseBlock)[VGOFF_(sh_esp)] =
336 VG_(baseBlock)[VGOFF_(sh_ebp)] =
337 VG_(baseBlock)[VGOFF_(sh_eax)] =
338 VG_(baseBlock)[VGOFF_(sh_ecx)] =
339 VG_(baseBlock)[VGOFF_(sh_edx)] =
340 VG_(baseBlock)[VGOFF_(sh_ebx)] =
341 VG_(baseBlock)[VGOFF_(sh_esi)] =
342 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
343 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
344
njncc7bb472002-10-14 09:25:19 +0000345 } else {
njn25e49d8e72002-09-23 09:36:25 +0000346 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000347 }
sewardjde4a1d02002-03-22 01:27:54 +0000348}
349
350
351/* ---------------------------------------------------------------------
352 Global entities which are not referenced from generated code.
353 ------------------------------------------------------------------ */
354
355/* The stack on which Valgrind runs. We can't use the same stack as
356 the simulatee -- that's an important design decision. */
357UInt VG_(stack)[10000];
358
359/* Ditto our signal delivery stack. */
360UInt VG_(sigstack)[10000];
361
362/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000363UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
364Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000365
366/* Counts downwards in vg_run_innerloop. */
367UInt VG_(dispatch_ctr);
368
sewardjde4a1d02002-03-22 01:27:54 +0000369
370/* 64-bit counter for the number of basic blocks done. */
371ULong VG_(bbs_done);
372/* 64-bit counter for the number of bbs to go before a debug exit. */
373ULong VG_(bbs_to_go);
374
sewardjde4a1d02002-03-22 01:27:54 +0000375/* The current LRU epoch. */
376UInt VG_(current_epoch) = 0;
377
sewardj7e87e382002-05-03 19:09:05 +0000378/* This is the ThreadId of the last thread the scheduler ran. */
379ThreadId VG_(last_run_tid) = 0;
380
njn25e49d8e72002-09-23 09:36:25 +0000381/* This is the argument to __NR_exit() supplied by the first thread to
382 call that syscall. We eventually pass that to __NR_exit() for
383 real. */
384UInt VG_(exitcode) = 0;
385
sewardj73cf3bc2002-11-03 03:20:15 +0000386/* Tell the logging mechanism whether we are logging to a file
387 descriptor or a socket descriptor. */
388Bool VG_(logging_to_filedes) = True;
389
sewardjde4a1d02002-03-22 01:27:54 +0000390
391/* ---------------------------------------------------------------------
392 Counters, for informational purposes only.
393 ------------------------------------------------------------------ */
394
395/* Number of lookups which miss the fast tt helper. */
396UInt VG_(tt_fast_misses) = 0;
397
398
399/* Counts for LRU informational messages. */
400
401/* Number and total o/t size of new translations this epoch. */
402UInt VG_(this_epoch_in_count) = 0;
403UInt VG_(this_epoch_in_osize) = 0;
404UInt VG_(this_epoch_in_tsize) = 0;
405/* Number and total o/t size of discarded translations this epoch. */
406UInt VG_(this_epoch_out_count) = 0;
407UInt VG_(this_epoch_out_osize) = 0;
408UInt VG_(this_epoch_out_tsize) = 0;
409/* Number and total o/t size of translations overall. */
410UInt VG_(overall_in_count) = 0;
411UInt VG_(overall_in_osize) = 0;
412UInt VG_(overall_in_tsize) = 0;
413/* Number and total o/t size of discards overall. */
414UInt VG_(overall_out_count) = 0;
415UInt VG_(overall_out_osize) = 0;
416UInt VG_(overall_out_tsize) = 0;
417
418/* The number of LRU-clearings of TT/TC. */
419UInt VG_(number_of_lrus) = 0;
420
421
422/* Counts pertaining to the register allocator. */
423
424/* total number of uinstrs input to reg-alloc */
425UInt VG_(uinstrs_prealloc) = 0;
426
427/* total number of uinstrs added due to spill code */
428UInt VG_(uinstrs_spill) = 0;
429
430/* number of bbs requiring spill code */
431UInt VG_(translations_needing_spill) = 0;
432
433/* total of register ranks over all translations */
434UInt VG_(total_reg_rank) = 0;
435
436
sewardjde4a1d02002-03-22 01:27:54 +0000437/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000438UInt VG_(sanity_fast_count) = 0;
439UInt VG_(sanity_slow_count) = 0;
440
sewardj2e93c502002-04-12 11:12:52 +0000441/* Counts pertaining to the scheduler. */
442UInt VG_(num_scheduling_events_MINOR) = 0;
443UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000444
445
446/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +0000447 Skin data structure initialisation
448 ------------------------------------------------------------------ */
449
450/* Init with default values. */
njnd04b7c62002-10-03 14:05:52 +0000451VgDetails VG_(details) = {
452 .name = NULL,
453 .version = NULL,
454 .description = NULL,
455 .copyright_author = NULL,
456 .bug_reports_to = NULL,
457};
458
njn25e49d8e72002-09-23 09:36:25 +0000459VgNeeds VG_(needs) = {
njnd04b7c62002-10-03 14:05:52 +0000460 .core_errors = False,
461 .skin_errors = False,
462 .libc_freeres = False,
463 .sizeof_shadow_block = 0,
464 .basic_block_discards = False,
465 .shadow_regs = False,
466 .command_line_options = False,
467 .client_requests = False,
468 .extended_UCode = False,
469 .syscall_wrapper = False,
470 .alternative_free = False,
471 .sanity_checks = False,
sewardj8fe15a32002-10-20 19:29:21 +0000472 .data_syms = False,
njn25e49d8e72002-09-23 09:36:25 +0000473};
474
475VgTrackEvents VG_(track_events) = {
476 /* Memory events */
477 .new_mem_startup = NULL,
478 .new_mem_heap = NULL,
479 .new_mem_stack = NULL,
480 .new_mem_stack_aligned = NULL,
481 .new_mem_stack_signal = NULL,
482 .new_mem_brk = NULL,
483 .new_mem_mmap = NULL,
484
485 .copy_mem_heap = NULL,
njnd04b7c62002-10-03 14:05:52 +0000486 .copy_mem_remap = NULL,
njn25e49d8e72002-09-23 09:36:25 +0000487 .change_mem_mprotect = NULL,
488
489 .ban_mem_heap = NULL,
490 .ban_mem_stack = NULL,
491
492 .die_mem_heap = NULL,
493 .die_mem_stack = NULL,
494 .die_mem_stack_aligned = NULL,
495 .die_mem_stack_signal = NULL,
496 .die_mem_brk = NULL,
497 .die_mem_munmap = NULL,
498
499 .bad_free = NULL,
500 .mismatched_free = NULL,
501
502 .pre_mem_read = NULL,
503 .pre_mem_read_asciiz = NULL,
504 .pre_mem_write = NULL,
505 .post_mem_write = NULL,
506
njnd04b7c62002-10-03 14:05:52 +0000507 /* Scheduler events */
508 .thread_run = NULL,
509
njn25e49d8e72002-09-23 09:36:25 +0000510 /* Mutex events */
511 .post_mutex_lock = NULL,
512 .post_mutex_unlock = NULL,
513};
514
515static void sanity_check_needs ( void )
516{
njne427a662002-10-02 11:08:25 +0000517#define CHECK_NOT(var, value) \
518 if ((var)==(value)) { \
519 VG_(printf)("\nSkin error: `%s' not initialised\n", \
520 VG__STRING(var)); \
521 VG_(skin_panic)("Uninitialised needs field\n"); \
njn25e49d8e72002-09-23 09:36:25 +0000522 }
523
njnd04b7c62002-10-03 14:05:52 +0000524 CHECK_NOT(VG_(details).name, NULL);
525 /* Nb: .version can be NULL */
526 CHECK_NOT(VG_(details).description, NULL);
527 CHECK_NOT(VG_(details).copyright_author, NULL);
528 CHECK_NOT(VG_(details).bug_reports_to, NULL);
njn25e49d8e72002-09-23 09:36:25 +0000529
530#undef CHECK_NOT
531#undef INVALID_Bool
532}
533
534/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000535 Values derived from command-line options.
536 ------------------------------------------------------------------ */
537
njn25e49d8e72002-09-23 09:36:25 +0000538/* Define, and set defaults. */
539Bool VG_(clo_error_limit) = True;
540Bool VG_(clo_GDB_attach) = False;
541Int VG_(sanity_level) = 1;
542Int VG_(clo_verbosity) = 1;
543Bool VG_(clo_demangle) = True;
544Bool VG_(clo_sloppy_malloc) = False;
545Int VG_(clo_alignment) = 4;
546Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000547
548/* See big comment in vg_include.h for meaning of these three. */
549VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
550Int VG_(clo_logfile_fd) = 2;
551Char* VG_(clo_logfile_name) = NULL;
552
njn25e49d8e72002-09-23 09:36:25 +0000553Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000554Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000555Bool VG_(clo_profile) = False;
556Bool VG_(clo_single_step) = False;
557Bool VG_(clo_optimise) = True;
558UChar VG_(clo_trace_codegen) = 0; // 00000000b
559Bool VG_(clo_trace_syscalls) = False;
560Bool VG_(clo_trace_signals) = False;
561Bool VG_(clo_trace_symtab) = False;
562Bool VG_(clo_trace_malloc) = False;
563Bool VG_(clo_trace_sched) = False;
564Int VG_(clo_trace_pthread_level) = 0;
565ULong VG_(clo_stop_after) = 1000000000000LL;
566Int VG_(clo_dump_error) = 0;
567Int VG_(clo_backtrace_size) = 4;
568Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000569Bool VG_(clo_run_libc_freeres) = True;
sewardjde4a1d02002-03-22 01:27:54 +0000570
571/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
572 to behave. Initially we say False. */
573Bool VG_(running_on_simd_CPU) = False;
574
575/* Holds client's %esp at the point we gained control. */
576Addr VG_(esp_at_startup);
577
578/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
579 envp[] as extracted from the client's stack at startup-time. */
580Int VG_(client_argc);
581Char** VG_(client_argv);
582Char** VG_(client_envp);
583
584/* A place into which to copy the value of env var VG_ARGS, so we
585 don't have to modify the original. */
586static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
587
sewardjde4a1d02002-03-22 01:27:54 +0000588/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000589 Processing of command-line options.
590 ------------------------------------------------------------------ */
591
njn25e49d8e72002-09-23 09:36:25 +0000592void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000593{
594 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000595 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000596 VG_(clo_logfile_fd) = 2; /* stderr */
597 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
598 VG_(exit)(1);
599}
600
601static void config_error ( Char* msg )
602{
603 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000604 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000605 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000606 VG_(printf)(
607 "valgrind.so: Startup or configuration error:\n %s\n", msg);
608 VG_(printf)(
609 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000610 VG_(exit)(1);
611}
612
sewardja1679dd2002-05-10 22:31:40 +0000613static void args_grok_error ( Char* msg )
614{
615 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000616 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000617 VG_(clo_logfile_fd) = 2; /* stderr */
618 VG_(printf)("valgrind.so: When searching for "
619 "client's argc/argc/envp:\n\t%s\n", msg);
620 config_error("couldn't find client's argc/argc/envp");
621}
622
njn25e49d8e72002-09-23 09:36:25 +0000623static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000624{
njn25e49d8e72002-09-23 09:36:25 +0000625 Char* usage1 =
626"usage: valgrind [options] prog-and-args\n"
627"\n"
628" core user options, with defaults in [ ], are:\n"
629" --help show this message\n"
630" --version show version\n"
631" --skin=<name> main task (skin to use) [Valgrind]\n"
632" -q --quiet run silently; only print error msgs\n"
633" -v --verbose be more verbose, incl counts of errors\n"
634" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
635" --demangle=no|yes automatically demangle C++ names? [yes]\n"
636" --num-callers=<number> show <num> callers in stack traces [4]\n"
637" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
638" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
639" --alignment=<number> set minimum alignment of allocations [4]\n"
640" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000641" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000642" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000643" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000644" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000645" --suppressions=<filename> suppress errors described in\n"
646" suppressions file <filename>\n"
647" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000648" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000649"\n"
650" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000651
njn7cf0bd32002-06-08 13:36:03 +0000652
njn25e49d8e72002-09-23 09:36:25 +0000653 Char* usage2 =
654"\n"
655" core options for debugging Valgrind itself are:\n"
656" --sanity-level=<number> level of sanity checking to do [1]\n"
657" --single-step=no|yes translate each instr separately? [no]\n"
658" --optimise=no|yes improve intermediate code? [yes]\n"
659" --profile=no|yes profile? (skin must be built for it) [no]\n"
660" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
661" --trace-syscalls=no|yes show all system calls? [no]\n"
662" --trace-signals=no|yes show signal handling details? [no]\n"
663" --trace-symtab=no|yes show symbol table details? [no]\n"
664" --trace-malloc=no|yes show client malloc details? [no]\n"
665" --trace-sched=no|yes show thread scheduler details? [no]\n"
666" --trace-pthread=none|some|all show pthread event details? [no]\n"
667" --stop-after=<number> switch to real CPU after executing\n"
668" <number> basic blocks [infinity]\n"
669" --dump-error=<number> show translation for basic block\n"
670" associated with <number>'th\n"
671" error context [0=don't show any]\n"
672"\n"
673" Extra options are read from env variable $VALGRIND_OPTS\n"
674"\n"
675" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
676" and licensed under the GNU General Public License, version 2.\n"
677" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000678"\n"
679" Skins are copyright and licensed by their authors. See each\n"
680" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000681"\n";
njn7cf0bd32002-06-08 13:36:03 +0000682
njnd04b7c62002-10-03 14:05:52 +0000683 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000684 /* Don't print skin string directly for security, ha! */
685 if (VG_(needs).command_line_options)
686 VG_(printf)("%s", SK_(usage)());
687 else
688 VG_(printf)(" (none)\n");
689 VG_(printf)(usage2, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000690
njn25e49d8e72002-09-23 09:36:25 +0000691 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000692 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000693 VG_(clo_logfile_fd) = 2; /* stderr */
694 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000695}
sewardjde4a1d02002-03-22 01:27:54 +0000696
697static void process_cmd_line_options ( void )
698{
njn25e49d8e72002-09-23 09:36:25 +0000699 Char* argv[M_VG_CMDLINE_OPTS];
700 UInt argc;
701 Char* p;
702 Char* str;
703 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000704
705# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
706# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
707# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
708
sewardjde4a1d02002-03-22 01:27:54 +0000709 eventually_logfile_fd = VG_(clo_logfile_fd);
710
711 /* Once logging is started, we can safely send messages pertaining
712 to failures in initialisation. */
713 VG_(startup_logging)();
714
sewardj19d81412002-06-03 01:10:40 +0000715 /* Check for sane path in ./configure --prefix=... */
716 if (VG_(strlen)(VG_LIBDIR) < 1
717 || VG_LIBDIR[0] != '/')
718 config_error("Please use absolute paths in "
719 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000720
sewardja1679dd2002-05-10 22:31:40 +0000721 /* (Suggested by Fabrice Bellard ... )
722 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000723 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000724 change less often than the libc ones. */
725 {
sewardja1679dd2002-05-10 22:31:40 +0000726 UInt* sp = 0; /* bogus init to keep gcc -O happy */
727
sewardj38170912002-05-10 21:07:22 +0000728 /* locate the top of the stack */
sewardja1679dd2002-05-10 22:31:40 +0000729 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
730 VG_STARTUP_STACK_BASE_1 )) {
731 sp = (UInt*)VG_STARTUP_STACK_BASE_1;
732 } else
733 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
734 VG_STARTUP_STACK_BASE_2 )) {
735 sp = (UInt*)VG_STARTUP_STACK_BASE_2;
daywalkera2562202002-07-15 19:39:51 +0000736 } else
737 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
738 VG_STARTUP_STACK_BASE_3 )) {
739 sp = (UInt*)VG_STARTUP_STACK_BASE_3;
njn25e49d8e72002-09-23 09:36:25 +0000740 } else
741 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
742 VG_STARTUP_STACK_BASE_4 )) {
743 sp = (UInt*)VG_STARTUP_STACK_BASE_4;
sewardja1679dd2002-05-10 22:31:40 +0000744 } else {
745 args_grok_error(
746 "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
747 "constants defined in vg_include.h. You should investigate."
748 );
749 }
750
sewardj38170912002-05-10 21:07:22 +0000751 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
752 the elf interpreter table */
753 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000754 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000755 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000756 sp--;
757 }
sewardj38170912002-05-10 21:07:22 +0000758
759 if (sp[2] == VKI_AT_BASE
760 && sp[0] == VKI_AT_PAGESZ
761 && sp[-2] == VKI_AT_PHNUM
762 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000763 && sp[-6] == VKI_AT_PHDR
764 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000765 if (0)
766 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000767 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000768 } else
769 if (sp[2] == VKI_AT_CLKTCK
770 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000771 && sp[-2] == VKI_AT_HWCAP
772 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000773 if (0)
774 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
775 sp -= 2;
776 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000777 if (sp[2] == VKI_AT_CLKTCK
778 && sp[0] == VKI_AT_PAGESZ
779 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000780 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
781 && sp[-4-1] == 0) {
782 if (0)
783 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
784 "kernel here.\n");
785 sp -= 4;
786 } else
787 if (sp[2] == VKI_AT_CLKTCK
788 && sp[0] == VKI_AT_PAGESZ
789 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000790 && sp[-2-20-1] == 0) {
791 if (0)
792 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
793 sp -= 22;
794 } else
sewardja1679dd2002-05-10 22:31:40 +0000795 args_grok_error(
796 "ELF frame does not look like 2.2.X or 2.4.X.\n "
797 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
798 );
sewardj38170912002-05-10 21:07:22 +0000799
800 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000801 if (*sp != 0)
802 args_grok_error("can't find NULL at end of env[]");
803
sewardj38170912002-05-10 21:07:22 +0000804 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000805 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000806 while (True) {
807 sp --;
808 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000809 if (++ctr >= 1000)
810 args_grok_error(
811 "suspiciously many (1000) env[] entries; giving up");
812
sewardj38170912002-05-10 21:07:22 +0000813 }
814 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000815 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000816
sewardja1679dd2002-05-10 22:31:40 +0000817 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000818 VG_(client_argc) = 0;
819 while (True) {
820 sp--;
821 if (*sp == VG_(client_argc))
822 break;
823 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000824 if (++ctr >= 1000)
825 args_grok_error(
826 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000827 }
828
sewardja1679dd2002-05-10 22:31:40 +0000829 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000830 }
831
sewardjde4a1d02002-03-22 01:27:54 +0000832 /* Now that VG_(client_envp) has been set, we can extract the args
833 for Valgrind itself. Copy into global var so that we don't have to
834 write zeroes to the getenv'd value itself. */
835 str = VG_(getenv)("VG_ARGS");
836 argc = 0;
837
838 if (!str) {
839 config_error("Can't read options from env var VG_ARGS.");
840 }
841
842 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
843 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
844 }
845 VG_(strcpy)(vg_cmdline_copy, str);
846 str = NULL;
847
848 p = &vg_cmdline_copy[0];
849 while (True) {
850 while (ISSPACE(*p)) { *p = 0; p++; }
851 if (*p == 0) break;
852 if (argc < M_VG_CMDLINE_OPTS-1) {
853 argv[argc] = p; argc++;
854 } else {
855 config_error(
856 "Found more than M_CMDLINE_OPTS command-line opts.");
857 }
858 while (*p != 0 && !ISSPACE(*p)) p++;
859 }
860
861 for (i = 0; i < argc; i++) {
862
njn25e49d8e72002-09-23 09:36:25 +0000863 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000864 VG_(clo_verbosity)++;
865 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
866 VG_(clo_verbosity)--;
867
sewardj2e432902002-06-13 20:44:00 +0000868 else if (STREQ(argv[i], "--error-limit=yes"))
869 VG_(clo_error_limit) = True;
870 else if (STREQ(argv[i], "--error-limit=no"))
871 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000872
sewardjde4a1d02002-03-22 01:27:54 +0000873 else if (STREQ(argv[i], "--gdb-attach=yes"))
874 VG_(clo_GDB_attach) = True;
875 else if (STREQ(argv[i], "--gdb-attach=no"))
876 VG_(clo_GDB_attach) = False;
877
878 else if (STREQ(argv[i], "--demangle=yes"))
879 VG_(clo_demangle) = True;
880 else if (STREQ(argv[i], "--demangle=no"))
881 VG_(clo_demangle) = False;
882
sewardjde4a1d02002-03-22 01:27:54 +0000883 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
884 VG_(clo_sloppy_malloc) = True;
885 else if (STREQ(argv[i], "--sloppy-malloc=no"))
886 VG_(clo_sloppy_malloc) = False;
887
sewardj246d4662002-06-14 10:17:05 +0000888 else if (STREQN(12, argv[i], "--alignment="))
889 VG_(clo_alignment) = (Int)VG_(atoll)(&argv[i][12]);
890
sewardjde4a1d02002-03-22 01:27:54 +0000891 else if (STREQ(argv[i], "--trace-children=yes"))
892 VG_(clo_trace_children) = True;
893 else if (STREQ(argv[i], "--trace-children=no"))
894 VG_(clo_trace_children) = False;
895
sewardj858964b2002-10-05 14:15:43 +0000896 else if (STREQ(argv[i], "--run-libc-freeres=yes"))
897 VG_(clo_run_libc_freeres) = True;
898 else if (STREQ(argv[i], "--run-libc-freeres=no"))
899 VG_(clo_run_libc_freeres) = False;
900
sewardjde4a1d02002-03-22 01:27:54 +0000901 else if (STREQN(15, argv[i], "--sanity-level="))
902 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
903
sewardj4cf05692002-10-27 20:28:29 +0000904 else if (STREQN(13, argv[i], "--logfile-fd=")) {
905 VG_(clo_log_to) = VgLogTo_Fd;
906 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000907 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000908 }
909
910 else if (STREQN(10, argv[i], "--logfile=")) {
911 VG_(clo_log_to) = VgLogTo_File;
912 VG_(clo_logfile_name) = &argv[i][10];
913 }
sewardjde4a1d02002-03-22 01:27:54 +0000914
sewardj73cf3bc2002-11-03 03:20:15 +0000915 else if (STREQN(12, argv[i], "--logsocket=")) {
916 VG_(clo_log_to) = VgLogTo_Socket;
917 VG_(clo_logfile_name) = &argv[i][12];
918 }
919
sewardjde4a1d02002-03-22 01:27:54 +0000920 else if (STREQN(15, argv[i], "--suppressions=")) {
921 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000922 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000923 VG_(message)(Vg_UserMsg,
924 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000925 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000926 }
927 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
928 VG_(clo_n_suppressions)++;
929 }
njn25e49d8e72002-09-23 09:36:25 +0000930 else if (STREQ(argv[i], "--profile=yes"))
931 VG_(clo_profile) = True;
932 else if (STREQ(argv[i], "--profile=no"))
933 VG_(clo_profile) = False;
934
sewardjde4a1d02002-03-22 01:27:54 +0000935 else if (STREQ(argv[i], "--single-step=yes"))
936 VG_(clo_single_step) = True;
937 else if (STREQ(argv[i], "--single-step=no"))
938 VG_(clo_single_step) = False;
939
940 else if (STREQ(argv[i], "--optimise=yes"))
941 VG_(clo_optimise) = True;
942 else if (STREQ(argv[i], "--optimise=no"))
943 VG_(clo_optimise) = False;
944
njn25e49d8e72002-09-23 09:36:25 +0000945 /* "vwxyz" --> 000zyxwv (binary) */
946 else if (STREQN(16, argv[i], "--trace-codegen=")) {
947 Int j;
948 char* opt = & argv[i][16];
949
950 if (5 != VG_(strlen)(opt)) {
951 VG_(message)(Vg_UserMsg,
952 "--trace-codegen argument must have 5 digits");
953 VG_(bad_option)(argv[i]);
954 }
955 for (j = 0; j < 5; j++) {
956 if ('0' == opt[j]) { /* do nothing */ }
957 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
958 else {
959 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
960 "contain 0s and 1s");
961 VG_(bad_option)(argv[i]);
962 }
963 }
964 }
sewardjde4a1d02002-03-22 01:27:54 +0000965
966 else if (STREQ(argv[i], "--trace-syscalls=yes"))
967 VG_(clo_trace_syscalls) = True;
968 else if (STREQ(argv[i], "--trace-syscalls=no"))
969 VG_(clo_trace_syscalls) = False;
970
971 else if (STREQ(argv[i], "--trace-signals=yes"))
972 VG_(clo_trace_signals) = True;
973 else if (STREQ(argv[i], "--trace-signals=no"))
974 VG_(clo_trace_signals) = False;
975
976 else if (STREQ(argv[i], "--trace-symtab=yes"))
977 VG_(clo_trace_symtab) = True;
978 else if (STREQ(argv[i], "--trace-symtab=no"))
979 VG_(clo_trace_symtab) = False;
980
981 else if (STREQ(argv[i], "--trace-malloc=yes"))
982 VG_(clo_trace_malloc) = True;
983 else if (STREQ(argv[i], "--trace-malloc=no"))
984 VG_(clo_trace_malloc) = False;
985
sewardj8937c812002-04-12 20:12:20 +0000986 else if (STREQ(argv[i], "--trace-sched=yes"))
987 VG_(clo_trace_sched) = True;
988 else if (STREQ(argv[i], "--trace-sched=no"))
989 VG_(clo_trace_sched) = False;
990
sewardj45b4b372002-04-16 22:50:32 +0000991 else if (STREQ(argv[i], "--trace-pthread=none"))
992 VG_(clo_trace_pthread_level) = 0;
993 else if (STREQ(argv[i], "--trace-pthread=some"))
994 VG_(clo_trace_pthread_level) = 1;
995 else if (STREQ(argv[i], "--trace-pthread=all"))
996 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000997
sewardj8d365b52002-05-12 10:52:16 +0000998 else if (STREQN(14, argv[i], "--weird-hacks="))
999 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001000
sewardjde4a1d02002-03-22 01:27:54 +00001001 else if (STREQN(13, argv[i], "--stop-after="))
1002 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1003
1004 else if (STREQN(13, argv[i], "--dump-error="))
1005 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1006
1007 else if (STREQN(14, argv[i], "--num-callers=")) {
1008 /* Make sure it's sane. */
1009 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1010 if (VG_(clo_backtrace_size) < 2)
1011 VG_(clo_backtrace_size) = 2;
1012 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1013 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1014 }
1015
njn25e49d8e72002-09-23 09:36:25 +00001016 else if (VG_(needs).command_line_options) {
1017 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1018 if (!ok)
1019 usage();
1020 }
sewardjde4a1d02002-03-22 01:27:54 +00001021 else
njn25e49d8e72002-09-23 09:36:25 +00001022 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001023 }
1024
1025# undef ISSPACE
1026# undef STREQ
1027# undef STREQN
1028
1029 if (VG_(clo_verbosity < 0))
1030 VG_(clo_verbosity) = 0;
1031
sewardj246d4662002-06-14 10:17:05 +00001032 if (VG_(clo_alignment) < 4
1033 || VG_(clo_alignment) > 4096
1034 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
1035 VG_(message)(Vg_UserMsg, "");
1036 VG_(message)(Vg_UserMsg,
1037 "Invalid --alignment= setting. "
1038 "Should be a power of 2, >= 4, <= 4096.");
njn25e49d8e72002-09-23 09:36:25 +00001039 VG_(bad_option)("--alignment");
sewardj246d4662002-06-14 10:17:05 +00001040 }
1041
sewardjde4a1d02002-03-22 01:27:54 +00001042 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1043 VG_(message)(Vg_UserMsg, "");
1044 VG_(message)(Vg_UserMsg,
1045 "--gdb-attach=yes conflicts with --trace-children=yes");
1046 VG_(message)(Vg_UserMsg,
1047 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001048 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001049 }
1050
sewardj4cf05692002-10-27 20:28:29 +00001051 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1052 should be connected to whatever sink has been selected, and we
1053 indiscriminately chuck stuff into it without worrying what the
1054 nature of it is. Oh the wonder of Unix streams. */
1055
1056 /* So far we should be still attached to stderr, so we can show on
1057 the terminal any problems to do with processing command line
1058 opts. */
1059 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001060 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001061
1062 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001063
sewardj4cf05692002-10-27 20:28:29 +00001064 case VgLogTo_Fd:
1065 vg_assert(VG_(clo_logfile_name) == NULL);
1066 VG_(clo_logfile_fd) = eventually_logfile_fd;
1067 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001068
sewardj4cf05692002-10-27 20:28:29 +00001069 case VgLogTo_File: {
1070 Char logfilename[1000];
1071 vg_assert(VG_(clo_logfile_name) != NULL);
1072 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1073 VG_(sprintf)(logfilename, "%s.pid%d",
1074 VG_(clo_logfile_name), VG_(getpid)() );
1075 eventually_logfile_fd
1076 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1077 VKI_S_IRUSR|VKI_S_IWUSR);
1078 if (eventually_logfile_fd != -1) {
1079 VG_(clo_logfile_fd) = eventually_logfile_fd;
1080 } else {
1081 VG_(message)(Vg_UserMsg,
1082 "Can't create/open log file `%s.pid%d'; giving up!",
1083 VG_(clo_logfile_name), VG_(getpid)());
1084 VG_(bad_option)(
1085 "--logfile=<file> didn't work out for some reason.");
1086 }
1087 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001088 }
1089
1090 case VgLogTo_Socket: {
1091 vg_assert(VG_(clo_logfile_name) != NULL);
1092 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1093 eventually_logfile_fd
1094 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1095 if (eventually_logfile_fd == -1) {
1096 VG_(message)(Vg_UserMsg,
1097 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1098 VG_(message)(Vg_UserMsg,
1099 "of `%s'; giving up!", VG_(clo_logfile_name) );
1100 VG_(bad_option)(
1101 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001102 }
sewardj73cf3bc2002-11-03 03:20:15 +00001103 if (eventually_logfile_fd == -2) {
1104 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001105 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001106 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001107 VG_(message)(Vg_UserMsg,
1108 "Log messages will sent to stderr instead." );
1109 VG_(message)(Vg_UserMsg,
1110 "" );
1111 /* We don't change anything here. */
1112 } else {
1113 vg_assert(eventually_logfile_fd > 0);
1114 VG_(clo_logfile_fd) = eventually_logfile_fd;
1115 VG_(logging_to_filedes) = False;
1116 }
sewardj73cf3bc2002-11-03 03:20:15 +00001117 break;
1118 }
1119
sewardj4cf05692002-10-27 20:28:29 +00001120 }
1121
1122 /* Ok, the logging sink is running now. Print a suitable preamble.
1123 If logging to file or a socket, write details of parent PID and
1124 command line args, to help people trying to interpret the
1125 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001126
sewardj83adf412002-05-01 01:25:45 +00001127 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001128 /* Skin details */
1129 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1130 VG_(details).name,
1131 NULL == VG_(details).version ? "" : "-",
1132 NULL == VG_(details).version
1133 ? (Char*)"" : VG_(details).version,
1134 VG_(details).description);
1135 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001136
njnd04b7c62002-10-03 14:05:52 +00001137 /* Core details */
1138 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001139 "Using valgrind-%s, a program instrumentation system for x86-linux.",
1140 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001141 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001142 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001143 }
1144
sewardj4cf05692002-10-27 20:28:29 +00001145 if (VG_(clo_log_to) != VgLogTo_Fd) {
1146 VG_(message)(Vg_UserMsg, "");
1147 VG_(message)(Vg_UserMsg,
1148 "My PID = %d, parent PID = %d. Prog and args are:",
1149 VG_(getpid)(), VG_(getppid)() );
1150 for (i = 0; i < VG_(client_argc); i++)
1151 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1152 }
1153
sewardjde4a1d02002-03-22 01:27:54 +00001154 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001155 if (VG_(clo_log_to) != VgLogTo_Fd)
1156 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001157 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1158 for (i = 0; i < argc; i++) {
1159 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1160 }
1161 }
1162
njn25e49d8e72002-09-23 09:36:25 +00001163 if (VG_(clo_n_suppressions) == 0 &&
1164 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001165 config_error("No error-suppression files were specified.");
1166 }
sewardj4cf05692002-10-27 20:28:29 +00001167
sewardjde4a1d02002-03-22 01:27:54 +00001168}
1169
sewardjde4a1d02002-03-22 01:27:54 +00001170/* ---------------------------------------------------------------------
1171 Copying to/from m_state_static.
1172 ------------------------------------------------------------------ */
1173
sewardj92a59562002-09-30 00:53:10 +00001174UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1175 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001176 + 1 /* %eflags */
1177 + 1 /* %eip */
1178 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1179 ];
1180
1181void VG_(copy_baseBlock_to_m_state_static) ( void )
1182{
1183 Int i;
sewardj92a59562002-09-30 00:53:10 +00001184 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1185 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1186 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1187 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1188 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1189 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001190
sewardj92a59562002-09-30 00:53:10 +00001191 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1192 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1193 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1194 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1195 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1196 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1197 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1198 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1199
1200 VG_(m_state_static)[56/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
1201 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001202
1203 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001204 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001205 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1206}
1207
1208
1209void VG_(copy_m_state_static_to_baseBlock) ( void )
1210{
1211 Int i;
sewardj92a59562002-09-30 00:53:10 +00001212 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1213 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1214 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1215 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1216 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1217 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001218
sewardj92a59562002-09-30 00:53:10 +00001219 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1220 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1221 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1222 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1223 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1224 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1225 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1226 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1227
1228 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4];
1229 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001230
1231 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1232 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001233 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001234}
1235
njn25e49d8e72002-09-23 09:36:25 +00001236Addr VG_(get_stack_pointer) ( void )
1237{
1238 return VG_(baseBlock)[VGOFF_(m_esp)];
1239}
1240
1241/* Some random tests needed for leak checking */
1242
1243Bool VG_(within_stack)(Addr a)
1244{
1245 if (a >= ((Addr)(&VG_(stack)))
1246 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1247 return True;
1248 else
1249 return False;
1250}
1251
1252Bool VG_(within_m_state_static)(Addr a)
1253{
1254 if (a >= ((Addr)(&VG_(m_state_static)))
1255 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1256 return True;
1257 else
1258 return False;
1259}
sewardjde4a1d02002-03-22 01:27:54 +00001260
1261/* ---------------------------------------------------------------------
1262 Show accumulated counts.
1263 ------------------------------------------------------------------ */
1264
njn25e49d8e72002-09-23 09:36:25 +00001265static __inline__ Int safe_idiv(Int a, Int b)
1266{
1267 return (b == 0 ? 0 : a / b);
1268}
1269
sewardjde4a1d02002-03-22 01:27:54 +00001270static void vg_show_counts ( void )
1271{
1272 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001273 " lru: %d epochs, %d clearings.",
1274 VG_(current_epoch),
1275 VG_(number_of_lrus) );
sewardjde4a1d02002-03-22 01:27:54 +00001276 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001277 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001278 VG_(overall_in_count),
1279 VG_(overall_in_osize),
1280 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001281 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1282 VG_(message)(Vg_DebugMsg,
1283 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001284 VG_(overall_out_count),
1285 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001286 VG_(overall_out_tsize),
1287 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001288 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001289 " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
1290 VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
1291 VG_(num_scheduling_events_MINOR),
1292 VG_(tt_fast_misses));
sewardjde4a1d02002-03-22 01:27:54 +00001293 VG_(message)(Vg_DebugMsg,
1294 "reg-alloc: %d t-req-spill, "
1295 "%d+%d orig+spill uis, %d total-reg-r.",
1296 VG_(translations_needing_spill),
1297 VG_(uinstrs_prealloc),
1298 VG_(uinstrs_spill),
1299 VG_(total_reg_rank) );
1300 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001301 " sanity: %d cheap, %d expensive checks.",
1302 VG_(sanity_fast_count),
1303 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001304 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001305}
1306
1307
1308/* ---------------------------------------------------------------------
1309 Main!
1310 ------------------------------------------------------------------ */
1311
1312/* Where we jump to once Valgrind has got control, and the real
1313 machine's state has been copied to the m_state_static. */
1314
1315void VG_(main) ( void )
1316{
sewardj2e93c502002-04-12 11:12:52 +00001317 Int i;
1318 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001319 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001320
1321 /* Set up our stack sanity-check words. */
1322 for (i = 0; i < 10; i++) {
1323 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1324 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1325 }
1326
njn25e49d8e72002-09-23 09:36:25 +00001327 /* Setup stuff that depends on the skin. Must be before:
1328 - vg_init_baseBlock(): to register helpers
1329 - process_cmd_line_options(): to register skin name and description,
1330 and turn on/off 'command_line_options' need
1331 - init_memory() (to setup memory event trackers).
1332 */
njnd04b7c62002-10-03 14:05:52 +00001333 SK_(pre_clo_init) ( & VG_(details), & VG_(needs), & VG_(track_events) );
njn25e49d8e72002-09-23 09:36:25 +00001334 sanity_check_needs();
1335
njncc7bb472002-10-14 09:25:19 +00001336 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001337 process_cmd_line_options();
1338
njncc7bb472002-10-14 09:25:19 +00001339 /* Do post command-line processing initialisation */
1340 SK_(post_clo_init)();
1341
1342 /* Set up baseBlock offsets and copy the saved machine's state into it.
1343 Comes after SK_(post_clo_init) in case it registers helpers. */
1344 vg_init_baseBlock();
1345
sewardj64039bb2002-06-03 00:58:18 +00001346 /* Hook to delay things long enough so we can get the pid and
1347 attach GDB in another shell. */
sewardj92a59562002-09-30 00:53:10 +00001348 if (0) {
sewardj64039bb2002-06-03 00:58:18 +00001349 Int p, q;
sewardjc26cc252002-10-23 21:58:55 +00001350 VG_(printf)("pid=%d\n", VG_(getpid)());
sewardj64039bb2002-06-03 00:58:18 +00001351 for (p = 0; p < 50000; p++)
1352 for (q = 0; q < 50000; q++) ;
1353 }
1354
sewardj018f7622002-05-15 21:13:39 +00001355 /* Initialise the scheduler, and copy the client's state from
1356 baseBlock into VG_(threads)[1]. This has to come before signal
1357 initialisations. */
1358 VG_(scheduler_init)();
1359
1360 /* Initialise the signal handling subsystem, temporarily parking
1361 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001362 VG_(sigstartup_actions)();
1363
sewardj018f7622002-05-15 21:13:39 +00001364 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001365 if (VG_(clo_profile))
1366 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001367
sewardj5f07b662002-04-23 16:52:51 +00001368 /* Start calibration of our RDTSC-based clock. */
1369 VG_(start_rdtsc_calibration)();
1370
njn25e49d8e72002-09-23 09:36:25 +00001371 /* Must come after SK_(init) so memory handler accompaniments (eg.
1372 * shadow memory) can be setup ok */
1373 VGP_PUSHCC(VgpInitMem);
1374 VG_(init_memory)();
1375 VGP_POPCC(VgpInitMem);
1376
1377 /* Read the list of errors to suppress. This should be found in
1378 the file specified by vg_clo_suppressions. */
1379 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1380 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001381
sewardj5f07b662002-04-23 16:52:51 +00001382 /* End calibration of our RDTSC-based clock, leaving it as long as
1383 we can. */
1384 VG_(end_rdtsc_calibration)();
1385
njn25e49d8e72002-09-23 09:36:25 +00001386 /* This should come after init_memory_and_symbols(); otherwise the
1387 latter carefully sets up the permissions maps to cover the
1388 anonymous mmaps for the translation table and translation cache,
1389 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001390 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001391
1392 if (VG_(clo_verbosity) == 1) {
1393 VG_(message)(Vg_UserMsg,
1394 "For more details, rerun with: -v");
1395 }
1396
1397 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1398 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001399 if (VG_(clo_verbosity) > 0)
1400 VG_(message)(Vg_UserMsg, "");
1401
1402 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001403
sewardj018f7622002-05-15 21:13:39 +00001404 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001405 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001406 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001407 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001408 VGP_POPCC(VgpSched);
1409 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001410
1411 if (VG_(clo_verbosity) > 0)
1412 VG_(message)(Vg_UserMsg, "");
1413
sewardj2e93c502002-04-12 11:12:52 +00001414 if (src == VgSrc_Deadlock) {
1415 VG_(message)(Vg_UserMsg,
1416 "Warning: pthread scheduler exited due to deadlock");
1417 }
1418
njn25e49d8e72002-09-23 09:36:25 +00001419 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001420 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001421
njn25e49d8e72002-09-23 09:36:25 +00001422 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001423
sewardj0c3b53f2002-05-01 01:58:35 +00001424 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001425
1426 if (VG_(clo_verbosity) > 1)
1427 vg_show_counts();
1428
njn25e49d8e72002-09-23 09:36:25 +00001429 if (VG_(clo_verbosity) > 2)
1430 VG_(print_UInstr_histogram)();
1431
sewardjde4a1d02002-03-22 01:27:54 +00001432 if (0) {
1433 VG_(message)(Vg_DebugMsg, "");
1434 VG_(message)(Vg_DebugMsg,
1435 "------ Valgrind's internal memory use stats follow ------" );
1436 VG_(mallocSanityCheckAll)();
1437 VG_(show_all_arena_stats)();
1438 VG_(message)(Vg_DebugMsg,
1439 "------ Valgrind's ExeContext management stats follow ------" );
1440 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001441 }
1442
njn25e49d8e72002-09-23 09:36:25 +00001443 if (VG_(clo_profile))
1444 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001445
1446 VG_(shutdown_logging)();
1447
sewardj3e1eb1f2002-05-18 13:14:17 +00001448 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1449 processes don't get traced into. Also mess up $libdir/valgrind
1450 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001451 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001452 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1453 VG_(getenv)("LD_PRELOAD"),
1454 VG_(getenv)("LD_LIBRARY_PATH")
1455 );
sewardjde4a1d02002-03-22 01:27:54 +00001456 }
1457
sewardj7e87e382002-05-03 19:09:05 +00001458 /* Decide how to exit. This depends on what the scheduler
1459 returned. */
1460 switch (src) {
1461 case VgSrc_ExitSyscall: /* the normal way out */
1462 vg_assert(VG_(last_run_tid) > 0
1463 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001464 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001465 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001466 /* The thread's %EBX at the time it did __NR_exit() will hold
1467 the arg to __NR_exit(), so we just do __NR_exit() with
1468 that arg. */
1469 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001470 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001471 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001472 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001473
sewardj7e87e382002-05-03 19:09:05 +00001474 case VgSrc_Deadlock:
1475 /* Just exit now. No point in continuing. */
1476 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001477 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001478 break;
1479
1480 case VgSrc_BbsDone:
1481 /* Tricky; we have to try and switch back to the real CPU.
1482 This is all very dodgy and won't work at all in the
1483 presence of threads, or if the client happened to be
1484 running a signal handler. */
1485 /* Prepare to restore state to the real CPU. */
1486 VG_(load_thread_state)(1 /* root thread */ );
1487 VG_(copy_baseBlock_to_m_state_static)();
1488
1489 /* This pushes a return address on the simulator's stack,
1490 which is abandoned. We call vg_sigshutdown_actions() at
1491 the end of vg_switch_to_real_CPU(), so as to ensure that
1492 the original stack and machine state is restored before
1493 the real signal mechanism is restored. */
1494 VG_(switch_to_real_CPU)();
1495
1496 default:
njne427a662002-10-02 11:08:25 +00001497 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001498 }
sewardjde4a1d02002-03-22 01:27:54 +00001499}
1500
1501
1502/* Debugging thing .. can be called from assembly with OYNK macro. */
1503void VG_(oynk) ( Int n )
1504{
1505 OINK(n);
1506}
1507
1508
1509/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1510 "valgrinq.so", which doesn't do anything. This is used to avoid
1511 tracing into child processes. To make this work the build system
1512 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001513
njn25e49d8e72002-09-23 09:36:25 +00001514 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1515 without it, child processes try to find valgrind.so symbols in the
1516 skin .so.
1517
sewardj78e25c92002-05-20 23:38:33 +00001518 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1519 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1520 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001521*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001522void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1523 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001524{
njn25e49d8e72002-09-23 09:36:25 +00001525 Char* p_prel = NULL;
1526 Char* sk_prel = NULL;
1527 Char* p_path = NULL;
1528 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001529 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1530 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001531
sewardj78e25c92002-05-20 23:38:33 +00001532 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1533
1534 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001535 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001536 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1537
njn25e49d8e72002-09-23 09:36:25 +00001538 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001539 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001540 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001541 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1542 goto mutancy;
1543 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1544 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001545 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001546 }
1547
sewardj78e25c92002-05-20 23:38:33 +00001548 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001549 if (sk_prel == NULL) goto mutancy;
1550
1551 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001552 if (p_path == NULL) goto mutancy;
1553
njn25e49d8e72002-09-23 09:36:25 +00001554 what = 4;
1555 {
1556 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1557 Char* p = sk_prel;
1558 while (*p != ':' && p > ld_preload_str) {
1559 *p = ' ';
1560 p--;
1561 }
1562 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1563 while (*p != ':' && *p != '\0') {
1564 *p = ' ';
1565 p++;
1566 }
1567 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1568 *p = ' '; /* blank ending ':' */
1569 }
1570
sewardj78e25c92002-05-20 23:38:33 +00001571 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001572 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001573 if (p_prel[7] != 'd') goto mutancy;
1574 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001575
1576 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1577 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1578 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001579 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001580 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001581 if (p_path[0] != '/') goto mutancy;
1582 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001583 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001584 if (p_path[7] != 'd') goto mutancy;
1585 p_path[7] = 'q';
1586 return;
1587
1588 mutancy:
1589 VG_(printf)(
1590 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1591 " what = %d\n"
1592 " ld_preload_str = `%s'\n"
1593 " ld_library_path_str = `%s'\n"
1594 " p_prel = `%s'\n"
1595 " p_path = `%s'\n"
1596 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001597 what, ld_preload_str, ld_library_path_str,
1598 p_prel, p_path, VG_LIBDIR
1599 );
sewardjc26b4482002-07-13 12:20:35 +00001600 VG_(printf)(
1601 "\n"
1602 "Note that this is often caused by mis-installation of valgrind.\n"
1603 "Correct installation procedure is:\n"
1604 " ./configure --prefix=/install/dir\n"
1605 " make install\n"
1606 "And then use /install/dir/bin/valgrind\n"
1607 "Moving the installation directory elsewhere after 'make install'\n"
1608 "will cause the above error. Hand-editing the paths in the shell\n"
1609 "scripts is also likely to cause problems.\n"
1610 "\n"
1611 );
njne427a662002-10-02 11:08:25 +00001612 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001613}
1614
sewardj3e1eb1f2002-05-18 13:14:17 +00001615
sewardjde4a1d02002-03-22 01:27:54 +00001616/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1617 it to attach to this process. Called if the user requests this
1618 service after an error has been shown, so she can poke around and
1619 look at parameters, memory, etc. You can't meaningfully get GDB to
1620 continue the program, though; to continue, quit GDB. */
1621extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1622{
sewardje6a25242002-04-21 22:03:07 +00001623 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001624 UChar buf[100];
1625 VG_(sprintf)(buf,
1626 "/usr/bin/gdb -nw /proc/%d/exe %d",
1627 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001628 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1629 res = VG_(system)(buf);
1630 if (res == 0) {
1631 VG_(message)(Vg_UserMsg, "");
1632 VG_(message)(Vg_UserMsg,
1633 "GDB has detached. Valgrind regains control. We continue.");
1634 } else {
1635 VG_(message)(Vg_UserMsg, "Apparently failed!");
1636 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001637 }
sewardjde4a1d02002-03-22 01:27:54 +00001638}
1639
1640
1641/* Print some helpful-ish text about unimplemented things, and give
1642 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001643void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001644{
1645 VG_(message)(Vg_UserMsg, "");
1646 VG_(message)(Vg_UserMsg,
1647 "Valgrind detected that your program requires");
1648 VG_(message)(Vg_UserMsg,
1649 "the following unimplemented functionality:");
1650 VG_(message)(Vg_UserMsg, " %s", msg);
1651 VG_(message)(Vg_UserMsg,
1652 "This may be because the functionality is hard to implement,");
1653 VG_(message)(Vg_UserMsg,
1654 "or because no reasonable program would behave this way,");
1655 VG_(message)(Vg_UserMsg,
1656 "or because nobody has yet needed it. In any case, let me know");
1657 VG_(message)(Vg_UserMsg,
1658 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1659 VG_(message)(Vg_UserMsg,
1660 "");
1661 VG_(message)(Vg_UserMsg,
1662 "Valgrind has to exit now. Sorry. Bye!");
1663 VG_(message)(Vg_UserMsg,
1664 "");
sewardj15a43e12002-04-17 19:35:12 +00001665 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001666 VG_(exit)(1);
1667}
1668
1669
njn25e49d8e72002-09-23 09:36:25 +00001670/* ---------------------------------------------------------------------
1671 Sanity check machinery (permanently engaged).
1672 ------------------------------------------------------------------ */
1673
1674/* A fast sanity check -- suitable for calling circa once per
1675 millisecond. */
1676
1677void VG_(do_sanity_checks) ( Bool force_expensive )
1678{
1679 Int i;
1680
njn37cea302002-09-30 11:24:00 +00001681 VGP_PUSHCC(VgpCoreCheapSanity);
1682
njn25e49d8e72002-09-23 09:36:25 +00001683 if (VG_(sanity_level) < 1) return;
1684
1685 /* --- First do all the tests that we can do quickly. ---*/
1686
1687 VG_(sanity_fast_count)++;
1688
1689 /* Check that we haven't overrun our private stack. */
1690 for (i = 0; i < 10; i++) {
1691 vg_assert(VG_(stack)[i]
1692 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1693 vg_assert(VG_(stack)[10000-1-i]
1694 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1695 }
1696
1697 /* Check stuff pertaining to the memory check system. */
1698
1699 /* Check that nobody has spuriously claimed that the first or
1700 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001701 if (VG_(needs).sanity_checks) {
1702 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001703 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001704 VGP_POPCC(VgpSkinCheapSanity);
1705 }
njn25e49d8e72002-09-23 09:36:25 +00001706
1707 /* --- Now some more expensive checks. ---*/
1708
1709 /* Once every 25 times, check some more expensive stuff. */
1710 if ( force_expensive
1711 || VG_(sanity_level) > 1
1712 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1713
njn37cea302002-09-30 11:24:00 +00001714 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001715 VG_(sanity_slow_count)++;
1716
1717# if 0
1718 { void zzzmemscan(void); zzzmemscan(); }
1719# endif
1720
1721 if ((VG_(sanity_fast_count) % 250) == 0)
1722 VG_(sanity_check_tc_tt)();
1723
1724 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001725 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001726 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001727 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001728 }
1729 /*
1730 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1731 */
njn37cea302002-09-30 11:24:00 +00001732 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001733 }
1734
1735 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001736 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001737 /* Check sanity of the low-level memory manager. Note that bugs
1738 in the client's code can cause this to fail, so we don't do
1739 this check unless specially asked for. And because it's
1740 potentially very expensive. */
1741 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001742 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001743 }
njn37cea302002-09-30 11:24:00 +00001744 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001745}
sewardjde4a1d02002-03-22 01:27:54 +00001746/*--------------------------------------------------------------------*/
1747/*--- end vg_main.c ---*/
1748/*--------------------------------------------------------------------*/