blob: a7d9ad965169ba361da0954da8c5407f6f9c57d2 [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;
sewardjfa492d42002-12-08 18:20:01 +000051Int VGOFF_(m_dflag) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000052Int VGOFF_(m_fpustate) = INVALID_OFFSET;
sewardj92a59562002-09-30 00:53:10 +000053Int VGOFF_(ldt) = INVALID_OFFSET;
54Int VGOFF_(m_cs) = INVALID_OFFSET;
55Int VGOFF_(m_ss) = INVALID_OFFSET;
56Int VGOFF_(m_ds) = INVALID_OFFSET;
57Int VGOFF_(m_es) = INVALID_OFFSET;
58Int VGOFF_(m_fs) = INVALID_OFFSET;
59Int VGOFF_(m_gs) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000060Int VGOFF_(m_eip) = INVALID_OFFSET;
61Int VGOFF_(spillslots) = INVALID_OFFSET;
62Int VGOFF_(sh_eax) = INVALID_OFFSET;
63Int VGOFF_(sh_ecx) = INVALID_OFFSET;
64Int VGOFF_(sh_edx) = INVALID_OFFSET;
65Int VGOFF_(sh_ebx) = INVALID_OFFSET;
66Int VGOFF_(sh_esp) = INVALID_OFFSET;
67Int VGOFF_(sh_ebp) = INVALID_OFFSET;
68Int VGOFF_(sh_esi) = INVALID_OFFSET;
69Int VGOFF_(sh_edi) = INVALID_OFFSET;
70Int VGOFF_(sh_eflags) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +000071
sewardjde4a1d02002-03-22 01:27:54 +000072Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
73Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
74Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
75Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
76Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
77Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
78Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
79Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
80Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
81Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
82Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
83Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
84Int VGOFF_(helper_CLD) = INVALID_OFFSET;
85Int VGOFF_(helper_STD) = INVALID_OFFSET;
86Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
sewardj7d78e782002-06-02 00:04:00 +000087Int VGOFF_(helper_CLC) = INVALID_OFFSET;
88Int VGOFF_(helper_STC) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000089Int VGOFF_(helper_shldl) = INVALID_OFFSET;
90Int VGOFF_(helper_shldw) = INVALID_OFFSET;
91Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
92Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
93Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
94Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
95Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000096Int VGOFF_(helper_bsf) = INVALID_OFFSET;
97Int VGOFF_(helper_bsr) = INVALID_OFFSET;
98Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
99Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +0000100Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +0000101Int VGOFF_(helper_DAA) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +0000102Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET;
sewardj51096432002-12-14 23:59:09 +0000103Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +0000104
105/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
106 * increased too much, they won't really be compact any more... */
107#define MAX_COMPACT_HELPERS 8
njnf4ce3d32003-02-10 10:17:26 +0000108#define MAX_NONCOMPACT_HELPERS 24
njn25e49d8e72002-09-23 09:36:25 +0000109
110UInt VG_(n_compact_helpers) = 0;
111UInt VG_(n_noncompact_helpers) = 0;
112
113Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
114Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
115Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
116Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
sewardjde4a1d02002-03-22 01:27:54 +0000117
118/* This is the actual defn of baseblock. */
119UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
120
njn25e49d8e72002-09-23 09:36:25 +0000121
sewardjde4a1d02002-03-22 01:27:54 +0000122/* Words. */
123static Int baB_off = 0;
124
125/* Returns the offset, in words. */
126static Int alloc_BaB ( Int words )
127{
128 Int off = baB_off;
129 baB_off += words;
130 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000131 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000132
133 return off;
134}
135
136/* Allocate 1 word in baseBlock and set it to the given value. */
137static Int alloc_BaB_1_set ( Addr a )
138{
139 Int off = alloc_BaB(1);
140 VG_(baseBlock)[off] = (UInt)a;
141 return off;
142}
143
njn25e49d8e72002-09-23 09:36:25 +0000144/* Registers a function in compact_helper_addrs; compact_helper_offsets is
145 * filled in later.
146 */
147void VG_(register_compact_helper)(Addr a)
148{
149 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
150 VG_(printf)("Can only register %d compact helpers\n",
151 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000152 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000153 }
154 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
155 VG_(n_compact_helpers)++;
156}
157
158/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
159 * is filled in later.
160 */
161void VG_(register_noncompact_helper)(Addr a)
162{
163 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
164 VG_(printf)("Can only register %d non-compact helpers\n",
165 MAX_NONCOMPACT_HELPERS);
166 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000167 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000168 }
169 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
170 VG_(n_noncompact_helpers)++;
171}
172
173/* Allocate offsets in baseBlock for the skin helpers */
174static void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
175{
176 Int i;
177 for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
178}
sewardjde4a1d02002-03-22 01:27:54 +0000179
njnf4ce3d32003-02-10 10:17:26 +0000180/* Will we need to call VG_(handle_esp_assignment)() ? */
181Bool VG_(need_to_handle_esp_assignment)(void)
182{
183 return (VG_(track_events).new_mem_stack ||
184 VG_(track_events).new_mem_stack_aligned ||
185 VG_(track_events).die_mem_stack ||
186 VG_(track_events).die_mem_stack_aligned);
187}
188
sewardjde4a1d02002-03-22 01:27:54 +0000189/* Here we assign actual offsets. It's important to get the most
190 popular referents within 128 bytes of the start, so we can take
191 advantage of short addressing modes relative to %ebp. Popularity
192 of offsets was measured on 22 Feb 02 running a KDE application, and
193 the slots rearranged accordingly, with a 1.5% reduction in total
194 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000195static void vg_init_baseBlock ( void )
196{
sewardjde4a1d02002-03-22 01:27:54 +0000197 /* Those with offsets under 128 are carefully chosen. */
198
199 /* WORD offsets in this column */
200 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
201 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
202 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
203 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
204 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
205 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
206 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
207 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
208 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
209
njn25e49d8e72002-09-23 09:36:25 +0000210 if (VG_(needs).shadow_regs) {
211 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
212 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
213 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
214 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
215 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
216 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
217 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
218 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
219 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
220 }
sewardjde4a1d02002-03-22 01:27:54 +0000221
njn25e49d8e72002-09-23 09:36:25 +0000222 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
223 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000224
njn25e49d8e72002-09-23 09:36:25 +0000225 /* (9 or 18) + n_compact_helpers */
226 /* Register VG_(handle_esp_assignment) if needed. */
njnf4ce3d32003-02-10 10:17:26 +0000227 if (VG_(need_to_handle_esp_assignment)())
njn25e49d8e72002-09-23 09:36:25 +0000228 VG_(register_compact_helper)( (Addr) & VG_(handle_esp_assignment) );
sewardjde4a1d02002-03-22 01:27:54 +0000229
njn25e49d8e72002-09-23 09:36:25 +0000230 /* Allocate slots for compact helpers */
231 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
232 VG_(compact_helper_offsets),
233 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000234
njn25e49d8e72002-09-23 09:36:25 +0000235 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000236 VGOFF_(m_eip) = alloc_BaB(1);
237
238 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000239 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
240 * boundary at >= 32 words, but most spills are to low numbered spill
241 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000242 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
243
njn25e49d8e72002-09-23 09:36:25 +0000244 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000245 short-amode-boundary, there's no point. */
246
sewardjfa492d42002-12-08 18:20:01 +0000247 VGOFF_(m_dflag) = alloc_BaB(1);
248
sewardjde4a1d02002-03-22 01:27:54 +0000249 VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
250
sewardj92a59562002-09-30 00:53:10 +0000251 /* This thread's LDT pointer, and segment registers. */
252 VGOFF_(ldt) = alloc_BaB(1);
253 VGOFF_(m_cs) = alloc_BaB(1);
254 VGOFF_(m_ss) = alloc_BaB(1);
255 VGOFF_(m_ds) = alloc_BaB(1);
256 VGOFF_(m_es) = alloc_BaB(1);
257 VGOFF_(m_fs) = alloc_BaB(1);
258 VGOFF_(m_gs) = alloc_BaB(1);
259
sewardje1042472002-09-30 12:33:11 +0000260 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
261
sewardj92a59562002-09-30 00:53:10 +0000262 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000263 VGOFF_(helper_idiv_64_32)
264 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
265 VGOFF_(helper_div_64_32)
266 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
267 VGOFF_(helper_idiv_32_16)
268 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
269 VGOFF_(helper_div_32_16)
270 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
271 VGOFF_(helper_idiv_16_8)
272 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
273 VGOFF_(helper_div_16_8)
274 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
275
276 VGOFF_(helper_imul_32_64)
277 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
278 VGOFF_(helper_mul_32_64)
279 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
280 VGOFF_(helper_imul_16_32)
281 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
282 VGOFF_(helper_mul_16_32)
283 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
284 VGOFF_(helper_imul_8_16)
285 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
286 VGOFF_(helper_mul_8_16)
287 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
288
289 VGOFF_(helper_CLD)
290 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
291 VGOFF_(helper_STD)
292 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
293 VGOFF_(helper_get_dirflag)
294 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
295
sewardj7d78e782002-06-02 00:04:00 +0000296 VGOFF_(helper_CLC)
297 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000298 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000299 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
300
sewardjde4a1d02002-03-22 01:27:54 +0000301 VGOFF_(helper_shldl)
302 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
303 VGOFF_(helper_shldw)
304 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
305 VGOFF_(helper_shrdl)
306 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
307 VGOFF_(helper_shrdw)
308 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
309
310 VGOFF_(helper_RDTSC)
311 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
312 VGOFF_(helper_CPUID)
313 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
314
sewardjde4a1d02002-03-22 01:27:54 +0000315 VGOFF_(helper_bsf)
316 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
317 VGOFF_(helper_bsr)
318 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
319
320 VGOFF_(helper_fstsw_AX)
321 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
322 VGOFF_(helper_SAHF)
323 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000324 VGOFF_(helper_DAS)
325 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000326 VGOFF_(helper_DAA)
327 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000328
sewardj51096432002-12-14 23:59:09 +0000329 VGOFF_(helper_undefined_instruction)
330 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
331
sewardj92a59562002-09-30 00:53:10 +0000332 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000333 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
334 VG_(noncompact_helper_offsets),
335 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000336
njncc7bb472002-10-14 09:25:19 +0000337
338 /* Initialise slots that require it */
339 VG_(copy_m_state_static_to_baseBlock)();
340
341 /* Pretend the root thread has a completely empty LDT to start with. */
342 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
343
344 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000345 if (VG_(needs).shadow_regs) {
346 UInt eflags;
347
348 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
349 VG_(baseBlock)[VGOFF_(sh_esp)] =
350 VG_(baseBlock)[VGOFF_(sh_ebp)] =
351 VG_(baseBlock)[VGOFF_(sh_eax)] =
352 VG_(baseBlock)[VGOFF_(sh_ecx)] =
353 VG_(baseBlock)[VGOFF_(sh_edx)] =
354 VG_(baseBlock)[VGOFF_(sh_ebx)] =
355 VG_(baseBlock)[VGOFF_(sh_esi)] =
356 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
357 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
358
njncc7bb472002-10-14 09:25:19 +0000359 } else {
njn25e49d8e72002-09-23 09:36:25 +0000360 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000361 }
sewardjde4a1d02002-03-22 01:27:54 +0000362}
363
364
365/* ---------------------------------------------------------------------
366 Global entities which are not referenced from generated code.
367 ------------------------------------------------------------------ */
368
369/* The stack on which Valgrind runs. We can't use the same stack as
370 the simulatee -- that's an important design decision. */
371UInt VG_(stack)[10000];
372
373/* Ditto our signal delivery stack. */
374UInt VG_(sigstack)[10000];
375
376/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000377UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
378Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000379
380/* Counts downwards in vg_run_innerloop. */
381UInt VG_(dispatch_ctr);
382
sewardjde4a1d02002-03-22 01:27:54 +0000383
384/* 64-bit counter for the number of basic blocks done. */
385ULong VG_(bbs_done);
386/* 64-bit counter for the number of bbs to go before a debug exit. */
387ULong VG_(bbs_to_go);
388
sewardj7e87e382002-05-03 19:09:05 +0000389/* This is the ThreadId of the last thread the scheduler ran. */
390ThreadId VG_(last_run_tid) = 0;
391
njn25e49d8e72002-09-23 09:36:25 +0000392/* This is the argument to __NR_exit() supplied by the first thread to
393 call that syscall. We eventually pass that to __NR_exit() for
394 real. */
395UInt VG_(exitcode) = 0;
396
sewardj73cf3bc2002-11-03 03:20:15 +0000397/* Tell the logging mechanism whether we are logging to a file
398 descriptor or a socket descriptor. */
399Bool VG_(logging_to_filedes) = True;
400
sewardjde4a1d02002-03-22 01:27:54 +0000401
402/* ---------------------------------------------------------------------
403 Counters, for informational purposes only.
404 ------------------------------------------------------------------ */
405
406/* Number of lookups which miss the fast tt helper. */
407UInt VG_(tt_fast_misses) = 0;
408
409
sewardjc0d8f682002-11-30 00:49:43 +0000410/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000411
sewardjde4a1d02002-03-22 01:27:54 +0000412/* Number and total o/t size of translations overall. */
413UInt VG_(overall_in_count) = 0;
414UInt VG_(overall_in_osize) = 0;
415UInt VG_(overall_in_tsize) = 0;
416/* Number and total o/t size of discards overall. */
417UInt VG_(overall_out_count) = 0;
418UInt VG_(overall_out_osize) = 0;
419UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000420/* The number of discards of TT/TC. */
421UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000422/* Counts of chain and unchain operations done. */
423UInt VG_(bb_enchain_count) = 0;
424UInt VG_(bb_dechain_count) = 0;
425/* Number of unchained jumps performed. */
426UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000427
428
429/* Counts pertaining to the register allocator. */
430
431/* total number of uinstrs input to reg-alloc */
432UInt VG_(uinstrs_prealloc) = 0;
433
434/* total number of uinstrs added due to spill code */
435UInt VG_(uinstrs_spill) = 0;
436
437/* number of bbs requiring spill code */
438UInt VG_(translations_needing_spill) = 0;
439
440/* total of register ranks over all translations */
441UInt VG_(total_reg_rank) = 0;
442
443
sewardjde4a1d02002-03-22 01:27:54 +0000444/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000445UInt VG_(sanity_fast_count) = 0;
446UInt VG_(sanity_slow_count) = 0;
447
sewardj2e93c502002-04-12 11:12:52 +0000448/* Counts pertaining to the scheduler. */
449UInt VG_(num_scheduling_events_MINOR) = 0;
450UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000451
452
453/* ---------------------------------------------------------------------
454 Values derived from command-line options.
455 ------------------------------------------------------------------ */
456
njn25e49d8e72002-09-23 09:36:25 +0000457/* Define, and set defaults. */
458Bool VG_(clo_error_limit) = True;
459Bool VG_(clo_GDB_attach) = False;
460Int VG_(sanity_level) = 1;
461Int VG_(clo_verbosity) = 1;
462Bool VG_(clo_demangle) = True;
463Bool VG_(clo_sloppy_malloc) = False;
464Int VG_(clo_alignment) = 4;
465Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000466
467/* See big comment in vg_include.h for meaning of these three. */
468VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
469Int VG_(clo_logfile_fd) = 2;
470Char* VG_(clo_logfile_name) = NULL;
471
njn25e49d8e72002-09-23 09:36:25 +0000472Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000473Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000474Bool VG_(clo_profile) = False;
475Bool VG_(clo_single_step) = False;
476Bool VG_(clo_optimise) = True;
477UChar VG_(clo_trace_codegen) = 0; // 00000000b
478Bool VG_(clo_trace_syscalls) = False;
479Bool VG_(clo_trace_signals) = False;
480Bool VG_(clo_trace_symtab) = False;
481Bool VG_(clo_trace_malloc) = False;
482Bool VG_(clo_trace_sched) = False;
483Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000484ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000485Int VG_(clo_dump_error) = 0;
486Int VG_(clo_backtrace_size) = 4;
487Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000488Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000489Bool VG_(clo_chain_bb) = True;
sewardj2370f3b2002-11-30 15:01:01 +0000490
sewardjde4a1d02002-03-22 01:27:54 +0000491
492/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
493 to behave. Initially we say False. */
494Bool VG_(running_on_simd_CPU) = False;
495
496/* Holds client's %esp at the point we gained control. */
497Addr VG_(esp_at_startup);
498
499/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
500 envp[] as extracted from the client's stack at startup-time. */
501Int VG_(client_argc);
502Char** VG_(client_argv);
503Char** VG_(client_envp);
504
505/* A place into which to copy the value of env var VG_ARGS, so we
506 don't have to modify the original. */
507static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
508
sewardjde4a1d02002-03-22 01:27:54 +0000509/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000510 Processing of command-line options.
511 ------------------------------------------------------------------ */
512
njn25e49d8e72002-09-23 09:36:25 +0000513void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000514{
515 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000516 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000517 VG_(clo_logfile_fd) = 2; /* stderr */
518 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
519 VG_(exit)(1);
520}
521
522static void config_error ( Char* msg )
523{
524 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000525 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000526 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000527 VG_(printf)(
528 "valgrind.so: Startup or configuration error:\n %s\n", msg);
529 VG_(printf)(
530 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000531 VG_(exit)(1);
532}
533
sewardja1679dd2002-05-10 22:31:40 +0000534static void args_grok_error ( Char* msg )
535{
536 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000537 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000538 VG_(clo_logfile_fd) = 2; /* stderr */
539 VG_(printf)("valgrind.so: When searching for "
540 "client's argc/argc/envp:\n\t%s\n", msg);
541 config_error("couldn't find client's argc/argc/envp");
542}
543
njn25e49d8e72002-09-23 09:36:25 +0000544static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000545{
njn25e49d8e72002-09-23 09:36:25 +0000546 Char* usage1 =
547"usage: valgrind [options] prog-and-args\n"
548"\n"
549" core user options, with defaults in [ ], are:\n"
550" --help show this message\n"
551" --version show version\n"
552" --skin=<name> main task (skin to use) [Valgrind]\n"
553" -q --quiet run silently; only print error msgs\n"
554" -v --verbose be more verbose, incl counts of errors\n"
555" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
556" --demangle=no|yes automatically demangle C++ names? [yes]\n"
557" --num-callers=<number> show <num> callers in stack traces [4]\n"
558" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
559" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
560" --alignment=<number> set minimum alignment of allocations [4]\n"
561" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000562" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000563" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000564" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000565" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000566" --suppressions=<filename> suppress errors described in\n"
567" suppressions file <filename>\n"
568" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000569" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000570"\n"
571" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000572
njn7cf0bd32002-06-08 13:36:03 +0000573
njn25e49d8e72002-09-23 09:36:25 +0000574 Char* usage2 =
575"\n"
576" core options for debugging Valgrind itself are:\n"
577" --sanity-level=<number> level of sanity checking to do [1]\n"
578" --single-step=no|yes translate each instr separately? [no]\n"
579" --optimise=no|yes improve intermediate code? [yes]\n"
580" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000581" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000582" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
583" --trace-syscalls=no|yes show all system calls? [no]\n"
584" --trace-signals=no|yes show signal handling details? [no]\n"
585" --trace-symtab=no|yes show symbol table details? [no]\n"
586" --trace-malloc=no|yes show client malloc details? [no]\n"
587" --trace-sched=no|yes show thread scheduler details? [no]\n"
588" --trace-pthread=none|some|all show pthread event details? [no]\n"
589" --stop-after=<number> switch to real CPU after executing\n"
590" <number> basic blocks [infinity]\n"
591" --dump-error=<number> show translation for basic block\n"
592" associated with <number>'th\n"
593" error context [0=don't show any]\n"
594"\n"
595" Extra options are read from env variable $VALGRIND_OPTS\n"
596"\n"
597" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
598" and licensed under the GNU General Public License, version 2.\n"
599" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000600"\n"
601" Skins are copyright and licensed by their authors. See each\n"
602" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000603"\n";
njn7cf0bd32002-06-08 13:36:03 +0000604
njnd04b7c62002-10-03 14:05:52 +0000605 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000606 /* Don't print skin string directly for security, ha! */
607 if (VG_(needs).command_line_options)
608 VG_(printf)("%s", SK_(usage)());
609 else
610 VG_(printf)(" (none)\n");
611 VG_(printf)(usage2, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000612
njn25e49d8e72002-09-23 09:36:25 +0000613 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000614 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000615 VG_(clo_logfile_fd) = 2; /* stderr */
616 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000617}
sewardjde4a1d02002-03-22 01:27:54 +0000618
619static void process_cmd_line_options ( void )
620{
njn25e49d8e72002-09-23 09:36:25 +0000621 Char* argv[M_VG_CMDLINE_OPTS];
622 UInt argc;
623 Char* p;
624 Char* str;
625 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000626
627# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
628# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
629# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
630
sewardjde4a1d02002-03-22 01:27:54 +0000631 eventually_logfile_fd = VG_(clo_logfile_fd);
632
633 /* Once logging is started, we can safely send messages pertaining
634 to failures in initialisation. */
635 VG_(startup_logging)();
636
sewardj19d81412002-06-03 01:10:40 +0000637 /* Check for sane path in ./configure --prefix=... */
638 if (VG_(strlen)(VG_LIBDIR) < 1
639 || VG_LIBDIR[0] != '/')
640 config_error("Please use absolute paths in "
641 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000642
sewardja1679dd2002-05-10 22:31:40 +0000643 /* (Suggested by Fabrice Bellard ... )
644 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000645 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000646 change less often than the libc ones. */
647 {
sewardja1679dd2002-05-10 22:31:40 +0000648 UInt* sp = 0; /* bogus init to keep gcc -O happy */
649
sewardj38170912002-05-10 21:07:22 +0000650 /* locate the top of the stack */
sewardja1679dd2002-05-10 22:31:40 +0000651 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
652 VG_STARTUP_STACK_BASE_1 )) {
653 sp = (UInt*)VG_STARTUP_STACK_BASE_1;
654 } else
655 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
656 VG_STARTUP_STACK_BASE_2 )) {
657 sp = (UInt*)VG_STARTUP_STACK_BASE_2;
daywalkera2562202002-07-15 19:39:51 +0000658 } else
659 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
660 VG_STARTUP_STACK_BASE_3 )) {
661 sp = (UInt*)VG_STARTUP_STACK_BASE_3;
njn25e49d8e72002-09-23 09:36:25 +0000662 } else
663 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
664 VG_STARTUP_STACK_BASE_4 )) {
665 sp = (UInt*)VG_STARTUP_STACK_BASE_4;
sewardja1679dd2002-05-10 22:31:40 +0000666 } else {
667 args_grok_error(
668 "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
669 "constants defined in vg_include.h. You should investigate."
670 );
671 }
672
sewardj38170912002-05-10 21:07:22 +0000673 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
674 the elf interpreter table */
675 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000676 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000677 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000678 sp--;
679 }
sewardj38170912002-05-10 21:07:22 +0000680
681 if (sp[2] == VKI_AT_BASE
682 && sp[0] == VKI_AT_PAGESZ
683 && sp[-2] == VKI_AT_PHNUM
684 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000685 && sp[-6] == VKI_AT_PHDR
686 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000687 if (0)
688 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000689 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000690 } else
691 if (sp[2] == VKI_AT_CLKTCK
692 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000693 && sp[-2] == VKI_AT_HWCAP
694 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000695 if (0)
696 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
697 sp -= 2;
698 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000699 if (sp[2] == VKI_AT_CLKTCK
700 && sp[0] == VKI_AT_PAGESZ
701 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000702 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
703 && sp[-4-1] == 0) {
704 if (0)
705 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
706 "kernel here.\n");
707 sp -= 4;
708 } else
709 if (sp[2] == VKI_AT_CLKTCK
710 && sp[0] == VKI_AT_PAGESZ
711 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000712 && sp[-2-20-1] == 0) {
713 if (0)
714 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
715 sp -= 22;
716 } else
sewardja1679dd2002-05-10 22:31:40 +0000717 args_grok_error(
718 "ELF frame does not look like 2.2.X or 2.4.X.\n "
719 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
720 );
sewardj38170912002-05-10 21:07:22 +0000721
722 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000723 if (*sp != 0)
724 args_grok_error("can't find NULL at end of env[]");
725
sewardj38170912002-05-10 21:07:22 +0000726 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000727 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000728 while (True) {
729 sp --;
730 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000731 if (++ctr >= 1000)
732 args_grok_error(
733 "suspiciously many (1000) env[] entries; giving up");
734
sewardj38170912002-05-10 21:07:22 +0000735 }
736 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000737 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000738
sewardja1679dd2002-05-10 22:31:40 +0000739 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000740 VG_(client_argc) = 0;
741 while (True) {
742 sp--;
743 if (*sp == VG_(client_argc))
744 break;
745 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000746 if (++ctr >= 1000)
747 args_grok_error(
748 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000749 }
750
sewardja1679dd2002-05-10 22:31:40 +0000751 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000752 }
753
sewardjde4a1d02002-03-22 01:27:54 +0000754 /* Now that VG_(client_envp) has been set, we can extract the args
755 for Valgrind itself. Copy into global var so that we don't have to
756 write zeroes to the getenv'd value itself. */
757 str = VG_(getenv)("VG_ARGS");
758 argc = 0;
759
760 if (!str) {
761 config_error("Can't read options from env var VG_ARGS.");
762 }
763
764 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
765 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
766 }
767 VG_(strcpy)(vg_cmdline_copy, str);
768 str = NULL;
769
770 p = &vg_cmdline_copy[0];
771 while (True) {
772 while (ISSPACE(*p)) { *p = 0; p++; }
773 if (*p == 0) break;
774 if (argc < M_VG_CMDLINE_OPTS-1) {
775 argv[argc] = p; argc++;
776 } else {
777 config_error(
778 "Found more than M_CMDLINE_OPTS command-line opts.");
779 }
780 while (*p != 0 && !ISSPACE(*p)) p++;
781 }
782
783 for (i = 0; i < argc; i++) {
784
njn25e49d8e72002-09-23 09:36:25 +0000785 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000786 VG_(clo_verbosity)++;
787 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
788 VG_(clo_verbosity)--;
789
sewardj2e432902002-06-13 20:44:00 +0000790 else if (STREQ(argv[i], "--error-limit=yes"))
791 VG_(clo_error_limit) = True;
792 else if (STREQ(argv[i], "--error-limit=no"))
793 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000794
sewardjde4a1d02002-03-22 01:27:54 +0000795 else if (STREQ(argv[i], "--gdb-attach=yes"))
796 VG_(clo_GDB_attach) = True;
797 else if (STREQ(argv[i], "--gdb-attach=no"))
798 VG_(clo_GDB_attach) = False;
799
800 else if (STREQ(argv[i], "--demangle=yes"))
801 VG_(clo_demangle) = True;
802 else if (STREQ(argv[i], "--demangle=no"))
803 VG_(clo_demangle) = False;
804
sewardjde4a1d02002-03-22 01:27:54 +0000805 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
806 VG_(clo_sloppy_malloc) = True;
807 else if (STREQ(argv[i], "--sloppy-malloc=no"))
808 VG_(clo_sloppy_malloc) = False;
809
sewardj246d4662002-06-14 10:17:05 +0000810 else if (STREQN(12, argv[i], "--alignment="))
811 VG_(clo_alignment) = (Int)VG_(atoll)(&argv[i][12]);
812
sewardjde4a1d02002-03-22 01:27:54 +0000813 else if (STREQ(argv[i], "--trace-children=yes"))
814 VG_(clo_trace_children) = True;
815 else if (STREQ(argv[i], "--trace-children=no"))
816 VG_(clo_trace_children) = False;
817
sewardj858964b2002-10-05 14:15:43 +0000818 else if (STREQ(argv[i], "--run-libc-freeres=yes"))
819 VG_(clo_run_libc_freeres) = True;
820 else if (STREQ(argv[i], "--run-libc-freeres=no"))
821 VG_(clo_run_libc_freeres) = False;
822
sewardjde4a1d02002-03-22 01:27:54 +0000823 else if (STREQN(15, argv[i], "--sanity-level="))
824 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
825
sewardj4cf05692002-10-27 20:28:29 +0000826 else if (STREQN(13, argv[i], "--logfile-fd=")) {
827 VG_(clo_log_to) = VgLogTo_Fd;
828 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000829 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000830 }
831
832 else if (STREQN(10, argv[i], "--logfile=")) {
833 VG_(clo_log_to) = VgLogTo_File;
834 VG_(clo_logfile_name) = &argv[i][10];
835 }
sewardjde4a1d02002-03-22 01:27:54 +0000836
sewardj73cf3bc2002-11-03 03:20:15 +0000837 else if (STREQN(12, argv[i], "--logsocket=")) {
838 VG_(clo_log_to) = VgLogTo_Socket;
839 VG_(clo_logfile_name) = &argv[i][12];
840 }
841
sewardjde4a1d02002-03-22 01:27:54 +0000842 else if (STREQN(15, argv[i], "--suppressions=")) {
843 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000844 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000845 VG_(message)(Vg_UserMsg,
846 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000847 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000848 }
849 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
850 VG_(clo_n_suppressions)++;
851 }
njn25e49d8e72002-09-23 09:36:25 +0000852 else if (STREQ(argv[i], "--profile=yes"))
853 VG_(clo_profile) = True;
854 else if (STREQ(argv[i], "--profile=no"))
855 VG_(clo_profile) = False;
856
sewardj22854b92002-11-30 14:00:47 +0000857 else if (STREQ(argv[i], "--chain-bb=yes"))
858 VG_(clo_chain_bb) = True;
859 else if (STREQ(argv[i], "--chain-bb=no"))
860 VG_(clo_chain_bb) = False;
861
sewardjde4a1d02002-03-22 01:27:54 +0000862 else if (STREQ(argv[i], "--single-step=yes"))
863 VG_(clo_single_step) = True;
864 else if (STREQ(argv[i], "--single-step=no"))
865 VG_(clo_single_step) = False;
866
867 else if (STREQ(argv[i], "--optimise=yes"))
868 VG_(clo_optimise) = True;
869 else if (STREQ(argv[i], "--optimise=no"))
870 VG_(clo_optimise) = False;
871
njn25e49d8e72002-09-23 09:36:25 +0000872 /* "vwxyz" --> 000zyxwv (binary) */
873 else if (STREQN(16, argv[i], "--trace-codegen=")) {
874 Int j;
875 char* opt = & argv[i][16];
876
877 if (5 != VG_(strlen)(opt)) {
878 VG_(message)(Vg_UserMsg,
879 "--trace-codegen argument must have 5 digits");
880 VG_(bad_option)(argv[i]);
881 }
882 for (j = 0; j < 5; j++) {
883 if ('0' == opt[j]) { /* do nothing */ }
884 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
885 else {
886 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
887 "contain 0s and 1s");
888 VG_(bad_option)(argv[i]);
889 }
890 }
891 }
sewardjde4a1d02002-03-22 01:27:54 +0000892
893 else if (STREQ(argv[i], "--trace-syscalls=yes"))
894 VG_(clo_trace_syscalls) = True;
895 else if (STREQ(argv[i], "--trace-syscalls=no"))
896 VG_(clo_trace_syscalls) = False;
897
898 else if (STREQ(argv[i], "--trace-signals=yes"))
899 VG_(clo_trace_signals) = True;
900 else if (STREQ(argv[i], "--trace-signals=no"))
901 VG_(clo_trace_signals) = False;
902
903 else if (STREQ(argv[i], "--trace-symtab=yes"))
904 VG_(clo_trace_symtab) = True;
905 else if (STREQ(argv[i], "--trace-symtab=no"))
906 VG_(clo_trace_symtab) = False;
907
908 else if (STREQ(argv[i], "--trace-malloc=yes"))
909 VG_(clo_trace_malloc) = True;
910 else if (STREQ(argv[i], "--trace-malloc=no"))
911 VG_(clo_trace_malloc) = False;
912
sewardj8937c812002-04-12 20:12:20 +0000913 else if (STREQ(argv[i], "--trace-sched=yes"))
914 VG_(clo_trace_sched) = True;
915 else if (STREQ(argv[i], "--trace-sched=no"))
916 VG_(clo_trace_sched) = False;
917
sewardj45b4b372002-04-16 22:50:32 +0000918 else if (STREQ(argv[i], "--trace-pthread=none"))
919 VG_(clo_trace_pthread_level) = 0;
920 else if (STREQ(argv[i], "--trace-pthread=some"))
921 VG_(clo_trace_pthread_level) = 1;
922 else if (STREQ(argv[i], "--trace-pthread=all"))
923 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000924
sewardj8d365b52002-05-12 10:52:16 +0000925 else if (STREQN(14, argv[i], "--weird-hacks="))
926 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000927
sewardjde4a1d02002-03-22 01:27:54 +0000928 else if (STREQN(13, argv[i], "--stop-after="))
929 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
930
931 else if (STREQN(13, argv[i], "--dump-error="))
932 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
933
934 else if (STREQN(14, argv[i], "--num-callers=")) {
935 /* Make sure it's sane. */
936 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
937 if (VG_(clo_backtrace_size) < 2)
938 VG_(clo_backtrace_size) = 2;
939 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
940 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
941 }
942
njn25e49d8e72002-09-23 09:36:25 +0000943 else if (VG_(needs).command_line_options) {
944 Bool ok = SK_(process_cmd_line_option)(argv[i]);
945 if (!ok)
946 usage();
947 }
sewardjde4a1d02002-03-22 01:27:54 +0000948 else
njn25e49d8e72002-09-23 09:36:25 +0000949 usage();
sewardjde4a1d02002-03-22 01:27:54 +0000950 }
951
952# undef ISSPACE
953# undef STREQ
954# undef STREQN
955
956 if (VG_(clo_verbosity < 0))
957 VG_(clo_verbosity) = 0;
958
sewardj246d4662002-06-14 10:17:05 +0000959 if (VG_(clo_alignment) < 4
960 || VG_(clo_alignment) > 4096
961 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
962 VG_(message)(Vg_UserMsg, "");
963 VG_(message)(Vg_UserMsg,
964 "Invalid --alignment= setting. "
965 "Should be a power of 2, >= 4, <= 4096.");
njn25e49d8e72002-09-23 09:36:25 +0000966 VG_(bad_option)("--alignment");
sewardj246d4662002-06-14 10:17:05 +0000967 }
968
sewardjde4a1d02002-03-22 01:27:54 +0000969 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
970 VG_(message)(Vg_UserMsg, "");
971 VG_(message)(Vg_UserMsg,
972 "--gdb-attach=yes conflicts with --trace-children=yes");
973 VG_(message)(Vg_UserMsg,
974 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +0000975 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +0000976 }
977
sewardj4cf05692002-10-27 20:28:29 +0000978 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
979 should be connected to whatever sink has been selected, and we
980 indiscriminately chuck stuff into it without worrying what the
981 nature of it is. Oh the wonder of Unix streams. */
982
983 /* So far we should be still attached to stderr, so we can show on
984 the terminal any problems to do with processing command line
985 opts. */
986 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +0000987 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +0000988
989 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +0000990
sewardj4cf05692002-10-27 20:28:29 +0000991 case VgLogTo_Fd:
992 vg_assert(VG_(clo_logfile_name) == NULL);
993 VG_(clo_logfile_fd) = eventually_logfile_fd;
994 break;
sewardj73cf3bc2002-11-03 03:20:15 +0000995
sewardj4cf05692002-10-27 20:28:29 +0000996 case VgLogTo_File: {
997 Char logfilename[1000];
998 vg_assert(VG_(clo_logfile_name) != NULL);
999 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1000 VG_(sprintf)(logfilename, "%s.pid%d",
1001 VG_(clo_logfile_name), VG_(getpid)() );
1002 eventually_logfile_fd
1003 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1004 VKI_S_IRUSR|VKI_S_IWUSR);
1005 if (eventually_logfile_fd != -1) {
1006 VG_(clo_logfile_fd) = eventually_logfile_fd;
1007 } else {
1008 VG_(message)(Vg_UserMsg,
1009 "Can't create/open log file `%s.pid%d'; giving up!",
1010 VG_(clo_logfile_name), VG_(getpid)());
1011 VG_(bad_option)(
1012 "--logfile=<file> didn't work out for some reason.");
1013 }
1014 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001015 }
1016
1017 case VgLogTo_Socket: {
1018 vg_assert(VG_(clo_logfile_name) != NULL);
1019 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1020 eventually_logfile_fd
1021 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1022 if (eventually_logfile_fd == -1) {
1023 VG_(message)(Vg_UserMsg,
1024 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1025 VG_(message)(Vg_UserMsg,
1026 "of `%s'; giving up!", VG_(clo_logfile_name) );
1027 VG_(bad_option)(
1028 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001029 }
sewardj73cf3bc2002-11-03 03:20:15 +00001030 if (eventually_logfile_fd == -2) {
1031 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001032 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001033 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001034 VG_(message)(Vg_UserMsg,
1035 "Log messages will sent to stderr instead." );
1036 VG_(message)(Vg_UserMsg,
1037 "" );
1038 /* We don't change anything here. */
1039 } else {
1040 vg_assert(eventually_logfile_fd > 0);
1041 VG_(clo_logfile_fd) = eventually_logfile_fd;
1042 VG_(logging_to_filedes) = False;
1043 }
sewardj73cf3bc2002-11-03 03:20:15 +00001044 break;
1045 }
1046
sewardj4cf05692002-10-27 20:28:29 +00001047 }
1048
1049 /* Ok, the logging sink is running now. Print a suitable preamble.
1050 If logging to file or a socket, write details of parent PID and
1051 command line args, to help people trying to interpret the
1052 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001053
sewardj83adf412002-05-01 01:25:45 +00001054 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001055 /* Skin details */
1056 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1057 VG_(details).name,
1058 NULL == VG_(details).version ? "" : "-",
1059 NULL == VG_(details).version
1060 ? (Char*)"" : VG_(details).version,
1061 VG_(details).description);
1062 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001063
njnd04b7c62002-10-03 14:05:52 +00001064 /* Core details */
1065 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001066 "Using valgrind-%s, a program instrumentation system for x86-linux.",
1067 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001068 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001069 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001070 }
1071
sewardj4cf05692002-10-27 20:28:29 +00001072 if (VG_(clo_log_to) != VgLogTo_Fd) {
1073 VG_(message)(Vg_UserMsg, "");
1074 VG_(message)(Vg_UserMsg,
1075 "My PID = %d, parent PID = %d. Prog and args are:",
1076 VG_(getpid)(), VG_(getppid)() );
1077 for (i = 0; i < VG_(client_argc); i++)
1078 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1079 }
1080
sewardjde4a1d02002-03-22 01:27:54 +00001081 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001082 if (VG_(clo_log_to) != VgLogTo_Fd)
1083 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001084 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1085 for (i = 0; i < argc; i++) {
1086 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1087 }
1088 }
1089
njn25e49d8e72002-09-23 09:36:25 +00001090 if (VG_(clo_n_suppressions) == 0 &&
1091 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001092 config_error("No error-suppression files were specified.");
1093 }
sewardj4cf05692002-10-27 20:28:29 +00001094
sewardjde4a1d02002-03-22 01:27:54 +00001095}
1096
sewardjde4a1d02002-03-22 01:27:54 +00001097/* ---------------------------------------------------------------------
1098 Copying to/from m_state_static.
1099 ------------------------------------------------------------------ */
1100
sewardj92a59562002-09-30 00:53:10 +00001101UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1102 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001103 + 1 /* %eflags */
1104 + 1 /* %eip */
1105 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1106 ];
1107
sewardjfa492d42002-12-08 18:20:01 +00001108UInt VG_(insertDflag)(UInt eflags, Int d)
1109{
1110 vg_assert(d == 1 || d == -1);
1111 eflags &= ~EFlagD;
1112
1113 if (d < 0)
1114 eflags |= EFlagD;
1115
1116 return eflags;
1117}
1118
1119Int VG_(extractDflag)(UInt eflags)
1120{
1121 Int ret;
1122
1123 if (eflags & EFlagD)
1124 ret = -1;
1125 else
1126 ret = 1;
1127
1128 return ret;
1129}
1130
sewardjde4a1d02002-03-22 01:27:54 +00001131void VG_(copy_baseBlock_to_m_state_static) ( void )
1132{
1133 Int i;
sewardj92a59562002-09-30 00:53:10 +00001134 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1135 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1136 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1137 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1138 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1139 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001140
sewardj92a59562002-09-30 00:53:10 +00001141 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1142 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1143 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1144 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1145 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1146 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1147 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1148 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1149
sewardjfa492d42002-12-08 18:20:01 +00001150 VG_(m_state_static)[56/4] = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1151 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001152 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001153
1154 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001155 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001156 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1157}
1158
1159
1160void VG_(copy_m_state_static_to_baseBlock) ( void )
1161{
1162 Int i;
sewardj92a59562002-09-30 00:53:10 +00001163 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1164 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1165 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1166 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1167 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1168 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001169
sewardj92a59562002-09-30 00:53:10 +00001170 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1171 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1172 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1173 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1174 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1175 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1176 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1177 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1178
sewardjfa492d42002-12-08 18:20:01 +00001179 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4] & ~EFlagD;
1180 VG_(baseBlock)[VGOFF_(m_dflag)] = VG_(extractDflag)(VG_(m_state_static)[56/4]);
1181
sewardj92a59562002-09-30 00:53:10 +00001182 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001183
1184 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1185 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001186 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001187}
1188
njn25e49d8e72002-09-23 09:36:25 +00001189Addr VG_(get_stack_pointer) ( void )
1190{
1191 return VG_(baseBlock)[VGOFF_(m_esp)];
1192}
1193
1194/* Some random tests needed for leak checking */
1195
1196Bool VG_(within_stack)(Addr a)
1197{
1198 if (a >= ((Addr)(&VG_(stack)))
1199 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1200 return True;
1201 else
1202 return False;
1203}
1204
1205Bool VG_(within_m_state_static)(Addr a)
1206{
1207 if (a >= ((Addr)(&VG_(m_state_static)))
1208 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1209 return True;
1210 else
1211 return False;
1212}
sewardjde4a1d02002-03-22 01:27:54 +00001213
1214/* ---------------------------------------------------------------------
1215 Show accumulated counts.
1216 ------------------------------------------------------------------ */
1217
njn25e49d8e72002-09-23 09:36:25 +00001218static __inline__ Int safe_idiv(Int a, Int b)
1219{
1220 return (b == 0 ? 0 : a / b);
1221}
1222
sewardjde4a1d02002-03-22 01:27:54 +00001223static void vg_show_counts ( void )
1224{
1225 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001226 " TT/TC: %d tc sectors discarded.",
1227 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001228 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001229 " %d chainings, %d unchainings.",
1230 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1231 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001232 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001233 VG_(overall_in_count),
1234 VG_(overall_in_osize),
1235 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001236 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1237 VG_(message)(Vg_DebugMsg,
1238 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001239 VG_(overall_out_count),
1240 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001241 VG_(overall_out_tsize),
1242 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001243 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001244 " dispatch: %lu jumps (bb entries), of which %u (%lu%%) were unchained.",
1245 VG_(bbs_done),
1246 VG_(unchained_jumps_done),
1247 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1248 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1249 );
1250
1251 VG_(message)(Vg_DebugMsg,
1252 " %d/%d major/minor sched events. %d tt_fast misses.",
1253 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001254 VG_(num_scheduling_events_MINOR),
1255 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001256
sewardjde4a1d02002-03-22 01:27:54 +00001257 VG_(message)(Vg_DebugMsg,
1258 "reg-alloc: %d t-req-spill, "
1259 "%d+%d orig+spill uis, %d total-reg-r.",
1260 VG_(translations_needing_spill),
1261 VG_(uinstrs_prealloc),
1262 VG_(uinstrs_spill),
1263 VG_(total_reg_rank) );
1264 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001265 " sanity: %d cheap, %d expensive checks.",
1266 VG_(sanity_fast_count),
1267 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001268 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001269}
1270
1271
1272/* ---------------------------------------------------------------------
1273 Main!
1274 ------------------------------------------------------------------ */
1275
1276/* Where we jump to once Valgrind has got control, and the real
1277 machine's state has been copied to the m_state_static. */
1278
1279void VG_(main) ( void )
1280{
sewardj2e93c502002-04-12 11:12:52 +00001281 Int i;
1282 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001283 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001284
njn27f1a382002-11-08 15:48:16 +00001285 /* Check skin and core versions are compatible */
1286 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1287 VG_(printf)("Error:\n"
1288 " Skin and core interface versions do not match.\n"
1289 " Interface version used by core is: %d.%d\n"
1290 " Interface version used by skin is: %d.%d\n"
1291 " The major version numbers must match.\n",
1292 VG_CORE_INTERFACE_MAJOR_VERSION,
1293 VG_CORE_INTERFACE_MINOR_VERSION,
1294 VG_(skin_interface_major_version),
1295 VG_(skin_interface_minor_version));
1296 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1297 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1298 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1299 else
1300 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1301 VG_(printf)(" Aborting, sorry.\n");
1302 VG_(exit)(1);
1303 }
1304
sewardjde4a1d02002-03-22 01:27:54 +00001305 /* Set up our stack sanity-check words. */
1306 for (i = 0; i < 10; i++) {
1307 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1308 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1309 }
1310
njn25e49d8e72002-09-23 09:36:25 +00001311 /* Setup stuff that depends on the skin. Must be before:
1312 - vg_init_baseBlock(): to register helpers
1313 - process_cmd_line_options(): to register skin name and description,
1314 and turn on/off 'command_line_options' need
1315 - init_memory() (to setup memory event trackers).
1316 */
njn810086f2002-11-14 12:42:47 +00001317 SK_(pre_clo_init)();
1318 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001319
njncc7bb472002-10-14 09:25:19 +00001320 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001321 process_cmd_line_options();
1322
njncc7bb472002-10-14 09:25:19 +00001323 /* Do post command-line processing initialisation */
1324 SK_(post_clo_init)();
1325
1326 /* Set up baseBlock offsets and copy the saved machine's state into it.
1327 Comes after SK_(post_clo_init) in case it registers helpers. */
1328 vg_init_baseBlock();
1329
sewardj64039bb2002-06-03 00:58:18 +00001330 /* Hook to delay things long enough so we can get the pid and
1331 attach GDB in another shell. */
sewardj92a59562002-09-30 00:53:10 +00001332 if (0) {
sewardj64039bb2002-06-03 00:58:18 +00001333 Int p, q;
sewardjc26cc252002-10-23 21:58:55 +00001334 VG_(printf)("pid=%d\n", VG_(getpid)());
sewardjfa492d42002-12-08 18:20:01 +00001335 for (p = 0; p < 5000; p++)
sewardj64039bb2002-06-03 00:58:18 +00001336 for (q = 0; q < 50000; q++) ;
1337 }
1338
sewardj018f7622002-05-15 21:13:39 +00001339 /* Initialise the scheduler, and copy the client's state from
1340 baseBlock into VG_(threads)[1]. This has to come before signal
1341 initialisations. */
1342 VG_(scheduler_init)();
1343
1344 /* Initialise the signal handling subsystem, temporarily parking
1345 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001346 VG_(sigstartup_actions)();
1347
sewardj018f7622002-05-15 21:13:39 +00001348 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001349 if (VG_(clo_profile))
1350 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001351
sewardj5f07b662002-04-23 16:52:51 +00001352 /* Start calibration of our RDTSC-based clock. */
1353 VG_(start_rdtsc_calibration)();
1354
njn25e49d8e72002-09-23 09:36:25 +00001355 /* Must come after SK_(init) so memory handler accompaniments (eg.
1356 * shadow memory) can be setup ok */
1357 VGP_PUSHCC(VgpInitMem);
1358 VG_(init_memory)();
1359 VGP_POPCC(VgpInitMem);
1360
1361 /* Read the list of errors to suppress. This should be found in
1362 the file specified by vg_clo_suppressions. */
1363 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1364 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001365
sewardj5f07b662002-04-23 16:52:51 +00001366 /* End calibration of our RDTSC-based clock, leaving it as long as
1367 we can. */
1368 VG_(end_rdtsc_calibration)();
1369
njn25e49d8e72002-09-23 09:36:25 +00001370 /* This should come after init_memory_and_symbols(); otherwise the
1371 latter carefully sets up the permissions maps to cover the
1372 anonymous mmaps for the translation table and translation cache,
1373 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001374 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001375
1376 if (VG_(clo_verbosity) == 1) {
1377 VG_(message)(Vg_UserMsg,
1378 "For more details, rerun with: -v");
1379 }
1380
1381 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1382 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001383 if (VG_(clo_verbosity) > 0)
1384 VG_(message)(Vg_UserMsg, "");
1385
1386 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001387
sewardj018f7622002-05-15 21:13:39 +00001388 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001389 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001390 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001391 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001392 VGP_POPCC(VgpSched);
1393 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001394
1395 if (VG_(clo_verbosity) > 0)
1396 VG_(message)(Vg_UserMsg, "");
1397
sewardj2e93c502002-04-12 11:12:52 +00001398 if (src == VgSrc_Deadlock) {
1399 VG_(message)(Vg_UserMsg,
1400 "Warning: pthread scheduler exited due to deadlock");
1401 }
1402
njn25e49d8e72002-09-23 09:36:25 +00001403 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001404 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001405
njn25e49d8e72002-09-23 09:36:25 +00001406 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001407
sewardj0c3b53f2002-05-01 01:58:35 +00001408 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001409
1410 if (VG_(clo_verbosity) > 1)
1411 vg_show_counts();
1412
sewardjc0d8f682002-11-30 00:49:43 +00001413 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001414 VG_(print_UInstr_histogram)();
1415
sewardjde4a1d02002-03-22 01:27:54 +00001416 if (0) {
1417 VG_(message)(Vg_DebugMsg, "");
1418 VG_(message)(Vg_DebugMsg,
1419 "------ Valgrind's internal memory use stats follow ------" );
1420 VG_(mallocSanityCheckAll)();
1421 VG_(show_all_arena_stats)();
1422 VG_(message)(Vg_DebugMsg,
1423 "------ Valgrind's ExeContext management stats follow ------" );
1424 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001425 }
1426
njn25e49d8e72002-09-23 09:36:25 +00001427 if (VG_(clo_profile))
1428 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001429
1430 VG_(shutdown_logging)();
1431
sewardj3e1eb1f2002-05-18 13:14:17 +00001432 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1433 processes don't get traced into. Also mess up $libdir/valgrind
1434 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001435 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001436 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1437 VG_(getenv)("LD_PRELOAD"),
1438 VG_(getenv)("LD_LIBRARY_PATH")
1439 );
sewardjde4a1d02002-03-22 01:27:54 +00001440 }
1441
sewardj7e87e382002-05-03 19:09:05 +00001442 /* Decide how to exit. This depends on what the scheduler
1443 returned. */
1444 switch (src) {
1445 case VgSrc_ExitSyscall: /* the normal way out */
1446 vg_assert(VG_(last_run_tid) > 0
1447 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001448 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001449 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001450 /* The thread's %EBX at the time it did __NR_exit() will hold
1451 the arg to __NR_exit(), so we just do __NR_exit() with
1452 that arg. */
1453 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001454 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001455 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001456 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001457
sewardj7e87e382002-05-03 19:09:05 +00001458 case VgSrc_Deadlock:
1459 /* Just exit now. No point in continuing. */
1460 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001461 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001462 break;
1463
1464 case VgSrc_BbsDone:
1465 /* Tricky; we have to try and switch back to the real CPU.
1466 This is all very dodgy and won't work at all in the
1467 presence of threads, or if the client happened to be
1468 running a signal handler. */
1469 /* Prepare to restore state to the real CPU. */
1470 VG_(load_thread_state)(1 /* root thread */ );
1471 VG_(copy_baseBlock_to_m_state_static)();
1472
1473 /* This pushes a return address on the simulator's stack,
1474 which is abandoned. We call vg_sigshutdown_actions() at
1475 the end of vg_switch_to_real_CPU(), so as to ensure that
1476 the original stack and machine state is restored before
1477 the real signal mechanism is restored. */
1478 VG_(switch_to_real_CPU)();
1479
1480 default:
njne427a662002-10-02 11:08:25 +00001481 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001482 }
sewardjde4a1d02002-03-22 01:27:54 +00001483}
1484
1485
1486/* Debugging thing .. can be called from assembly with OYNK macro. */
1487void VG_(oynk) ( Int n )
1488{
1489 OINK(n);
1490}
1491
1492
1493/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1494 "valgrinq.so", which doesn't do anything. This is used to avoid
1495 tracing into child processes. To make this work the build system
1496 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001497
njn25e49d8e72002-09-23 09:36:25 +00001498 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1499 without it, child processes try to find valgrind.so symbols in the
1500 skin .so.
1501
sewardj78e25c92002-05-20 23:38:33 +00001502 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1503 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1504 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001505*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001506void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1507 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001508{
njn25e49d8e72002-09-23 09:36:25 +00001509 Char* p_prel = NULL;
1510 Char* sk_prel = NULL;
1511 Char* p_path = NULL;
1512 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001513 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1514 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001515
sewardj78e25c92002-05-20 23:38:33 +00001516 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1517
1518 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001519 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001520 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1521
njn25e49d8e72002-09-23 09:36:25 +00001522 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001523 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001524 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001525 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1526 goto mutancy;
1527 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1528 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001529 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001530 }
1531
sewardj78e25c92002-05-20 23:38:33 +00001532 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001533 if (sk_prel == NULL) goto mutancy;
1534
1535 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001536 if (p_path == NULL) goto mutancy;
1537
njn25e49d8e72002-09-23 09:36:25 +00001538 what = 4;
1539 {
1540 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1541 Char* p = sk_prel;
1542 while (*p != ':' && p > ld_preload_str) {
1543 *p = ' ';
1544 p--;
1545 }
1546 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1547 while (*p != ':' && *p != '\0') {
1548 *p = ' ';
1549 p++;
1550 }
1551 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1552 *p = ' '; /* blank ending ':' */
1553 }
1554
sewardj78e25c92002-05-20 23:38:33 +00001555 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001556 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001557 if (p_prel[7] != 'd') goto mutancy;
1558 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001559
1560 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1561 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1562 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001563 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001564 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001565 if (p_path[0] != '/') goto mutancy;
1566 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001567 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001568 if (p_path[7] != 'd') goto mutancy;
1569 p_path[7] = 'q';
1570 return;
1571
1572 mutancy:
1573 VG_(printf)(
1574 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1575 " what = %d\n"
1576 " ld_preload_str = `%s'\n"
1577 " ld_library_path_str = `%s'\n"
1578 " p_prel = `%s'\n"
1579 " p_path = `%s'\n"
1580 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001581 what, ld_preload_str, ld_library_path_str,
1582 p_prel, p_path, VG_LIBDIR
1583 );
sewardjc26b4482002-07-13 12:20:35 +00001584 VG_(printf)(
1585 "\n"
1586 "Note that this is often caused by mis-installation of valgrind.\n"
1587 "Correct installation procedure is:\n"
1588 " ./configure --prefix=/install/dir\n"
1589 " make install\n"
1590 "And then use /install/dir/bin/valgrind\n"
1591 "Moving the installation directory elsewhere after 'make install'\n"
1592 "will cause the above error. Hand-editing the paths in the shell\n"
1593 "scripts is also likely to cause problems.\n"
1594 "\n"
1595 );
njne427a662002-10-02 11:08:25 +00001596 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001597}
1598
sewardj3e1eb1f2002-05-18 13:14:17 +00001599
sewardjde4a1d02002-03-22 01:27:54 +00001600/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1601 it to attach to this process. Called if the user requests this
1602 service after an error has been shown, so she can poke around and
1603 look at parameters, memory, etc. You can't meaningfully get GDB to
1604 continue the program, though; to continue, quit GDB. */
1605extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1606{
sewardje6a25242002-04-21 22:03:07 +00001607 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001608 UChar buf[100];
1609 VG_(sprintf)(buf,
1610 "/usr/bin/gdb -nw /proc/%d/exe %d",
1611 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001612 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1613 res = VG_(system)(buf);
1614 if (res == 0) {
1615 VG_(message)(Vg_UserMsg, "");
1616 VG_(message)(Vg_UserMsg,
1617 "GDB has detached. Valgrind regains control. We continue.");
1618 } else {
1619 VG_(message)(Vg_UserMsg, "Apparently failed!");
1620 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001621 }
sewardjde4a1d02002-03-22 01:27:54 +00001622}
1623
1624
1625/* Print some helpful-ish text about unimplemented things, and give
1626 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001627void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001628{
1629 VG_(message)(Vg_UserMsg, "");
1630 VG_(message)(Vg_UserMsg,
1631 "Valgrind detected that your program requires");
1632 VG_(message)(Vg_UserMsg,
1633 "the following unimplemented functionality:");
1634 VG_(message)(Vg_UserMsg, " %s", msg);
1635 VG_(message)(Vg_UserMsg,
1636 "This may be because the functionality is hard to implement,");
1637 VG_(message)(Vg_UserMsg,
1638 "or because no reasonable program would behave this way,");
1639 VG_(message)(Vg_UserMsg,
1640 "or because nobody has yet needed it. In any case, let me know");
1641 VG_(message)(Vg_UserMsg,
1642 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1643 VG_(message)(Vg_UserMsg,
1644 "");
1645 VG_(message)(Vg_UserMsg,
1646 "Valgrind has to exit now. Sorry. Bye!");
1647 VG_(message)(Vg_UserMsg,
1648 "");
sewardj15a43e12002-04-17 19:35:12 +00001649 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001650 VG_(exit)(1);
1651}
1652
1653
njn25e49d8e72002-09-23 09:36:25 +00001654/* ---------------------------------------------------------------------
1655 Sanity check machinery (permanently engaged).
1656 ------------------------------------------------------------------ */
1657
1658/* A fast sanity check -- suitable for calling circa once per
1659 millisecond. */
1660
1661void VG_(do_sanity_checks) ( Bool force_expensive )
1662{
1663 Int i;
1664
njn37cea302002-09-30 11:24:00 +00001665 VGP_PUSHCC(VgpCoreCheapSanity);
1666
njn25e49d8e72002-09-23 09:36:25 +00001667 if (VG_(sanity_level) < 1) return;
1668
1669 /* --- First do all the tests that we can do quickly. ---*/
1670
1671 VG_(sanity_fast_count)++;
1672
1673 /* Check that we haven't overrun our private stack. */
1674 for (i = 0; i < 10; i++) {
1675 vg_assert(VG_(stack)[i]
1676 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1677 vg_assert(VG_(stack)[10000-1-i]
1678 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1679 }
1680
1681 /* Check stuff pertaining to the memory check system. */
1682
1683 /* Check that nobody has spuriously claimed that the first or
1684 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001685 if (VG_(needs).sanity_checks) {
1686 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001687 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001688 VGP_POPCC(VgpSkinCheapSanity);
1689 }
njn25e49d8e72002-09-23 09:36:25 +00001690
1691 /* --- Now some more expensive checks. ---*/
1692
1693 /* Once every 25 times, check some more expensive stuff. */
1694 if ( force_expensive
1695 || VG_(sanity_level) > 1
1696 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1697
njn37cea302002-09-30 11:24:00 +00001698 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001699 VG_(sanity_slow_count)++;
1700
1701# if 0
1702 { void zzzmemscan(void); zzzmemscan(); }
1703# endif
1704
1705 if ((VG_(sanity_fast_count) % 250) == 0)
1706 VG_(sanity_check_tc_tt)();
1707
1708 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001709 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001710 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001711 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001712 }
1713 /*
1714 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1715 */
njn37cea302002-09-30 11:24:00 +00001716 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001717 }
1718
1719 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001720 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001721 /* Check sanity of the low-level memory manager. Note that bugs
1722 in the client's code can cause this to fail, so we don't do
1723 this check unless specially asked for. And because it's
1724 potentially very expensive. */
1725 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001726 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001727 }
njn37cea302002-09-30 11:24:00 +00001728 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001729}
sewardjde4a1d02002-03-22 01:27:54 +00001730/*--------------------------------------------------------------------*/
1731/*--- end vg_main.c ---*/
1732/*--------------------------------------------------------------------*/