blob: cb5891ed14bc484ee573fa559246110e180168d9 [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) );
287 VGOFF_(helper_STC)
288 = 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));
322}
323
324static void vg_init_shadow_regs ( void )
325{
326 if (VG_(needs).shadow_regs) {
327 UInt eflags;
328
329 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
330 VG_(baseBlock)[VGOFF_(sh_esp)] =
331 VG_(baseBlock)[VGOFF_(sh_ebp)] =
332 VG_(baseBlock)[VGOFF_(sh_eax)] =
333 VG_(baseBlock)[VGOFF_(sh_ecx)] =
334 VG_(baseBlock)[VGOFF_(sh_edx)] =
335 VG_(baseBlock)[VGOFF_(sh_ebx)] =
336 VG_(baseBlock)[VGOFF_(sh_esi)] =
337 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
338 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
339
340 } else
341 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
sewardjde4a1d02002-03-22 01:27:54 +0000342}
343
344
345/* ---------------------------------------------------------------------
346 Global entities which are not referenced from generated code.
347 ------------------------------------------------------------------ */
348
349/* The stack on which Valgrind runs. We can't use the same stack as
350 the simulatee -- that's an important design decision. */
351UInt VG_(stack)[10000];
352
353/* Ditto our signal delivery stack. */
354UInt VG_(sigstack)[10000];
355
356/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000357UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
358Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000359
360/* Counts downwards in vg_run_innerloop. */
361UInt VG_(dispatch_ctr);
362
sewardjde4a1d02002-03-22 01:27:54 +0000363
364/* 64-bit counter for the number of basic blocks done. */
365ULong VG_(bbs_done);
366/* 64-bit counter for the number of bbs to go before a debug exit. */
367ULong VG_(bbs_to_go);
368
sewardjde4a1d02002-03-22 01:27:54 +0000369/* The current LRU epoch. */
370UInt VG_(current_epoch) = 0;
371
sewardj7e87e382002-05-03 19:09:05 +0000372/* This is the ThreadId of the last thread the scheduler ran. */
373ThreadId VG_(last_run_tid) = 0;
374
njn25e49d8e72002-09-23 09:36:25 +0000375/* This is the argument to __NR_exit() supplied by the first thread to
376 call that syscall. We eventually pass that to __NR_exit() for
377 real. */
378UInt VG_(exitcode) = 0;
379
sewardjde4a1d02002-03-22 01:27:54 +0000380
381/* ---------------------------------------------------------------------
382 Counters, for informational purposes only.
383 ------------------------------------------------------------------ */
384
385/* Number of lookups which miss the fast tt helper. */
386UInt VG_(tt_fast_misses) = 0;
387
388
389/* Counts for LRU informational messages. */
390
391/* Number and total o/t size of new translations this epoch. */
392UInt VG_(this_epoch_in_count) = 0;
393UInt VG_(this_epoch_in_osize) = 0;
394UInt VG_(this_epoch_in_tsize) = 0;
395/* Number and total o/t size of discarded translations this epoch. */
396UInt VG_(this_epoch_out_count) = 0;
397UInt VG_(this_epoch_out_osize) = 0;
398UInt VG_(this_epoch_out_tsize) = 0;
399/* Number and total o/t size of translations overall. */
400UInt VG_(overall_in_count) = 0;
401UInt VG_(overall_in_osize) = 0;
402UInt VG_(overall_in_tsize) = 0;
403/* Number and total o/t size of discards overall. */
404UInt VG_(overall_out_count) = 0;
405UInt VG_(overall_out_osize) = 0;
406UInt VG_(overall_out_tsize) = 0;
407
408/* The number of LRU-clearings of TT/TC. */
409UInt VG_(number_of_lrus) = 0;
410
411
412/* Counts pertaining to the register allocator. */
413
414/* total number of uinstrs input to reg-alloc */
415UInt VG_(uinstrs_prealloc) = 0;
416
417/* total number of uinstrs added due to spill code */
418UInt VG_(uinstrs_spill) = 0;
419
420/* number of bbs requiring spill code */
421UInt VG_(translations_needing_spill) = 0;
422
423/* total of register ranks over all translations */
424UInt VG_(total_reg_rank) = 0;
425
426
sewardjde4a1d02002-03-22 01:27:54 +0000427/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000428UInt VG_(sanity_fast_count) = 0;
429UInt VG_(sanity_slow_count) = 0;
430
sewardj2e93c502002-04-12 11:12:52 +0000431/* Counts pertaining to the scheduler. */
432UInt VG_(num_scheduling_events_MINOR) = 0;
433UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000434
435
436/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +0000437 Skin data structure initialisation
438 ------------------------------------------------------------------ */
439
440/* Init with default values. */
njnd04b7c62002-10-03 14:05:52 +0000441VgDetails VG_(details) = {
442 .name = NULL,
443 .version = NULL,
444 .description = NULL,
445 .copyright_author = NULL,
446 .bug_reports_to = NULL,
447};
448
njn25e49d8e72002-09-23 09:36:25 +0000449VgNeeds VG_(needs) = {
njnd04b7c62002-10-03 14:05:52 +0000450 .core_errors = False,
451 .skin_errors = False,
452 .libc_freeres = False,
453 .sizeof_shadow_block = 0,
454 .basic_block_discards = False,
455 .shadow_regs = False,
456 .command_line_options = False,
457 .client_requests = False,
458 .extended_UCode = False,
459 .syscall_wrapper = False,
460 .alternative_free = False,
461 .sanity_checks = False,
njn25e49d8e72002-09-23 09:36:25 +0000462};
463
464VgTrackEvents VG_(track_events) = {
465 /* Memory events */
466 .new_mem_startup = NULL,
467 .new_mem_heap = NULL,
468 .new_mem_stack = NULL,
469 .new_mem_stack_aligned = NULL,
470 .new_mem_stack_signal = NULL,
471 .new_mem_brk = NULL,
472 .new_mem_mmap = NULL,
473
474 .copy_mem_heap = NULL,
njnd04b7c62002-10-03 14:05:52 +0000475 .copy_mem_remap = NULL,
njn25e49d8e72002-09-23 09:36:25 +0000476 .change_mem_mprotect = NULL,
477
478 .ban_mem_heap = NULL,
479 .ban_mem_stack = NULL,
480
481 .die_mem_heap = NULL,
482 .die_mem_stack = NULL,
483 .die_mem_stack_aligned = NULL,
484 .die_mem_stack_signal = NULL,
485 .die_mem_brk = NULL,
486 .die_mem_munmap = NULL,
487
488 .bad_free = NULL,
489 .mismatched_free = NULL,
490
491 .pre_mem_read = NULL,
492 .pre_mem_read_asciiz = NULL,
493 .pre_mem_write = NULL,
494 .post_mem_write = NULL,
495
njnd04b7c62002-10-03 14:05:52 +0000496 /* Scheduler events */
497 .thread_run = NULL,
498
njn25e49d8e72002-09-23 09:36:25 +0000499 /* Mutex events */
500 .post_mutex_lock = NULL,
501 .post_mutex_unlock = NULL,
502};
503
504static void sanity_check_needs ( void )
505{
njne427a662002-10-02 11:08:25 +0000506#define CHECK_NOT(var, value) \
507 if ((var)==(value)) { \
508 VG_(printf)("\nSkin error: `%s' not initialised\n", \
509 VG__STRING(var)); \
510 VG_(skin_panic)("Uninitialised needs field\n"); \
njn25e49d8e72002-09-23 09:36:25 +0000511 }
512
njnd04b7c62002-10-03 14:05:52 +0000513 CHECK_NOT(VG_(details).name, NULL);
514 /* Nb: .version can be NULL */
515 CHECK_NOT(VG_(details).description, NULL);
516 CHECK_NOT(VG_(details).copyright_author, NULL);
517 CHECK_NOT(VG_(details).bug_reports_to, NULL);
njn25e49d8e72002-09-23 09:36:25 +0000518
519#undef CHECK_NOT
520#undef INVALID_Bool
521}
522
523/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000524 Values derived from command-line options.
525 ------------------------------------------------------------------ */
526
njn25e49d8e72002-09-23 09:36:25 +0000527/* Define, and set defaults. */
528Bool VG_(clo_error_limit) = True;
529Bool VG_(clo_GDB_attach) = False;
530Int VG_(sanity_level) = 1;
531Int VG_(clo_verbosity) = 1;
532Bool VG_(clo_demangle) = True;
533Bool VG_(clo_sloppy_malloc) = False;
534Int VG_(clo_alignment) = 4;
535Bool VG_(clo_trace_children) = False;
536Int VG_(clo_logfile_fd) = 2;
537Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000538Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000539Bool VG_(clo_profile) = False;
540Bool VG_(clo_single_step) = False;
541Bool VG_(clo_optimise) = True;
542UChar VG_(clo_trace_codegen) = 0; // 00000000b
543Bool VG_(clo_trace_syscalls) = False;
544Bool VG_(clo_trace_signals) = False;
545Bool VG_(clo_trace_symtab) = False;
546Bool VG_(clo_trace_malloc) = False;
547Bool VG_(clo_trace_sched) = False;
548Int VG_(clo_trace_pthread_level) = 0;
549ULong VG_(clo_stop_after) = 1000000000000LL;
550Int VG_(clo_dump_error) = 0;
551Int VG_(clo_backtrace_size) = 4;
552Char* VG_(clo_weird_hacks) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000553
554/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
555 to behave. Initially we say False. */
556Bool VG_(running_on_simd_CPU) = False;
557
558/* Holds client's %esp at the point we gained control. */
559Addr VG_(esp_at_startup);
560
561/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
562 envp[] as extracted from the client's stack at startup-time. */
563Int VG_(client_argc);
564Char** VG_(client_argv);
565Char** VG_(client_envp);
566
567/* A place into which to copy the value of env var VG_ARGS, so we
568 don't have to modify the original. */
569static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
570
sewardjde4a1d02002-03-22 01:27:54 +0000571/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000572 Processing of command-line options.
573 ------------------------------------------------------------------ */
574
njn25e49d8e72002-09-23 09:36:25 +0000575void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000576{
577 VG_(shutdown_logging)();
578 VG_(clo_logfile_fd) = 2; /* stderr */
579 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
580 VG_(exit)(1);
581}
582
583static void config_error ( Char* msg )
584{
585 VG_(shutdown_logging)();
586 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000587 VG_(printf)(
588 "valgrind.so: Startup or configuration error:\n %s\n", msg);
589 VG_(printf)(
590 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000591 VG_(exit)(1);
592}
593
sewardja1679dd2002-05-10 22:31:40 +0000594static void args_grok_error ( Char* msg )
595{
596 VG_(shutdown_logging)();
597 VG_(clo_logfile_fd) = 2; /* stderr */
598 VG_(printf)("valgrind.so: When searching for "
599 "client's argc/argc/envp:\n\t%s\n", msg);
600 config_error("couldn't find client's argc/argc/envp");
601}
602
njn25e49d8e72002-09-23 09:36:25 +0000603static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000604{
njn25e49d8e72002-09-23 09:36:25 +0000605 Char* usage1 =
606"usage: valgrind [options] prog-and-args\n"
607"\n"
608" core user options, with defaults in [ ], are:\n"
609" --help show this message\n"
610" --version show version\n"
611" --skin=<name> main task (skin to use) [Valgrind]\n"
612" -q --quiet run silently; only print error msgs\n"
613" -v --verbose be more verbose, incl counts of errors\n"
614" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
615" --demangle=no|yes automatically demangle C++ names? [yes]\n"
616" --num-callers=<number> show <num> callers in stack traces [4]\n"
617" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
618" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
619" --alignment=<number> set minimum alignment of allocations [4]\n"
620" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
621" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
622" --suppressions=<filename> suppress errors described in\n"
623" suppressions file <filename>\n"
624" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
625" recognised hacks are: ioctl-VTIME truncate-writes\n"
626"\n"
627" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000628
njn7cf0bd32002-06-08 13:36:03 +0000629
njn25e49d8e72002-09-23 09:36:25 +0000630 Char* usage2 =
631"\n"
632" core options for debugging Valgrind itself are:\n"
633" --sanity-level=<number> level of sanity checking to do [1]\n"
634" --single-step=no|yes translate each instr separately? [no]\n"
635" --optimise=no|yes improve intermediate code? [yes]\n"
636" --profile=no|yes profile? (skin must be built for it) [no]\n"
637" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
638" --trace-syscalls=no|yes show all system calls? [no]\n"
639" --trace-signals=no|yes show signal handling details? [no]\n"
640" --trace-symtab=no|yes show symbol table details? [no]\n"
641" --trace-malloc=no|yes show client malloc details? [no]\n"
642" --trace-sched=no|yes show thread scheduler details? [no]\n"
643" --trace-pthread=none|some|all show pthread event details? [no]\n"
644" --stop-after=<number> switch to real CPU after executing\n"
645" <number> basic blocks [infinity]\n"
646" --dump-error=<number> show translation for basic block\n"
647" associated with <number>'th\n"
648" error context [0=don't show any]\n"
649"\n"
650" Extra options are read from env variable $VALGRIND_OPTS\n"
651"\n"
652" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
653" and licensed under the GNU General Public License, version 2.\n"
654" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000655"\n"
656" Skins are copyright and licensed by their authors. See each\n"
657" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000658"\n";
njn7cf0bd32002-06-08 13:36:03 +0000659
njnd04b7c62002-10-03 14:05:52 +0000660 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000661 /* Don't print skin string directly for security, ha! */
662 if (VG_(needs).command_line_options)
663 VG_(printf)("%s", SK_(usage)());
664 else
665 VG_(printf)(" (none)\n");
666 VG_(printf)(usage2, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000667
njn25e49d8e72002-09-23 09:36:25 +0000668 VG_(shutdown_logging)();
669 VG_(clo_logfile_fd) = 2; /* stderr */
670 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000671}
sewardjde4a1d02002-03-22 01:27:54 +0000672
673static void process_cmd_line_options ( void )
674{
njn25e49d8e72002-09-23 09:36:25 +0000675 Char* argv[M_VG_CMDLINE_OPTS];
676 UInt argc;
677 Char* p;
678 Char* str;
679 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000680
681# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
682# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
683# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
684
sewardjde4a1d02002-03-22 01:27:54 +0000685 eventually_logfile_fd = VG_(clo_logfile_fd);
686
687 /* Once logging is started, we can safely send messages pertaining
688 to failures in initialisation. */
689 VG_(startup_logging)();
690
sewardj19d81412002-06-03 01:10:40 +0000691 /* Check for sane path in ./configure --prefix=... */
692 if (VG_(strlen)(VG_LIBDIR) < 1
693 || VG_LIBDIR[0] != '/')
694 config_error("Please use absolute paths in "
695 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000696
sewardja1679dd2002-05-10 22:31:40 +0000697 /* (Suggested by Fabrice Bellard ... )
698 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000699 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000700 change less often than the libc ones. */
701 {
sewardja1679dd2002-05-10 22:31:40 +0000702 UInt* sp = 0; /* bogus init to keep gcc -O happy */
703
sewardj38170912002-05-10 21:07:22 +0000704 /* locate the top of the stack */
sewardja1679dd2002-05-10 22:31:40 +0000705 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
706 VG_STARTUP_STACK_BASE_1 )) {
707 sp = (UInt*)VG_STARTUP_STACK_BASE_1;
708 } else
709 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
710 VG_STARTUP_STACK_BASE_2 )) {
711 sp = (UInt*)VG_STARTUP_STACK_BASE_2;
daywalkera2562202002-07-15 19:39:51 +0000712 } else
713 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
714 VG_STARTUP_STACK_BASE_3 )) {
715 sp = (UInt*)VG_STARTUP_STACK_BASE_3;
njn25e49d8e72002-09-23 09:36:25 +0000716 } else
717 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
718 VG_STARTUP_STACK_BASE_4 )) {
719 sp = (UInt*)VG_STARTUP_STACK_BASE_4;
sewardja1679dd2002-05-10 22:31:40 +0000720 } else {
721 args_grok_error(
722 "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
723 "constants defined in vg_include.h. You should investigate."
724 );
725 }
726
sewardj38170912002-05-10 21:07:22 +0000727 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
728 the elf interpreter table */
729 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000730 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000731 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000732 sp--;
733 }
sewardj38170912002-05-10 21:07:22 +0000734
735 if (sp[2] == VKI_AT_BASE
736 && sp[0] == VKI_AT_PAGESZ
737 && sp[-2] == VKI_AT_PHNUM
738 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000739 && sp[-6] == VKI_AT_PHDR
740 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000741 if (0)
742 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000743 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000744 } else
745 if (sp[2] == VKI_AT_CLKTCK
746 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000747 && sp[-2] == VKI_AT_HWCAP
748 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000749 if (0)
750 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
751 sp -= 2;
752 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000753 if (sp[2] == VKI_AT_CLKTCK
754 && sp[0] == VKI_AT_PAGESZ
755 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000756 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
757 && sp[-4-1] == 0) {
758 if (0)
759 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
760 "kernel here.\n");
761 sp -= 4;
762 } else
763 if (sp[2] == VKI_AT_CLKTCK
764 && sp[0] == VKI_AT_PAGESZ
765 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000766 && sp[-2-20-1] == 0) {
767 if (0)
768 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
769 sp -= 22;
770 } else
sewardja1679dd2002-05-10 22:31:40 +0000771 args_grok_error(
772 "ELF frame does not look like 2.2.X or 2.4.X.\n "
773 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
774 );
sewardj38170912002-05-10 21:07:22 +0000775
776 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000777 if (*sp != 0)
778 args_grok_error("can't find NULL at end of env[]");
779
sewardj38170912002-05-10 21:07:22 +0000780 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000781 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000782 while (True) {
783 sp --;
784 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000785 if (++ctr >= 1000)
786 args_grok_error(
787 "suspiciously many (1000) env[] entries; giving up");
788
sewardj38170912002-05-10 21:07:22 +0000789 }
790 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000791 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000792
sewardja1679dd2002-05-10 22:31:40 +0000793 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000794 VG_(client_argc) = 0;
795 while (True) {
796 sp--;
797 if (*sp == VG_(client_argc))
798 break;
799 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000800 if (++ctr >= 1000)
801 args_grok_error(
802 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000803 }
804
sewardja1679dd2002-05-10 22:31:40 +0000805 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000806 }
807
sewardjde4a1d02002-03-22 01:27:54 +0000808 /* Now that VG_(client_envp) has been set, we can extract the args
809 for Valgrind itself. Copy into global var so that we don't have to
810 write zeroes to the getenv'd value itself. */
811 str = VG_(getenv)("VG_ARGS");
812 argc = 0;
813
814 if (!str) {
815 config_error("Can't read options from env var VG_ARGS.");
816 }
817
818 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
819 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
820 }
821 VG_(strcpy)(vg_cmdline_copy, str);
822 str = NULL;
823
824 p = &vg_cmdline_copy[0];
825 while (True) {
826 while (ISSPACE(*p)) { *p = 0; p++; }
827 if (*p == 0) break;
828 if (argc < M_VG_CMDLINE_OPTS-1) {
829 argv[argc] = p; argc++;
830 } else {
831 config_error(
832 "Found more than M_CMDLINE_OPTS command-line opts.");
833 }
834 while (*p != 0 && !ISSPACE(*p)) p++;
835 }
836
837 for (i = 0; i < argc; i++) {
838
njn25e49d8e72002-09-23 09:36:25 +0000839 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000840 VG_(clo_verbosity)++;
841 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
842 VG_(clo_verbosity)--;
843
sewardj2e432902002-06-13 20:44:00 +0000844 else if (STREQ(argv[i], "--error-limit=yes"))
845 VG_(clo_error_limit) = True;
846 else if (STREQ(argv[i], "--error-limit=no"))
847 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000848
sewardjde4a1d02002-03-22 01:27:54 +0000849 else if (STREQ(argv[i], "--gdb-attach=yes"))
850 VG_(clo_GDB_attach) = True;
851 else if (STREQ(argv[i], "--gdb-attach=no"))
852 VG_(clo_GDB_attach) = False;
853
854 else if (STREQ(argv[i], "--demangle=yes"))
855 VG_(clo_demangle) = True;
856 else if (STREQ(argv[i], "--demangle=no"))
857 VG_(clo_demangle) = False;
858
sewardjde4a1d02002-03-22 01:27:54 +0000859 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
860 VG_(clo_sloppy_malloc) = True;
861 else if (STREQ(argv[i], "--sloppy-malloc=no"))
862 VG_(clo_sloppy_malloc) = False;
863
sewardj246d4662002-06-14 10:17:05 +0000864 else if (STREQN(12, argv[i], "--alignment="))
865 VG_(clo_alignment) = (Int)VG_(atoll)(&argv[i][12]);
866
sewardjde4a1d02002-03-22 01:27:54 +0000867 else if (STREQ(argv[i], "--trace-children=yes"))
868 VG_(clo_trace_children) = True;
869 else if (STREQ(argv[i], "--trace-children=no"))
870 VG_(clo_trace_children) = False;
871
sewardjde4a1d02002-03-22 01:27:54 +0000872 else if (STREQN(15, argv[i], "--sanity-level="))
873 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
874
875 else if (STREQN(13, argv[i], "--logfile-fd="))
876 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
877
sewardjde4a1d02002-03-22 01:27:54 +0000878 else if (STREQN(15, argv[i], "--suppressions=")) {
879 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000880 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000881 VG_(message)(Vg_UserMsg,
882 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000883 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000884 }
885 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
886 VG_(clo_n_suppressions)++;
887 }
njn25e49d8e72002-09-23 09:36:25 +0000888 else if (STREQ(argv[i], "--profile=yes"))
889 VG_(clo_profile) = True;
890 else if (STREQ(argv[i], "--profile=no"))
891 VG_(clo_profile) = False;
892
sewardjde4a1d02002-03-22 01:27:54 +0000893 else if (STREQ(argv[i], "--single-step=yes"))
894 VG_(clo_single_step) = True;
895 else if (STREQ(argv[i], "--single-step=no"))
896 VG_(clo_single_step) = False;
897
898 else if (STREQ(argv[i], "--optimise=yes"))
899 VG_(clo_optimise) = True;
900 else if (STREQ(argv[i], "--optimise=no"))
901 VG_(clo_optimise) = False;
902
njn25e49d8e72002-09-23 09:36:25 +0000903 /* "vwxyz" --> 000zyxwv (binary) */
904 else if (STREQN(16, argv[i], "--trace-codegen=")) {
905 Int j;
906 char* opt = & argv[i][16];
907
908 if (5 != VG_(strlen)(opt)) {
909 VG_(message)(Vg_UserMsg,
910 "--trace-codegen argument must have 5 digits");
911 VG_(bad_option)(argv[i]);
912 }
913 for (j = 0; j < 5; j++) {
914 if ('0' == opt[j]) { /* do nothing */ }
915 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
916 else {
917 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
918 "contain 0s and 1s");
919 VG_(bad_option)(argv[i]);
920 }
921 }
922 }
sewardjde4a1d02002-03-22 01:27:54 +0000923
924 else if (STREQ(argv[i], "--trace-syscalls=yes"))
925 VG_(clo_trace_syscalls) = True;
926 else if (STREQ(argv[i], "--trace-syscalls=no"))
927 VG_(clo_trace_syscalls) = False;
928
929 else if (STREQ(argv[i], "--trace-signals=yes"))
930 VG_(clo_trace_signals) = True;
931 else if (STREQ(argv[i], "--trace-signals=no"))
932 VG_(clo_trace_signals) = False;
933
934 else if (STREQ(argv[i], "--trace-symtab=yes"))
935 VG_(clo_trace_symtab) = True;
936 else if (STREQ(argv[i], "--trace-symtab=no"))
937 VG_(clo_trace_symtab) = False;
938
939 else if (STREQ(argv[i], "--trace-malloc=yes"))
940 VG_(clo_trace_malloc) = True;
941 else if (STREQ(argv[i], "--trace-malloc=no"))
942 VG_(clo_trace_malloc) = False;
943
sewardj8937c812002-04-12 20:12:20 +0000944 else if (STREQ(argv[i], "--trace-sched=yes"))
945 VG_(clo_trace_sched) = True;
946 else if (STREQ(argv[i], "--trace-sched=no"))
947 VG_(clo_trace_sched) = False;
948
sewardj45b4b372002-04-16 22:50:32 +0000949 else if (STREQ(argv[i], "--trace-pthread=none"))
950 VG_(clo_trace_pthread_level) = 0;
951 else if (STREQ(argv[i], "--trace-pthread=some"))
952 VG_(clo_trace_pthread_level) = 1;
953 else if (STREQ(argv[i], "--trace-pthread=all"))
954 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000955
sewardj8d365b52002-05-12 10:52:16 +0000956 else if (STREQN(14, argv[i], "--weird-hacks="))
957 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000958
sewardjde4a1d02002-03-22 01:27:54 +0000959 else if (STREQN(13, argv[i], "--stop-after="))
960 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
961
962 else if (STREQN(13, argv[i], "--dump-error="))
963 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
964
965 else if (STREQN(14, argv[i], "--num-callers=")) {
966 /* Make sure it's sane. */
967 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
968 if (VG_(clo_backtrace_size) < 2)
969 VG_(clo_backtrace_size) = 2;
970 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
971 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
972 }
973
njn25e49d8e72002-09-23 09:36:25 +0000974 else if (VG_(needs).command_line_options) {
975 Bool ok = SK_(process_cmd_line_option)(argv[i]);
976 if (!ok)
977 usage();
978 }
sewardjde4a1d02002-03-22 01:27:54 +0000979 else
njn25e49d8e72002-09-23 09:36:25 +0000980 usage();
sewardjde4a1d02002-03-22 01:27:54 +0000981 }
982
983# undef ISSPACE
984# undef STREQ
985# undef STREQN
986
987 if (VG_(clo_verbosity < 0))
988 VG_(clo_verbosity) = 0;
989
sewardj246d4662002-06-14 10:17:05 +0000990 if (VG_(clo_alignment) < 4
991 || VG_(clo_alignment) > 4096
992 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
993 VG_(message)(Vg_UserMsg, "");
994 VG_(message)(Vg_UserMsg,
995 "Invalid --alignment= setting. "
996 "Should be a power of 2, >= 4, <= 4096.");
njn25e49d8e72002-09-23 09:36:25 +0000997 VG_(bad_option)("--alignment");
sewardj246d4662002-06-14 10:17:05 +0000998 }
999
sewardjde4a1d02002-03-22 01:27:54 +00001000 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1001 VG_(message)(Vg_UserMsg, "");
1002 VG_(message)(Vg_UserMsg,
1003 "--gdb-attach=yes conflicts with --trace-children=yes");
1004 VG_(message)(Vg_UserMsg,
1005 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001006 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001007 }
1008
sewardjde4a1d02002-03-22 01:27:54 +00001009 VG_(clo_logfile_fd) = eventually_logfile_fd;
1010
sewardj83adf412002-05-01 01:25:45 +00001011 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001012 /* Skin details */
1013 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1014 VG_(details).name,
1015 NULL == VG_(details).version ? "" : "-",
1016 NULL == VG_(details).version
1017 ? (Char*)"" : VG_(details).version,
1018 VG_(details).description);
1019 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001020
njnd04b7c62002-10-03 14:05:52 +00001021 /* Core details */
1022 VG_(message)(Vg_UserMsg,
1023 "Built with valgrind-%s, a program execution monitor.",
1024 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001025 VG_(message)(Vg_UserMsg,
1026 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001027 }
1028
sewardjde4a1d02002-03-22 01:27:54 +00001029 if (VG_(clo_verbosity) > 1) {
1030 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1031 for (i = 0; i < argc; i++) {
1032 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1033 }
1034 }
1035
njn25e49d8e72002-09-23 09:36:25 +00001036 if (VG_(clo_n_suppressions) == 0 &&
1037 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001038 config_error("No error-suppression files were specified.");
1039 }
1040}
1041
sewardjde4a1d02002-03-22 01:27:54 +00001042/* ---------------------------------------------------------------------
1043 Copying to/from m_state_static.
1044 ------------------------------------------------------------------ */
1045
sewardj92a59562002-09-30 00:53:10 +00001046UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1047 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001048 + 1 /* %eflags */
1049 + 1 /* %eip */
1050 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1051 ];
1052
1053void VG_(copy_baseBlock_to_m_state_static) ( void )
1054{
1055 Int i;
sewardj92a59562002-09-30 00:53:10 +00001056 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1057 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1058 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1059 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1060 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1061 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001062
sewardj92a59562002-09-30 00:53:10 +00001063 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1064 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1065 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1066 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1067 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1068 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1069 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1070 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1071
1072 VG_(m_state_static)[56/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
1073 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001074
1075 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001076 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001077 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1078}
1079
1080
1081void VG_(copy_m_state_static_to_baseBlock) ( void )
1082{
1083 Int i;
sewardj92a59562002-09-30 00:53:10 +00001084 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1085 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1086 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1087 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1088 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1089 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001090
sewardj92a59562002-09-30 00:53:10 +00001091 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1092 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1093 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1094 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1095 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1096 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1097 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1098 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1099
1100 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4];
1101 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001102
1103 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1104 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001105 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001106}
1107
njn25e49d8e72002-09-23 09:36:25 +00001108Addr VG_(get_stack_pointer) ( void )
1109{
1110 return VG_(baseBlock)[VGOFF_(m_esp)];
1111}
1112
1113/* Some random tests needed for leak checking */
1114
1115Bool VG_(within_stack)(Addr a)
1116{
1117 if (a >= ((Addr)(&VG_(stack)))
1118 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1119 return True;
1120 else
1121 return False;
1122}
1123
1124Bool VG_(within_m_state_static)(Addr a)
1125{
1126 if (a >= ((Addr)(&VG_(m_state_static)))
1127 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1128 return True;
1129 else
1130 return False;
1131}
sewardjde4a1d02002-03-22 01:27:54 +00001132
1133/* ---------------------------------------------------------------------
1134 Show accumulated counts.
1135 ------------------------------------------------------------------ */
1136
njn25e49d8e72002-09-23 09:36:25 +00001137static __inline__ Int safe_idiv(Int a, Int b)
1138{
1139 return (b == 0 ? 0 : a / b);
1140}
1141
sewardjde4a1d02002-03-22 01:27:54 +00001142static void vg_show_counts ( void )
1143{
1144 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001145 " lru: %d epochs, %d clearings.",
1146 VG_(current_epoch),
1147 VG_(number_of_lrus) );
sewardjde4a1d02002-03-22 01:27:54 +00001148 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001149 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001150 VG_(overall_in_count),
1151 VG_(overall_in_osize),
1152 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001153 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1154 VG_(message)(Vg_DebugMsg,
1155 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001156 VG_(overall_out_count),
1157 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001158 VG_(overall_out_tsize),
1159 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001160 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001161 " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
1162 VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
1163 VG_(num_scheduling_events_MINOR),
1164 VG_(tt_fast_misses));
sewardjde4a1d02002-03-22 01:27:54 +00001165 VG_(message)(Vg_DebugMsg,
1166 "reg-alloc: %d t-req-spill, "
1167 "%d+%d orig+spill uis, %d total-reg-r.",
1168 VG_(translations_needing_spill),
1169 VG_(uinstrs_prealloc),
1170 VG_(uinstrs_spill),
1171 VG_(total_reg_rank) );
1172 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001173 " sanity: %d cheap, %d expensive checks.",
1174 VG_(sanity_fast_count),
1175 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001176 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001177}
1178
1179
1180/* ---------------------------------------------------------------------
1181 Main!
1182 ------------------------------------------------------------------ */
1183
1184/* Where we jump to once Valgrind has got control, and the real
1185 machine's state has been copied to the m_state_static. */
1186
1187void VG_(main) ( void )
1188{
sewardj2e93c502002-04-12 11:12:52 +00001189 Int i;
1190 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001191 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001192
1193 /* Set up our stack sanity-check words. */
1194 for (i = 0; i < 10; i++) {
1195 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1196 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1197 }
1198
njn25e49d8e72002-09-23 09:36:25 +00001199 /* Setup stuff that depends on the skin. Must be before:
1200 - vg_init_baseBlock(): to register helpers
1201 - process_cmd_line_options(): to register skin name and description,
1202 and turn on/off 'command_line_options' need
1203 - init_memory() (to setup memory event trackers).
1204 */
njnd04b7c62002-10-03 14:05:52 +00001205 SK_(pre_clo_init) ( & VG_(details), & VG_(needs), & VG_(track_events) );
njn25e49d8e72002-09-23 09:36:25 +00001206 sanity_check_needs();
1207
1208 /* Set up baseBlock offsets and copy the saved machine's state into it. */
sewardjde4a1d02002-03-22 01:27:54 +00001209 vg_init_baseBlock();
1210 VG_(copy_m_state_static_to_baseBlock)();
sewardj92a59562002-09-30 00:53:10 +00001211 /* Pretend that the root thread has a completely empty LDT to start
1212 with. */
1213 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
njn25e49d8e72002-09-23 09:36:25 +00001214 vg_init_shadow_regs();
sewardjde4a1d02002-03-22 01:27:54 +00001215
1216 /* Process Valgrind's command-line opts (from env var VG_OPTS). */
1217 process_cmd_line_options();
1218
sewardj64039bb2002-06-03 00:58:18 +00001219 /* Hook to delay things long enough so we can get the pid and
1220 attach GDB in another shell. */
sewardj92a59562002-09-30 00:53:10 +00001221 if (0) {
sewardj64039bb2002-06-03 00:58:18 +00001222 Int p, q;
1223 for (p = 0; p < 50000; p++)
1224 for (q = 0; q < 50000; q++) ;
1225 }
1226
sewardj018f7622002-05-15 21:13:39 +00001227 /* Initialise the scheduler, and copy the client's state from
1228 baseBlock into VG_(threads)[1]. This has to come before signal
1229 initialisations. */
1230 VG_(scheduler_init)();
1231
1232 /* Initialise the signal handling subsystem, temporarily parking
1233 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001234 VG_(sigstartup_actions)();
1235
sewardj018f7622002-05-15 21:13:39 +00001236 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001237 if (VG_(clo_profile))
1238 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001239
sewardj5f07b662002-04-23 16:52:51 +00001240 /* Start calibration of our RDTSC-based clock. */
1241 VG_(start_rdtsc_calibration)();
1242
njn25e49d8e72002-09-23 09:36:25 +00001243 /* Do this here just to give rdtsc calibration more time */
1244 SK_(post_clo_init)();
sewardjde4a1d02002-03-22 01:27:54 +00001245
njn25e49d8e72002-09-23 09:36:25 +00001246 /* Must come after SK_(init) so memory handler accompaniments (eg.
1247 * shadow memory) can be setup ok */
1248 VGP_PUSHCC(VgpInitMem);
1249 VG_(init_memory)();
1250 VGP_POPCC(VgpInitMem);
1251
1252 /* Read the list of errors to suppress. This should be found in
1253 the file specified by vg_clo_suppressions. */
1254 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1255 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001256
sewardj5f07b662002-04-23 16:52:51 +00001257 /* End calibration of our RDTSC-based clock, leaving it as long as
1258 we can. */
1259 VG_(end_rdtsc_calibration)();
1260
njn25e49d8e72002-09-23 09:36:25 +00001261 /* This should come after init_memory_and_symbols(); otherwise the
1262 latter carefully sets up the permissions maps to cover the
1263 anonymous mmaps for the translation table and translation cache,
1264 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001265 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001266
1267 if (VG_(clo_verbosity) == 1) {
1268 VG_(message)(Vg_UserMsg,
1269 "For more details, rerun with: -v");
1270 }
1271
1272 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1273 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001274 if (VG_(clo_verbosity) > 0)
1275 VG_(message)(Vg_UserMsg, "");
1276
1277 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001278
sewardj018f7622002-05-15 21:13:39 +00001279 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001280 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001281 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001282 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001283 VGP_POPCC(VgpSched);
1284 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001285
1286 if (VG_(clo_verbosity) > 0)
1287 VG_(message)(Vg_UserMsg, "");
1288
sewardj2e93c502002-04-12 11:12:52 +00001289 if (src == VgSrc_Deadlock) {
1290 VG_(message)(Vg_UserMsg,
1291 "Warning: pthread scheduler exited due to deadlock");
1292 }
1293
njn25e49d8e72002-09-23 09:36:25 +00001294 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001295 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001296
njn25e49d8e72002-09-23 09:36:25 +00001297 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001298
sewardj0c3b53f2002-05-01 01:58:35 +00001299 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001300
1301 if (VG_(clo_verbosity) > 1)
1302 vg_show_counts();
1303
njn25e49d8e72002-09-23 09:36:25 +00001304 if (VG_(clo_verbosity) > 2)
1305 VG_(print_UInstr_histogram)();
1306
sewardjde4a1d02002-03-22 01:27:54 +00001307 if (0) {
1308 VG_(message)(Vg_DebugMsg, "");
1309 VG_(message)(Vg_DebugMsg,
1310 "------ Valgrind's internal memory use stats follow ------" );
1311 VG_(mallocSanityCheckAll)();
1312 VG_(show_all_arena_stats)();
1313 VG_(message)(Vg_DebugMsg,
1314 "------ Valgrind's ExeContext management stats follow ------" );
1315 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001316 }
1317
njn25e49d8e72002-09-23 09:36:25 +00001318 if (VG_(clo_profile))
1319 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001320
1321 VG_(shutdown_logging)();
1322
sewardj3e1eb1f2002-05-18 13:14:17 +00001323 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1324 processes don't get traced into. Also mess up $libdir/valgrind
1325 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001326 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001327 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1328 VG_(getenv)("LD_PRELOAD"),
1329 VG_(getenv)("LD_LIBRARY_PATH")
1330 );
sewardjde4a1d02002-03-22 01:27:54 +00001331 }
1332
sewardj7e87e382002-05-03 19:09:05 +00001333 /* Decide how to exit. This depends on what the scheduler
1334 returned. */
1335 switch (src) {
1336 case VgSrc_ExitSyscall: /* the normal way out */
1337 vg_assert(VG_(last_run_tid) > 0
1338 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001339 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001340 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001341 /* The thread's %EBX at the time it did __NR_exit() will hold
1342 the arg to __NR_exit(), so we just do __NR_exit() with
1343 that arg. */
1344 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001345 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001346 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001347 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001348
sewardj7e87e382002-05-03 19:09:05 +00001349 case VgSrc_Deadlock:
1350 /* Just exit now. No point in continuing. */
1351 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001352 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001353 break;
1354
1355 case VgSrc_BbsDone:
1356 /* Tricky; we have to try and switch back to the real CPU.
1357 This is all very dodgy and won't work at all in the
1358 presence of threads, or if the client happened to be
1359 running a signal handler. */
1360 /* Prepare to restore state to the real CPU. */
1361 VG_(load_thread_state)(1 /* root thread */ );
1362 VG_(copy_baseBlock_to_m_state_static)();
1363
1364 /* This pushes a return address on the simulator's stack,
1365 which is abandoned. We call vg_sigshutdown_actions() at
1366 the end of vg_switch_to_real_CPU(), so as to ensure that
1367 the original stack and machine state is restored before
1368 the real signal mechanism is restored. */
1369 VG_(switch_to_real_CPU)();
1370
1371 default:
njne427a662002-10-02 11:08:25 +00001372 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001373 }
sewardjde4a1d02002-03-22 01:27:54 +00001374}
1375
1376
1377/* Debugging thing .. can be called from assembly with OYNK macro. */
1378void VG_(oynk) ( Int n )
1379{
1380 OINK(n);
1381}
1382
1383
1384/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1385 "valgrinq.so", which doesn't do anything. This is used to avoid
1386 tracing into child processes. To make this work the build system
1387 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001388
njn25e49d8e72002-09-23 09:36:25 +00001389 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1390 without it, child processes try to find valgrind.so symbols in the
1391 skin .so.
1392
sewardj78e25c92002-05-20 23:38:33 +00001393 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1394 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1395 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001396*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001397void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1398 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001399{
njn25e49d8e72002-09-23 09:36:25 +00001400 Char* p_prel = NULL;
1401 Char* sk_prel = NULL;
1402 Char* p_path = NULL;
1403 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001404 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1405 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001406
sewardj78e25c92002-05-20 23:38:33 +00001407 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1408
1409 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001410 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001411 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1412
njn25e49d8e72002-09-23 09:36:25 +00001413 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001414 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001415 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001416 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1417 goto mutancy;
1418 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1419 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001420 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001421 }
1422
sewardj78e25c92002-05-20 23:38:33 +00001423 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001424 if (sk_prel == NULL) goto mutancy;
1425
1426 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001427 if (p_path == NULL) goto mutancy;
1428
njn25e49d8e72002-09-23 09:36:25 +00001429 what = 4;
1430 {
1431 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1432 Char* p = sk_prel;
1433 while (*p != ':' && p > ld_preload_str) {
1434 *p = ' ';
1435 p--;
1436 }
1437 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1438 while (*p != ':' && *p != '\0') {
1439 *p = ' ';
1440 p++;
1441 }
1442 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1443 *p = ' '; /* blank ending ':' */
1444 }
1445
sewardj78e25c92002-05-20 23:38:33 +00001446 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001447 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001448 if (p_prel[7] != 'd') goto mutancy;
1449 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001450
1451 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1452 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1453 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001454 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001455 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001456 if (p_path[0] != '/') goto mutancy;
1457 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001458 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001459 if (p_path[7] != 'd') goto mutancy;
1460 p_path[7] = 'q';
1461 return;
1462
1463 mutancy:
1464 VG_(printf)(
1465 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1466 " what = %d\n"
1467 " ld_preload_str = `%s'\n"
1468 " ld_library_path_str = `%s'\n"
1469 " p_prel = `%s'\n"
1470 " p_path = `%s'\n"
1471 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001472 what, ld_preload_str, ld_library_path_str,
1473 p_prel, p_path, VG_LIBDIR
1474 );
sewardjc26b4482002-07-13 12:20:35 +00001475 VG_(printf)(
1476 "\n"
1477 "Note that this is often caused by mis-installation of valgrind.\n"
1478 "Correct installation procedure is:\n"
1479 " ./configure --prefix=/install/dir\n"
1480 " make install\n"
1481 "And then use /install/dir/bin/valgrind\n"
1482 "Moving the installation directory elsewhere after 'make install'\n"
1483 "will cause the above error. Hand-editing the paths in the shell\n"
1484 "scripts is also likely to cause problems.\n"
1485 "\n"
1486 );
njne427a662002-10-02 11:08:25 +00001487 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001488}
1489
sewardj3e1eb1f2002-05-18 13:14:17 +00001490
sewardjde4a1d02002-03-22 01:27:54 +00001491/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1492 it to attach to this process. Called if the user requests this
1493 service after an error has been shown, so she can poke around and
1494 look at parameters, memory, etc. You can't meaningfully get GDB to
1495 continue the program, though; to continue, quit GDB. */
1496extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1497{
sewardje6a25242002-04-21 22:03:07 +00001498 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001499 UChar buf[100];
1500 VG_(sprintf)(buf,
1501 "/usr/bin/gdb -nw /proc/%d/exe %d",
1502 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001503 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1504 res = VG_(system)(buf);
1505 if (res == 0) {
1506 VG_(message)(Vg_UserMsg, "");
1507 VG_(message)(Vg_UserMsg,
1508 "GDB has detached. Valgrind regains control. We continue.");
1509 } else {
1510 VG_(message)(Vg_UserMsg, "Apparently failed!");
1511 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001512 }
sewardjde4a1d02002-03-22 01:27:54 +00001513}
1514
1515
1516/* Print some helpful-ish text about unimplemented things, and give
1517 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001518void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001519{
1520 VG_(message)(Vg_UserMsg, "");
1521 VG_(message)(Vg_UserMsg,
1522 "Valgrind detected that your program requires");
1523 VG_(message)(Vg_UserMsg,
1524 "the following unimplemented functionality:");
1525 VG_(message)(Vg_UserMsg, " %s", msg);
1526 VG_(message)(Vg_UserMsg,
1527 "This may be because the functionality is hard to implement,");
1528 VG_(message)(Vg_UserMsg,
1529 "or because no reasonable program would behave this way,");
1530 VG_(message)(Vg_UserMsg,
1531 "or because nobody has yet needed it. In any case, let me know");
1532 VG_(message)(Vg_UserMsg,
1533 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1534 VG_(message)(Vg_UserMsg,
1535 "");
1536 VG_(message)(Vg_UserMsg,
1537 "Valgrind has to exit now. Sorry. Bye!");
1538 VG_(message)(Vg_UserMsg,
1539 "");
sewardj15a43e12002-04-17 19:35:12 +00001540 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001541 VG_(exit)(1);
1542}
1543
1544
njn25e49d8e72002-09-23 09:36:25 +00001545/* ---------------------------------------------------------------------
1546 Sanity check machinery (permanently engaged).
1547 ------------------------------------------------------------------ */
1548
1549/* A fast sanity check -- suitable for calling circa once per
1550 millisecond. */
1551
1552void VG_(do_sanity_checks) ( Bool force_expensive )
1553{
1554 Int i;
1555
njn37cea302002-09-30 11:24:00 +00001556 VGP_PUSHCC(VgpCoreCheapSanity);
1557
njn25e49d8e72002-09-23 09:36:25 +00001558 if (VG_(sanity_level) < 1) return;
1559
1560 /* --- First do all the tests that we can do quickly. ---*/
1561
1562 VG_(sanity_fast_count)++;
1563
1564 /* Check that we haven't overrun our private stack. */
1565 for (i = 0; i < 10; i++) {
1566 vg_assert(VG_(stack)[i]
1567 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1568 vg_assert(VG_(stack)[10000-1-i]
1569 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1570 }
1571
1572 /* Check stuff pertaining to the memory check system. */
1573
1574 /* Check that nobody has spuriously claimed that the first or
1575 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001576 if (VG_(needs).sanity_checks) {
1577 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001578 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001579 VGP_POPCC(VgpSkinCheapSanity);
1580 }
njn25e49d8e72002-09-23 09:36:25 +00001581
1582 /* --- Now some more expensive checks. ---*/
1583
1584 /* Once every 25 times, check some more expensive stuff. */
1585 if ( force_expensive
1586 || VG_(sanity_level) > 1
1587 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1588
njn37cea302002-09-30 11:24:00 +00001589 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001590 VG_(sanity_slow_count)++;
1591
1592# if 0
1593 { void zzzmemscan(void); zzzmemscan(); }
1594# endif
1595
1596 if ((VG_(sanity_fast_count) % 250) == 0)
1597 VG_(sanity_check_tc_tt)();
1598
1599 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001600 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001601 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001602 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001603 }
1604 /*
1605 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1606 */
njn37cea302002-09-30 11:24:00 +00001607 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001608 }
1609
1610 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001611 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001612 /* Check sanity of the low-level memory manager. Note that bugs
1613 in the client's code can cause this to fail, so we don't do
1614 this check unless specially asked for. And because it's
1615 potentially very expensive. */
1616 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001617 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001618 }
njn37cea302002-09-30 11:24:00 +00001619 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001620}
sewardjde4a1d02002-03-22 01:27:54 +00001621/*--------------------------------------------------------------------*/
1622/*--- end vg_main.c ---*/
1623/*--------------------------------------------------------------------*/