blob: 30fcac7363d879489e5f9971737a6f932a870ffa [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,
1105 "Failed to connect to logging server `%s'; giving up",
1106 VG_(clo_logfile_name) );
1107 VG_(bad_option)(
1108 "--logsocket= (timeout during connect)");
1109 }
1110 vg_assert(eventually_logfile_fd > 0);
1111 VG_(clo_logfile_fd) = eventually_logfile_fd;
1112 VG_(logging_to_filedes) = False;
1113 break;
1114 }
1115
sewardj4cf05692002-10-27 20:28:29 +00001116 }
1117
1118 /* Ok, the logging sink is running now. Print a suitable preamble.
1119 If logging to file or a socket, write details of parent PID and
1120 command line args, to help people trying to interpret the
1121 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001122
sewardj83adf412002-05-01 01:25:45 +00001123 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001124 /* Skin details */
1125 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1126 VG_(details).name,
1127 NULL == VG_(details).version ? "" : "-",
1128 NULL == VG_(details).version
1129 ? (Char*)"" : VG_(details).version,
1130 VG_(details).description);
1131 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001132
njnd04b7c62002-10-03 14:05:52 +00001133 /* Core details */
1134 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001135 "Using valgrind-%s, a program instrumentation system for x86-linux.",
1136 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001137 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001138 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001139 }
1140
sewardj4cf05692002-10-27 20:28:29 +00001141 if (VG_(clo_log_to) != VgLogTo_Fd) {
1142 VG_(message)(Vg_UserMsg, "");
1143 VG_(message)(Vg_UserMsg,
1144 "My PID = %d, parent PID = %d. Prog and args are:",
1145 VG_(getpid)(), VG_(getppid)() );
1146 for (i = 0; i < VG_(client_argc); i++)
1147 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1148 }
1149
sewardjde4a1d02002-03-22 01:27:54 +00001150 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001151 if (VG_(clo_log_to) != VgLogTo_Fd)
1152 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001153 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1154 for (i = 0; i < argc; i++) {
1155 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1156 }
1157 }
1158
njn25e49d8e72002-09-23 09:36:25 +00001159 if (VG_(clo_n_suppressions) == 0 &&
1160 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001161 config_error("No error-suppression files were specified.");
1162 }
sewardj4cf05692002-10-27 20:28:29 +00001163
sewardjde4a1d02002-03-22 01:27:54 +00001164}
1165
sewardjde4a1d02002-03-22 01:27:54 +00001166/* ---------------------------------------------------------------------
1167 Copying to/from m_state_static.
1168 ------------------------------------------------------------------ */
1169
sewardj92a59562002-09-30 00:53:10 +00001170UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1171 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001172 + 1 /* %eflags */
1173 + 1 /* %eip */
1174 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1175 ];
1176
1177void VG_(copy_baseBlock_to_m_state_static) ( void )
1178{
1179 Int i;
sewardj92a59562002-09-30 00:53:10 +00001180 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1181 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1182 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1183 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1184 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1185 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001186
sewardj92a59562002-09-30 00:53:10 +00001187 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1188 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1189 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1190 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1191 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1192 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1193 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1194 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1195
1196 VG_(m_state_static)[56/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
1197 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001198
1199 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001200 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001201 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1202}
1203
1204
1205void VG_(copy_m_state_static_to_baseBlock) ( void )
1206{
1207 Int i;
sewardj92a59562002-09-30 00:53:10 +00001208 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1209 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1210 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1211 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1212 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1213 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001214
sewardj92a59562002-09-30 00:53:10 +00001215 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1216 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1217 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1218 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1219 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1220 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1221 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1222 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1223
1224 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4];
1225 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001226
1227 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1228 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001229 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001230}
1231
njn25e49d8e72002-09-23 09:36:25 +00001232Addr VG_(get_stack_pointer) ( void )
1233{
1234 return VG_(baseBlock)[VGOFF_(m_esp)];
1235}
1236
1237/* Some random tests needed for leak checking */
1238
1239Bool VG_(within_stack)(Addr a)
1240{
1241 if (a >= ((Addr)(&VG_(stack)))
1242 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1243 return True;
1244 else
1245 return False;
1246}
1247
1248Bool VG_(within_m_state_static)(Addr a)
1249{
1250 if (a >= ((Addr)(&VG_(m_state_static)))
1251 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1252 return True;
1253 else
1254 return False;
1255}
sewardjde4a1d02002-03-22 01:27:54 +00001256
1257/* ---------------------------------------------------------------------
1258 Show accumulated counts.
1259 ------------------------------------------------------------------ */
1260
njn25e49d8e72002-09-23 09:36:25 +00001261static __inline__ Int safe_idiv(Int a, Int b)
1262{
1263 return (b == 0 ? 0 : a / b);
1264}
1265
sewardjde4a1d02002-03-22 01:27:54 +00001266static void vg_show_counts ( void )
1267{
1268 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001269 " lru: %d epochs, %d clearings.",
1270 VG_(current_epoch),
1271 VG_(number_of_lrus) );
sewardjde4a1d02002-03-22 01:27:54 +00001272 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001273 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001274 VG_(overall_in_count),
1275 VG_(overall_in_osize),
1276 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001277 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1278 VG_(message)(Vg_DebugMsg,
1279 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001280 VG_(overall_out_count),
1281 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001282 VG_(overall_out_tsize),
1283 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001284 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001285 " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
1286 VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
1287 VG_(num_scheduling_events_MINOR),
1288 VG_(tt_fast_misses));
sewardjde4a1d02002-03-22 01:27:54 +00001289 VG_(message)(Vg_DebugMsg,
1290 "reg-alloc: %d t-req-spill, "
1291 "%d+%d orig+spill uis, %d total-reg-r.",
1292 VG_(translations_needing_spill),
1293 VG_(uinstrs_prealloc),
1294 VG_(uinstrs_spill),
1295 VG_(total_reg_rank) );
1296 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001297 " sanity: %d cheap, %d expensive checks.",
1298 VG_(sanity_fast_count),
1299 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001300 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001301}
1302
1303
1304/* ---------------------------------------------------------------------
1305 Main!
1306 ------------------------------------------------------------------ */
1307
1308/* Where we jump to once Valgrind has got control, and the real
1309 machine's state has been copied to the m_state_static. */
1310
1311void VG_(main) ( void )
1312{
sewardj2e93c502002-04-12 11:12:52 +00001313 Int i;
1314 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001315 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001316
1317 /* Set up our stack sanity-check words. */
1318 for (i = 0; i < 10; i++) {
1319 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1320 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1321 }
1322
njn25e49d8e72002-09-23 09:36:25 +00001323 /* Setup stuff that depends on the skin. Must be before:
1324 - vg_init_baseBlock(): to register helpers
1325 - process_cmd_line_options(): to register skin name and description,
1326 and turn on/off 'command_line_options' need
1327 - init_memory() (to setup memory event trackers).
1328 */
njnd04b7c62002-10-03 14:05:52 +00001329 SK_(pre_clo_init) ( & VG_(details), & VG_(needs), & VG_(track_events) );
njn25e49d8e72002-09-23 09:36:25 +00001330 sanity_check_needs();
1331
njncc7bb472002-10-14 09:25:19 +00001332 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001333 process_cmd_line_options();
1334
njncc7bb472002-10-14 09:25:19 +00001335 /* Do post command-line processing initialisation */
1336 SK_(post_clo_init)();
1337
1338 /* Set up baseBlock offsets and copy the saved machine's state into it.
1339 Comes after SK_(post_clo_init) in case it registers helpers. */
1340 vg_init_baseBlock();
1341
sewardj64039bb2002-06-03 00:58:18 +00001342 /* Hook to delay things long enough so we can get the pid and
1343 attach GDB in another shell. */
sewardj92a59562002-09-30 00:53:10 +00001344 if (0) {
sewardj64039bb2002-06-03 00:58:18 +00001345 Int p, q;
sewardjc26cc252002-10-23 21:58:55 +00001346 VG_(printf)("pid=%d\n", VG_(getpid)());
sewardj64039bb2002-06-03 00:58:18 +00001347 for (p = 0; p < 50000; p++)
1348 for (q = 0; q < 50000; q++) ;
1349 }
1350
sewardj018f7622002-05-15 21:13:39 +00001351 /* Initialise the scheduler, and copy the client's state from
1352 baseBlock into VG_(threads)[1]. This has to come before signal
1353 initialisations. */
1354 VG_(scheduler_init)();
1355
1356 /* Initialise the signal handling subsystem, temporarily parking
1357 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001358 VG_(sigstartup_actions)();
1359
sewardj018f7622002-05-15 21:13:39 +00001360 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001361 if (VG_(clo_profile))
1362 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001363
sewardj5f07b662002-04-23 16:52:51 +00001364 /* Start calibration of our RDTSC-based clock. */
1365 VG_(start_rdtsc_calibration)();
1366
njn25e49d8e72002-09-23 09:36:25 +00001367 /* Must come after SK_(init) so memory handler accompaniments (eg.
1368 * shadow memory) can be setup ok */
1369 VGP_PUSHCC(VgpInitMem);
1370 VG_(init_memory)();
1371 VGP_POPCC(VgpInitMem);
1372
1373 /* Read the list of errors to suppress. This should be found in
1374 the file specified by vg_clo_suppressions. */
1375 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1376 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001377
sewardj5f07b662002-04-23 16:52:51 +00001378 /* End calibration of our RDTSC-based clock, leaving it as long as
1379 we can. */
1380 VG_(end_rdtsc_calibration)();
1381
njn25e49d8e72002-09-23 09:36:25 +00001382 /* This should come after init_memory_and_symbols(); otherwise the
1383 latter carefully sets up the permissions maps to cover the
1384 anonymous mmaps for the translation table and translation cache,
1385 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001386 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001387
1388 if (VG_(clo_verbosity) == 1) {
1389 VG_(message)(Vg_UserMsg,
1390 "For more details, rerun with: -v");
1391 }
1392
1393 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1394 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001395 if (VG_(clo_verbosity) > 0)
1396 VG_(message)(Vg_UserMsg, "");
1397
1398 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001399
sewardj018f7622002-05-15 21:13:39 +00001400 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001401 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001402 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001403 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001404 VGP_POPCC(VgpSched);
1405 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001406
1407 if (VG_(clo_verbosity) > 0)
1408 VG_(message)(Vg_UserMsg, "");
1409
sewardj2e93c502002-04-12 11:12:52 +00001410 if (src == VgSrc_Deadlock) {
1411 VG_(message)(Vg_UserMsg,
1412 "Warning: pthread scheduler exited due to deadlock");
1413 }
1414
njn25e49d8e72002-09-23 09:36:25 +00001415 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001416 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001417
njn25e49d8e72002-09-23 09:36:25 +00001418 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001419
sewardj0c3b53f2002-05-01 01:58:35 +00001420 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001421
1422 if (VG_(clo_verbosity) > 1)
1423 vg_show_counts();
1424
njn25e49d8e72002-09-23 09:36:25 +00001425 if (VG_(clo_verbosity) > 2)
1426 VG_(print_UInstr_histogram)();
1427
sewardjde4a1d02002-03-22 01:27:54 +00001428 if (0) {
1429 VG_(message)(Vg_DebugMsg, "");
1430 VG_(message)(Vg_DebugMsg,
1431 "------ Valgrind's internal memory use stats follow ------" );
1432 VG_(mallocSanityCheckAll)();
1433 VG_(show_all_arena_stats)();
1434 VG_(message)(Vg_DebugMsg,
1435 "------ Valgrind's ExeContext management stats follow ------" );
1436 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001437 }
1438
njn25e49d8e72002-09-23 09:36:25 +00001439 if (VG_(clo_profile))
1440 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001441
1442 VG_(shutdown_logging)();
1443
sewardj3e1eb1f2002-05-18 13:14:17 +00001444 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1445 processes don't get traced into. Also mess up $libdir/valgrind
1446 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001447 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001448 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1449 VG_(getenv)("LD_PRELOAD"),
1450 VG_(getenv)("LD_LIBRARY_PATH")
1451 );
sewardjde4a1d02002-03-22 01:27:54 +00001452 }
1453
sewardj7e87e382002-05-03 19:09:05 +00001454 /* Decide how to exit. This depends on what the scheduler
1455 returned. */
1456 switch (src) {
1457 case VgSrc_ExitSyscall: /* the normal way out */
1458 vg_assert(VG_(last_run_tid) > 0
1459 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001460 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001461 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001462 /* The thread's %EBX at the time it did __NR_exit() will hold
1463 the arg to __NR_exit(), so we just do __NR_exit() with
1464 that arg. */
1465 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001466 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001467 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001468 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001469
sewardj7e87e382002-05-03 19:09:05 +00001470 case VgSrc_Deadlock:
1471 /* Just exit now. No point in continuing. */
1472 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001473 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001474 break;
1475
1476 case VgSrc_BbsDone:
1477 /* Tricky; we have to try and switch back to the real CPU.
1478 This is all very dodgy and won't work at all in the
1479 presence of threads, or if the client happened to be
1480 running a signal handler. */
1481 /* Prepare to restore state to the real CPU. */
1482 VG_(load_thread_state)(1 /* root thread */ );
1483 VG_(copy_baseBlock_to_m_state_static)();
1484
1485 /* This pushes a return address on the simulator's stack,
1486 which is abandoned. We call vg_sigshutdown_actions() at
1487 the end of vg_switch_to_real_CPU(), so as to ensure that
1488 the original stack and machine state is restored before
1489 the real signal mechanism is restored. */
1490 VG_(switch_to_real_CPU)();
1491
1492 default:
njne427a662002-10-02 11:08:25 +00001493 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001494 }
sewardjde4a1d02002-03-22 01:27:54 +00001495}
1496
1497
1498/* Debugging thing .. can be called from assembly with OYNK macro. */
1499void VG_(oynk) ( Int n )
1500{
1501 OINK(n);
1502}
1503
1504
1505/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1506 "valgrinq.so", which doesn't do anything. This is used to avoid
1507 tracing into child processes. To make this work the build system
1508 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001509
njn25e49d8e72002-09-23 09:36:25 +00001510 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1511 without it, child processes try to find valgrind.so symbols in the
1512 skin .so.
1513
sewardj78e25c92002-05-20 23:38:33 +00001514 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1515 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1516 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001517*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001518void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1519 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001520{
njn25e49d8e72002-09-23 09:36:25 +00001521 Char* p_prel = NULL;
1522 Char* sk_prel = NULL;
1523 Char* p_path = NULL;
1524 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001525 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1526 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001527
sewardj78e25c92002-05-20 23:38:33 +00001528 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1529
1530 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001531 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001532 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1533
njn25e49d8e72002-09-23 09:36:25 +00001534 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001535 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001536 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001537 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1538 goto mutancy;
1539 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1540 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001541 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001542 }
1543
sewardj78e25c92002-05-20 23:38:33 +00001544 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001545 if (sk_prel == NULL) goto mutancy;
1546
1547 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001548 if (p_path == NULL) goto mutancy;
1549
njn25e49d8e72002-09-23 09:36:25 +00001550 what = 4;
1551 {
1552 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1553 Char* p = sk_prel;
1554 while (*p != ':' && p > ld_preload_str) {
1555 *p = ' ';
1556 p--;
1557 }
1558 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1559 while (*p != ':' && *p != '\0') {
1560 *p = ' ';
1561 p++;
1562 }
1563 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1564 *p = ' '; /* blank ending ':' */
1565 }
1566
sewardj78e25c92002-05-20 23:38:33 +00001567 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001568 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001569 if (p_prel[7] != 'd') goto mutancy;
1570 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001571
1572 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1573 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1574 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001575 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001576 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001577 if (p_path[0] != '/') goto mutancy;
1578 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001579 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001580 if (p_path[7] != 'd') goto mutancy;
1581 p_path[7] = 'q';
1582 return;
1583
1584 mutancy:
1585 VG_(printf)(
1586 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1587 " what = %d\n"
1588 " ld_preload_str = `%s'\n"
1589 " ld_library_path_str = `%s'\n"
1590 " p_prel = `%s'\n"
1591 " p_path = `%s'\n"
1592 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001593 what, ld_preload_str, ld_library_path_str,
1594 p_prel, p_path, VG_LIBDIR
1595 );
sewardjc26b4482002-07-13 12:20:35 +00001596 VG_(printf)(
1597 "\n"
1598 "Note that this is often caused by mis-installation of valgrind.\n"
1599 "Correct installation procedure is:\n"
1600 " ./configure --prefix=/install/dir\n"
1601 " make install\n"
1602 "And then use /install/dir/bin/valgrind\n"
1603 "Moving the installation directory elsewhere after 'make install'\n"
1604 "will cause the above error. Hand-editing the paths in the shell\n"
1605 "scripts is also likely to cause problems.\n"
1606 "\n"
1607 );
njne427a662002-10-02 11:08:25 +00001608 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001609}
1610
sewardj3e1eb1f2002-05-18 13:14:17 +00001611
sewardjde4a1d02002-03-22 01:27:54 +00001612/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1613 it to attach to this process. Called if the user requests this
1614 service after an error has been shown, so she can poke around and
1615 look at parameters, memory, etc. You can't meaningfully get GDB to
1616 continue the program, though; to continue, quit GDB. */
1617extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1618{
sewardje6a25242002-04-21 22:03:07 +00001619 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001620 UChar buf[100];
1621 VG_(sprintf)(buf,
1622 "/usr/bin/gdb -nw /proc/%d/exe %d",
1623 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001624 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1625 res = VG_(system)(buf);
1626 if (res == 0) {
1627 VG_(message)(Vg_UserMsg, "");
1628 VG_(message)(Vg_UserMsg,
1629 "GDB has detached. Valgrind regains control. We continue.");
1630 } else {
1631 VG_(message)(Vg_UserMsg, "Apparently failed!");
1632 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001633 }
sewardjde4a1d02002-03-22 01:27:54 +00001634}
1635
1636
1637/* Print some helpful-ish text about unimplemented things, and give
1638 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001639void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001640{
1641 VG_(message)(Vg_UserMsg, "");
1642 VG_(message)(Vg_UserMsg,
1643 "Valgrind detected that your program requires");
1644 VG_(message)(Vg_UserMsg,
1645 "the following unimplemented functionality:");
1646 VG_(message)(Vg_UserMsg, " %s", msg);
1647 VG_(message)(Vg_UserMsg,
1648 "This may be because the functionality is hard to implement,");
1649 VG_(message)(Vg_UserMsg,
1650 "or because no reasonable program would behave this way,");
1651 VG_(message)(Vg_UserMsg,
1652 "or because nobody has yet needed it. In any case, let me know");
1653 VG_(message)(Vg_UserMsg,
1654 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1655 VG_(message)(Vg_UserMsg,
1656 "");
1657 VG_(message)(Vg_UserMsg,
1658 "Valgrind has to exit now. Sorry. Bye!");
1659 VG_(message)(Vg_UserMsg,
1660 "");
sewardj15a43e12002-04-17 19:35:12 +00001661 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001662 VG_(exit)(1);
1663}
1664
1665
njn25e49d8e72002-09-23 09:36:25 +00001666/* ---------------------------------------------------------------------
1667 Sanity check machinery (permanently engaged).
1668 ------------------------------------------------------------------ */
1669
1670/* A fast sanity check -- suitable for calling circa once per
1671 millisecond. */
1672
1673void VG_(do_sanity_checks) ( Bool force_expensive )
1674{
1675 Int i;
1676
njn37cea302002-09-30 11:24:00 +00001677 VGP_PUSHCC(VgpCoreCheapSanity);
1678
njn25e49d8e72002-09-23 09:36:25 +00001679 if (VG_(sanity_level) < 1) return;
1680
1681 /* --- First do all the tests that we can do quickly. ---*/
1682
1683 VG_(sanity_fast_count)++;
1684
1685 /* Check that we haven't overrun our private stack. */
1686 for (i = 0; i < 10; i++) {
1687 vg_assert(VG_(stack)[i]
1688 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1689 vg_assert(VG_(stack)[10000-1-i]
1690 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1691 }
1692
1693 /* Check stuff pertaining to the memory check system. */
1694
1695 /* Check that nobody has spuriously claimed that the first or
1696 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001697 if (VG_(needs).sanity_checks) {
1698 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001699 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001700 VGP_POPCC(VgpSkinCheapSanity);
1701 }
njn25e49d8e72002-09-23 09:36:25 +00001702
1703 /* --- Now some more expensive checks. ---*/
1704
1705 /* Once every 25 times, check some more expensive stuff. */
1706 if ( force_expensive
1707 || VG_(sanity_level) > 1
1708 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1709
njn37cea302002-09-30 11:24:00 +00001710 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001711 VG_(sanity_slow_count)++;
1712
1713# if 0
1714 { void zzzmemscan(void); zzzmemscan(); }
1715# endif
1716
1717 if ((VG_(sanity_fast_count) % 250) == 0)
1718 VG_(sanity_check_tc_tt)();
1719
1720 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001721 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001722 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001723 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001724 }
1725 /*
1726 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1727 */
njn37cea302002-09-30 11:24:00 +00001728 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001729 }
1730
1731 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001732 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001733 /* Check sanity of the low-level memory manager. Note that bugs
1734 in the client's code can cause this to fail, so we don't do
1735 this check unless specially asked for. And because it's
1736 potentially very expensive. */
1737 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001738 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001739 }
njn37cea302002-09-30 11:24:00 +00001740 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001741}
sewardjde4a1d02002-03-22 01:27:54 +00001742/*--------------------------------------------------------------------*/
1743/*--- end vg_main.c ---*/
1744/*--------------------------------------------------------------------*/