blob: 4af88d375f2795bc559e8bb7b0c31d36f85d4976 [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/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
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)
129 VG_(panic)( "alloc_BaB: baseBlock is too small");
130
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);
150 VG_(panic)("Too many compact helpers registered");
151 }
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");
165 VG_(panic)("Too many non-compact helpers registered");
166 }
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
249 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000250 VGOFF_(helper_idiv_64_32)
251 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
252 VGOFF_(helper_div_64_32)
253 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
254 VGOFF_(helper_idiv_32_16)
255 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
256 VGOFF_(helper_div_32_16)
257 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
258 VGOFF_(helper_idiv_16_8)
259 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
260 VGOFF_(helper_div_16_8)
261 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
262
263 VGOFF_(helper_imul_32_64)
264 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
265 VGOFF_(helper_mul_32_64)
266 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
267 VGOFF_(helper_imul_16_32)
268 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
269 VGOFF_(helper_mul_16_32)
270 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
271 VGOFF_(helper_imul_8_16)
272 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
273 VGOFF_(helper_mul_8_16)
274 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
275
276 VGOFF_(helper_CLD)
277 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
278 VGOFF_(helper_STD)
279 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
280 VGOFF_(helper_get_dirflag)
281 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
282
sewardj7d78e782002-06-02 00:04:00 +0000283 VGOFF_(helper_CLC)
284 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
285 VGOFF_(helper_STC)
286 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
287
sewardjde4a1d02002-03-22 01:27:54 +0000288 VGOFF_(helper_shldl)
289 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
290 VGOFF_(helper_shldw)
291 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
292 VGOFF_(helper_shrdl)
293 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
294 VGOFF_(helper_shrdw)
295 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
296
297 VGOFF_(helper_RDTSC)
298 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
299 VGOFF_(helper_CPUID)
300 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
301
sewardjde4a1d02002-03-22 01:27:54 +0000302 VGOFF_(helper_bsf)
303 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
304 VGOFF_(helper_bsr)
305 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
306
307 VGOFF_(helper_fstsw_AX)
308 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
309 VGOFF_(helper_SAHF)
310 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000311 VGOFF_(helper_DAS)
312 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000313 VGOFF_(helper_DAA)
314 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000315
sewardj92a59562002-09-30 00:53:10 +0000316 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000317 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
318 VG_(noncompact_helper_offsets),
319 VG_(noncompact_helper_addrs));
320}
321
322static void vg_init_shadow_regs ( void )
323{
324 if (VG_(needs).shadow_regs) {
325 UInt eflags;
326
327 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
328 VG_(baseBlock)[VGOFF_(sh_esp)] =
329 VG_(baseBlock)[VGOFF_(sh_ebp)] =
330 VG_(baseBlock)[VGOFF_(sh_eax)] =
331 VG_(baseBlock)[VGOFF_(sh_ecx)] =
332 VG_(baseBlock)[VGOFF_(sh_edx)] =
333 VG_(baseBlock)[VGOFF_(sh_ebx)] =
334 VG_(baseBlock)[VGOFF_(sh_esi)] =
335 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
336 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
337
338 } else
339 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
sewardjde4a1d02002-03-22 01:27:54 +0000340}
341
342
343/* ---------------------------------------------------------------------
344 Global entities which are not referenced from generated code.
345 ------------------------------------------------------------------ */
346
347/* The stack on which Valgrind runs. We can't use the same stack as
348 the simulatee -- that's an important design decision. */
349UInt VG_(stack)[10000];
350
351/* Ditto our signal delivery stack. */
352UInt VG_(sigstack)[10000];
353
354/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000355UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
356Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000357
358/* Counts downwards in vg_run_innerloop. */
359UInt VG_(dispatch_ctr);
360
sewardjde4a1d02002-03-22 01:27:54 +0000361
362/* 64-bit counter for the number of basic blocks done. */
363ULong VG_(bbs_done);
364/* 64-bit counter for the number of bbs to go before a debug exit. */
365ULong VG_(bbs_to_go);
366
sewardjde4a1d02002-03-22 01:27:54 +0000367/* The current LRU epoch. */
368UInt VG_(current_epoch) = 0;
369
sewardj7e87e382002-05-03 19:09:05 +0000370/* This is the ThreadId of the last thread the scheduler ran. */
371ThreadId VG_(last_run_tid) = 0;
372
njn25e49d8e72002-09-23 09:36:25 +0000373/* This is the argument to __NR_exit() supplied by the first thread to
374 call that syscall. We eventually pass that to __NR_exit() for
375 real. */
376UInt VG_(exitcode) = 0;
377
sewardjde4a1d02002-03-22 01:27:54 +0000378
379/* ---------------------------------------------------------------------
380 Counters, for informational purposes only.
381 ------------------------------------------------------------------ */
382
383/* Number of lookups which miss the fast tt helper. */
384UInt VG_(tt_fast_misses) = 0;
385
386
387/* Counts for LRU informational messages. */
388
389/* Number and total o/t size of new translations this epoch. */
390UInt VG_(this_epoch_in_count) = 0;
391UInt VG_(this_epoch_in_osize) = 0;
392UInt VG_(this_epoch_in_tsize) = 0;
393/* Number and total o/t size of discarded translations this epoch. */
394UInt VG_(this_epoch_out_count) = 0;
395UInt VG_(this_epoch_out_osize) = 0;
396UInt VG_(this_epoch_out_tsize) = 0;
397/* Number and total o/t size of translations overall. */
398UInt VG_(overall_in_count) = 0;
399UInt VG_(overall_in_osize) = 0;
400UInt VG_(overall_in_tsize) = 0;
401/* Number and total o/t size of discards overall. */
402UInt VG_(overall_out_count) = 0;
403UInt VG_(overall_out_osize) = 0;
404UInt VG_(overall_out_tsize) = 0;
405
406/* The number of LRU-clearings of TT/TC. */
407UInt VG_(number_of_lrus) = 0;
408
409
410/* Counts pertaining to the register allocator. */
411
412/* total number of uinstrs input to reg-alloc */
413UInt VG_(uinstrs_prealloc) = 0;
414
415/* total number of uinstrs added due to spill code */
416UInt VG_(uinstrs_spill) = 0;
417
418/* number of bbs requiring spill code */
419UInt VG_(translations_needing_spill) = 0;
420
421/* total of register ranks over all translations */
422UInt VG_(total_reg_rank) = 0;
423
424
sewardjde4a1d02002-03-22 01:27:54 +0000425/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000426UInt VG_(sanity_fast_count) = 0;
427UInt VG_(sanity_slow_count) = 0;
428
sewardj2e93c502002-04-12 11:12:52 +0000429/* Counts pertaining to the scheduler. */
430UInt VG_(num_scheduling_events_MINOR) = 0;
431UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000432
433
434/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +0000435 Skin data structure initialisation
436 ------------------------------------------------------------------ */
437
438/* Init with default values. */
439VgNeeds VG_(needs) = {
440 .name = NULL,
441 .description = NULL,
442
443 .core_errors = False,
444 .skin_errors = False,
445 .run_libc_freeres = False,
446
447 .sizeof_shadow_block = 0,
448
449 .basic_block_discards = False,
450 .shadow_regs = False,
451 .command_line_options = False,
452 .client_requests = False,
453 .extended_UCode = False,
454 .syscall_wrapper = False,
455 .alternative_free = False,
456 .sanity_checks = False,
457};
458
459VgTrackEvents VG_(track_events) = {
460 /* Memory events */
461 .new_mem_startup = NULL,
462 .new_mem_heap = NULL,
463 .new_mem_stack = NULL,
464 .new_mem_stack_aligned = NULL,
465 .new_mem_stack_signal = NULL,
466 .new_mem_brk = NULL,
467 .new_mem_mmap = NULL,
468
469 .copy_mem_heap = NULL,
470 .change_mem_mprotect = NULL,
471
472 .ban_mem_heap = NULL,
473 .ban_mem_stack = NULL,
474
475 .die_mem_heap = NULL,
476 .die_mem_stack = NULL,
477 .die_mem_stack_aligned = NULL,
478 .die_mem_stack_signal = NULL,
479 .die_mem_brk = NULL,
480 .die_mem_munmap = NULL,
481
482 .bad_free = NULL,
483 .mismatched_free = NULL,
484
485 .pre_mem_read = NULL,
486 .pre_mem_read_asciiz = NULL,
487 .pre_mem_write = NULL,
488 .post_mem_write = NULL,
489
490 /* Mutex events */
491 .post_mutex_lock = NULL,
492 .post_mutex_unlock = NULL,
493};
494
495static void sanity_check_needs ( void )
496{
497#define CHECK_NOT(var, value) \
498 if ((var)==(value)) { \
499 VG_(printf)("\n`%s' not initialised\n", VG__STRING(var)); \
500 VG_(skin_error)("Uninitialised needs field\n"); \
501 }
502
503 CHECK_NOT(VG_(needs).name, NULL);
504 CHECK_NOT(VG_(needs).description, NULL);
505
506#undef CHECK_NOT
507#undef INVALID_Bool
508}
509
510/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000511 Values derived from command-line options.
512 ------------------------------------------------------------------ */
513
njn25e49d8e72002-09-23 09:36:25 +0000514/* Define, and set defaults. */
515Bool VG_(clo_error_limit) = True;
516Bool VG_(clo_GDB_attach) = False;
517Int VG_(sanity_level) = 1;
518Int VG_(clo_verbosity) = 1;
519Bool VG_(clo_demangle) = True;
520Bool VG_(clo_sloppy_malloc) = False;
521Int VG_(clo_alignment) = 4;
522Bool VG_(clo_trace_children) = False;
523Int VG_(clo_logfile_fd) = 2;
524Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000525Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000526Bool VG_(clo_profile) = False;
527Bool VG_(clo_single_step) = False;
528Bool VG_(clo_optimise) = True;
529UChar VG_(clo_trace_codegen) = 0; // 00000000b
530Bool VG_(clo_trace_syscalls) = False;
531Bool VG_(clo_trace_signals) = False;
532Bool VG_(clo_trace_symtab) = False;
533Bool VG_(clo_trace_malloc) = False;
534Bool VG_(clo_trace_sched) = False;
535Int VG_(clo_trace_pthread_level) = 0;
536ULong VG_(clo_stop_after) = 1000000000000LL;
537Int VG_(clo_dump_error) = 0;
538Int VG_(clo_backtrace_size) = 4;
539Char* VG_(clo_weird_hacks) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000540
541/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
542 to behave. Initially we say False. */
543Bool VG_(running_on_simd_CPU) = False;
544
545/* Holds client's %esp at the point we gained control. */
546Addr VG_(esp_at_startup);
547
548/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
549 envp[] as extracted from the client's stack at startup-time. */
550Int VG_(client_argc);
551Char** VG_(client_argv);
552Char** VG_(client_envp);
553
554/* A place into which to copy the value of env var VG_ARGS, so we
555 don't have to modify the original. */
556static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
557
sewardjde4a1d02002-03-22 01:27:54 +0000558/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000559 Processing of command-line options.
560 ------------------------------------------------------------------ */
561
njn25e49d8e72002-09-23 09:36:25 +0000562void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000563{
564 VG_(shutdown_logging)();
565 VG_(clo_logfile_fd) = 2; /* stderr */
566 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
567 VG_(exit)(1);
568}
569
570static void config_error ( Char* msg )
571{
572 VG_(shutdown_logging)();
573 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000574 VG_(printf)(
575 "valgrind.so: Startup or configuration error:\n %s\n", msg);
576 VG_(printf)(
577 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000578 VG_(exit)(1);
579}
580
sewardja1679dd2002-05-10 22:31:40 +0000581static void args_grok_error ( Char* msg )
582{
583 VG_(shutdown_logging)();
584 VG_(clo_logfile_fd) = 2; /* stderr */
585 VG_(printf)("valgrind.so: When searching for "
586 "client's argc/argc/envp:\n\t%s\n", msg);
587 config_error("couldn't find client's argc/argc/envp");
588}
589
njn25e49d8e72002-09-23 09:36:25 +0000590static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000591{
njn25e49d8e72002-09-23 09:36:25 +0000592 Char* usage1 =
593"usage: valgrind [options] prog-and-args\n"
594"\n"
595" core user options, with defaults in [ ], are:\n"
596" --help show this message\n"
597" --version show version\n"
598" --skin=<name> main task (skin to use) [Valgrind]\n"
599" -q --quiet run silently; only print error msgs\n"
600" -v --verbose be more verbose, incl counts of errors\n"
601" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
602" --demangle=no|yes automatically demangle C++ names? [yes]\n"
603" --num-callers=<number> show <num> callers in stack traces [4]\n"
604" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
605" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
606" --alignment=<number> set minimum alignment of allocations [4]\n"
607" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
608" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
609" --suppressions=<filename> suppress errors described in\n"
610" suppressions file <filename>\n"
611" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
612" recognised hacks are: ioctl-VTIME truncate-writes\n"
613"\n"
614" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000615
njn7cf0bd32002-06-08 13:36:03 +0000616
njn25e49d8e72002-09-23 09:36:25 +0000617 Char* usage2 =
618"\n"
619" core options for debugging Valgrind itself are:\n"
620" --sanity-level=<number> level of sanity checking to do [1]\n"
621" --single-step=no|yes translate each instr separately? [no]\n"
622" --optimise=no|yes improve intermediate code? [yes]\n"
623" --profile=no|yes profile? (skin must be built for it) [no]\n"
624" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
625" --trace-syscalls=no|yes show all system calls? [no]\n"
626" --trace-signals=no|yes show signal handling details? [no]\n"
627" --trace-symtab=no|yes show symbol table details? [no]\n"
628" --trace-malloc=no|yes show client malloc details? [no]\n"
629" --trace-sched=no|yes show thread scheduler details? [no]\n"
630" --trace-pthread=none|some|all show pthread event details? [no]\n"
631" --stop-after=<number> switch to real CPU after executing\n"
632" <number> basic blocks [infinity]\n"
633" --dump-error=<number> show translation for basic block\n"
634" associated with <number>'th\n"
635" error context [0=don't show any]\n"
636"\n"
637" Extra options are read from env variable $VALGRIND_OPTS\n"
638"\n"
639" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
640" and licensed under the GNU General Public License, version 2.\n"
641" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
642"\n";
njn7cf0bd32002-06-08 13:36:03 +0000643
njn25e49d8e72002-09-23 09:36:25 +0000644 VG_(printf)(usage1, VG_(needs).name);
645 /* Don't print skin string directly for security, ha! */
646 if (VG_(needs).command_line_options)
647 VG_(printf)("%s", SK_(usage)());
648 else
649 VG_(printf)(" (none)\n");
650 VG_(printf)(usage2, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000651
njn25e49d8e72002-09-23 09:36:25 +0000652 VG_(shutdown_logging)();
653 VG_(clo_logfile_fd) = 2; /* stderr */
654 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000655}
sewardjde4a1d02002-03-22 01:27:54 +0000656
657static void process_cmd_line_options ( void )
658{
njn25e49d8e72002-09-23 09:36:25 +0000659 Char* argv[M_VG_CMDLINE_OPTS];
660 UInt argc;
661 Char* p;
662 Char* str;
663 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000664
665# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
666# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
667# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
668
sewardjde4a1d02002-03-22 01:27:54 +0000669 eventually_logfile_fd = VG_(clo_logfile_fd);
670
671 /* Once logging is started, we can safely send messages pertaining
672 to failures in initialisation. */
673 VG_(startup_logging)();
674
sewardj19d81412002-06-03 01:10:40 +0000675 /* Check for sane path in ./configure --prefix=... */
676 if (VG_(strlen)(VG_LIBDIR) < 1
677 || VG_LIBDIR[0] != '/')
678 config_error("Please use absolute paths in "
679 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000680
sewardja1679dd2002-05-10 22:31:40 +0000681 /* (Suggested by Fabrice Bellard ... )
682 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000683 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000684 change less often than the libc ones. */
685 {
sewardja1679dd2002-05-10 22:31:40 +0000686 UInt* sp = 0; /* bogus init to keep gcc -O happy */
687
sewardj38170912002-05-10 21:07:22 +0000688 /* locate the top of the stack */
sewardja1679dd2002-05-10 22:31:40 +0000689 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
690 VG_STARTUP_STACK_BASE_1 )) {
691 sp = (UInt*)VG_STARTUP_STACK_BASE_1;
692 } else
693 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
694 VG_STARTUP_STACK_BASE_2 )) {
695 sp = (UInt*)VG_STARTUP_STACK_BASE_2;
daywalkera2562202002-07-15 19:39:51 +0000696 } else
697 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
698 VG_STARTUP_STACK_BASE_3 )) {
699 sp = (UInt*)VG_STARTUP_STACK_BASE_3;
njn25e49d8e72002-09-23 09:36:25 +0000700 } else
701 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
702 VG_STARTUP_STACK_BASE_4 )) {
703 sp = (UInt*)VG_STARTUP_STACK_BASE_4;
sewardja1679dd2002-05-10 22:31:40 +0000704 } else {
705 args_grok_error(
706 "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
707 "constants defined in vg_include.h. You should investigate."
708 );
709 }
710
sewardj38170912002-05-10 21:07:22 +0000711 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
712 the elf interpreter table */
713 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000714 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000715 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000716 sp--;
717 }
sewardj38170912002-05-10 21:07:22 +0000718
719 if (sp[2] == VKI_AT_BASE
720 && sp[0] == VKI_AT_PAGESZ
721 && sp[-2] == VKI_AT_PHNUM
722 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000723 && sp[-6] == VKI_AT_PHDR
724 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000725 if (0)
726 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000727 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000728 } else
729 if (sp[2] == VKI_AT_CLKTCK
730 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000731 && sp[-2] == VKI_AT_HWCAP
732 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000733 if (0)
734 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
735 sp -= 2;
736 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000737 if (sp[2] == VKI_AT_CLKTCK
738 && sp[0] == VKI_AT_PAGESZ
739 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000740 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
741 && sp[-4-1] == 0) {
742 if (0)
743 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
744 "kernel here.\n");
745 sp -= 4;
746 } else
747 if (sp[2] == VKI_AT_CLKTCK
748 && sp[0] == VKI_AT_PAGESZ
749 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000750 && sp[-2-20-1] == 0) {
751 if (0)
752 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
753 sp -= 22;
754 } else
sewardja1679dd2002-05-10 22:31:40 +0000755 args_grok_error(
756 "ELF frame does not look like 2.2.X or 2.4.X.\n "
757 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
758 );
sewardj38170912002-05-10 21:07:22 +0000759
760 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000761 if (*sp != 0)
762 args_grok_error("can't find NULL at end of env[]");
763
sewardj38170912002-05-10 21:07:22 +0000764 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000765 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000766 while (True) {
767 sp --;
768 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000769 if (++ctr >= 1000)
770 args_grok_error(
771 "suspiciously many (1000) env[] entries; giving up");
772
sewardj38170912002-05-10 21:07:22 +0000773 }
774 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000775 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000776
sewardja1679dd2002-05-10 22:31:40 +0000777 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000778 VG_(client_argc) = 0;
779 while (True) {
780 sp--;
781 if (*sp == VG_(client_argc))
782 break;
783 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000784 if (++ctr >= 1000)
785 args_grok_error(
786 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000787 }
788
sewardja1679dd2002-05-10 22:31:40 +0000789 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000790 }
791
sewardjde4a1d02002-03-22 01:27:54 +0000792 /* Now that VG_(client_envp) has been set, we can extract the args
793 for Valgrind itself. Copy into global var so that we don't have to
794 write zeroes to the getenv'd value itself. */
795 str = VG_(getenv)("VG_ARGS");
796 argc = 0;
797
798 if (!str) {
799 config_error("Can't read options from env var VG_ARGS.");
800 }
801
802 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
803 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
804 }
805 VG_(strcpy)(vg_cmdline_copy, str);
806 str = NULL;
807
808 p = &vg_cmdline_copy[0];
809 while (True) {
810 while (ISSPACE(*p)) { *p = 0; p++; }
811 if (*p == 0) break;
812 if (argc < M_VG_CMDLINE_OPTS-1) {
813 argv[argc] = p; argc++;
814 } else {
815 config_error(
816 "Found more than M_CMDLINE_OPTS command-line opts.");
817 }
818 while (*p != 0 && !ISSPACE(*p)) p++;
819 }
820
821 for (i = 0; i < argc; i++) {
822
njn25e49d8e72002-09-23 09:36:25 +0000823 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000824 VG_(clo_verbosity)++;
825 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
826 VG_(clo_verbosity)--;
827
sewardj2e432902002-06-13 20:44:00 +0000828 else if (STREQ(argv[i], "--error-limit=yes"))
829 VG_(clo_error_limit) = True;
830 else if (STREQ(argv[i], "--error-limit=no"))
831 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000832
sewardjde4a1d02002-03-22 01:27:54 +0000833 else if (STREQ(argv[i], "--gdb-attach=yes"))
834 VG_(clo_GDB_attach) = True;
835 else if (STREQ(argv[i], "--gdb-attach=no"))
836 VG_(clo_GDB_attach) = False;
837
838 else if (STREQ(argv[i], "--demangle=yes"))
839 VG_(clo_demangle) = True;
840 else if (STREQ(argv[i], "--demangle=no"))
841 VG_(clo_demangle) = False;
842
sewardjde4a1d02002-03-22 01:27:54 +0000843 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
844 VG_(clo_sloppy_malloc) = True;
845 else if (STREQ(argv[i], "--sloppy-malloc=no"))
846 VG_(clo_sloppy_malloc) = False;
847
sewardj246d4662002-06-14 10:17:05 +0000848 else if (STREQN(12, argv[i], "--alignment="))
849 VG_(clo_alignment) = (Int)VG_(atoll)(&argv[i][12]);
850
sewardjde4a1d02002-03-22 01:27:54 +0000851 else if (STREQ(argv[i], "--trace-children=yes"))
852 VG_(clo_trace_children) = True;
853 else if (STREQ(argv[i], "--trace-children=no"))
854 VG_(clo_trace_children) = False;
855
sewardjde4a1d02002-03-22 01:27:54 +0000856 else if (STREQN(15, argv[i], "--sanity-level="))
857 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
858
859 else if (STREQN(13, argv[i], "--logfile-fd="))
860 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
861
sewardjde4a1d02002-03-22 01:27:54 +0000862 else if (STREQN(15, argv[i], "--suppressions=")) {
863 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000864 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000865 VG_(message)(Vg_UserMsg,
866 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000867 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000868 }
869 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
870 VG_(clo_n_suppressions)++;
871 }
njn25e49d8e72002-09-23 09:36:25 +0000872 else if (STREQ(argv[i], "--profile=yes"))
873 VG_(clo_profile) = True;
874 else if (STREQ(argv[i], "--profile=no"))
875 VG_(clo_profile) = False;
876
sewardjde4a1d02002-03-22 01:27:54 +0000877 else if (STREQ(argv[i], "--single-step=yes"))
878 VG_(clo_single_step) = True;
879 else if (STREQ(argv[i], "--single-step=no"))
880 VG_(clo_single_step) = False;
881
882 else if (STREQ(argv[i], "--optimise=yes"))
883 VG_(clo_optimise) = True;
884 else if (STREQ(argv[i], "--optimise=no"))
885 VG_(clo_optimise) = False;
886
njn25e49d8e72002-09-23 09:36:25 +0000887 /* "vwxyz" --> 000zyxwv (binary) */
888 else if (STREQN(16, argv[i], "--trace-codegen=")) {
889 Int j;
890 char* opt = & argv[i][16];
891
892 if (5 != VG_(strlen)(opt)) {
893 VG_(message)(Vg_UserMsg,
894 "--trace-codegen argument must have 5 digits");
895 VG_(bad_option)(argv[i]);
896 }
897 for (j = 0; j < 5; j++) {
898 if ('0' == opt[j]) { /* do nothing */ }
899 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
900 else {
901 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
902 "contain 0s and 1s");
903 VG_(bad_option)(argv[i]);
904 }
905 }
906 }
sewardjde4a1d02002-03-22 01:27:54 +0000907
908 else if (STREQ(argv[i], "--trace-syscalls=yes"))
909 VG_(clo_trace_syscalls) = True;
910 else if (STREQ(argv[i], "--trace-syscalls=no"))
911 VG_(clo_trace_syscalls) = False;
912
913 else if (STREQ(argv[i], "--trace-signals=yes"))
914 VG_(clo_trace_signals) = True;
915 else if (STREQ(argv[i], "--trace-signals=no"))
916 VG_(clo_trace_signals) = False;
917
918 else if (STREQ(argv[i], "--trace-symtab=yes"))
919 VG_(clo_trace_symtab) = True;
920 else if (STREQ(argv[i], "--trace-symtab=no"))
921 VG_(clo_trace_symtab) = False;
922
923 else if (STREQ(argv[i], "--trace-malloc=yes"))
924 VG_(clo_trace_malloc) = True;
925 else if (STREQ(argv[i], "--trace-malloc=no"))
926 VG_(clo_trace_malloc) = False;
927
sewardj8937c812002-04-12 20:12:20 +0000928 else if (STREQ(argv[i], "--trace-sched=yes"))
929 VG_(clo_trace_sched) = True;
930 else if (STREQ(argv[i], "--trace-sched=no"))
931 VG_(clo_trace_sched) = False;
932
sewardj45b4b372002-04-16 22:50:32 +0000933 else if (STREQ(argv[i], "--trace-pthread=none"))
934 VG_(clo_trace_pthread_level) = 0;
935 else if (STREQ(argv[i], "--trace-pthread=some"))
936 VG_(clo_trace_pthread_level) = 1;
937 else if (STREQ(argv[i], "--trace-pthread=all"))
938 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000939
sewardj8d365b52002-05-12 10:52:16 +0000940 else if (STREQN(14, argv[i], "--weird-hacks="))
941 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000942
sewardjde4a1d02002-03-22 01:27:54 +0000943 else if (STREQN(13, argv[i], "--stop-after="))
944 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
945
946 else if (STREQN(13, argv[i], "--dump-error="))
947 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
948
949 else if (STREQN(14, argv[i], "--num-callers=")) {
950 /* Make sure it's sane. */
951 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
952 if (VG_(clo_backtrace_size) < 2)
953 VG_(clo_backtrace_size) = 2;
954 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
955 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
956 }
957
njn25e49d8e72002-09-23 09:36:25 +0000958 else if (VG_(needs).command_line_options) {
959 Bool ok = SK_(process_cmd_line_option)(argv[i]);
960 if (!ok)
961 usage();
962 }
sewardjde4a1d02002-03-22 01:27:54 +0000963 else
njn25e49d8e72002-09-23 09:36:25 +0000964 usage();
sewardjde4a1d02002-03-22 01:27:54 +0000965 }
966
967# undef ISSPACE
968# undef STREQ
969# undef STREQN
970
971 if (VG_(clo_verbosity < 0))
972 VG_(clo_verbosity) = 0;
973
sewardj246d4662002-06-14 10:17:05 +0000974 if (VG_(clo_alignment) < 4
975 || VG_(clo_alignment) > 4096
976 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
977 VG_(message)(Vg_UserMsg, "");
978 VG_(message)(Vg_UserMsg,
979 "Invalid --alignment= setting. "
980 "Should be a power of 2, >= 4, <= 4096.");
njn25e49d8e72002-09-23 09:36:25 +0000981 VG_(bad_option)("--alignment");
sewardj246d4662002-06-14 10:17:05 +0000982 }
983
sewardjde4a1d02002-03-22 01:27:54 +0000984 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
985 VG_(message)(Vg_UserMsg, "");
986 VG_(message)(Vg_UserMsg,
987 "--gdb-attach=yes conflicts with --trace-children=yes");
988 VG_(message)(Vg_UserMsg,
989 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +0000990 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +0000991 }
992
sewardjde4a1d02002-03-22 01:27:54 +0000993 VG_(clo_logfile_fd) = eventually_logfile_fd;
994
sewardj83adf412002-05-01 01:25:45 +0000995 if (VG_(clo_verbosity > 0)) {
njn25e49d8e72002-09-23 09:36:25 +0000996 VG_(message)(Vg_UserMsg, "%s-%s, %s for x86 GNU/Linux.",
997 VG_(needs).name, VERSION, VG_(needs).description);
sewardj83adf412002-05-01 01:25:45 +0000998 }
sewardj3b2736a2002-03-24 12:18:35 +0000999
sewardjde4a1d02002-03-22 01:27:54 +00001000 if (VG_(clo_verbosity > 0))
1001 VG_(message)(Vg_UserMsg,
1002 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
1003 if (VG_(clo_verbosity) > 1) {
1004 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1005 for (i = 0; i < argc; i++) {
1006 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1007 }
1008 }
1009
njn25e49d8e72002-09-23 09:36:25 +00001010 if (VG_(clo_n_suppressions) == 0 &&
1011 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001012 config_error("No error-suppression files were specified.");
1013 }
1014}
1015
sewardjde4a1d02002-03-22 01:27:54 +00001016/* ---------------------------------------------------------------------
1017 Copying to/from m_state_static.
1018 ------------------------------------------------------------------ */
1019
sewardj92a59562002-09-30 00:53:10 +00001020UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1021 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001022 + 1 /* %eflags */
1023 + 1 /* %eip */
1024 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1025 ];
1026
1027void VG_(copy_baseBlock_to_m_state_static) ( void )
1028{
1029 Int i;
sewardj92a59562002-09-30 00:53:10 +00001030 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1031 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1032 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1033 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1034 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1035 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001036
sewardj92a59562002-09-30 00:53:10 +00001037 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1038 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1039 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1040 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1041 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1042 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1043 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1044 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1045
1046 VG_(m_state_static)[56/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
1047 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001048
1049 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001050 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001051 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1052}
1053
1054
1055void VG_(copy_m_state_static_to_baseBlock) ( void )
1056{
1057 Int i;
sewardj92a59562002-09-30 00:53:10 +00001058 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1059 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1060 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1061 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1062 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1063 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001064
sewardj92a59562002-09-30 00:53:10 +00001065 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1066 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1067 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1068 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1069 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1070 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1071 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1072 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1073
1074 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4];
1075 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001076
1077 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1078 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001079 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001080}
1081
njn25e49d8e72002-09-23 09:36:25 +00001082Addr VG_(get_stack_pointer) ( void )
1083{
1084 return VG_(baseBlock)[VGOFF_(m_esp)];
1085}
1086
1087/* Some random tests needed for leak checking */
1088
1089Bool VG_(within_stack)(Addr a)
1090{
1091 if (a >= ((Addr)(&VG_(stack)))
1092 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1093 return True;
1094 else
1095 return False;
1096}
1097
1098Bool VG_(within_m_state_static)(Addr a)
1099{
1100 if (a >= ((Addr)(&VG_(m_state_static)))
1101 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1102 return True;
1103 else
1104 return False;
1105}
sewardjde4a1d02002-03-22 01:27:54 +00001106
1107/* ---------------------------------------------------------------------
1108 Show accumulated counts.
1109 ------------------------------------------------------------------ */
1110
njn25e49d8e72002-09-23 09:36:25 +00001111static __inline__ Int safe_idiv(Int a, Int b)
1112{
1113 return (b == 0 ? 0 : a / b);
1114}
1115
sewardjde4a1d02002-03-22 01:27:54 +00001116static void vg_show_counts ( void )
1117{
1118 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001119 " lru: %d epochs, %d clearings.",
1120 VG_(current_epoch),
1121 VG_(number_of_lrus) );
sewardjde4a1d02002-03-22 01:27:54 +00001122 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001123 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001124 VG_(overall_in_count),
1125 VG_(overall_in_osize),
1126 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001127 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1128 VG_(message)(Vg_DebugMsg,
1129 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001130 VG_(overall_out_count),
1131 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001132 VG_(overall_out_tsize),
1133 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001134 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001135 " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
1136 VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
1137 VG_(num_scheduling_events_MINOR),
1138 VG_(tt_fast_misses));
sewardjde4a1d02002-03-22 01:27:54 +00001139 VG_(message)(Vg_DebugMsg,
1140 "reg-alloc: %d t-req-spill, "
1141 "%d+%d orig+spill uis, %d total-reg-r.",
1142 VG_(translations_needing_spill),
1143 VG_(uinstrs_prealloc),
1144 VG_(uinstrs_spill),
1145 VG_(total_reg_rank) );
1146 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001147 " sanity: %d cheap, %d expensive checks.",
1148 VG_(sanity_fast_count),
1149 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001150 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001151}
1152
1153
1154/* ---------------------------------------------------------------------
1155 Main!
1156 ------------------------------------------------------------------ */
1157
1158/* Where we jump to once Valgrind has got control, and the real
1159 machine's state has been copied to the m_state_static. */
1160
1161void VG_(main) ( void )
1162{
sewardj2e93c502002-04-12 11:12:52 +00001163 Int i;
1164 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001165 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001166
1167 /* Set up our stack sanity-check words. */
1168 for (i = 0; i < 10; i++) {
1169 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1170 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1171 }
1172
njn25e49d8e72002-09-23 09:36:25 +00001173 /* Setup stuff that depends on the skin. Must be before:
1174 - vg_init_baseBlock(): to register helpers
1175 - process_cmd_line_options(): to register skin name and description,
1176 and turn on/off 'command_line_options' need
1177 - init_memory() (to setup memory event trackers).
1178 */
1179 SK_(pre_clo_init) ( & VG_(needs), & VG_(track_events) );
1180 sanity_check_needs();
1181
1182 /* Set up baseBlock offsets and copy the saved machine's state into it. */
sewardjde4a1d02002-03-22 01:27:54 +00001183 vg_init_baseBlock();
1184 VG_(copy_m_state_static_to_baseBlock)();
sewardj92a59562002-09-30 00:53:10 +00001185 /* Pretend that the root thread has a completely empty LDT to start
1186 with. */
1187 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
njn25e49d8e72002-09-23 09:36:25 +00001188 vg_init_shadow_regs();
sewardjde4a1d02002-03-22 01:27:54 +00001189
1190 /* Process Valgrind's command-line opts (from env var VG_OPTS). */
1191 process_cmd_line_options();
1192
sewardj64039bb2002-06-03 00:58:18 +00001193 /* Hook to delay things long enough so we can get the pid and
1194 attach GDB in another shell. */
sewardj92a59562002-09-30 00:53:10 +00001195 if (0) {
sewardj64039bb2002-06-03 00:58:18 +00001196 Int p, q;
1197 for (p = 0; p < 50000; p++)
1198 for (q = 0; q < 50000; q++) ;
1199 }
1200
sewardj018f7622002-05-15 21:13:39 +00001201 /* Initialise the scheduler, and copy the client's state from
1202 baseBlock into VG_(threads)[1]. This has to come before signal
1203 initialisations. */
1204 VG_(scheduler_init)();
1205
1206 /* Initialise the signal handling subsystem, temporarily parking
1207 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001208 VG_(sigstartup_actions)();
1209
sewardj018f7622002-05-15 21:13:39 +00001210 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001211 if (VG_(clo_profile))
1212 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001213
sewardj5f07b662002-04-23 16:52:51 +00001214 /* Start calibration of our RDTSC-based clock. */
1215 VG_(start_rdtsc_calibration)();
1216
njn25e49d8e72002-09-23 09:36:25 +00001217 /* Do this here just to give rdtsc calibration more time */
1218 SK_(post_clo_init)();
sewardjde4a1d02002-03-22 01:27:54 +00001219
njn25e49d8e72002-09-23 09:36:25 +00001220 /* Must come after SK_(init) so memory handler accompaniments (eg.
1221 * shadow memory) can be setup ok */
1222 VGP_PUSHCC(VgpInitMem);
1223 VG_(init_memory)();
1224 VGP_POPCC(VgpInitMem);
1225
1226 /* Read the list of errors to suppress. This should be found in
1227 the file specified by vg_clo_suppressions. */
1228 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1229 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001230
sewardj5f07b662002-04-23 16:52:51 +00001231 /* End calibration of our RDTSC-based clock, leaving it as long as
1232 we can. */
1233 VG_(end_rdtsc_calibration)();
1234
njn25e49d8e72002-09-23 09:36:25 +00001235 /* This should come after init_memory_and_symbols(); otherwise the
1236 latter carefully sets up the permissions maps to cover the
1237 anonymous mmaps for the translation table and translation cache,
1238 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001239 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001240
1241 if (VG_(clo_verbosity) == 1) {
1242 VG_(message)(Vg_UserMsg,
1243 "For more details, rerun with: -v");
1244 }
1245
1246 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1247 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001248 if (VG_(clo_verbosity) > 0)
1249 VG_(message)(Vg_UserMsg, "");
1250
1251 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001252
sewardj018f7622002-05-15 21:13:39 +00001253 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001254 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001255 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001256 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001257 VGP_POPCC(VgpSched);
1258 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001259
1260 if (VG_(clo_verbosity) > 0)
1261 VG_(message)(Vg_UserMsg, "");
1262
sewardj2e93c502002-04-12 11:12:52 +00001263 if (src == VgSrc_Deadlock) {
1264 VG_(message)(Vg_UserMsg,
1265 "Warning: pthread scheduler exited due to deadlock");
1266 }
1267
njn25e49d8e72002-09-23 09:36:25 +00001268 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001269 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001270
njn25e49d8e72002-09-23 09:36:25 +00001271 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001272
sewardj0c3b53f2002-05-01 01:58:35 +00001273 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001274
1275 if (VG_(clo_verbosity) > 1)
1276 vg_show_counts();
1277
njn25e49d8e72002-09-23 09:36:25 +00001278 if (VG_(clo_verbosity) > 2)
1279 VG_(print_UInstr_histogram)();
1280
sewardjde4a1d02002-03-22 01:27:54 +00001281 if (0) {
1282 VG_(message)(Vg_DebugMsg, "");
1283 VG_(message)(Vg_DebugMsg,
1284 "------ Valgrind's internal memory use stats follow ------" );
1285 VG_(mallocSanityCheckAll)();
1286 VG_(show_all_arena_stats)();
1287 VG_(message)(Vg_DebugMsg,
1288 "------ Valgrind's ExeContext management stats follow ------" );
1289 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001290 }
1291
njn25e49d8e72002-09-23 09:36:25 +00001292 if (VG_(clo_profile))
1293 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001294
1295 VG_(shutdown_logging)();
1296
sewardj3e1eb1f2002-05-18 13:14:17 +00001297 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1298 processes don't get traced into. Also mess up $libdir/valgrind
1299 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001300 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001301 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1302 VG_(getenv)("LD_PRELOAD"),
1303 VG_(getenv)("LD_LIBRARY_PATH")
1304 );
sewardjde4a1d02002-03-22 01:27:54 +00001305 }
1306
sewardj7e87e382002-05-03 19:09:05 +00001307 /* Decide how to exit. This depends on what the scheduler
1308 returned. */
1309 switch (src) {
1310 case VgSrc_ExitSyscall: /* the normal way out */
1311 vg_assert(VG_(last_run_tid) > 0
1312 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001313 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001314 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001315 /* The thread's %EBX at the time it did __NR_exit() will hold
1316 the arg to __NR_exit(), so we just do __NR_exit() with
1317 that arg. */
1318 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001319 /* NOT ALIVE HERE! */
1320 VG_(panic)("entered the afterlife in vg_main() -- ExitSyscall");
1321 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001322
sewardj7e87e382002-05-03 19:09:05 +00001323 case VgSrc_Deadlock:
1324 /* Just exit now. No point in continuing. */
1325 VG_(exit)(0);
1326 VG_(panic)("entered the afterlife in vg_main() -- Deadlock");
1327 break;
1328
1329 case VgSrc_BbsDone:
1330 /* Tricky; we have to try and switch back to the real CPU.
1331 This is all very dodgy and won't work at all in the
1332 presence of threads, or if the client happened to be
1333 running a signal handler. */
1334 /* Prepare to restore state to the real CPU. */
1335 VG_(load_thread_state)(1 /* root thread */ );
1336 VG_(copy_baseBlock_to_m_state_static)();
1337
1338 /* This pushes a return address on the simulator's stack,
1339 which is abandoned. We call vg_sigshutdown_actions() at
1340 the end of vg_switch_to_real_CPU(), so as to ensure that
1341 the original stack and machine state is restored before
1342 the real signal mechanism is restored. */
1343 VG_(switch_to_real_CPU)();
1344
1345 default:
1346 VG_(panic)("vg_main(): unexpected scheduler return code");
1347 }
sewardjde4a1d02002-03-22 01:27:54 +00001348}
1349
1350
1351/* Debugging thing .. can be called from assembly with OYNK macro. */
1352void VG_(oynk) ( Int n )
1353{
1354 OINK(n);
1355}
1356
1357
1358/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1359 "valgrinq.so", which doesn't do anything. This is used to avoid
1360 tracing into child processes. To make this work the build system
1361 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001362
njn25e49d8e72002-09-23 09:36:25 +00001363 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1364 without it, child processes try to find valgrind.so symbols in the
1365 skin .so.
1366
sewardj78e25c92002-05-20 23:38:33 +00001367 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1368 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1369 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001370*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001371void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1372 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001373{
njn25e49d8e72002-09-23 09:36:25 +00001374 Char* p_prel = NULL;
1375 Char* sk_prel = NULL;
1376 Char* p_path = NULL;
1377 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001378 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1379 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001380
sewardj78e25c92002-05-20 23:38:33 +00001381 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1382
1383 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001384 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001385 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1386
njn25e49d8e72002-09-23 09:36:25 +00001387 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001388 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001389 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001390 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1391 goto mutancy;
1392 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1393 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001394 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001395 }
1396
sewardj78e25c92002-05-20 23:38:33 +00001397 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001398 if (sk_prel == NULL) goto mutancy;
1399
1400 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001401 if (p_path == NULL) goto mutancy;
1402
njn25e49d8e72002-09-23 09:36:25 +00001403 what = 4;
1404 {
1405 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1406 Char* p = sk_prel;
1407 while (*p != ':' && p > ld_preload_str) {
1408 *p = ' ';
1409 p--;
1410 }
1411 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1412 while (*p != ':' && *p != '\0') {
1413 *p = ' ';
1414 p++;
1415 }
1416 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1417 *p = ' '; /* blank ending ':' */
1418 }
1419
sewardj78e25c92002-05-20 23:38:33 +00001420 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001421 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001422 if (p_prel[7] != 'd') goto mutancy;
1423 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001424
1425 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1426 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1427 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001428 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001429 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001430 if (p_path[0] != '/') goto mutancy;
1431 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001432 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001433 if (p_path[7] != 'd') goto mutancy;
1434 p_path[7] = 'q';
1435 return;
1436
1437 mutancy:
1438 VG_(printf)(
1439 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1440 " what = %d\n"
1441 " ld_preload_str = `%s'\n"
1442 " ld_library_path_str = `%s'\n"
1443 " p_prel = `%s'\n"
1444 " p_path = `%s'\n"
1445 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001446 what, ld_preload_str, ld_library_path_str,
1447 p_prel, p_path, VG_LIBDIR
1448 );
sewardjc26b4482002-07-13 12:20:35 +00001449 VG_(printf)(
1450 "\n"
1451 "Note that this is often caused by mis-installation of valgrind.\n"
1452 "Correct installation procedure is:\n"
1453 " ./configure --prefix=/install/dir\n"
1454 " make install\n"
1455 "And then use /install/dir/bin/valgrind\n"
1456 "Moving the installation directory elsewhere after 'make install'\n"
1457 "will cause the above error. Hand-editing the paths in the shell\n"
1458 "scripts is also likely to cause problems.\n"
1459 "\n"
1460 );
sewardj78e25c92002-05-20 23:38:33 +00001461 VG_(panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001462}
1463
sewardj3e1eb1f2002-05-18 13:14:17 +00001464
sewardjde4a1d02002-03-22 01:27:54 +00001465/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1466 it to attach to this process. Called if the user requests this
1467 service after an error has been shown, so she can poke around and
1468 look at parameters, memory, etc. You can't meaningfully get GDB to
1469 continue the program, though; to continue, quit GDB. */
1470extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1471{
sewardje6a25242002-04-21 22:03:07 +00001472 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001473 UChar buf[100];
1474 VG_(sprintf)(buf,
1475 "/usr/bin/gdb -nw /proc/%d/exe %d",
1476 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001477 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1478 res = VG_(system)(buf);
1479 if (res == 0) {
1480 VG_(message)(Vg_UserMsg, "");
1481 VG_(message)(Vg_UserMsg,
1482 "GDB has detached. Valgrind regains control. We continue.");
1483 } else {
1484 VG_(message)(Vg_UserMsg, "Apparently failed!");
1485 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001486 }
sewardjde4a1d02002-03-22 01:27:54 +00001487}
1488
1489
1490/* Print some helpful-ish text about unimplemented things, and give
1491 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001492void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001493{
1494 VG_(message)(Vg_UserMsg, "");
1495 VG_(message)(Vg_UserMsg,
1496 "Valgrind detected that your program requires");
1497 VG_(message)(Vg_UserMsg,
1498 "the following unimplemented functionality:");
1499 VG_(message)(Vg_UserMsg, " %s", msg);
1500 VG_(message)(Vg_UserMsg,
1501 "This may be because the functionality is hard to implement,");
1502 VG_(message)(Vg_UserMsg,
1503 "or because no reasonable program would behave this way,");
1504 VG_(message)(Vg_UserMsg,
1505 "or because nobody has yet needed it. In any case, let me know");
1506 VG_(message)(Vg_UserMsg,
1507 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1508 VG_(message)(Vg_UserMsg,
1509 "");
1510 VG_(message)(Vg_UserMsg,
1511 "Valgrind has to exit now. Sorry. Bye!");
1512 VG_(message)(Vg_UserMsg,
1513 "");
sewardj15a43e12002-04-17 19:35:12 +00001514 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001515 VG_(exit)(1);
1516}
1517
1518
njn25e49d8e72002-09-23 09:36:25 +00001519/* ---------------------------------------------------------------------
1520 Sanity check machinery (permanently engaged).
1521 ------------------------------------------------------------------ */
1522
1523/* A fast sanity check -- suitable for calling circa once per
1524 millisecond. */
1525
1526void VG_(do_sanity_checks) ( Bool force_expensive )
1527{
1528 Int i;
1529
njn37cea302002-09-30 11:24:00 +00001530 VGP_PUSHCC(VgpCoreCheapSanity);
1531
njn25e49d8e72002-09-23 09:36:25 +00001532 if (VG_(sanity_level) < 1) return;
1533
1534 /* --- First do all the tests that we can do quickly. ---*/
1535
1536 VG_(sanity_fast_count)++;
1537
1538 /* Check that we haven't overrun our private stack. */
1539 for (i = 0; i < 10; i++) {
1540 vg_assert(VG_(stack)[i]
1541 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1542 vg_assert(VG_(stack)[10000-1-i]
1543 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1544 }
1545
1546 /* Check stuff pertaining to the memory check system. */
1547
1548 /* Check that nobody has spuriously claimed that the first or
1549 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001550 if (VG_(needs).sanity_checks) {
1551 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001552 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001553 VGP_POPCC(VgpSkinCheapSanity);
1554 }
njn25e49d8e72002-09-23 09:36:25 +00001555
1556 /* --- Now some more expensive checks. ---*/
1557
1558 /* Once every 25 times, check some more expensive stuff. */
1559 if ( force_expensive
1560 || VG_(sanity_level) > 1
1561 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1562
njn37cea302002-09-30 11:24:00 +00001563 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001564 VG_(sanity_slow_count)++;
1565
1566# if 0
1567 { void zzzmemscan(void); zzzmemscan(); }
1568# endif
1569
1570 if ((VG_(sanity_fast_count) % 250) == 0)
1571 VG_(sanity_check_tc_tt)();
1572
1573 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001574 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001575 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001576 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001577 }
1578 /*
1579 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1580 */
njn37cea302002-09-30 11:24:00 +00001581 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001582 }
1583
1584 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001585 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001586 /* Check sanity of the low-level memory manager. Note that bugs
1587 in the client's code can cause this to fail, so we don't do
1588 this check unless specially asked for. And because it's
1589 potentially very expensive. */
1590 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001591 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001592 }
njn37cea302002-09-30 11:24:00 +00001593 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001594}
sewardjde4a1d02002-03-22 01:27:54 +00001595/*--------------------------------------------------------------------*/
1596/*--- end vg_main.c ---*/
1597/*--------------------------------------------------------------------*/