blob: f007714e9b7f30afc34b33d3635af30a8d8c768e [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
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32#include "vg_include.h"
sewardjde4a1d02002-03-22 01:27:54 +000033
34/* ---------------------------------------------------------------------
35 Compute offsets into baseBlock. See comments in vg_include.h.
36 ------------------------------------------------------------------ */
37
38/* The variables storing offsets. */
39
40#define INVALID_OFFSET (-1)
41
42Int VGOFF_(m_eax) = INVALID_OFFSET;
43Int VGOFF_(m_ecx) = INVALID_OFFSET;
44Int VGOFF_(m_edx) = INVALID_OFFSET;
45Int VGOFF_(m_ebx) = INVALID_OFFSET;
46Int VGOFF_(m_esp) = INVALID_OFFSET;
47Int VGOFF_(m_ebp) = INVALID_OFFSET;
48Int VGOFF_(m_esi) = INVALID_OFFSET;
49Int VGOFF_(m_edi) = INVALID_OFFSET;
50Int VGOFF_(m_eflags) = INVALID_OFFSET;
sewardjfa492d42002-12-08 18:20:01 +000051Int VGOFF_(m_dflag) = INVALID_OFFSET;
sewardjb91ae7f2003-04-29 23:50:00 +000052Int VGOFF_(m_ssestate) = INVALID_OFFSET;
sewardj92a59562002-09-30 00:53:10 +000053Int VGOFF_(ldt) = INVALID_OFFSET;
54Int VGOFF_(m_cs) = INVALID_OFFSET;
55Int VGOFF_(m_ss) = INVALID_OFFSET;
56Int VGOFF_(m_ds) = INVALID_OFFSET;
57Int VGOFF_(m_es) = INVALID_OFFSET;
58Int VGOFF_(m_fs) = INVALID_OFFSET;
59Int VGOFF_(m_gs) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000060Int VGOFF_(m_eip) = INVALID_OFFSET;
61Int VGOFF_(spillslots) = INVALID_OFFSET;
62Int VGOFF_(sh_eax) = INVALID_OFFSET;
63Int VGOFF_(sh_ecx) = INVALID_OFFSET;
64Int VGOFF_(sh_edx) = INVALID_OFFSET;
65Int VGOFF_(sh_ebx) = INVALID_OFFSET;
66Int VGOFF_(sh_esp) = INVALID_OFFSET;
67Int VGOFF_(sh_ebp) = INVALID_OFFSET;
68Int VGOFF_(sh_esi) = INVALID_OFFSET;
69Int VGOFF_(sh_edi) = INVALID_OFFSET;
70Int VGOFF_(sh_eflags) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +000071
sewardjde4a1d02002-03-22 01:27:54 +000072Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
73Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
74Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
75Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
76Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
77Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
78Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
79Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
80Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
81Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
82Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
83Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
84Int VGOFF_(helper_CLD) = INVALID_OFFSET;
85Int VGOFF_(helper_STD) = INVALID_OFFSET;
86Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
sewardj7d78e782002-06-02 00:04:00 +000087Int VGOFF_(helper_CLC) = INVALID_OFFSET;
88Int VGOFF_(helper_STC) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000089Int VGOFF_(helper_shldl) = INVALID_OFFSET;
90Int VGOFF_(helper_shldw) = INVALID_OFFSET;
91Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
92Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
daywalkerb18d2532003-09-27 20:15:01 +000093Int VGOFF_(helper_IN) = INVALID_OFFSET;
94Int VGOFF_(helper_OUT) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000095Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
96Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
97Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000098Int VGOFF_(helper_bsf) = INVALID_OFFSET;
99Int VGOFF_(helper_bsr) = INVALID_OFFSET;
100Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
101Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
njnd6251f12003-06-03 13:38:51 +0000102Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +0000103Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +0000104Int VGOFF_(helper_DAA) = INVALID_OFFSET;
sewardj51096432002-12-14 23:59:09 +0000105Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +0000106
107/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
108 * increased too much, they won't really be compact any more... */
109#define MAX_COMPACT_HELPERS 8
njnfedb7362003-02-24 10:21:45 +0000110#define MAX_NONCOMPACT_HELPERS 50
njn25e49d8e72002-09-23 09:36:25 +0000111
112UInt VG_(n_compact_helpers) = 0;
113UInt VG_(n_noncompact_helpers) = 0;
114
115Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
116Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
117Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
118Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
sewardjde4a1d02002-03-22 01:27:54 +0000119
120/* This is the actual defn of baseblock. */
121UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
122
fitzhardinge98abfc72003-12-16 02:05:15 +0000123/* Client address space */
124Addr VG_(client_base); /* client address space limits */
125Addr VG_(client_end);
126Addr VG_(client_mapbase);
127Addr VG_(clstk_base);
128Addr VG_(clstk_end);
129Addr VG_(brk_base); /* start of brk */
130Addr VG_(brk_limit); /* current brk */
131Addr VG_(shadow_base); /* skin's shadow memory */
132Addr VG_(shadow_end);
133Addr VG_(valgrind_base); /* valgrind's address range */
134Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
135Addr VG_(valgrind_end);
136
137/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000138Int VG_(vgexecfd) = -1;
139
140/* client executable */
141Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000142
143/* Path to library directory */
144const Char *VG_(libdir) = VG_LIBDIR;
145
146/* our argc/argv */
147Int VG_(vg_argc);
148Char **VG_(vg_argv);
149
jsgf855d93d2003-10-13 22:26:55 +0000150/* PID of the main thread */
151Int VG_(main_pid);
152
153/* PGRP of process */
154Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000155
fitzhardingef0046f22003-12-18 02:39:22 +0000156/* Maximum allowed application-visible file descriptor */
157Int VG_(max_fd);
158
sewardjde4a1d02002-03-22 01:27:54 +0000159/* Words. */
160static Int baB_off = 0;
161
jsgf855d93d2003-10-13 22:26:55 +0000162/* jmp_buf for fatal signals */
163Int VG_(fatal_sigNo) = -1;
164Bool VG_(fatal_signal_set) = False;
165jmp_buf VG_(fatal_signal_jmpbuf);
166
sewardjde4a1d02002-03-22 01:27:54 +0000167/* Returns the offset, in words. */
168static Int alloc_BaB ( Int words )
169{
170 Int off = baB_off;
171 baB_off += words;
172 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000173 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000174
175 return off;
176}
177
njn0c7a5b52003-04-30 09:00:33 +0000178/* Align offset, in *bytes* */
179static void align_BaB ( UInt align )
180{
181 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
182 baB_off += (align-1);
183 baB_off &= ~(align-1);
184}
185
sewardjde4a1d02002-03-22 01:27:54 +0000186/* Allocate 1 word in baseBlock and set it to the given value. */
daywalkerb106c422003-09-29 10:56:24 +0000187static Int alloc_BaB_1_set ( Addr a )
sewardjde4a1d02002-03-22 01:27:54 +0000188{
189 Int off = alloc_BaB(1);
190 VG_(baseBlock)[off] = (UInt)a;
191 return off;
192}
193
njn25e49d8e72002-09-23 09:36:25 +0000194/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000195 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000196void VG_(register_compact_helper)(Addr a)
197{
198 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
199 VG_(printf)("Can only register %d compact helpers\n",
200 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000201 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000202 }
203 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
204 VG_(n_compact_helpers)++;
205}
206
207/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
208 * is filled in later.
209 */
210void VG_(register_noncompact_helper)(Addr a)
211{
212 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
213 VG_(printf)("Can only register %d non-compact helpers\n",
214 MAX_NONCOMPACT_HELPERS);
215 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000216 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000217 }
218 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
219 VG_(n_noncompact_helpers)++;
220}
221
222/* Allocate offsets in baseBlock for the skin helpers */
sewardj05bcdcb2003-05-18 10:05:38 +0000223static
224void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
njn25e49d8e72002-09-23 09:36:25 +0000225{
sewardj05bcdcb2003-05-18 10:05:38 +0000226 UInt i;
227 for (i = 0; i < n; i++)
daywalkerb106c422003-09-29 10:56:24 +0000228 offsets[i] = alloc_BaB_1_set( addrs[i] );
njn25e49d8e72002-09-23 09:36:25 +0000229}
sewardjde4a1d02002-03-22 01:27:54 +0000230
njnf4ce3d32003-02-10 10:17:26 +0000231Bool VG_(need_to_handle_esp_assignment)(void)
232{
fitzhardinge98abfc72003-12-16 02:05:15 +0000233 return ( VG_(defined_new_mem_stack_4)() ||
234 VG_(defined_die_mem_stack_4)() ||
235 VG_(defined_new_mem_stack_8)() ||
236 VG_(defined_die_mem_stack_8)() ||
237 VG_(defined_new_mem_stack_12)() ||
238 VG_(defined_die_mem_stack_12)() ||
239 VG_(defined_new_mem_stack_16)() ||
240 VG_(defined_die_mem_stack_16)() ||
241 VG_(defined_new_mem_stack_32)() ||
242 VG_(defined_die_mem_stack_32)() ||
243 VG_(defined_new_mem_stack)() ||
244 VG_(defined_die_mem_stack)()
njn9b007f62003-04-07 14:40:25 +0000245 );
njnf4ce3d32003-02-10 10:17:26 +0000246}
247
sewardjde4a1d02002-03-22 01:27:54 +0000248/* Here we assign actual offsets. It's important to get the most
249 popular referents within 128 bytes of the start, so we can take
250 advantage of short addressing modes relative to %ebp. Popularity
251 of offsets was measured on 22 Feb 02 running a KDE application, and
252 the slots rearranged accordingly, with a 1.5% reduction in total
253 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000254static void vg_init_baseBlock ( void )
255{
sewardjde4a1d02002-03-22 01:27:54 +0000256 /* Those with offsets under 128 are carefully chosen. */
257
258 /* WORD offsets in this column */
259 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
260 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
261 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
262 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
263 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
264 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
265 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
266 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
267 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
268
njn25e49d8e72002-09-23 09:36:25 +0000269 if (VG_(needs).shadow_regs) {
270 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
271 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
272 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
273 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
274 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
275 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
276 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
277 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
278 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
279 }
sewardjde4a1d02002-03-22 01:27:54 +0000280
njn25e49d8e72002-09-23 09:36:25 +0000281 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
282 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000283
njn9b007f62003-04-07 14:40:25 +0000284 /* Make these most-frequently-called specialised ones compact, if they
285 are used. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000286 if (VG_(defined_new_mem_stack_4)())
287 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000288
fitzhardinge98abfc72003-12-16 02:05:15 +0000289 if (VG_(defined_die_mem_stack_4)())
290 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
njn9b007f62003-04-07 14:40:25 +0000291
292 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000293 /* Allocate slots for compact helpers */
294 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
295 VG_(compact_helper_offsets),
296 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000297
njn25e49d8e72002-09-23 09:36:25 +0000298 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000299 VGOFF_(m_eip) = alloc_BaB(1);
300
301 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000302 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
303 * boundary at >= 32 words, but most spills are to low numbered spill
304 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000305 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
306
njn25e49d8e72002-09-23 09:36:25 +0000307 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000308 short-amode-boundary, there's no point. */
309
sewardjfa492d42002-12-08 18:20:01 +0000310 VGOFF_(m_dflag) = alloc_BaB(1);
311
sewardjb91ae7f2003-04-29 23:50:00 +0000312 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000313 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000314 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
315 vg_assert(
316 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
317 % 16 )
318 == 0
319 );
sewardjde4a1d02002-03-22 01:27:54 +0000320
sewardj92a59562002-09-30 00:53:10 +0000321 /* This thread's LDT pointer, and segment registers. */
322 VGOFF_(ldt) = alloc_BaB(1);
323 VGOFF_(m_cs) = alloc_BaB(1);
324 VGOFF_(m_ss) = alloc_BaB(1);
325 VGOFF_(m_ds) = alloc_BaB(1);
326 VGOFF_(m_es) = alloc_BaB(1);
327 VGOFF_(m_fs) = alloc_BaB(1);
328 VGOFF_(m_gs) = alloc_BaB(1);
329
sewardje1042472002-09-30 12:33:11 +0000330 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
331
njn9b007f62003-04-07 14:40:25 +0000332#define REG(kind, size) \
fitzhardinge98abfc72003-12-16 02:05:15 +0000333 if (VG_(defined_##kind##_mem_stack##size)()) \
njn9b007f62003-04-07 14:40:25 +0000334 VG_(register_noncompact_helper)( \
fitzhardinge98abfc72003-12-16 02:05:15 +0000335 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
njn9b007f62003-04-07 14:40:25 +0000336
337 REG(new, _8);
338 REG(new, _12);
339 REG(new, _16);
340 REG(new, _32);
341 REG(new, );
342 REG(die, _8);
343 REG(die, _12);
344 REG(die, _16);
345 REG(die, _32);
346 REG(die, );
347#undef REG
348
349 if (VG_(need_to_handle_esp_assignment)())
350 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
351
sewardj92a59562002-09-30 00:53:10 +0000352 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000353 VGOFF_(helper_idiv_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000354 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000355 VGOFF_(helper_div_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000356 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000357 VGOFF_(helper_idiv_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000358 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000359 VGOFF_(helper_div_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000360 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000361 VGOFF_(helper_idiv_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000362 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000363 VGOFF_(helper_div_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000364 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000365
366 VGOFF_(helper_imul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000367 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000368 VGOFF_(helper_mul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000369 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000370 VGOFF_(helper_imul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000371 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000372 VGOFF_(helper_mul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000373 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000374 VGOFF_(helper_imul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000375 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000376 VGOFF_(helper_mul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000377 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000378
379 VGOFF_(helper_CLD)
daywalkerb106c422003-09-29 10:56:24 +0000380 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD));
sewardjde4a1d02002-03-22 01:27:54 +0000381 VGOFF_(helper_STD)
daywalkerb106c422003-09-29 10:56:24 +0000382 = alloc_BaB_1_set( (Addr) & VG_(helper_STD));
sewardjde4a1d02002-03-22 01:27:54 +0000383 VGOFF_(helper_get_dirflag)
daywalkerb106c422003-09-29 10:56:24 +0000384 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag));
sewardjde4a1d02002-03-22 01:27:54 +0000385
sewardj7d78e782002-06-02 00:04:00 +0000386 VGOFF_(helper_CLC)
daywalkerb106c422003-09-29 10:56:24 +0000387 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC));
sewardj73cf3bc2002-11-03 03:20:15 +0000388 VGOFF_(helper_STC)
daywalkerb106c422003-09-29 10:56:24 +0000389 = alloc_BaB_1_set( (Addr) & VG_(helper_STC));
sewardj7d78e782002-06-02 00:04:00 +0000390
sewardjde4a1d02002-03-22 01:27:54 +0000391 VGOFF_(helper_shldl)
daywalkerb106c422003-09-29 10:56:24 +0000392 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl));
sewardjde4a1d02002-03-22 01:27:54 +0000393 VGOFF_(helper_shldw)
daywalkerb106c422003-09-29 10:56:24 +0000394 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw));
sewardjde4a1d02002-03-22 01:27:54 +0000395 VGOFF_(helper_shrdl)
daywalkerb106c422003-09-29 10:56:24 +0000396 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl));
sewardjde4a1d02002-03-22 01:27:54 +0000397 VGOFF_(helper_shrdw)
daywalkerb106c422003-09-29 10:56:24 +0000398 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw));
sewardjde4a1d02002-03-22 01:27:54 +0000399
400 VGOFF_(helper_RDTSC)
daywalkerb106c422003-09-29 10:56:24 +0000401 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC));
sewardjde4a1d02002-03-22 01:27:54 +0000402 VGOFF_(helper_CPUID)
daywalkerb106c422003-09-29 10:56:24 +0000403 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID));
sewardjde4a1d02002-03-22 01:27:54 +0000404
sewardjde4a1d02002-03-22 01:27:54 +0000405 VGOFF_(helper_bsf)
daywalkerb106c422003-09-29 10:56:24 +0000406 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf));
sewardjde4a1d02002-03-22 01:27:54 +0000407 VGOFF_(helper_bsr)
daywalkerb106c422003-09-29 10:56:24 +0000408 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr));
sewardjde4a1d02002-03-22 01:27:54 +0000409
410 VGOFF_(helper_fstsw_AX)
daywalkerb106c422003-09-29 10:56:24 +0000411 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX));
sewardjde4a1d02002-03-22 01:27:54 +0000412 VGOFF_(helper_SAHF)
daywalkerb106c422003-09-29 10:56:24 +0000413 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF));
njnd6251f12003-06-03 13:38:51 +0000414 VGOFF_(helper_LAHF)
daywalkerb106c422003-09-29 10:56:24 +0000415 = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF));
sewardj4d0ab1f2002-03-24 10:00:09 +0000416 VGOFF_(helper_DAS)
daywalkerb106c422003-09-29 10:56:24 +0000417 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS));
sewardjfe8a1662002-03-24 11:54:07 +0000418 VGOFF_(helper_DAA)
daywalkerb106c422003-09-29 10:56:24 +0000419 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA));
daywalkerb18d2532003-09-27 20:15:01 +0000420 VGOFF_(helper_IN)
daywalkerb106c422003-09-29 10:56:24 +0000421 = alloc_BaB_1_set( (Addr) & VG_(helper_IN));
daywalkerb18d2532003-09-27 20:15:01 +0000422 VGOFF_(helper_OUT)
daywalkerb106c422003-09-29 10:56:24 +0000423 = alloc_BaB_1_set( (Addr) & VG_(helper_OUT));
njn25e49d8e72002-09-23 09:36:25 +0000424
sewardj51096432002-12-14 23:59:09 +0000425 VGOFF_(helper_undefined_instruction)
daywalkerb106c422003-09-29 10:56:24 +0000426 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction));
sewardj51096432002-12-14 23:59:09 +0000427
sewardj92a59562002-09-30 00:53:10 +0000428 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000429 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
430 VG_(noncompact_helper_offsets),
431 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000432
njncc7bb472002-10-14 09:25:19 +0000433
434 /* Initialise slots that require it */
435 VG_(copy_m_state_static_to_baseBlock)();
436
437 /* Pretend the root thread has a completely empty LDT to start with. */
438 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
439
440 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000441 if (VG_(needs).shadow_regs) {
njn25e49d8e72002-09-23 09:36:25 +0000442 VG_(baseBlock)[VGOFF_(sh_esp)] =
443 VG_(baseBlock)[VGOFF_(sh_ebp)] =
444 VG_(baseBlock)[VGOFF_(sh_eax)] =
445 VG_(baseBlock)[VGOFF_(sh_ecx)] =
446 VG_(baseBlock)[VGOFF_(sh_edx)] =
447 VG_(baseBlock)[VGOFF_(sh_ebx)] =
448 VG_(baseBlock)[VGOFF_(sh_esi)] =
njnd3040452003-05-19 15:04:06 +0000449 VG_(baseBlock)[VGOFF_(sh_edi)] = 0;
450 VG_(baseBlock)[VGOFF_(sh_eflags)] = 0;
451 VG_TRACK( post_regs_write_init );
njncc7bb472002-10-14 09:25:19 +0000452 }
sewardjde4a1d02002-03-22 01:27:54 +0000453}
454
455
456/* ---------------------------------------------------------------------
457 Global entities which are not referenced from generated code.
458 ------------------------------------------------------------------ */
459
sewardjde4a1d02002-03-22 01:27:54 +0000460/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000461UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000462
463/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000464__attribute__ ((aligned (16)))
465UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000466Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000467
468/* Counts downwards in vg_run_innerloop. */
469UInt VG_(dispatch_ctr);
470
sewardjde4a1d02002-03-22 01:27:54 +0000471
472/* 64-bit counter for the number of basic blocks done. */
473ULong VG_(bbs_done);
474/* 64-bit counter for the number of bbs to go before a debug exit. */
475ULong VG_(bbs_to_go);
476
sewardj7e87e382002-05-03 19:09:05 +0000477/* This is the ThreadId of the last thread the scheduler ran. */
478ThreadId VG_(last_run_tid) = 0;
479
njn25e49d8e72002-09-23 09:36:25 +0000480/* This is the argument to __NR_exit() supplied by the first thread to
481 call that syscall. We eventually pass that to __NR_exit() for
482 real. */
njn633de322003-05-12 20:40:13 +0000483Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000484
sewardj73cf3bc2002-11-03 03:20:15 +0000485/* Tell the logging mechanism whether we are logging to a file
486 descriptor or a socket descriptor. */
487Bool VG_(logging_to_filedes) = True;
488
sewardjb91ae7f2003-04-29 23:50:00 +0000489/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
490 the SSE state all over the place. This is set up very early, in
491 vg_startup.S. We have to determine it early since we can't even
492 correctly snapshot the startup machine state without it. */
493/* Initially True. Safer to err on the side of SSEness and get SIGILL
daywalker7e73e5f2003-07-04 16:18:15 +0000494 than to not notice for some reason that we have SSE and get weird
sewardjb91ae7f2003-04-29 23:50:00 +0000495 errors later on. */
496Bool VG_(have_ssestate) = True;
497
sewardjde4a1d02002-03-22 01:27:54 +0000498
499/* ---------------------------------------------------------------------
500 Counters, for informational purposes only.
501 ------------------------------------------------------------------ */
502
503/* Number of lookups which miss the fast tt helper. */
504UInt VG_(tt_fast_misses) = 0;
505
506
sewardjc0d8f682002-11-30 00:49:43 +0000507/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000508
sewardjde4a1d02002-03-22 01:27:54 +0000509/* Number and total o/t size of translations overall. */
510UInt VG_(overall_in_count) = 0;
511UInt VG_(overall_in_osize) = 0;
512UInt VG_(overall_in_tsize) = 0;
513/* Number and total o/t size of discards overall. */
514UInt VG_(overall_out_count) = 0;
515UInt VG_(overall_out_osize) = 0;
516UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000517/* The number of discards of TT/TC. */
518UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000519/* Counts of chain and unchain operations done. */
520UInt VG_(bb_enchain_count) = 0;
521UInt VG_(bb_dechain_count) = 0;
522/* Number of unchained jumps performed. */
523UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000524
525
526/* Counts pertaining to the register allocator. */
527
528/* total number of uinstrs input to reg-alloc */
529UInt VG_(uinstrs_prealloc) = 0;
530
531/* total number of uinstrs added due to spill code */
532UInt VG_(uinstrs_spill) = 0;
533
534/* number of bbs requiring spill code */
535UInt VG_(translations_needing_spill) = 0;
536
537/* total of register ranks over all translations */
538UInt VG_(total_reg_rank) = 0;
539
540
sewardjde4a1d02002-03-22 01:27:54 +0000541/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000542UInt VG_(sanity_fast_count) = 0;
543UInt VG_(sanity_slow_count) = 0;
544
sewardj2e93c502002-04-12 11:12:52 +0000545/* Counts pertaining to the scheduler. */
546UInt VG_(num_scheduling_events_MINOR) = 0;
547UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000548
549
550/* ---------------------------------------------------------------------
551 Values derived from command-line options.
552 ------------------------------------------------------------------ */
553
njn25e49d8e72002-09-23 09:36:25 +0000554/* Define, and set defaults. */
555Bool VG_(clo_error_limit) = True;
556Bool VG_(clo_GDB_attach) = False;
sewardj6024b212003-07-13 10:54:33 +0000557Char* VG_(clo_GDB_path) = GDB_PATH;
njn43c799e2003-04-08 00:08:52 +0000558Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000559Int VG_(sanity_level) = 1;
560Int VG_(clo_verbosity) = 1;
561Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000562Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000563
nethercotee1730692003-11-20 10:38:07 +0000564/* See big comment in vg_include.h for meaning of these three.
565 fd is initially stdout, for --help, but gets moved to stderr by default
566 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +0000567VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +0000568Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +0000569Char* VG_(clo_logfile_name) = NULL;
570
sewardj6024b212003-07-13 10:54:33 +0000571Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +0000572Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000573Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000574Bool VG_(clo_profile) = False;
575Bool VG_(clo_single_step) = False;
576Bool VG_(clo_optimise) = True;
577UChar VG_(clo_trace_codegen) = 0; // 00000000b
578Bool VG_(clo_trace_syscalls) = False;
579Bool VG_(clo_trace_signals) = False;
580Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000581Bool VG_(clo_trace_sched) = False;
582Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000583ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000584Int VG_(clo_dump_error) = 0;
585Int VG_(clo_backtrace_size) = 4;
586Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000587Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +0000588Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +0000589Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +0000590Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000591Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +0000592Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +0000593
jsgf855d93d2003-10-13 22:26:55 +0000594static Bool VG_(clo_wait_for_gdb) = False;
595
596/* If we're doing signal routing, poll for signals every 50mS by
597 default. */
598Int VG_(clo_signal_polltime) = 50;
599
600/* These flags reduce thread wakeup latency on syscall completion and
601 signal delivery, respectively. The downside is possible unfairness. */
602Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
603Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
604
sewardjde4a1d02002-03-22 01:27:54 +0000605/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
606 to behave. Initially we say False. */
607Bool VG_(running_on_simd_CPU) = False;
608
609/* Holds client's %esp at the point we gained control. */
610Addr VG_(esp_at_startup);
611
sewardjd5815ec2003-04-06 12:23:27 +0000612/* Indicates presence, and holds address of client's sysinfo page, a
613 feature of some modern kernels used to provide vsyscalls, etc. */
614Bool VG_(sysinfo_page_exists) = False;
615Addr VG_(sysinfo_page_addr) = 0;
616
sewardjde4a1d02002-03-22 01:27:54 +0000617/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
618 envp[] as extracted from the client's stack at startup-time. */
619Int VG_(client_argc);
620Char** VG_(client_argv);
621Char** VG_(client_envp);
622
sewardjde4a1d02002-03-22 01:27:54 +0000623/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000624 Processing of command-line options.
625 ------------------------------------------------------------------ */
626
njn25e49d8e72002-09-23 09:36:25 +0000627void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000628{
629 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000630 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000631 VG_(clo_logfile_fd) = 2; /* stderr */
632 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
633 VG_(exit)(1);
634}
635
636static void config_error ( Char* msg )
637{
638 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000639 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000640 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000641 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +0000642 "valgrind: Startup or configuration error:\n %s\n", msg);
sewardj19d81412002-06-03 01:10:40 +0000643 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +0000644 "valgrind: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000645 VG_(exit)(1);
646}
647
fitzhardinge98abfc72003-12-16 02:05:15 +0000648void VG_(usage) ( void )
njn7cf0bd32002-06-08 13:36:03 +0000649{
njn25e49d8e72002-09-23 09:36:25 +0000650 Char* usage1 =
651"usage: valgrind [options] prog-and-args\n"
652"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000653" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote137bc552003-11-14 17:47:54 +0000654" --tool=<name> Use the Valgrind tool named <name> [memcheck]\n"
njn25e49d8e72002-09-23 09:36:25 +0000655" --help show this message\n"
656" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000657" -q --quiet run silently; only print error msgs\n"
658" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000659" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +0000660" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000661"\n"
662" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +0000663" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
664" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +0000665" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000666" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
667" Only applies for older kernels which need\n"
668" signal routing [50]\n"
669" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
670" a signal [no]\n"
671" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
672" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000673" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000674"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000675" user options for Valgrind tools that report errors:\n"
676" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
677" --logfile=<file> log messages to <file>.pid<pid>\n"
678" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
679" --demangle=no|yes automatically demangle C++ names? [yes]\n"
680" --num-callers=<number> show <num> callers in stack traces [4]\n"
681" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
682" --show-below-main=no|yes continue stack traces below main() [no]\n"
683" --suppressions=<filename> suppress errors described in <filename>\n"
684" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +0000685
nethercote2b0793f2003-12-02 10:41:18 +0000686" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
687" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
688" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000689"\n";
njn7cf0bd32002-06-08 13:36:03 +0000690
njn25e49d8e72002-09-23 09:36:25 +0000691 Char* usage2 =
692"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000693" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000694" --sanity-level=<number> level of sanity checking to do [1]\n"
695" --single-step=no|yes translate each instr separately? [no]\n"
696" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +0000697" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000698" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +0000699" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000700" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
701" --trace-syscalls=no|yes show all system calls? [no]\n"
702" --trace-signals=no|yes show signal handling details? [no]\n"
703" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000704" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000705" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000706" --stop-after=<number> switch to real CPU after executing\n"
707" <number> basic blocks [infinity]\n"
jsgf855d93d2003-10-13 22:26:55 +0000708" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000709"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000710" debugging options for Valgrind tools that report errors\n"
711" --dump-error=<number> show translation for basic block associated\n"
712" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000713"\n";
njn3e884182003-04-15 13:03:23 +0000714
715 Char* usage3 =
716"\n"
njn25e49d8e72002-09-23 09:36:25 +0000717" Extra options are read from env variable $VALGRIND_OPTS\n"
718"\n"
njn0e1b5142003-04-15 14:58:06 +0000719" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000720" and licensed under the GNU General Public License, version 2.\n"
721" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000722"\n"
nethercote137bc552003-11-14 17:47:54 +0000723" Tools are copyright and licensed by their authors. See each\n"
724" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000725"\n";
njn7cf0bd32002-06-08 13:36:03 +0000726
fitzhardinge98abfc72003-12-16 02:05:15 +0000727 VG_(printf)(usage1);
728 if (VG_(details).name) {
729 VG_(printf)(" user options for %s:\n", VG_(details).name);
730 /* Don't print skin string directly for security, ha! */
731 if (VG_(needs).command_line_options)
732 SK_(print_usage)();
733 else
734 VG_(printf)(" (none)\n");
735 }
736 VG_(printf)(usage2);
737
738 if (VG_(details).name) {
739 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
740
741 if (VG_(needs).command_line_options)
742 SK_(print_debug_usage)();
743 else
744 VG_(printf)(" (none)\n");
745 }
nethercote421281e2003-11-20 16:20:55 +0000746 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +0000747
njn25e49d8e72002-09-23 09:36:25 +0000748 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000749 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000750 VG_(clo_logfile_fd) = 2; /* stderr */
751 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000752}
sewardjde4a1d02002-03-22 01:27:54 +0000753
sewardj1c1b1162003-02-23 01:25:51 +0000754
fitzhardinge98abfc72003-12-16 02:05:15 +0000755static void process_cmd_line_options ( const KickstartParams *kp )
sewardj1c1b1162003-02-23 01:25:51 +0000756{
fitzhardinge98abfc72003-12-16 02:05:15 +0000757 Int argc;
758 Char **argv;
759 Int i, eventually_logfile_fd;
760 Int *auxp;
sewardjde4a1d02002-03-22 01:27:54 +0000761
762# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000763
nethercotee1730692003-11-20 10:38:07 +0000764 /* log to stderr by default, but usage message goes to stdout */
765 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +0000766
767 /* Once logging is started, we can safely send messages pertaining
768 to failures in initialisation. */
769 VG_(startup_logging)();
770
sewardj19d81412002-06-03 01:10:40 +0000771 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +0000772 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +0000773 config_error("Please use absolute paths in "
774 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000775
fitzhardinge98abfc72003-12-16 02:05:15 +0000776 for(auxp = kp->client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
777 switch(auxp[0]) {
778 case VKI_AT_SYSINFO:
779 VG_(sysinfo_page_exists) = True;
780 VG_(sysinfo_page_addr) = auxp[1];
781 break;
sewardjde4a1d02002-03-22 01:27:54 +0000782 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000783 }
sewardjde4a1d02002-03-22 01:27:54 +0000784
fitzhardinge98abfc72003-12-16 02:05:15 +0000785 VG_(client_envp) = kp->client_envp;
sewardjde4a1d02002-03-22 01:27:54 +0000786
fitzhardinge98abfc72003-12-16 02:05:15 +0000787 argc = kp->argc;
788 argv = kp->argv;
789
790 VG_(vg_argc) = argc;
791 VG_(vg_argv) = argv;
792
793 /* We know the initial ESP is pointing at argc/argv */
794 VG_(client_argc) = *(Int *)kp->client_esp;
795 VG_(client_argv) = (Char **)(kp->client_esp + sizeof(Int));
796
797 for (i = 1; i < argc; i++) {
798 /* Ignore these options - they've already been handled */
799 if (VG_CLO_STREQN(7, argv[i], "--tool=") ||
800 VG_CLO_STREQN(7, argv[i], "--skin="))
801 continue;
802 if (VG_CLO_STREQN(7, argv[i], "--exec="))
803 continue;
804
805 if ( VG_CLO_STREQ(argv[i], "--"))
806 continue;
807 else if (VG_CLO_STREQ(argv[i], "-v") ||
njn43c799e2003-04-08 00:08:52 +0000808 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000809 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000810 else if (VG_CLO_STREQ(argv[i], "-q") ||
811 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000812 VG_(clo_verbosity)--;
813
njn43c799e2003-04-08 00:08:52 +0000814 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000815 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000816 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000817 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000818
njn43c799e2003-04-08 00:08:52 +0000819 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000820 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000821 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000822 VG_(clo_GDB_attach) = False;
823
sewardj6024b212003-07-13 10:54:33 +0000824 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
825 VG_(clo_GDB_path) = &argv[i][11];
826
njn43c799e2003-04-08 00:08:52 +0000827 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
828 VG_(clo_gen_suppressions) = True;
829 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
830 VG_(clo_gen_suppressions) = False;
831
nethercote77eba602003-11-13 17:35:04 +0000832 else if (VG_CLO_STREQ(argv[i], "--show-below-main=yes"))
833 VG_(clo_show_below_main) = True;
834 else if (VG_CLO_STREQ(argv[i], "--show-below-main=no"))
835 VG_(clo_show_below_main) = False;
836
fitzhardinge98abfc72003-12-16 02:05:15 +0000837 else if (VG_CLO_STREQ(argv[i], "--pointercheck=yes"))
838 VG_(clo_pointercheck) = True;
839 else if (VG_CLO_STREQ(argv[i], "--pointercheck=no"))
840 VG_(clo_pointercheck) = False;
841
njn43c799e2003-04-08 00:08:52 +0000842 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000843 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000844 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000845 VG_(clo_demangle) = False;
846
njn43c799e2003-04-08 00:08:52 +0000847 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000848 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000849 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000850 VG_(clo_trace_children) = False;
851
njn43c799e2003-04-08 00:08:52 +0000852 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000853 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000854 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000855 VG_(clo_run_libc_freeres) = False;
856
rjwalshf5f536f2003-11-17 17:45:00 +0000857 else if (VG_CLO_STREQ(argv[i], "--track-fds=yes"))
858 VG_(clo_track_fds) = True;
859 else if (VG_CLO_STREQ(argv[i], "--track-fds=no"))
860 VG_(clo_track_fds) = False;
861
njn43c799e2003-04-08 00:08:52 +0000862 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000863 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
864
njn43c799e2003-04-08 00:08:52 +0000865 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000866 VG_(clo_log_to) = VgLogTo_Fd;
867 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000868 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000869 }
870
njn43c799e2003-04-08 00:08:52 +0000871 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000872 VG_(clo_log_to) = VgLogTo_File;
873 VG_(clo_logfile_name) = &argv[i][10];
874 }
sewardjde4a1d02002-03-22 01:27:54 +0000875
njn43c799e2003-04-08 00:08:52 +0000876 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000877 VG_(clo_log_to) = VgLogTo_Socket;
878 VG_(clo_logfile_name) = &argv[i][12];
879 }
880
sewardj6024b212003-07-13 10:54:33 +0000881 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
882 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
883
njn43c799e2003-04-08 00:08:52 +0000884 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000885 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000886 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000887 VG_(message)(Vg_UserMsg,
888 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000889 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000890 }
891 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
892 VG_(clo_n_suppressions)++;
893 }
njn43c799e2003-04-08 00:08:52 +0000894 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000895 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000896 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000897 VG_(clo_profile) = False;
898
njn43c799e2003-04-08 00:08:52 +0000899 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000900 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000901 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000902 VG_(clo_chain_bb) = False;
903
fitzhardinge462f4f92003-12-18 02:10:54 +0000904 else if (VG_CLO_STREQ(argv[i], "--branchpred=yes"))
905 VG_(clo_branchpred) = True;
906 else if (VG_CLO_STREQ(argv[i], "--branchpred=no"))
907 VG_(clo_branchpred) = False;
908
njn43c799e2003-04-08 00:08:52 +0000909 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000910 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000911 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000912 VG_(clo_single_step) = False;
913
njn43c799e2003-04-08 00:08:52 +0000914 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000915 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000916 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000917 VG_(clo_optimise) = False;
918
njn25e49d8e72002-09-23 09:36:25 +0000919 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +0000920 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +0000921 Int j;
922 char* opt = & argv[i][16];
923
924 if (5 != VG_(strlen)(opt)) {
925 VG_(message)(Vg_UserMsg,
926 "--trace-codegen argument must have 5 digits");
927 VG_(bad_option)(argv[i]);
928 }
929 for (j = 0; j < 5; j++) {
930 if ('0' == opt[j]) { /* do nothing */ }
931 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
932 else {
933 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
934 "contain 0s and 1s");
935 VG_(bad_option)(argv[i]);
936 }
937 }
938 }
sewardjde4a1d02002-03-22 01:27:54 +0000939
njn43c799e2003-04-08 00:08:52 +0000940 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000941 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +0000942 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000943 VG_(clo_trace_syscalls) = False;
944
njn43c799e2003-04-08 00:08:52 +0000945 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000946 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +0000947 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000948 VG_(clo_trace_signals) = False;
949
njn43c799e2003-04-08 00:08:52 +0000950 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000951 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +0000952 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000953 VG_(clo_trace_symtab) = False;
954
njn43c799e2003-04-08 00:08:52 +0000955 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +0000956 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +0000957 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +0000958 VG_(clo_trace_sched) = False;
959
njn43c799e2003-04-08 00:08:52 +0000960 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +0000961 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +0000962 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +0000963 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +0000964 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +0000965 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000966
njn43c799e2003-04-08 00:08:52 +0000967 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +0000968 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000969
jsgf855d93d2003-10-13 22:26:55 +0000970 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
971 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
972
973 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
974 VG_(clo_lowlat_signals) = True;
975 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
976 VG_(clo_lowlat_signals) = False;
977
978 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
979 VG_(clo_lowlat_syscalls) = True;
980 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
981 VG_(clo_lowlat_syscalls) = False;
982
njn43c799e2003-04-08 00:08:52 +0000983 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +0000984 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
985
njn43c799e2003-04-08 00:08:52 +0000986 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +0000987 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
988
jsgf855d93d2003-10-13 22:26:55 +0000989 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
990 VG_(clo_wait_for_gdb) = True;
991 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
992 VG_(clo_wait_for_gdb) = False;
993
njn43c799e2003-04-08 00:08:52 +0000994 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000995 /* Make sure it's sane. */
996 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +0000997 if (VG_(clo_backtrace_size) < 1)
998 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +0000999 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1000 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1001 }
1002
njn25e49d8e72002-09-23 09:36:25 +00001003 else if (VG_(needs).command_line_options) {
1004 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1005 if (!ok)
fitzhardinge98abfc72003-12-16 02:05:15 +00001006 VG_(usage)();
njn25e49d8e72002-09-23 09:36:25 +00001007 }
sewardjde4a1d02002-03-22 01:27:54 +00001008 else
fitzhardinge98abfc72003-12-16 02:05:15 +00001009 VG_(usage)();
sewardjde4a1d02002-03-22 01:27:54 +00001010 }
1011
1012# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001013
njnf9ebf672003-05-12 21:41:30 +00001014 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001015 VG_(clo_verbosity) = 0;
1016
1017 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1018 VG_(message)(Vg_UserMsg, "");
1019 VG_(message)(Vg_UserMsg,
1020 "--gdb-attach=yes conflicts with --trace-children=yes");
1021 VG_(message)(Vg_UserMsg,
1022 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001023 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001024 }
1025
sewardj4cf05692002-10-27 20:28:29 +00001026 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1027 should be connected to whatever sink has been selected, and we
1028 indiscriminately chuck stuff into it without worrying what the
1029 nature of it is. Oh the wonder of Unix streams. */
1030
nethercotee1730692003-11-20 10:38:07 +00001031 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001032 the terminal any problems to do with processing command line
1033 opts. */
nethercotee1730692003-11-20 10:38:07 +00001034 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001035 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001036
1037 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001038
sewardj4cf05692002-10-27 20:28:29 +00001039 case VgLogTo_Fd:
1040 vg_assert(VG_(clo_logfile_name) == NULL);
1041 VG_(clo_logfile_fd) = eventually_logfile_fd;
1042 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001043
sewardj4cf05692002-10-27 20:28:29 +00001044 case VgLogTo_File: {
1045 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001046 Int seq = 0;
1047 Int pid = VG_(getpid)();
1048
sewardj4cf05692002-10-27 20:28:29 +00001049 vg_assert(VG_(clo_logfile_name) != NULL);
1050 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001051
1052 for(;;) {
1053 if (seq == 0)
1054 VG_(sprintf)(logfilename, "%s.pid%d",
1055 VG_(clo_logfile_name), pid );
1056 else
1057 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1058 VG_(clo_logfile_name), pid, seq );
1059 seq++;
1060
1061 eventually_logfile_fd
1062 = VG_(open)(logfilename,
1063 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1064 VKI_S_IRUSR|VKI_S_IWUSR);
1065 if (eventually_logfile_fd >= 0) {
1066 VG_(clo_logfile_fd) = eventually_logfile_fd;
1067 break;
1068 } else {
1069 if (eventually_logfile_fd != -VKI_EEXIST) {
1070 VG_(message)(Vg_UserMsg,
1071 "Can't create/open log file `%s.pid%d'; giving up!",
1072 VG_(clo_logfile_name), pid);
1073 VG_(bad_option)(
1074 "--logfile=<file> didn't work out for some reason.");
1075 break;
1076 }
1077 }
1078 }
sewardj4cf05692002-10-27 20:28:29 +00001079 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001080 }
1081
1082 case VgLogTo_Socket: {
1083 vg_assert(VG_(clo_logfile_name) != NULL);
1084 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1085 eventually_logfile_fd
1086 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1087 if (eventually_logfile_fd == -1) {
1088 VG_(message)(Vg_UserMsg,
1089 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1090 VG_(message)(Vg_UserMsg,
1091 "of `%s'; giving up!", VG_(clo_logfile_name) );
1092 VG_(bad_option)(
1093 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001094 }
sewardj73cf3bc2002-11-03 03:20:15 +00001095 if (eventually_logfile_fd == -2) {
1096 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001097 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001098 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001099 VG_(message)(Vg_UserMsg,
1100 "Log messages will sent to stderr instead." );
1101 VG_(message)(Vg_UserMsg,
1102 "" );
1103 /* We don't change anything here. */
1104 } else {
1105 vg_assert(eventually_logfile_fd > 0);
1106 VG_(clo_logfile_fd) = eventually_logfile_fd;
1107 VG_(logging_to_filedes) = False;
1108 }
sewardj73cf3bc2002-11-03 03:20:15 +00001109 break;
1110 }
1111
sewardj4cf05692002-10-27 20:28:29 +00001112 }
1113
jsgf855d93d2003-10-13 22:26:55 +00001114 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00001115 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001116 if (eventually_logfile_fd < 0)
1117 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1118 else {
1119 VG_(clo_logfile_fd) = eventually_logfile_fd;
1120 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1121 }
1122
sewardj4cf05692002-10-27 20:28:29 +00001123 /* Ok, the logging sink is running now. Print a suitable preamble.
1124 If logging to file or a socket, write details of parent PID and
1125 command line args, to help people trying to interpret the
1126 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001127
sewardj83adf412002-05-01 01:25:45 +00001128 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001129 /* Skin details */
1130 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1131 VG_(details).name,
1132 NULL == VG_(details).version ? "" : "-",
1133 NULL == VG_(details).version
1134 ? (Char*)"" : VG_(details).version,
1135 VG_(details).description);
1136 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001137
njnd04b7c62002-10-03 14:05:52 +00001138 /* Core details */
1139 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001140 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001141 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001142 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001143 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001144 }
1145
nethercotec1e395d2003-11-10 13:26:49 +00001146 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001147 VG_(message)(Vg_UserMsg, "");
1148 VG_(message)(Vg_UserMsg,
1149 "My PID = %d, parent PID = %d. Prog and args are:",
1150 VG_(getpid)(), VG_(getppid)() );
1151 for (i = 0; i < VG_(client_argc); i++)
1152 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1153 }
1154
sewardjde4a1d02002-03-22 01:27:54 +00001155 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001156 if (VG_(clo_log_to) != VgLogTo_Fd)
1157 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001158 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001159 VG_(message)(Vg_UserMsg, "Command line");
1160 for (i = 0; i < VG_(client_argc); i++)
1161 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1162
sewardjde4a1d02002-03-22 01:27:54 +00001163 VG_(message)(Vg_UserMsg, "Startup, with flags:");
fitzhardinge98abfc72003-12-16 02:05:15 +00001164 for (i = 1; i < argc; i++) {
sewardjde4a1d02002-03-22 01:27:54 +00001165 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1166 }
1167 }
1168
fitzhardinge98abfc72003-12-16 02:05:15 +00001169 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001170 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001171 /* If there are no suppression files specified and the skin
1172 needs one, load the default */
1173 static const Char default_supp[] = "default.supp";
1174 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1175 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1176 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1177 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1178 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001179 }
sewardj4cf05692002-10-27 20:28:29 +00001180
njn6a230532003-07-21 10:38:23 +00001181 if (VG_(clo_gen_suppressions) &&
1182 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1183 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1184 " as it doesn't generate errors.");
1185 }
1186
sewardjde4a1d02002-03-22 01:27:54 +00001187}
1188
sewardjde4a1d02002-03-22 01:27:54 +00001189/* ---------------------------------------------------------------------
1190 Copying to/from m_state_static.
1191 ------------------------------------------------------------------ */
1192
sewardjb91ae7f2003-04-29 23:50:00 +00001193/* See comment about this in vg_include.h. Change only with
1194 great care.
1195*/
1196__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001197UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1198 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001199 + 1 /* %eflags */
1200 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001201 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001202 ];
1203
sewardjfa492d42002-12-08 18:20:01 +00001204UInt VG_(insertDflag)(UInt eflags, Int d)
1205{
1206 vg_assert(d == 1 || d == -1);
1207 eflags &= ~EFlagD;
1208
1209 if (d < 0)
1210 eflags |= EFlagD;
1211
1212 return eflags;
1213}
1214
1215Int VG_(extractDflag)(UInt eflags)
1216{
1217 Int ret;
1218
1219 if (eflags & EFlagD)
1220 ret = -1;
1221 else
1222 ret = 1;
1223
1224 return ret;
1225}
1226
sewardjde4a1d02002-03-22 01:27:54 +00001227void VG_(copy_baseBlock_to_m_state_static) ( void )
1228{
1229 Int i;
sewardj92a59562002-09-30 00:53:10 +00001230 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1231 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1232 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1233 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1234 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1235 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001236
sewardj92a59562002-09-30 00:53:10 +00001237 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1238 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1239 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1240 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1241 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1242 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1243 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1244 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1245
sewardjb91ae7f2003-04-29 23:50:00 +00001246 VG_(m_state_static)[56/4]
1247 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1248 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001249 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001250
sewardjb91ae7f2003-04-29 23:50:00 +00001251 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001252 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001253 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001254}
1255
1256
1257void VG_(copy_m_state_static_to_baseBlock) ( void )
1258{
1259 Int i;
sewardj92a59562002-09-30 00:53:10 +00001260 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1261 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1262 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1263 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1264 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1265 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001266
sewardj92a59562002-09-30 00:53:10 +00001267 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1268 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1269 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1270 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1271 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1272 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1273 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1274 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1275
sewardjb91ae7f2003-04-29 23:50:00 +00001276 VG_(baseBlock)[VGOFF_(m_eflags)]
1277 = VG_(m_state_static)[56/4] & ~EFlagD;
1278 VG_(baseBlock)[VGOFF_(m_dflag)]
1279 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001280
sewardj92a59562002-09-30 00:53:10 +00001281 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001282
sewardjb91ae7f2003-04-29 23:50:00 +00001283 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1284 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001285 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001286}
1287
njn25e49d8e72002-09-23 09:36:25 +00001288Addr VG_(get_stack_pointer) ( void )
1289{
1290 return VG_(baseBlock)[VGOFF_(m_esp)];
1291}
1292
sewardjde4a1d02002-03-22 01:27:54 +00001293/* ---------------------------------------------------------------------
1294 Show accumulated counts.
1295 ------------------------------------------------------------------ */
1296
njn25e49d8e72002-09-23 09:36:25 +00001297static __inline__ Int safe_idiv(Int a, Int b)
1298{
1299 return (b == 0 ? 0 : a / b);
1300}
1301
sewardjde4a1d02002-03-22 01:27:54 +00001302static void vg_show_counts ( void )
1303{
1304 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001305 " TT/TC: %d tc sectors discarded.",
1306 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001307 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001308 " %d chainings, %d unchainings.",
1309 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1310 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001311 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001312 VG_(overall_in_count),
1313 VG_(overall_in_osize),
1314 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001315 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1316 VG_(message)(Vg_DebugMsg,
1317 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001318 VG_(overall_out_count),
1319 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001320 VG_(overall_out_tsize),
1321 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001322 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001323 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001324 VG_(bbs_done),
1325 VG_(unchained_jumps_done),
1326 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1327 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1328 );
1329
1330 VG_(message)(Vg_DebugMsg,
1331 " %d/%d major/minor sched events. %d tt_fast misses.",
1332 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001333 VG_(num_scheduling_events_MINOR),
1334 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001335
sewardjde4a1d02002-03-22 01:27:54 +00001336 VG_(message)(Vg_DebugMsg,
1337 "reg-alloc: %d t-req-spill, "
1338 "%d+%d orig+spill uis, %d total-reg-r.",
1339 VG_(translations_needing_spill),
1340 VG_(uinstrs_prealloc),
1341 VG_(uinstrs_spill),
1342 VG_(total_reg_rank) );
1343 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001344 " sanity: %d cheap, %d expensive checks.",
1345 VG_(sanity_fast_count),
1346 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001347 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001348}
1349
1350
1351/* ---------------------------------------------------------------------
1352 Main!
1353 ------------------------------------------------------------------ */
1354
jsgf855d93d2003-10-13 22:26:55 +00001355/* Initialize the PID and PGRP of scheduler LWP; this is also called
1356 in any new children after fork. */
1357static void newpid(ThreadId unused)
1358{
1359 /* PID of scheduler LWP */
1360 VG_(main_pid) = VG_(getpid)();
1361 VG_(main_pgrp) = VG_(getpgrp)();
1362}
1363
sewardjde4a1d02002-03-22 01:27:54 +00001364/* Where we jump to once Valgrind has got control, and the real
1365 machine's state has been copied to the m_state_static. */
1366
fitzhardinge98abfc72003-12-16 02:05:15 +00001367void VG_(main) ( const KickstartParams *kp, void (*tool_init)(void), void *tool_dlhandle )
sewardjde4a1d02002-03-22 01:27:54 +00001368{
sewardj2e93c502002-04-12 11:12:52 +00001369 VgSchedReturnCode src;
fitzhardingef0046f22003-12-18 02:39:22 +00001370 struct vki_rlimit rl;
sewardjde4a1d02002-03-22 01:27:54 +00001371
fitzhardinge98abfc72003-12-16 02:05:15 +00001372 /* initial state */
1373 if (0)
1374 VG_(printf)("starting esp=%p eip=%p, esp=%p\n", kp->client_esp, kp->client_eip, &src);
1375 VG_(esp_at_startup) = kp->client_esp;
1376 VG_(memset)(&VG_(m_state_static), 0, sizeof(VG_(m_state_static)));
1377 VG_(m_state_static)[40/4] = kp->client_esp;
1378 VG_(m_state_static)[60/4] = kp->client_eip;
1379
1380 /* set up an initial FPU state (doesn't really matter what it is,
1381 so long as it's somewhat valid) */
1382 if (!VG_(have_ssestate))
1383 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
1384 : : "m" (VG_(m_state_static)[64/4]) : "cc", "memory");
1385 else
1386 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1; fxrstor %0; fwait"
1387 : : "m" (VG_(m_state_static)[64/4]), "m" (VG_(m_state_static)[(64+24)/4]) : "cc", "memory");
1388
1389 VG_(brk_base) = VG_(brk_limit) = kp->client_brkbase;
1390 VG_(client_base) = kp->client_base;
1391 VG_(client_end) = kp->client_end;
1392 VG_(client_mapbase) = kp->client_mapbase;
1393 VG_(clstk_base) = kp->clstk_base;
1394 VG_(clstk_end) = kp->clstk_end;
1395
1396 VG_(shadow_base) = kp->shadow_base;
1397 VG_(shadow_end) = kp->shadow_end;
1398 VG_(valgrind_base) = kp->vg_base;
1399 VG_(valgrind_mmap_end) = kp->vg_mmap_end;
1400 VG_(valgrind_end) = kp->vg_end;
1401
1402 VG_(libdir) = kp->libdir;
1403
1404 vg_assert(VG_(clstk_end) == VG_(client_end));
1405
fitzhardingea49f9b52003-12-16 22:26:45 +00001406 if (kp->vgexecfd != -1)
1407 VG_(vgexecfd) = VG_(safe_fd)(kp->vgexecfd);
1408 if (kp->clexecfd != -1)
1409 VG_(clexecfd) = VG_(safe_fd)(kp->clexecfd);
fitzhardinge98abfc72003-12-16 02:05:15 +00001410
njn0c7a5b52003-04-30 09:00:33 +00001411 if (0) {
1412 if (VG_(have_ssestate))
1413 VG_(printf)("Looks like a SSE-capable CPU\n");
1414 else
1415 VG_(printf)("Looks like a MMX-only CPU\n");
1416 }
sewardjb91ae7f2003-04-29 23:50:00 +00001417
jsgf855d93d2003-10-13 22:26:55 +00001418 VG_(atfork)(NULL, NULL, newpid);
1419 newpid(VG_INVALID_THREADID);
1420
fitzhardingef0046f22003-12-18 02:39:22 +00001421 /* Get the current file descriptor limits. */
1422 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1423 rl.rlim_cur = 1024;
1424 rl.rlim_max = 1024;
1425 }
1426
1427 /* Work out where to move the soft limit to. */
1428 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
1429 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
1430 } else {
1431 rl.rlim_cur = rl.rlim_max;
1432 }
1433
1434 /* Reserve some file descriptors for our use. */
1435 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
1436
1437 /* Update the soft limit. */
1438 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1439
njn3e884182003-04-15 13:03:23 +00001440 /* Read /proc/self/maps into a buffer. Must be before:
1441 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1442 superblocks are not erroneously identified as being owned by the
1443 client, which would be bad.
1444 - init_memory(): that's where the buffer is parsed
1445 - init_tt_tc(): so the anonymous mmaps for the translation table and
1446 translation cache aren't identified as part of the client, which would
1447 waste > 20M of virtual address space, and be bad.
1448 */
njnfa1016e2003-09-25 17:54:11 +00001449 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001450
njn25e49d8e72002-09-23 09:36:25 +00001451 /* Setup stuff that depends on the skin. Must be before:
1452 - vg_init_baseBlock(): to register helpers
1453 - process_cmd_line_options(): to register skin name and description,
1454 and turn on/off 'command_line_options' need
1455 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001456 */
fitzhardinge98abfc72003-12-16 02:05:15 +00001457 (*tool_init)();
1458 VG_(tool_init_dlsym)(tool_dlhandle);
1459
njn810086f2002-11-14 12:42:47 +00001460 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001461
fitzhardinge98abfc72003-12-16 02:05:15 +00001462 /* Process Valgrind's command-line opts */
1463 process_cmd_line_options(kp);
sewardjde4a1d02002-03-22 01:27:54 +00001464
jsgf855d93d2003-10-13 22:26:55 +00001465 /* Hook to delay things long enough so we can get the pid and
1466 attach GDB in another shell. */
1467 if (VG_(clo_wait_for_gdb)) {
1468 VG_(printf)("pid=%d\n", VG_(getpid)());
1469 /* do "jump *$eip" to skip this in gdb */
1470 VG_(do_syscall)(__NR_pause);
1471 }
1472
njn3e884182003-04-15 13:03:23 +00001473 /* Do post command-line processing initialisation. Must be before:
1474 - vg_init_baseBlock(): to register any more helpers
1475 */
njncc7bb472002-10-14 09:25:19 +00001476 SK_(post_clo_init)();
1477
njn3e884182003-04-15 13:03:23 +00001478 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001479 vg_init_baseBlock();
1480
rjwalshf5f536f2003-11-17 17:45:00 +00001481 /* Search for file descriptors that are inherited from our parent. */
1482 if (VG_(clo_track_fds))
1483 VG_(init_preopened_fds)();
1484
sewardj018f7622002-05-15 21:13:39 +00001485 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001486 baseBlock into VG_(threads)[1]. Must be before:
1487 - VG_(sigstartup_actions)()
1488 */
sewardj018f7622002-05-15 21:13:39 +00001489 VG_(scheduler_init)();
1490
jsgf855d93d2003-10-13 22:26:55 +00001491 /* Set up the ProxyLWP machinery */
1492 VG_(proxy_init)();
1493
sewardj018f7622002-05-15 21:13:39 +00001494 /* Initialise the signal handling subsystem, temporarily parking
1495 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001496 VG_(sigstartup_actions)();
1497
sewardj018f7622002-05-15 21:13:39 +00001498 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001499 if (VG_(clo_profile))
1500 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001501
sewardj5f07b662002-04-23 16:52:51 +00001502 /* Start calibration of our RDTSC-based clock. */
1503 VG_(start_rdtsc_calibration)();
1504
njn3e884182003-04-15 13:03:23 +00001505 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001506 VGP_PUSHCC(VgpInitMem);
1507 VG_(init_memory)();
1508 VGP_POPCC(VgpInitMem);
1509
1510 /* Read the list of errors to suppress. This should be found in
1511 the file specified by vg_clo_suppressions. */
1512 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1513 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001514
sewardj5f07b662002-04-23 16:52:51 +00001515 /* End calibration of our RDTSC-based clock, leaving it as long as
1516 we can. */
1517 VG_(end_rdtsc_calibration)();
1518
njn3e884182003-04-15 13:03:23 +00001519 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001520 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001521
1522 if (VG_(clo_verbosity) == 1) {
1523 VG_(message)(Vg_UserMsg,
1524 "For more details, rerun with: -v");
1525 }
1526
sewardj25c7c3a2003-07-10 00:17:58 +00001527 /* Force a read of the debug info so that we can look for
1528 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001529 VG_(setup_code_redirect_table)();
1530
sewardjde4a1d02002-03-22 01:27:54 +00001531 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1532 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001533 if (VG_(clo_verbosity) > 0)
1534 VG_(message)(Vg_UserMsg, "");
1535
1536 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001537
fitzhardinge98abfc72003-12-16 02:05:15 +00001538 if (VG_(clo_pointercheck)) {
1539 vki_modify_ldt_t ldt = { VG_POINTERCHECK_SEGIDX,
1540 VG_(client_base),
1541 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE,
1542 1, /* 32 bit */
1543 0, /* contents: data, RW, non-expanding */
1544 0, /* not read-exec only */
1545 1, /* limit in pages */
1546 0, /* !seg not present */
1547 1, /* usable */
1548 };
1549 Int ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
1550
1551 if (ret < 0) {
1552 VG_(message)(Vg_UserMsg,
1553 "Warning: ignoring --pointercheck=yes, "
1554 "because modify_ldt failed (errno=%d)", -ret);
1555 VG_(clo_pointercheck) = False;
1556 }
1557 }
1558
sewardj018f7622002-05-15 21:13:39 +00001559 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001560 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001561 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001562
1563 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1564 VG_(fatal_signal_set) = True;
1565 src = VG_(scheduler)();
1566 } else
1567 src = VgSrc_FatalSig;
1568
njn25e49d8e72002-09-23 09:36:25 +00001569 VGP_POPCC(VgpSched);
1570 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001571
1572 if (VG_(clo_verbosity) > 0)
1573 VG_(message)(Vg_UserMsg, "");
1574
sewardj2e93c502002-04-12 11:12:52 +00001575 if (src == VgSrc_Deadlock) {
1576 VG_(message)(Vg_UserMsg,
1577 "Warning: pthread scheduler exited due to deadlock");
1578 }
1579
rjwalshf5f536f2003-11-17 17:45:00 +00001580 /* Print out file descriptor summary and stats. */
1581 if(VG_(clo_track_fds))
1582 VG_(fd_stats)();
1583
njn25e49d8e72002-09-23 09:36:25 +00001584 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001585 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001586
njn7d9f94d2003-04-22 21:41:40 +00001587 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001588
sewardj0c3b53f2002-05-01 01:58:35 +00001589 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001590
1591 if (VG_(clo_verbosity) > 1)
1592 vg_show_counts();
1593
sewardjc0d8f682002-11-30 00:49:43 +00001594 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001595 VG_(print_UInstr_histogram)();
1596
sewardjde4a1d02002-03-22 01:27:54 +00001597 if (0) {
1598 VG_(message)(Vg_DebugMsg, "");
1599 VG_(message)(Vg_DebugMsg,
1600 "------ Valgrind's internal memory use stats follow ------" );
1601 VG_(mallocSanityCheckAll)();
1602 VG_(show_all_arena_stats)();
1603 VG_(message)(Vg_DebugMsg,
1604 "------ Valgrind's ExeContext management stats follow ------" );
1605 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001606 }
1607
njn25e49d8e72002-09-23 09:36:25 +00001608 if (VG_(clo_profile))
1609 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001610
1611 VG_(shutdown_logging)();
1612
jsgf855d93d2003-10-13 22:26:55 +00001613 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1614 vg_assert(src == VgSrc_FatalSig ||
1615 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1616 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1617 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1618
sewardj7e87e382002-05-03 19:09:05 +00001619 /* Decide how to exit. This depends on what the scheduler
1620 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001621
sewardj7e87e382002-05-03 19:09:05 +00001622 switch (src) {
1623 case VgSrc_ExitSyscall: /* the normal way out */
1624 vg_assert(VG_(last_run_tid) > 0
1625 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001626 VG_(proxy_shutdown)();
1627
njn25e49d8e72002-09-23 09:36:25 +00001628 /* The thread's %EBX at the time it did __NR_exit() will hold
1629 the arg to __NR_exit(), so we just do __NR_exit() with
1630 that arg. */
1631 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001632 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001633 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001634 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001635
sewardj7e87e382002-05-03 19:09:05 +00001636 case VgSrc_Deadlock:
1637 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001638 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001639 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001640 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001641 break;
1642
1643 case VgSrc_BbsDone:
1644 /* Tricky; we have to try and switch back to the real CPU.
1645 This is all very dodgy and won't work at all in the
1646 presence of threads, or if the client happened to be
1647 running a signal handler. */
1648 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001649 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001650 VG_(load_thread_state)(1 /* root thread */ );
1651 VG_(copy_baseBlock_to_m_state_static)();
1652
jsgf855d93d2003-10-13 22:26:55 +00001653 VG_(proxy_shutdown)();
1654
sewardj7e87e382002-05-03 19:09:05 +00001655 /* This pushes a return address on the simulator's stack,
1656 which is abandoned. We call vg_sigshutdown_actions() at
1657 the end of vg_switch_to_real_CPU(), so as to ensure that
1658 the original stack and machine state is restored before
1659 the real signal mechanism is restored. */
1660 VG_(switch_to_real_CPU)();
1661
jsgf855d93d2003-10-13 22:26:55 +00001662 case VgSrc_FatalSig:
1663 /* We were killed by a fatal signal, so replicate the effect */
1664 vg_assert(VG_(fatal_sigNo) != -1);
1665 VG_(kill_self)(VG_(fatal_sigNo));
1666 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1667 break;
1668
sewardj7e87e382002-05-03 19:09:05 +00001669 default:
njne427a662002-10-02 11:08:25 +00001670 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001671 }
sewardjde4a1d02002-03-22 01:27:54 +00001672}
1673
1674
1675/* Debugging thing .. can be called from assembly with OYNK macro. */
1676void VG_(oynk) ( Int n )
1677{
1678 OINK(n);
1679}
1680
1681
fitzhardinge98abfc72003-12-16 02:05:15 +00001682/* Walk through a colon-separated environment variable, and remove the
1683 entries which matches file_pattern. It slides everything down over
1684 the removed entries, and pads the remaining space with '\0'. It
1685 modifies the entries in place (in the client address space), but it
1686 shouldn't matter too much, since we only do this just before an
1687 execve().
sewardj78e25c92002-05-20 23:38:33 +00001688
fitzhardinge98abfc72003-12-16 02:05:15 +00001689 This is also careful to mop up any excess ':'s, since empty strings
1690 delimited by ':' are considered to be '.' in a path.
sewardjde4a1d02002-03-22 01:27:54 +00001691*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001692void VG_(mash_colon_env)(Char *varp, const Char *remove_pattern)
sewardj45b672d2003-07-25 19:58:11 +00001693{
fitzhardinge98abfc72003-12-16 02:05:15 +00001694 Char *const start = varp;
1695 Char *entry_start = varp;
1696 Char *output = varp;
sewardj45b672d2003-07-25 19:58:11 +00001697
fitzhardinge98abfc72003-12-16 02:05:15 +00001698 if (varp == NULL)
sewardjde4a1d02002-03-22 01:27:54 +00001699 return;
fitzhardinge98abfc72003-12-16 02:05:15 +00001700
1701 while(*varp) {
1702 if (*varp == ':') {
1703 Char prev;
1704 Bool match;
1705
1706 /* This is a bit subtle: we want to match against the entry
1707 we just copied, because it may have overlapped with
1708 itself, junking the original. */
1709
1710 prev = *output;
1711 *output = '\0';
1712
1713 match = VG_(string_match)(remove_pattern, entry_start);
1714
1715 *output = prev;
1716
1717 if (match) {
1718 output = entry_start;
1719 varp++; /* skip ':' after removed entry */
1720 } else
1721 entry_start = output+1; /* entry starts after ':' */
1722 }
1723
1724 *output++ = *varp++;
sewardj3e1eb1f2002-05-18 13:14:17 +00001725 }
1726
fitzhardinge98abfc72003-12-16 02:05:15 +00001727 /* match against the last entry */
1728 if (VG_(string_match)(remove_pattern, entry_start)) {
1729 output = entry_start;
1730 if (output > start) {
1731 /* remove trailing ':' */
1732 output--;
1733 vg_assert(*output == ':');
1734 }
1735 }
njn25e49d8e72002-09-23 09:36:25 +00001736
fitzhardinge98abfc72003-12-16 02:05:15 +00001737 /* pad out the left-overs with '\0' */
1738 while(output < varp)
1739 *output++ = '\0';
sewardjde4a1d02002-03-22 01:27:54 +00001740}
1741
1742/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1743 it to attach to this process. Called if the user requests this
1744 service after an error has been shown, so she can poke around and
1745 look at parameters, memory, etc. You can't meaningfully get GDB to
1746 continue the program, though; to continue, quit GDB. */
fitzhardingea49f9b52003-12-16 22:26:45 +00001747void VG_(start_GDB_whilst_on_client_stack) ( void )
sewardjde4a1d02002-03-22 01:27:54 +00001748{
sewardje6a25242002-04-21 22:03:07 +00001749 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001750 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001751
fitzhardingea49f9b52003-12-16 22:26:45 +00001752 VG_(sprintf)(buf, "%s -nw /proc/%d/fd/%d %d",
1753 VG_(clo_GDB_path), VG_(getpid)(), VG_(clexecfd), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001754 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1755 res = VG_(system)(buf);
1756 if (res == 0) {
1757 VG_(message)(Vg_UserMsg, "");
1758 VG_(message)(Vg_UserMsg,
1759 "GDB has detached. Valgrind regains control. We continue.");
1760 } else {
1761 VG_(message)(Vg_UserMsg, "Apparently failed!");
1762 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001763 }
sewardjde4a1d02002-03-22 01:27:54 +00001764}
1765
1766
1767/* Print some helpful-ish text about unimplemented things, and give
1768 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001769void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001770{
1771 VG_(message)(Vg_UserMsg, "");
1772 VG_(message)(Vg_UserMsg,
1773 "Valgrind detected that your program requires");
1774 VG_(message)(Vg_UserMsg,
1775 "the following unimplemented functionality:");
1776 VG_(message)(Vg_UserMsg, " %s", msg);
1777 VG_(message)(Vg_UserMsg,
1778 "This may be because the functionality is hard to implement,");
1779 VG_(message)(Vg_UserMsg,
1780 "or because no reasonable program would behave this way,");
1781 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001782 "or because nobody has yet needed it. In any case, let us know at");
sewardjde4a1d02002-03-22 01:27:54 +00001783 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001784 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
sewardjde4a1d02002-03-22 01:27:54 +00001785 VG_(message)(Vg_UserMsg,
1786 "");
1787 VG_(message)(Vg_UserMsg,
1788 "Valgrind has to exit now. Sorry. Bye!");
1789 VG_(message)(Vg_UserMsg,
1790 "");
sewardj15a43e12002-04-17 19:35:12 +00001791 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001792 VG_(exit)(1);
1793}
1794
1795
njn25e49d8e72002-09-23 09:36:25 +00001796/* ---------------------------------------------------------------------
1797 Sanity check machinery (permanently engaged).
1798 ------------------------------------------------------------------ */
1799
1800/* A fast sanity check -- suitable for calling circa once per
1801 millisecond. */
1802
1803void VG_(do_sanity_checks) ( Bool force_expensive )
1804{
njn37cea302002-09-30 11:24:00 +00001805 VGP_PUSHCC(VgpCoreCheapSanity);
1806
njn25e49d8e72002-09-23 09:36:25 +00001807 if (VG_(sanity_level) < 1) return;
1808
1809 /* --- First do all the tests that we can do quickly. ---*/
1810
1811 VG_(sanity_fast_count)++;
1812
njn25e49d8e72002-09-23 09:36:25 +00001813 /* Check stuff pertaining to the memory check system. */
1814
1815 /* Check that nobody has spuriously claimed that the first or
1816 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001817 if (VG_(needs).sanity_checks) {
1818 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001819 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001820 VGP_POPCC(VgpSkinCheapSanity);
1821 }
njn25e49d8e72002-09-23 09:36:25 +00001822
1823 /* --- Now some more expensive checks. ---*/
1824
1825 /* Once every 25 times, check some more expensive stuff. */
1826 if ( force_expensive
1827 || VG_(sanity_level) > 1
1828 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1829
njn37cea302002-09-30 11:24:00 +00001830 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001831 VG_(sanity_slow_count)++;
1832
jsgf855d93d2003-10-13 22:26:55 +00001833 VG_(proxy_sanity)();
1834
njn25e49d8e72002-09-23 09:36:25 +00001835# if 0
1836 { void zzzmemscan(void); zzzmemscan(); }
1837# endif
1838
1839 if ((VG_(sanity_fast_count) % 250) == 0)
1840 VG_(sanity_check_tc_tt)();
1841
1842 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001843 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001844 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001845 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001846 }
1847 /*
1848 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1849 */
njn37cea302002-09-30 11:24:00 +00001850 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001851 }
1852
1853 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001854 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001855 /* Check sanity of the low-level memory manager. Note that bugs
1856 in the client's code can cause this to fail, so we don't do
1857 this check unless specially asked for. And because it's
1858 potentially very expensive. */
1859 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001860 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001861 }
njn37cea302002-09-30 11:24:00 +00001862 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001863}
sewardjde4a1d02002-03-22 01:27:54 +00001864/*--------------------------------------------------------------------*/
1865/*--- end vg_main.c ---*/
1866/*--------------------------------------------------------------------*/