blob: d26bc29b25ee13b7484eb63f8ad797d81a964c45 [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));
njn25e49d8e72002-09-23 09:36:25 +0000322
njncc7bb472002-10-14 09:25:19 +0000323
324 /* Initialise slots that require it */
325 VG_(copy_m_state_static_to_baseBlock)();
326
327 /* Pretend the root thread has a completely empty LDT to start with. */
328 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
329
330 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000331 if (VG_(needs).shadow_regs) {
332 UInt eflags;
333
334 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
335 VG_(baseBlock)[VGOFF_(sh_esp)] =
336 VG_(baseBlock)[VGOFF_(sh_ebp)] =
337 VG_(baseBlock)[VGOFF_(sh_eax)] =
338 VG_(baseBlock)[VGOFF_(sh_ecx)] =
339 VG_(baseBlock)[VGOFF_(sh_edx)] =
340 VG_(baseBlock)[VGOFF_(sh_ebx)] =
341 VG_(baseBlock)[VGOFF_(sh_esi)] =
342 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
343 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
344
njncc7bb472002-10-14 09:25:19 +0000345 } else {
njn25e49d8e72002-09-23 09:36:25 +0000346 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000347 }
sewardjde4a1d02002-03-22 01:27:54 +0000348}
349
350
351/* ---------------------------------------------------------------------
352 Global entities which are not referenced from generated code.
353 ------------------------------------------------------------------ */
354
355/* The stack on which Valgrind runs. We can't use the same stack as
356 the simulatee -- that's an important design decision. */
357UInt VG_(stack)[10000];
358
359/* Ditto our signal delivery stack. */
360UInt VG_(sigstack)[10000];
361
362/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000363UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
364Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000365
366/* Counts downwards in vg_run_innerloop. */
367UInt VG_(dispatch_ctr);
368
sewardjde4a1d02002-03-22 01:27:54 +0000369
370/* 64-bit counter for the number of basic blocks done. */
371ULong VG_(bbs_done);
372/* 64-bit counter for the number of bbs to go before a debug exit. */
373ULong VG_(bbs_to_go);
374
sewardjde4a1d02002-03-22 01:27:54 +0000375/* The current LRU epoch. */
376UInt VG_(current_epoch) = 0;
377
sewardj7e87e382002-05-03 19:09:05 +0000378/* This is the ThreadId of the last thread the scheduler ran. */
379ThreadId VG_(last_run_tid) = 0;
380
njn25e49d8e72002-09-23 09:36:25 +0000381/* This is the argument to __NR_exit() supplied by the first thread to
382 call that syscall. We eventually pass that to __NR_exit() for
383 real. */
384UInt VG_(exitcode) = 0;
385
sewardjde4a1d02002-03-22 01:27:54 +0000386
387/* ---------------------------------------------------------------------
388 Counters, for informational purposes only.
389 ------------------------------------------------------------------ */
390
391/* Number of lookups which miss the fast tt helper. */
392UInt VG_(tt_fast_misses) = 0;
393
394
395/* Counts for LRU informational messages. */
396
397/* Number and total o/t size of new translations this epoch. */
398UInt VG_(this_epoch_in_count) = 0;
399UInt VG_(this_epoch_in_osize) = 0;
400UInt VG_(this_epoch_in_tsize) = 0;
401/* Number and total o/t size of discarded translations this epoch. */
402UInt VG_(this_epoch_out_count) = 0;
403UInt VG_(this_epoch_out_osize) = 0;
404UInt VG_(this_epoch_out_tsize) = 0;
405/* Number and total o/t size of translations overall. */
406UInt VG_(overall_in_count) = 0;
407UInt VG_(overall_in_osize) = 0;
408UInt VG_(overall_in_tsize) = 0;
409/* Number and total o/t size of discards overall. */
410UInt VG_(overall_out_count) = 0;
411UInt VG_(overall_out_osize) = 0;
412UInt VG_(overall_out_tsize) = 0;
413
414/* The number of LRU-clearings of TT/TC. */
415UInt VG_(number_of_lrus) = 0;
416
417
418/* Counts pertaining to the register allocator. */
419
420/* total number of uinstrs input to reg-alloc */
421UInt VG_(uinstrs_prealloc) = 0;
422
423/* total number of uinstrs added due to spill code */
424UInt VG_(uinstrs_spill) = 0;
425
426/* number of bbs requiring spill code */
427UInt VG_(translations_needing_spill) = 0;
428
429/* total of register ranks over all translations */
430UInt VG_(total_reg_rank) = 0;
431
432
sewardjde4a1d02002-03-22 01:27:54 +0000433/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000434UInt VG_(sanity_fast_count) = 0;
435UInt VG_(sanity_slow_count) = 0;
436
sewardj2e93c502002-04-12 11:12:52 +0000437/* Counts pertaining to the scheduler. */
438UInt VG_(num_scheduling_events_MINOR) = 0;
439UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000440
441
442/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +0000443 Skin data structure initialisation
444 ------------------------------------------------------------------ */
445
446/* Init with default values. */
njnd04b7c62002-10-03 14:05:52 +0000447VgDetails VG_(details) = {
448 .name = NULL,
449 .version = NULL,
450 .description = NULL,
451 .copyright_author = NULL,
452 .bug_reports_to = NULL,
453};
454
njn25e49d8e72002-09-23 09:36:25 +0000455VgNeeds VG_(needs) = {
njnd04b7c62002-10-03 14:05:52 +0000456 .core_errors = False,
457 .skin_errors = False,
458 .libc_freeres = False,
459 .sizeof_shadow_block = 0,
460 .basic_block_discards = False,
461 .shadow_regs = False,
462 .command_line_options = False,
463 .client_requests = False,
464 .extended_UCode = False,
465 .syscall_wrapper = False,
466 .alternative_free = False,
467 .sanity_checks = False,
sewardj8fe15a32002-10-20 19:29:21 +0000468 .data_syms = False,
njn25e49d8e72002-09-23 09:36:25 +0000469};
470
471VgTrackEvents VG_(track_events) = {
472 /* Memory events */
473 .new_mem_startup = NULL,
474 .new_mem_heap = NULL,
475 .new_mem_stack = NULL,
476 .new_mem_stack_aligned = NULL,
477 .new_mem_stack_signal = NULL,
478 .new_mem_brk = NULL,
479 .new_mem_mmap = NULL,
480
481 .copy_mem_heap = NULL,
njnd04b7c62002-10-03 14:05:52 +0000482 .copy_mem_remap = NULL,
njn25e49d8e72002-09-23 09:36:25 +0000483 .change_mem_mprotect = NULL,
484
485 .ban_mem_heap = NULL,
486 .ban_mem_stack = NULL,
487
488 .die_mem_heap = NULL,
489 .die_mem_stack = NULL,
490 .die_mem_stack_aligned = NULL,
491 .die_mem_stack_signal = NULL,
492 .die_mem_brk = NULL,
493 .die_mem_munmap = NULL,
494
495 .bad_free = NULL,
496 .mismatched_free = NULL,
497
498 .pre_mem_read = NULL,
499 .pre_mem_read_asciiz = NULL,
500 .pre_mem_write = NULL,
501 .post_mem_write = NULL,
502
njnd04b7c62002-10-03 14:05:52 +0000503 /* Scheduler events */
504 .thread_run = NULL,
505
njn25e49d8e72002-09-23 09:36:25 +0000506 /* Mutex events */
507 .post_mutex_lock = NULL,
508 .post_mutex_unlock = NULL,
509};
510
511static void sanity_check_needs ( void )
512{
njne427a662002-10-02 11:08:25 +0000513#define CHECK_NOT(var, value) \
514 if ((var)==(value)) { \
515 VG_(printf)("\nSkin error: `%s' not initialised\n", \
516 VG__STRING(var)); \
517 VG_(skin_panic)("Uninitialised needs field\n"); \
njn25e49d8e72002-09-23 09:36:25 +0000518 }
519
njnd04b7c62002-10-03 14:05:52 +0000520 CHECK_NOT(VG_(details).name, NULL);
521 /* Nb: .version can be NULL */
522 CHECK_NOT(VG_(details).description, NULL);
523 CHECK_NOT(VG_(details).copyright_author, NULL);
524 CHECK_NOT(VG_(details).bug_reports_to, NULL);
njn25e49d8e72002-09-23 09:36:25 +0000525
526#undef CHECK_NOT
527#undef INVALID_Bool
528}
529
530/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000531 Values derived from command-line options.
532 ------------------------------------------------------------------ */
533
njn25e49d8e72002-09-23 09:36:25 +0000534/* Define, and set defaults. */
535Bool VG_(clo_error_limit) = True;
536Bool VG_(clo_GDB_attach) = False;
537Int VG_(sanity_level) = 1;
538Int VG_(clo_verbosity) = 1;
539Bool VG_(clo_demangle) = True;
540Bool VG_(clo_sloppy_malloc) = False;
541Int VG_(clo_alignment) = 4;
542Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000543
544/* See big comment in vg_include.h for meaning of these three. */
545VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
546Int VG_(clo_logfile_fd) = 2;
547Char* VG_(clo_logfile_name) = NULL;
548
njn25e49d8e72002-09-23 09:36:25 +0000549Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000550Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000551Bool VG_(clo_profile) = False;
552Bool VG_(clo_single_step) = False;
553Bool VG_(clo_optimise) = True;
554UChar VG_(clo_trace_codegen) = 0; // 00000000b
555Bool VG_(clo_trace_syscalls) = False;
556Bool VG_(clo_trace_signals) = False;
557Bool VG_(clo_trace_symtab) = False;
558Bool VG_(clo_trace_malloc) = False;
559Bool VG_(clo_trace_sched) = False;
560Int VG_(clo_trace_pthread_level) = 0;
561ULong VG_(clo_stop_after) = 1000000000000LL;
562Int VG_(clo_dump_error) = 0;
563Int VG_(clo_backtrace_size) = 4;
564Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000565Bool VG_(clo_run_libc_freeres) = True;
sewardjde4a1d02002-03-22 01:27:54 +0000566
567/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
568 to behave. Initially we say False. */
569Bool VG_(running_on_simd_CPU) = False;
570
571/* Holds client's %esp at the point we gained control. */
572Addr VG_(esp_at_startup);
573
574/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
575 envp[] as extracted from the client's stack at startup-time. */
576Int VG_(client_argc);
577Char** VG_(client_argv);
578Char** VG_(client_envp);
579
580/* A place into which to copy the value of env var VG_ARGS, so we
581 don't have to modify the original. */
582static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
583
sewardjde4a1d02002-03-22 01:27:54 +0000584/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000585 Processing of command-line options.
586 ------------------------------------------------------------------ */
587
njn25e49d8e72002-09-23 09:36:25 +0000588void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000589{
590 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000591 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000592 VG_(clo_logfile_fd) = 2; /* stderr */
593 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
594 VG_(exit)(1);
595}
596
597static void config_error ( Char* msg )
598{
599 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000600 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000601 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000602 VG_(printf)(
603 "valgrind.so: Startup or configuration error:\n %s\n", msg);
604 VG_(printf)(
605 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000606 VG_(exit)(1);
607}
608
sewardja1679dd2002-05-10 22:31:40 +0000609static void args_grok_error ( Char* msg )
610{
611 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000612 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000613 VG_(clo_logfile_fd) = 2; /* stderr */
614 VG_(printf)("valgrind.so: When searching for "
615 "client's argc/argc/envp:\n\t%s\n", msg);
616 config_error("couldn't find client's argc/argc/envp");
617}
618
njn25e49d8e72002-09-23 09:36:25 +0000619static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000620{
njn25e49d8e72002-09-23 09:36:25 +0000621 Char* usage1 =
622"usage: valgrind [options] prog-and-args\n"
623"\n"
624" core user options, with defaults in [ ], are:\n"
625" --help show this message\n"
626" --version show version\n"
627" --skin=<name> main task (skin to use) [Valgrind]\n"
628" -q --quiet run silently; only print error msgs\n"
629" -v --verbose be more verbose, incl counts of errors\n"
630" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
631" --demangle=no|yes automatically demangle C++ names? [yes]\n"
632" --num-callers=<number> show <num> callers in stack traces [4]\n"
633" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
634" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
635" --alignment=<number> set minimum alignment of allocations [4]\n"
636" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000637" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000638" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000639" --logfile=<file> log messages to <file>.pid<pid>\n"
njn25e49d8e72002-09-23 09:36:25 +0000640" --suppressions=<filename> suppress errors described in\n"
641" suppressions file <filename>\n"
642" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000643" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000644"\n"
645" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000646
njn7cf0bd32002-06-08 13:36:03 +0000647
njn25e49d8e72002-09-23 09:36:25 +0000648 Char* usage2 =
649"\n"
650" core options for debugging Valgrind itself are:\n"
651" --sanity-level=<number> level of sanity checking to do [1]\n"
652" --single-step=no|yes translate each instr separately? [no]\n"
653" --optimise=no|yes improve intermediate code? [yes]\n"
654" --profile=no|yes profile? (skin must be built for it) [no]\n"
655" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
656" --trace-syscalls=no|yes show all system calls? [no]\n"
657" --trace-signals=no|yes show signal handling details? [no]\n"
658" --trace-symtab=no|yes show symbol table details? [no]\n"
659" --trace-malloc=no|yes show client malloc details? [no]\n"
660" --trace-sched=no|yes show thread scheduler details? [no]\n"
661" --trace-pthread=none|some|all show pthread event details? [no]\n"
662" --stop-after=<number> switch to real CPU after executing\n"
663" <number> basic blocks [infinity]\n"
664" --dump-error=<number> show translation for basic block\n"
665" associated with <number>'th\n"
666" error context [0=don't show any]\n"
667"\n"
668" Extra options are read from env variable $VALGRIND_OPTS\n"
669"\n"
670" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
671" and licensed under the GNU General Public License, version 2.\n"
672" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000673"\n"
674" Skins are copyright and licensed by their authors. See each\n"
675" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000676"\n";
njn7cf0bd32002-06-08 13:36:03 +0000677
njnd04b7c62002-10-03 14:05:52 +0000678 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000679 /* Don't print skin string directly for security, ha! */
680 if (VG_(needs).command_line_options)
681 VG_(printf)("%s", SK_(usage)());
682 else
683 VG_(printf)(" (none)\n");
684 VG_(printf)(usage2, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000685
njn25e49d8e72002-09-23 09:36:25 +0000686 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000687 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000688 VG_(clo_logfile_fd) = 2; /* stderr */
689 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000690}
sewardjde4a1d02002-03-22 01:27:54 +0000691
692static void process_cmd_line_options ( void )
693{
njn25e49d8e72002-09-23 09:36:25 +0000694 Char* argv[M_VG_CMDLINE_OPTS];
695 UInt argc;
696 Char* p;
697 Char* str;
698 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000699
700# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
701# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
702# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
703
sewardjde4a1d02002-03-22 01:27:54 +0000704 eventually_logfile_fd = VG_(clo_logfile_fd);
705
706 /* Once logging is started, we can safely send messages pertaining
707 to failures in initialisation. */
708 VG_(startup_logging)();
709
sewardj19d81412002-06-03 01:10:40 +0000710 /* Check for sane path in ./configure --prefix=... */
711 if (VG_(strlen)(VG_LIBDIR) < 1
712 || VG_LIBDIR[0] != '/')
713 config_error("Please use absolute paths in "
714 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000715
sewardja1679dd2002-05-10 22:31:40 +0000716 /* (Suggested by Fabrice Bellard ... )
717 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000718 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000719 change less often than the libc ones. */
720 {
sewardja1679dd2002-05-10 22:31:40 +0000721 UInt* sp = 0; /* bogus init to keep gcc -O happy */
722
sewardj38170912002-05-10 21:07:22 +0000723 /* locate the top of the stack */
sewardja1679dd2002-05-10 22:31:40 +0000724 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
725 VG_STARTUP_STACK_BASE_1 )) {
726 sp = (UInt*)VG_STARTUP_STACK_BASE_1;
727 } else
728 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
729 VG_STARTUP_STACK_BASE_2 )) {
730 sp = (UInt*)VG_STARTUP_STACK_BASE_2;
daywalkera2562202002-07-15 19:39:51 +0000731 } else
732 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
733 VG_STARTUP_STACK_BASE_3 )) {
734 sp = (UInt*)VG_STARTUP_STACK_BASE_3;
njn25e49d8e72002-09-23 09:36:25 +0000735 } else
736 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
737 VG_STARTUP_STACK_BASE_4 )) {
738 sp = (UInt*)VG_STARTUP_STACK_BASE_4;
sewardja1679dd2002-05-10 22:31:40 +0000739 } else {
740 args_grok_error(
741 "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
742 "constants defined in vg_include.h. You should investigate."
743 );
744 }
745
sewardj38170912002-05-10 21:07:22 +0000746 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
747 the elf interpreter table */
748 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000749 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000750 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000751 sp--;
752 }
sewardj38170912002-05-10 21:07:22 +0000753
754 if (sp[2] == VKI_AT_BASE
755 && sp[0] == VKI_AT_PAGESZ
756 && sp[-2] == VKI_AT_PHNUM
757 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000758 && sp[-6] == VKI_AT_PHDR
759 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000760 if (0)
761 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000762 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000763 } else
764 if (sp[2] == VKI_AT_CLKTCK
765 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000766 && sp[-2] == VKI_AT_HWCAP
767 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000768 if (0)
769 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
770 sp -= 2;
771 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000772 if (sp[2] == VKI_AT_CLKTCK
773 && sp[0] == VKI_AT_PAGESZ
774 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000775 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
776 && sp[-4-1] == 0) {
777 if (0)
778 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
779 "kernel here.\n");
780 sp -= 4;
781 } else
782 if (sp[2] == VKI_AT_CLKTCK
783 && sp[0] == VKI_AT_PAGESZ
784 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000785 && sp[-2-20-1] == 0) {
786 if (0)
787 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
788 sp -= 22;
789 } else
sewardja1679dd2002-05-10 22:31:40 +0000790 args_grok_error(
791 "ELF frame does not look like 2.2.X or 2.4.X.\n "
792 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
793 );
sewardj38170912002-05-10 21:07:22 +0000794
795 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000796 if (*sp != 0)
797 args_grok_error("can't find NULL at end of env[]");
798
sewardj38170912002-05-10 21:07:22 +0000799 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000800 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000801 while (True) {
802 sp --;
803 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000804 if (++ctr >= 1000)
805 args_grok_error(
806 "suspiciously many (1000) env[] entries; giving up");
807
sewardj38170912002-05-10 21:07:22 +0000808 }
809 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000810 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000811
sewardja1679dd2002-05-10 22:31:40 +0000812 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000813 VG_(client_argc) = 0;
814 while (True) {
815 sp--;
816 if (*sp == VG_(client_argc))
817 break;
818 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000819 if (++ctr >= 1000)
820 args_grok_error(
821 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000822 }
823
sewardja1679dd2002-05-10 22:31:40 +0000824 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000825 }
826
sewardjde4a1d02002-03-22 01:27:54 +0000827 /* Now that VG_(client_envp) has been set, we can extract the args
828 for Valgrind itself. Copy into global var so that we don't have to
829 write zeroes to the getenv'd value itself. */
830 str = VG_(getenv)("VG_ARGS");
831 argc = 0;
832
833 if (!str) {
834 config_error("Can't read options from env var VG_ARGS.");
835 }
836
837 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
838 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
839 }
840 VG_(strcpy)(vg_cmdline_copy, str);
841 str = NULL;
842
843 p = &vg_cmdline_copy[0];
844 while (True) {
845 while (ISSPACE(*p)) { *p = 0; p++; }
846 if (*p == 0) break;
847 if (argc < M_VG_CMDLINE_OPTS-1) {
848 argv[argc] = p; argc++;
849 } else {
850 config_error(
851 "Found more than M_CMDLINE_OPTS command-line opts.");
852 }
853 while (*p != 0 && !ISSPACE(*p)) p++;
854 }
855
856 for (i = 0; i < argc; i++) {
857
njn25e49d8e72002-09-23 09:36:25 +0000858 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000859 VG_(clo_verbosity)++;
860 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
861 VG_(clo_verbosity)--;
862
sewardj2e432902002-06-13 20:44:00 +0000863 else if (STREQ(argv[i], "--error-limit=yes"))
864 VG_(clo_error_limit) = True;
865 else if (STREQ(argv[i], "--error-limit=no"))
866 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000867
sewardjde4a1d02002-03-22 01:27:54 +0000868 else if (STREQ(argv[i], "--gdb-attach=yes"))
869 VG_(clo_GDB_attach) = True;
870 else if (STREQ(argv[i], "--gdb-attach=no"))
871 VG_(clo_GDB_attach) = False;
872
873 else if (STREQ(argv[i], "--demangle=yes"))
874 VG_(clo_demangle) = True;
875 else if (STREQ(argv[i], "--demangle=no"))
876 VG_(clo_demangle) = False;
877
sewardjde4a1d02002-03-22 01:27:54 +0000878 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
879 VG_(clo_sloppy_malloc) = True;
880 else if (STREQ(argv[i], "--sloppy-malloc=no"))
881 VG_(clo_sloppy_malloc) = False;
882
sewardj246d4662002-06-14 10:17:05 +0000883 else if (STREQN(12, argv[i], "--alignment="))
884 VG_(clo_alignment) = (Int)VG_(atoll)(&argv[i][12]);
885
sewardjde4a1d02002-03-22 01:27:54 +0000886 else if (STREQ(argv[i], "--trace-children=yes"))
887 VG_(clo_trace_children) = True;
888 else if (STREQ(argv[i], "--trace-children=no"))
889 VG_(clo_trace_children) = False;
890
sewardj858964b2002-10-05 14:15:43 +0000891 else if (STREQ(argv[i], "--run-libc-freeres=yes"))
892 VG_(clo_run_libc_freeres) = True;
893 else if (STREQ(argv[i], "--run-libc-freeres=no"))
894 VG_(clo_run_libc_freeres) = False;
895
sewardjde4a1d02002-03-22 01:27:54 +0000896 else if (STREQN(15, argv[i], "--sanity-level="))
897 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
898
sewardj4cf05692002-10-27 20:28:29 +0000899 else if (STREQN(13, argv[i], "--logfile-fd=")) {
900 VG_(clo_log_to) = VgLogTo_Fd;
901 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000902 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000903 }
904
905 else if (STREQN(10, argv[i], "--logfile=")) {
906 VG_(clo_log_to) = VgLogTo_File;
907 VG_(clo_logfile_name) = &argv[i][10];
908 }
sewardjde4a1d02002-03-22 01:27:54 +0000909
sewardjde4a1d02002-03-22 01:27:54 +0000910 else if (STREQN(15, argv[i], "--suppressions=")) {
911 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000912 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000913 VG_(message)(Vg_UserMsg,
914 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000915 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000916 }
917 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
918 VG_(clo_n_suppressions)++;
919 }
njn25e49d8e72002-09-23 09:36:25 +0000920 else if (STREQ(argv[i], "--profile=yes"))
921 VG_(clo_profile) = True;
922 else if (STREQ(argv[i], "--profile=no"))
923 VG_(clo_profile) = False;
924
sewardjde4a1d02002-03-22 01:27:54 +0000925 else if (STREQ(argv[i], "--single-step=yes"))
926 VG_(clo_single_step) = True;
927 else if (STREQ(argv[i], "--single-step=no"))
928 VG_(clo_single_step) = False;
929
930 else if (STREQ(argv[i], "--optimise=yes"))
931 VG_(clo_optimise) = True;
932 else if (STREQ(argv[i], "--optimise=no"))
933 VG_(clo_optimise) = False;
934
njn25e49d8e72002-09-23 09:36:25 +0000935 /* "vwxyz" --> 000zyxwv (binary) */
936 else if (STREQN(16, argv[i], "--trace-codegen=")) {
937 Int j;
938 char* opt = & argv[i][16];
939
940 if (5 != VG_(strlen)(opt)) {
941 VG_(message)(Vg_UserMsg,
942 "--trace-codegen argument must have 5 digits");
943 VG_(bad_option)(argv[i]);
944 }
945 for (j = 0; j < 5; j++) {
946 if ('0' == opt[j]) { /* do nothing */ }
947 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
948 else {
949 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
950 "contain 0s and 1s");
951 VG_(bad_option)(argv[i]);
952 }
953 }
954 }
sewardjde4a1d02002-03-22 01:27:54 +0000955
956 else if (STREQ(argv[i], "--trace-syscalls=yes"))
957 VG_(clo_trace_syscalls) = True;
958 else if (STREQ(argv[i], "--trace-syscalls=no"))
959 VG_(clo_trace_syscalls) = False;
960
961 else if (STREQ(argv[i], "--trace-signals=yes"))
962 VG_(clo_trace_signals) = True;
963 else if (STREQ(argv[i], "--trace-signals=no"))
964 VG_(clo_trace_signals) = False;
965
966 else if (STREQ(argv[i], "--trace-symtab=yes"))
967 VG_(clo_trace_symtab) = True;
968 else if (STREQ(argv[i], "--trace-symtab=no"))
969 VG_(clo_trace_symtab) = False;
970
971 else if (STREQ(argv[i], "--trace-malloc=yes"))
972 VG_(clo_trace_malloc) = True;
973 else if (STREQ(argv[i], "--trace-malloc=no"))
974 VG_(clo_trace_malloc) = False;
975
sewardj8937c812002-04-12 20:12:20 +0000976 else if (STREQ(argv[i], "--trace-sched=yes"))
977 VG_(clo_trace_sched) = True;
978 else if (STREQ(argv[i], "--trace-sched=no"))
979 VG_(clo_trace_sched) = False;
980
sewardj45b4b372002-04-16 22:50:32 +0000981 else if (STREQ(argv[i], "--trace-pthread=none"))
982 VG_(clo_trace_pthread_level) = 0;
983 else if (STREQ(argv[i], "--trace-pthread=some"))
984 VG_(clo_trace_pthread_level) = 1;
985 else if (STREQ(argv[i], "--trace-pthread=all"))
986 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000987
sewardj8d365b52002-05-12 10:52:16 +0000988 else if (STREQN(14, argv[i], "--weird-hacks="))
989 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000990
sewardjde4a1d02002-03-22 01:27:54 +0000991 else if (STREQN(13, argv[i], "--stop-after="))
992 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
993
994 else if (STREQN(13, argv[i], "--dump-error="))
995 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
996
997 else if (STREQN(14, argv[i], "--num-callers=")) {
998 /* Make sure it's sane. */
999 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1000 if (VG_(clo_backtrace_size) < 2)
1001 VG_(clo_backtrace_size) = 2;
1002 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1003 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1004 }
1005
njn25e49d8e72002-09-23 09:36:25 +00001006 else if (VG_(needs).command_line_options) {
1007 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1008 if (!ok)
1009 usage();
1010 }
sewardjde4a1d02002-03-22 01:27:54 +00001011 else
njn25e49d8e72002-09-23 09:36:25 +00001012 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001013 }
1014
1015# undef ISSPACE
1016# undef STREQ
1017# undef STREQN
1018
1019 if (VG_(clo_verbosity < 0))
1020 VG_(clo_verbosity) = 0;
1021
sewardj246d4662002-06-14 10:17:05 +00001022 if (VG_(clo_alignment) < 4
1023 || VG_(clo_alignment) > 4096
1024 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
1025 VG_(message)(Vg_UserMsg, "");
1026 VG_(message)(Vg_UserMsg,
1027 "Invalid --alignment= setting. "
1028 "Should be a power of 2, >= 4, <= 4096.");
njn25e49d8e72002-09-23 09:36:25 +00001029 VG_(bad_option)("--alignment");
sewardj246d4662002-06-14 10:17:05 +00001030 }
1031
sewardjde4a1d02002-03-22 01:27:54 +00001032 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1033 VG_(message)(Vg_UserMsg, "");
1034 VG_(message)(Vg_UserMsg,
1035 "--gdb-attach=yes conflicts with --trace-children=yes");
1036 VG_(message)(Vg_UserMsg,
1037 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001038 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001039 }
1040
sewardj4cf05692002-10-27 20:28:29 +00001041 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1042 should be connected to whatever sink has been selected, and we
1043 indiscriminately chuck stuff into it without worrying what the
1044 nature of it is. Oh the wonder of Unix streams. */
1045
1046 /* So far we should be still attached to stderr, so we can show on
1047 the terminal any problems to do with processing command line
1048 opts. */
1049 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
1050
1051 switch (VG_(clo_log_to)) {
1052 case VgLogTo_Socket:
1053 VG_(core_panic)("VgLogTo_Socket ?!");
1054 break;
1055 case VgLogTo_Fd:
1056 vg_assert(VG_(clo_logfile_name) == NULL);
1057 VG_(clo_logfile_fd) = eventually_logfile_fd;
1058 break;
1059 case VgLogTo_File: {
1060 Char logfilename[1000];
1061 vg_assert(VG_(clo_logfile_name) != NULL);
1062 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1063 VG_(sprintf)(logfilename, "%s.pid%d",
1064 VG_(clo_logfile_name), VG_(getpid)() );
1065 eventually_logfile_fd
1066 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1067 VKI_S_IRUSR|VKI_S_IWUSR);
1068 if (eventually_logfile_fd != -1) {
1069 VG_(clo_logfile_fd) = eventually_logfile_fd;
1070 } else {
1071 VG_(message)(Vg_UserMsg,
1072 "Can't create/open log file `%s.pid%d'; giving up!",
1073 VG_(clo_logfile_name), VG_(getpid)());
1074 VG_(bad_option)(
1075 "--logfile=<file> didn't work out for some reason.");
1076 }
1077 break;
1078 }
1079 }
1080
1081 /* Ok, the logging sink is running now. Print a suitable preamble.
1082 If logging to file or a socket, write details of parent PID and
1083 command line args, to help people trying to interpret the
1084 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001085
sewardj83adf412002-05-01 01:25:45 +00001086 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001087 /* Skin details */
1088 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1089 VG_(details).name,
1090 NULL == VG_(details).version ? "" : "-",
1091 NULL == VG_(details).version
1092 ? (Char*)"" : VG_(details).version,
1093 VG_(details).description);
1094 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001095
njnd04b7c62002-10-03 14:05:52 +00001096 /* Core details */
1097 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001098 "Using valgrind-%s, a program instrumentation system for x86-linux.",
1099 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001100 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001101 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001102 }
1103
sewardj4cf05692002-10-27 20:28:29 +00001104 if (VG_(clo_log_to) != VgLogTo_Fd) {
1105 VG_(message)(Vg_UserMsg, "");
1106 VG_(message)(Vg_UserMsg,
1107 "My PID = %d, parent PID = %d. Prog and args are:",
1108 VG_(getpid)(), VG_(getppid)() );
1109 for (i = 0; i < VG_(client_argc); i++)
1110 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1111 }
1112
sewardjde4a1d02002-03-22 01:27:54 +00001113 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001114 if (VG_(clo_log_to) != VgLogTo_Fd)
1115 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001116 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1117 for (i = 0; i < argc; i++) {
1118 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1119 }
1120 }
1121
njn25e49d8e72002-09-23 09:36:25 +00001122 if (VG_(clo_n_suppressions) == 0 &&
1123 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001124 config_error("No error-suppression files were specified.");
1125 }
sewardj4cf05692002-10-27 20:28:29 +00001126
sewardjde4a1d02002-03-22 01:27:54 +00001127}
1128
sewardjde4a1d02002-03-22 01:27:54 +00001129/* ---------------------------------------------------------------------
1130 Copying to/from m_state_static.
1131 ------------------------------------------------------------------ */
1132
sewardj92a59562002-09-30 00:53:10 +00001133UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1134 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001135 + 1 /* %eflags */
1136 + 1 /* %eip */
1137 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1138 ];
1139
1140void VG_(copy_baseBlock_to_m_state_static) ( void )
1141{
1142 Int i;
sewardj92a59562002-09-30 00:53:10 +00001143 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1144 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1145 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1146 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1147 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1148 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001149
sewardj92a59562002-09-30 00:53:10 +00001150 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1151 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1152 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1153 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1154 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1155 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1156 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1157 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1158
1159 VG_(m_state_static)[56/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
1160 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001161
1162 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001163 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001164 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1165}
1166
1167
1168void VG_(copy_m_state_static_to_baseBlock) ( void )
1169{
1170 Int i;
sewardj92a59562002-09-30 00:53:10 +00001171 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1172 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1173 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1174 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1175 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1176 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001177
sewardj92a59562002-09-30 00:53:10 +00001178 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1179 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1180 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1181 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1182 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1183 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1184 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1185 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1186
1187 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4];
1188 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001189
1190 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1191 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001192 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001193}
1194
njn25e49d8e72002-09-23 09:36:25 +00001195Addr VG_(get_stack_pointer) ( void )
1196{
1197 return VG_(baseBlock)[VGOFF_(m_esp)];
1198}
1199
1200/* Some random tests needed for leak checking */
1201
1202Bool VG_(within_stack)(Addr a)
1203{
1204 if (a >= ((Addr)(&VG_(stack)))
1205 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1206 return True;
1207 else
1208 return False;
1209}
1210
1211Bool VG_(within_m_state_static)(Addr a)
1212{
1213 if (a >= ((Addr)(&VG_(m_state_static)))
1214 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1215 return True;
1216 else
1217 return False;
1218}
sewardjde4a1d02002-03-22 01:27:54 +00001219
1220/* ---------------------------------------------------------------------
1221 Show accumulated counts.
1222 ------------------------------------------------------------------ */
1223
njn25e49d8e72002-09-23 09:36:25 +00001224static __inline__ Int safe_idiv(Int a, Int b)
1225{
1226 return (b == 0 ? 0 : a / b);
1227}
1228
sewardjde4a1d02002-03-22 01:27:54 +00001229static void vg_show_counts ( void )
1230{
1231 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001232 " lru: %d epochs, %d clearings.",
1233 VG_(current_epoch),
1234 VG_(number_of_lrus) );
sewardjde4a1d02002-03-22 01:27:54 +00001235 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001236 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001237 VG_(overall_in_count),
1238 VG_(overall_in_osize),
1239 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001240 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1241 VG_(message)(Vg_DebugMsg,
1242 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001243 VG_(overall_out_count),
1244 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001245 VG_(overall_out_tsize),
1246 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001247 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001248 " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
1249 VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
1250 VG_(num_scheduling_events_MINOR),
1251 VG_(tt_fast_misses));
sewardjde4a1d02002-03-22 01:27:54 +00001252 VG_(message)(Vg_DebugMsg,
1253 "reg-alloc: %d t-req-spill, "
1254 "%d+%d orig+spill uis, %d total-reg-r.",
1255 VG_(translations_needing_spill),
1256 VG_(uinstrs_prealloc),
1257 VG_(uinstrs_spill),
1258 VG_(total_reg_rank) );
1259 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001260 " sanity: %d cheap, %d expensive checks.",
1261 VG_(sanity_fast_count),
1262 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001263 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001264}
1265
1266
1267/* ---------------------------------------------------------------------
1268 Main!
1269 ------------------------------------------------------------------ */
1270
1271/* Where we jump to once Valgrind has got control, and the real
1272 machine's state has been copied to the m_state_static. */
1273
1274void VG_(main) ( void )
1275{
sewardj2e93c502002-04-12 11:12:52 +00001276 Int i;
1277 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001278 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001279
1280 /* Set up our stack sanity-check words. */
1281 for (i = 0; i < 10; i++) {
1282 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1283 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1284 }
1285
njn25e49d8e72002-09-23 09:36:25 +00001286 /* Setup stuff that depends on the skin. Must be before:
1287 - vg_init_baseBlock(): to register helpers
1288 - process_cmd_line_options(): to register skin name and description,
1289 and turn on/off 'command_line_options' need
1290 - init_memory() (to setup memory event trackers).
1291 */
njnd04b7c62002-10-03 14:05:52 +00001292 SK_(pre_clo_init) ( & VG_(details), & VG_(needs), & VG_(track_events) );
njn25e49d8e72002-09-23 09:36:25 +00001293 sanity_check_needs();
1294
njncc7bb472002-10-14 09:25:19 +00001295 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001296 process_cmd_line_options();
1297
njncc7bb472002-10-14 09:25:19 +00001298 /* Do post command-line processing initialisation */
1299 SK_(post_clo_init)();
1300
1301 /* Set up baseBlock offsets and copy the saved machine's state into it.
1302 Comes after SK_(post_clo_init) in case it registers helpers. */
1303 vg_init_baseBlock();
1304
sewardj64039bb2002-06-03 00:58:18 +00001305 /* Hook to delay things long enough so we can get the pid and
1306 attach GDB in another shell. */
sewardj92a59562002-09-30 00:53:10 +00001307 if (0) {
sewardj64039bb2002-06-03 00:58:18 +00001308 Int p, q;
sewardjc26cc252002-10-23 21:58:55 +00001309 VG_(printf)("pid=%d\n", VG_(getpid)());
sewardj64039bb2002-06-03 00:58:18 +00001310 for (p = 0; p < 50000; p++)
1311 for (q = 0; q < 50000; q++) ;
1312 }
1313
sewardj018f7622002-05-15 21:13:39 +00001314 /* Initialise the scheduler, and copy the client's state from
1315 baseBlock into VG_(threads)[1]. This has to come before signal
1316 initialisations. */
1317 VG_(scheduler_init)();
1318
1319 /* Initialise the signal handling subsystem, temporarily parking
1320 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001321 VG_(sigstartup_actions)();
1322
sewardj018f7622002-05-15 21:13:39 +00001323 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001324 if (VG_(clo_profile))
1325 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001326
sewardj5f07b662002-04-23 16:52:51 +00001327 /* Start calibration of our RDTSC-based clock. */
1328 VG_(start_rdtsc_calibration)();
1329
njn25e49d8e72002-09-23 09:36:25 +00001330 /* Must come after SK_(init) so memory handler accompaniments (eg.
1331 * shadow memory) can be setup ok */
1332 VGP_PUSHCC(VgpInitMem);
1333 VG_(init_memory)();
1334 VGP_POPCC(VgpInitMem);
1335
1336 /* Read the list of errors to suppress. This should be found in
1337 the file specified by vg_clo_suppressions. */
1338 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1339 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001340
sewardj5f07b662002-04-23 16:52:51 +00001341 /* End calibration of our RDTSC-based clock, leaving it as long as
1342 we can. */
1343 VG_(end_rdtsc_calibration)();
1344
njn25e49d8e72002-09-23 09:36:25 +00001345 /* This should come after init_memory_and_symbols(); otherwise the
1346 latter carefully sets up the permissions maps to cover the
1347 anonymous mmaps for the translation table and translation cache,
1348 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001349 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001350
1351 if (VG_(clo_verbosity) == 1) {
1352 VG_(message)(Vg_UserMsg,
1353 "For more details, rerun with: -v");
1354 }
1355
1356 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1357 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001358 if (VG_(clo_verbosity) > 0)
1359 VG_(message)(Vg_UserMsg, "");
1360
1361 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001362
sewardj018f7622002-05-15 21:13:39 +00001363 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001364 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001365 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001366 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001367 VGP_POPCC(VgpSched);
1368 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001369
1370 if (VG_(clo_verbosity) > 0)
1371 VG_(message)(Vg_UserMsg, "");
1372
sewardj2e93c502002-04-12 11:12:52 +00001373 if (src == VgSrc_Deadlock) {
1374 VG_(message)(Vg_UserMsg,
1375 "Warning: pthread scheduler exited due to deadlock");
1376 }
1377
njn25e49d8e72002-09-23 09:36:25 +00001378 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001379 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001380
njn25e49d8e72002-09-23 09:36:25 +00001381 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001382
sewardj0c3b53f2002-05-01 01:58:35 +00001383 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001384
1385 if (VG_(clo_verbosity) > 1)
1386 vg_show_counts();
1387
njn25e49d8e72002-09-23 09:36:25 +00001388 if (VG_(clo_verbosity) > 2)
1389 VG_(print_UInstr_histogram)();
1390
sewardjde4a1d02002-03-22 01:27:54 +00001391 if (0) {
1392 VG_(message)(Vg_DebugMsg, "");
1393 VG_(message)(Vg_DebugMsg,
1394 "------ Valgrind's internal memory use stats follow ------" );
1395 VG_(mallocSanityCheckAll)();
1396 VG_(show_all_arena_stats)();
1397 VG_(message)(Vg_DebugMsg,
1398 "------ Valgrind's ExeContext management stats follow ------" );
1399 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001400 }
1401
njn25e49d8e72002-09-23 09:36:25 +00001402 if (VG_(clo_profile))
1403 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001404
1405 VG_(shutdown_logging)();
1406
sewardj3e1eb1f2002-05-18 13:14:17 +00001407 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1408 processes don't get traced into. Also mess up $libdir/valgrind
1409 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001410 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001411 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1412 VG_(getenv)("LD_PRELOAD"),
1413 VG_(getenv)("LD_LIBRARY_PATH")
1414 );
sewardjde4a1d02002-03-22 01:27:54 +00001415 }
1416
sewardj7e87e382002-05-03 19:09:05 +00001417 /* Decide how to exit. This depends on what the scheduler
1418 returned. */
1419 switch (src) {
1420 case VgSrc_ExitSyscall: /* the normal way out */
1421 vg_assert(VG_(last_run_tid) > 0
1422 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001423 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001424 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001425 /* The thread's %EBX at the time it did __NR_exit() will hold
1426 the arg to __NR_exit(), so we just do __NR_exit() with
1427 that arg. */
1428 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001429 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001430 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001431 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001432
sewardj7e87e382002-05-03 19:09:05 +00001433 case VgSrc_Deadlock:
1434 /* Just exit now. No point in continuing. */
1435 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001436 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001437 break;
1438
1439 case VgSrc_BbsDone:
1440 /* Tricky; we have to try and switch back to the real CPU.
1441 This is all very dodgy and won't work at all in the
1442 presence of threads, or if the client happened to be
1443 running a signal handler. */
1444 /* Prepare to restore state to the real CPU. */
1445 VG_(load_thread_state)(1 /* root thread */ );
1446 VG_(copy_baseBlock_to_m_state_static)();
1447
1448 /* This pushes a return address on the simulator's stack,
1449 which is abandoned. We call vg_sigshutdown_actions() at
1450 the end of vg_switch_to_real_CPU(), so as to ensure that
1451 the original stack and machine state is restored before
1452 the real signal mechanism is restored. */
1453 VG_(switch_to_real_CPU)();
1454
1455 default:
njne427a662002-10-02 11:08:25 +00001456 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001457 }
sewardjde4a1d02002-03-22 01:27:54 +00001458}
1459
1460
1461/* Debugging thing .. can be called from assembly with OYNK macro. */
1462void VG_(oynk) ( Int n )
1463{
1464 OINK(n);
1465}
1466
1467
1468/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1469 "valgrinq.so", which doesn't do anything. This is used to avoid
1470 tracing into child processes. To make this work the build system
1471 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001472
njn25e49d8e72002-09-23 09:36:25 +00001473 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1474 without it, child processes try to find valgrind.so symbols in the
1475 skin .so.
1476
sewardj78e25c92002-05-20 23:38:33 +00001477 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1478 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1479 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001480*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001481void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1482 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001483{
njn25e49d8e72002-09-23 09:36:25 +00001484 Char* p_prel = NULL;
1485 Char* sk_prel = NULL;
1486 Char* p_path = NULL;
1487 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001488 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1489 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001490
sewardj78e25c92002-05-20 23:38:33 +00001491 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1492
1493 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001494 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001495 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1496
njn25e49d8e72002-09-23 09:36:25 +00001497 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001498 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001499 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001500 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1501 goto mutancy;
1502 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1503 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001504 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001505 }
1506
sewardj78e25c92002-05-20 23:38:33 +00001507 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001508 if (sk_prel == NULL) goto mutancy;
1509
1510 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001511 if (p_path == NULL) goto mutancy;
1512
njn25e49d8e72002-09-23 09:36:25 +00001513 what = 4;
1514 {
1515 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1516 Char* p = sk_prel;
1517 while (*p != ':' && p > ld_preload_str) {
1518 *p = ' ';
1519 p--;
1520 }
1521 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1522 while (*p != ':' && *p != '\0') {
1523 *p = ' ';
1524 p++;
1525 }
1526 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1527 *p = ' '; /* blank ending ':' */
1528 }
1529
sewardj78e25c92002-05-20 23:38:33 +00001530 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001531 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001532 if (p_prel[7] != 'd') goto mutancy;
1533 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001534
1535 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1536 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1537 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001538 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001539 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001540 if (p_path[0] != '/') goto mutancy;
1541 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001542 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001543 if (p_path[7] != 'd') goto mutancy;
1544 p_path[7] = 'q';
1545 return;
1546
1547 mutancy:
1548 VG_(printf)(
1549 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1550 " what = %d\n"
1551 " ld_preload_str = `%s'\n"
1552 " ld_library_path_str = `%s'\n"
1553 " p_prel = `%s'\n"
1554 " p_path = `%s'\n"
1555 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001556 what, ld_preload_str, ld_library_path_str,
1557 p_prel, p_path, VG_LIBDIR
1558 );
sewardjc26b4482002-07-13 12:20:35 +00001559 VG_(printf)(
1560 "\n"
1561 "Note that this is often caused by mis-installation of valgrind.\n"
1562 "Correct installation procedure is:\n"
1563 " ./configure --prefix=/install/dir\n"
1564 " make install\n"
1565 "And then use /install/dir/bin/valgrind\n"
1566 "Moving the installation directory elsewhere after 'make install'\n"
1567 "will cause the above error. Hand-editing the paths in the shell\n"
1568 "scripts is also likely to cause problems.\n"
1569 "\n"
1570 );
njne427a662002-10-02 11:08:25 +00001571 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001572}
1573
sewardj3e1eb1f2002-05-18 13:14:17 +00001574
sewardjde4a1d02002-03-22 01:27:54 +00001575/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1576 it to attach to this process. Called if the user requests this
1577 service after an error has been shown, so she can poke around and
1578 look at parameters, memory, etc. You can't meaningfully get GDB to
1579 continue the program, though; to continue, quit GDB. */
1580extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1581{
sewardje6a25242002-04-21 22:03:07 +00001582 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001583 UChar buf[100];
1584 VG_(sprintf)(buf,
1585 "/usr/bin/gdb -nw /proc/%d/exe %d",
1586 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001587 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1588 res = VG_(system)(buf);
1589 if (res == 0) {
1590 VG_(message)(Vg_UserMsg, "");
1591 VG_(message)(Vg_UserMsg,
1592 "GDB has detached. Valgrind regains control. We continue.");
1593 } else {
1594 VG_(message)(Vg_UserMsg, "Apparently failed!");
1595 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001596 }
sewardjde4a1d02002-03-22 01:27:54 +00001597}
1598
1599
1600/* Print some helpful-ish text about unimplemented things, and give
1601 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001602void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001603{
1604 VG_(message)(Vg_UserMsg, "");
1605 VG_(message)(Vg_UserMsg,
1606 "Valgrind detected that your program requires");
1607 VG_(message)(Vg_UserMsg,
1608 "the following unimplemented functionality:");
1609 VG_(message)(Vg_UserMsg, " %s", msg);
1610 VG_(message)(Vg_UserMsg,
1611 "This may be because the functionality is hard to implement,");
1612 VG_(message)(Vg_UserMsg,
1613 "or because no reasonable program would behave this way,");
1614 VG_(message)(Vg_UserMsg,
1615 "or because nobody has yet needed it. In any case, let me know");
1616 VG_(message)(Vg_UserMsg,
1617 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1618 VG_(message)(Vg_UserMsg,
1619 "");
1620 VG_(message)(Vg_UserMsg,
1621 "Valgrind has to exit now. Sorry. Bye!");
1622 VG_(message)(Vg_UserMsg,
1623 "");
sewardj15a43e12002-04-17 19:35:12 +00001624 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001625 VG_(exit)(1);
1626}
1627
1628
njn25e49d8e72002-09-23 09:36:25 +00001629/* ---------------------------------------------------------------------
1630 Sanity check machinery (permanently engaged).
1631 ------------------------------------------------------------------ */
1632
1633/* A fast sanity check -- suitable for calling circa once per
1634 millisecond. */
1635
1636void VG_(do_sanity_checks) ( Bool force_expensive )
1637{
1638 Int i;
1639
njn37cea302002-09-30 11:24:00 +00001640 VGP_PUSHCC(VgpCoreCheapSanity);
1641
njn25e49d8e72002-09-23 09:36:25 +00001642 if (VG_(sanity_level) < 1) return;
1643
1644 /* --- First do all the tests that we can do quickly. ---*/
1645
1646 VG_(sanity_fast_count)++;
1647
1648 /* Check that we haven't overrun our private stack. */
1649 for (i = 0; i < 10; i++) {
1650 vg_assert(VG_(stack)[i]
1651 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1652 vg_assert(VG_(stack)[10000-1-i]
1653 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1654 }
1655
1656 /* Check stuff pertaining to the memory check system. */
1657
1658 /* Check that nobody has spuriously claimed that the first or
1659 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001660 if (VG_(needs).sanity_checks) {
1661 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001662 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001663 VGP_POPCC(VgpSkinCheapSanity);
1664 }
njn25e49d8e72002-09-23 09:36:25 +00001665
1666 /* --- Now some more expensive checks. ---*/
1667
1668 /* Once every 25 times, check some more expensive stuff. */
1669 if ( force_expensive
1670 || VG_(sanity_level) > 1
1671 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1672
njn37cea302002-09-30 11:24:00 +00001673 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001674 VG_(sanity_slow_count)++;
1675
1676# if 0
1677 { void zzzmemscan(void); zzzmemscan(); }
1678# endif
1679
1680 if ((VG_(sanity_fast_count) % 250) == 0)
1681 VG_(sanity_check_tc_tt)();
1682
1683 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001684 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001685 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001686 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001687 }
1688 /*
1689 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1690 */
njn37cea302002-09-30 11:24:00 +00001691 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001692 }
1693
1694 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001695 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001696 /* Check sanity of the low-level memory manager. Note that bugs
1697 in the client's code can cause this to fail, so we don't do
1698 this check unless specially asked for. And because it's
1699 potentially very expensive. */
1700 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001701 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001702 }
njn37cea302002-09-30 11:24:00 +00001703 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001704}
sewardjde4a1d02002-03-22 01:27:54 +00001705/*--------------------------------------------------------------------*/
1706/*--- end vg_main.c ---*/
1707/*--------------------------------------------------------------------*/