blob: 9222f2e47e2c005ba44b7d69ecbed5eb272bb5ba [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
sewardjde4a1d02002-03-22 01:27:54 +0000156/* Words. */
157static Int baB_off = 0;
158
jsgf855d93d2003-10-13 22:26:55 +0000159/* jmp_buf for fatal signals */
160Int VG_(fatal_sigNo) = -1;
161Bool VG_(fatal_signal_set) = False;
162jmp_buf VG_(fatal_signal_jmpbuf);
163
sewardjde4a1d02002-03-22 01:27:54 +0000164/* Returns the offset, in words. */
165static Int alloc_BaB ( Int words )
166{
167 Int off = baB_off;
168 baB_off += words;
169 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000170 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000171
172 return off;
173}
174
njn0c7a5b52003-04-30 09:00:33 +0000175/* Align offset, in *bytes* */
176static void align_BaB ( UInt align )
177{
178 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
179 baB_off += (align-1);
180 baB_off &= ~(align-1);
181}
182
sewardjde4a1d02002-03-22 01:27:54 +0000183/* Allocate 1 word in baseBlock and set it to the given value. */
daywalkerb106c422003-09-29 10:56:24 +0000184static Int alloc_BaB_1_set ( Addr a )
sewardjde4a1d02002-03-22 01:27:54 +0000185{
186 Int off = alloc_BaB(1);
187 VG_(baseBlock)[off] = (UInt)a;
188 return off;
189}
190
njn25e49d8e72002-09-23 09:36:25 +0000191/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000192 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000193void VG_(register_compact_helper)(Addr a)
194{
195 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
196 VG_(printf)("Can only register %d compact helpers\n",
197 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000198 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000199 }
200 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
201 VG_(n_compact_helpers)++;
202}
203
204/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
205 * is filled in later.
206 */
207void VG_(register_noncompact_helper)(Addr a)
208{
209 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
210 VG_(printf)("Can only register %d non-compact helpers\n",
211 MAX_NONCOMPACT_HELPERS);
212 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000213 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000214 }
215 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
216 VG_(n_noncompact_helpers)++;
217}
218
219/* Allocate offsets in baseBlock for the skin helpers */
sewardj05bcdcb2003-05-18 10:05:38 +0000220static
221void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
njn25e49d8e72002-09-23 09:36:25 +0000222{
sewardj05bcdcb2003-05-18 10:05:38 +0000223 UInt i;
224 for (i = 0; i < n; i++)
daywalkerb106c422003-09-29 10:56:24 +0000225 offsets[i] = alloc_BaB_1_set( addrs[i] );
njn25e49d8e72002-09-23 09:36:25 +0000226}
sewardjde4a1d02002-03-22 01:27:54 +0000227
njnf4ce3d32003-02-10 10:17:26 +0000228Bool VG_(need_to_handle_esp_assignment)(void)
229{
fitzhardinge98abfc72003-12-16 02:05:15 +0000230 return ( VG_(defined_new_mem_stack_4)() ||
231 VG_(defined_die_mem_stack_4)() ||
232 VG_(defined_new_mem_stack_8)() ||
233 VG_(defined_die_mem_stack_8)() ||
234 VG_(defined_new_mem_stack_12)() ||
235 VG_(defined_die_mem_stack_12)() ||
236 VG_(defined_new_mem_stack_16)() ||
237 VG_(defined_die_mem_stack_16)() ||
238 VG_(defined_new_mem_stack_32)() ||
239 VG_(defined_die_mem_stack_32)() ||
240 VG_(defined_new_mem_stack)() ||
241 VG_(defined_die_mem_stack)()
njn9b007f62003-04-07 14:40:25 +0000242 );
njnf4ce3d32003-02-10 10:17:26 +0000243}
244
sewardjde4a1d02002-03-22 01:27:54 +0000245/* Here we assign actual offsets. It's important to get the most
246 popular referents within 128 bytes of the start, so we can take
247 advantage of short addressing modes relative to %ebp. Popularity
248 of offsets was measured on 22 Feb 02 running a KDE application, and
249 the slots rearranged accordingly, with a 1.5% reduction in total
250 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000251static void vg_init_baseBlock ( void )
252{
sewardjde4a1d02002-03-22 01:27:54 +0000253 /* Those with offsets under 128 are carefully chosen. */
254
255 /* WORD offsets in this column */
256 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
257 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
258 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
259 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
260 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
261 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
262 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
263 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
264 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
265
njn25e49d8e72002-09-23 09:36:25 +0000266 if (VG_(needs).shadow_regs) {
267 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
268 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
269 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
270 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
271 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
272 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
273 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
274 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
275 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
276 }
sewardjde4a1d02002-03-22 01:27:54 +0000277
njn25e49d8e72002-09-23 09:36:25 +0000278 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
279 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000280
njn9b007f62003-04-07 14:40:25 +0000281 /* Make these most-frequently-called specialised ones compact, if they
282 are used. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000283 if (VG_(defined_new_mem_stack_4)())
284 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000285
fitzhardinge98abfc72003-12-16 02:05:15 +0000286 if (VG_(defined_die_mem_stack_4)())
287 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
njn9b007f62003-04-07 14:40:25 +0000288
289 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000290 /* Allocate slots for compact helpers */
291 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
292 VG_(compact_helper_offsets),
293 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000294
njn25e49d8e72002-09-23 09:36:25 +0000295 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000296 VGOFF_(m_eip) = alloc_BaB(1);
297
298 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000299 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
300 * boundary at >= 32 words, but most spills are to low numbered spill
301 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000302 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
303
njn25e49d8e72002-09-23 09:36:25 +0000304 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000305 short-amode-boundary, there's no point. */
306
sewardjfa492d42002-12-08 18:20:01 +0000307 VGOFF_(m_dflag) = alloc_BaB(1);
308
sewardjb91ae7f2003-04-29 23:50:00 +0000309 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000310 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000311 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
312 vg_assert(
313 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
314 % 16 )
315 == 0
316 );
sewardjde4a1d02002-03-22 01:27:54 +0000317
sewardj92a59562002-09-30 00:53:10 +0000318 /* This thread's LDT pointer, and segment registers. */
319 VGOFF_(ldt) = alloc_BaB(1);
320 VGOFF_(m_cs) = alloc_BaB(1);
321 VGOFF_(m_ss) = alloc_BaB(1);
322 VGOFF_(m_ds) = alloc_BaB(1);
323 VGOFF_(m_es) = alloc_BaB(1);
324 VGOFF_(m_fs) = alloc_BaB(1);
325 VGOFF_(m_gs) = alloc_BaB(1);
326
sewardje1042472002-09-30 12:33:11 +0000327 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
328
njn9b007f62003-04-07 14:40:25 +0000329#define REG(kind, size) \
fitzhardinge98abfc72003-12-16 02:05:15 +0000330 if (VG_(defined_##kind##_mem_stack##size)()) \
njn9b007f62003-04-07 14:40:25 +0000331 VG_(register_noncompact_helper)( \
fitzhardinge98abfc72003-12-16 02:05:15 +0000332 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
njn9b007f62003-04-07 14:40:25 +0000333
334 REG(new, _8);
335 REG(new, _12);
336 REG(new, _16);
337 REG(new, _32);
338 REG(new, );
339 REG(die, _8);
340 REG(die, _12);
341 REG(die, _16);
342 REG(die, _32);
343 REG(die, );
344#undef REG
345
346 if (VG_(need_to_handle_esp_assignment)())
347 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
348
sewardj92a59562002-09-30 00:53:10 +0000349 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000350 VGOFF_(helper_idiv_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000351 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000352 VGOFF_(helper_div_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000353 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000354 VGOFF_(helper_idiv_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000355 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000356 VGOFF_(helper_div_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000357 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000358 VGOFF_(helper_idiv_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000359 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000360 VGOFF_(helper_div_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000361 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000362
363 VGOFF_(helper_imul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000364 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000365 VGOFF_(helper_mul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000366 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000367 VGOFF_(helper_imul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000368 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000369 VGOFF_(helper_mul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000370 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000371 VGOFF_(helper_imul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000372 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000373 VGOFF_(helper_mul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000374 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000375
376 VGOFF_(helper_CLD)
daywalkerb106c422003-09-29 10:56:24 +0000377 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD));
sewardjde4a1d02002-03-22 01:27:54 +0000378 VGOFF_(helper_STD)
daywalkerb106c422003-09-29 10:56:24 +0000379 = alloc_BaB_1_set( (Addr) & VG_(helper_STD));
sewardjde4a1d02002-03-22 01:27:54 +0000380 VGOFF_(helper_get_dirflag)
daywalkerb106c422003-09-29 10:56:24 +0000381 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag));
sewardjde4a1d02002-03-22 01:27:54 +0000382
sewardj7d78e782002-06-02 00:04:00 +0000383 VGOFF_(helper_CLC)
daywalkerb106c422003-09-29 10:56:24 +0000384 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC));
sewardj73cf3bc2002-11-03 03:20:15 +0000385 VGOFF_(helper_STC)
daywalkerb106c422003-09-29 10:56:24 +0000386 = alloc_BaB_1_set( (Addr) & VG_(helper_STC));
sewardj7d78e782002-06-02 00:04:00 +0000387
sewardjde4a1d02002-03-22 01:27:54 +0000388 VGOFF_(helper_shldl)
daywalkerb106c422003-09-29 10:56:24 +0000389 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl));
sewardjde4a1d02002-03-22 01:27:54 +0000390 VGOFF_(helper_shldw)
daywalkerb106c422003-09-29 10:56:24 +0000391 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw));
sewardjde4a1d02002-03-22 01:27:54 +0000392 VGOFF_(helper_shrdl)
daywalkerb106c422003-09-29 10:56:24 +0000393 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl));
sewardjde4a1d02002-03-22 01:27:54 +0000394 VGOFF_(helper_shrdw)
daywalkerb106c422003-09-29 10:56:24 +0000395 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw));
sewardjde4a1d02002-03-22 01:27:54 +0000396
397 VGOFF_(helper_RDTSC)
daywalkerb106c422003-09-29 10:56:24 +0000398 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC));
sewardjde4a1d02002-03-22 01:27:54 +0000399 VGOFF_(helper_CPUID)
daywalkerb106c422003-09-29 10:56:24 +0000400 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID));
sewardjde4a1d02002-03-22 01:27:54 +0000401
sewardjde4a1d02002-03-22 01:27:54 +0000402 VGOFF_(helper_bsf)
daywalkerb106c422003-09-29 10:56:24 +0000403 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf));
sewardjde4a1d02002-03-22 01:27:54 +0000404 VGOFF_(helper_bsr)
daywalkerb106c422003-09-29 10:56:24 +0000405 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr));
sewardjde4a1d02002-03-22 01:27:54 +0000406
407 VGOFF_(helper_fstsw_AX)
daywalkerb106c422003-09-29 10:56:24 +0000408 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX));
sewardjde4a1d02002-03-22 01:27:54 +0000409 VGOFF_(helper_SAHF)
daywalkerb106c422003-09-29 10:56:24 +0000410 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF));
njnd6251f12003-06-03 13:38:51 +0000411 VGOFF_(helper_LAHF)
daywalkerb106c422003-09-29 10:56:24 +0000412 = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF));
sewardj4d0ab1f2002-03-24 10:00:09 +0000413 VGOFF_(helper_DAS)
daywalkerb106c422003-09-29 10:56:24 +0000414 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS));
sewardjfe8a1662002-03-24 11:54:07 +0000415 VGOFF_(helper_DAA)
daywalkerb106c422003-09-29 10:56:24 +0000416 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA));
daywalkerb18d2532003-09-27 20:15:01 +0000417 VGOFF_(helper_IN)
daywalkerb106c422003-09-29 10:56:24 +0000418 = alloc_BaB_1_set( (Addr) & VG_(helper_IN));
daywalkerb18d2532003-09-27 20:15:01 +0000419 VGOFF_(helper_OUT)
daywalkerb106c422003-09-29 10:56:24 +0000420 = alloc_BaB_1_set( (Addr) & VG_(helper_OUT));
njn25e49d8e72002-09-23 09:36:25 +0000421
sewardj51096432002-12-14 23:59:09 +0000422 VGOFF_(helper_undefined_instruction)
daywalkerb106c422003-09-29 10:56:24 +0000423 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction));
sewardj51096432002-12-14 23:59:09 +0000424
sewardj92a59562002-09-30 00:53:10 +0000425 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000426 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
427 VG_(noncompact_helper_offsets),
428 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000429
njncc7bb472002-10-14 09:25:19 +0000430
431 /* Initialise slots that require it */
432 VG_(copy_m_state_static_to_baseBlock)();
433
434 /* Pretend the root thread has a completely empty LDT to start with. */
435 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
436
437 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000438 if (VG_(needs).shadow_regs) {
njn25e49d8e72002-09-23 09:36:25 +0000439 VG_(baseBlock)[VGOFF_(sh_esp)] =
440 VG_(baseBlock)[VGOFF_(sh_ebp)] =
441 VG_(baseBlock)[VGOFF_(sh_eax)] =
442 VG_(baseBlock)[VGOFF_(sh_ecx)] =
443 VG_(baseBlock)[VGOFF_(sh_edx)] =
444 VG_(baseBlock)[VGOFF_(sh_ebx)] =
445 VG_(baseBlock)[VGOFF_(sh_esi)] =
njnd3040452003-05-19 15:04:06 +0000446 VG_(baseBlock)[VGOFF_(sh_edi)] = 0;
447 VG_(baseBlock)[VGOFF_(sh_eflags)] = 0;
448 VG_TRACK( post_regs_write_init );
njncc7bb472002-10-14 09:25:19 +0000449 }
sewardjde4a1d02002-03-22 01:27:54 +0000450}
451
452
453/* ---------------------------------------------------------------------
454 Global entities which are not referenced from generated code.
455 ------------------------------------------------------------------ */
456
sewardjde4a1d02002-03-22 01:27:54 +0000457/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000458UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000459
460/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000461__attribute__ ((aligned (16)))
462UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000463Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000464
465/* Counts downwards in vg_run_innerloop. */
466UInt VG_(dispatch_ctr);
467
sewardjde4a1d02002-03-22 01:27:54 +0000468
469/* 64-bit counter for the number of basic blocks done. */
470ULong VG_(bbs_done);
471/* 64-bit counter for the number of bbs to go before a debug exit. */
472ULong VG_(bbs_to_go);
473
sewardj7e87e382002-05-03 19:09:05 +0000474/* This is the ThreadId of the last thread the scheduler ran. */
475ThreadId VG_(last_run_tid) = 0;
476
njn25e49d8e72002-09-23 09:36:25 +0000477/* This is the argument to __NR_exit() supplied by the first thread to
478 call that syscall. We eventually pass that to __NR_exit() for
479 real. */
njn633de322003-05-12 20:40:13 +0000480Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000481
sewardj73cf3bc2002-11-03 03:20:15 +0000482/* Tell the logging mechanism whether we are logging to a file
483 descriptor or a socket descriptor. */
484Bool VG_(logging_to_filedes) = True;
485
sewardjb91ae7f2003-04-29 23:50:00 +0000486/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
487 the SSE state all over the place. This is set up very early, in
488 vg_startup.S. We have to determine it early since we can't even
489 correctly snapshot the startup machine state without it. */
490/* Initially True. Safer to err on the side of SSEness and get SIGILL
daywalker7e73e5f2003-07-04 16:18:15 +0000491 than to not notice for some reason that we have SSE and get weird
sewardjb91ae7f2003-04-29 23:50:00 +0000492 errors later on. */
493Bool VG_(have_ssestate) = True;
494
sewardjde4a1d02002-03-22 01:27:54 +0000495
496/* ---------------------------------------------------------------------
497 Counters, for informational purposes only.
498 ------------------------------------------------------------------ */
499
500/* Number of lookups which miss the fast tt helper. */
501UInt VG_(tt_fast_misses) = 0;
502
503
sewardjc0d8f682002-11-30 00:49:43 +0000504/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000505
sewardjde4a1d02002-03-22 01:27:54 +0000506/* Number and total o/t size of translations overall. */
507UInt VG_(overall_in_count) = 0;
508UInt VG_(overall_in_osize) = 0;
509UInt VG_(overall_in_tsize) = 0;
510/* Number and total o/t size of discards overall. */
511UInt VG_(overall_out_count) = 0;
512UInt VG_(overall_out_osize) = 0;
513UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000514/* The number of discards of TT/TC. */
515UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000516/* Counts of chain and unchain operations done. */
517UInt VG_(bb_enchain_count) = 0;
518UInt VG_(bb_dechain_count) = 0;
519/* Number of unchained jumps performed. */
520UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000521
522
523/* Counts pertaining to the register allocator. */
524
525/* total number of uinstrs input to reg-alloc */
526UInt VG_(uinstrs_prealloc) = 0;
527
528/* total number of uinstrs added due to spill code */
529UInt VG_(uinstrs_spill) = 0;
530
531/* number of bbs requiring spill code */
532UInt VG_(translations_needing_spill) = 0;
533
534/* total of register ranks over all translations */
535UInt VG_(total_reg_rank) = 0;
536
537
sewardjde4a1d02002-03-22 01:27:54 +0000538/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000539UInt VG_(sanity_fast_count) = 0;
540UInt VG_(sanity_slow_count) = 0;
541
sewardj2e93c502002-04-12 11:12:52 +0000542/* Counts pertaining to the scheduler. */
543UInt VG_(num_scheduling_events_MINOR) = 0;
544UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000545
546
547/* ---------------------------------------------------------------------
548 Values derived from command-line options.
549 ------------------------------------------------------------------ */
550
njn25e49d8e72002-09-23 09:36:25 +0000551/* Define, and set defaults. */
552Bool VG_(clo_error_limit) = True;
553Bool VG_(clo_GDB_attach) = False;
sewardj6024b212003-07-13 10:54:33 +0000554Char* VG_(clo_GDB_path) = GDB_PATH;
njn43c799e2003-04-08 00:08:52 +0000555Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000556Int VG_(sanity_level) = 1;
557Int VG_(clo_verbosity) = 1;
558Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000559Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000560
nethercotee1730692003-11-20 10:38:07 +0000561/* See big comment in vg_include.h for meaning of these three.
562 fd is initially stdout, for --help, but gets moved to stderr by default
563 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +0000564VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +0000565Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +0000566Char* VG_(clo_logfile_name) = NULL;
567
sewardj6024b212003-07-13 10:54:33 +0000568Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +0000569Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000570Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000571Bool VG_(clo_profile) = False;
572Bool VG_(clo_single_step) = False;
573Bool VG_(clo_optimise) = True;
574UChar VG_(clo_trace_codegen) = 0; // 00000000b
575Bool VG_(clo_trace_syscalls) = False;
576Bool VG_(clo_trace_signals) = False;
577Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000578Bool VG_(clo_trace_sched) = False;
579Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000580ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000581Int VG_(clo_dump_error) = 0;
582Int VG_(clo_backtrace_size) = 4;
583Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000584Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +0000585Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +0000586Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +0000587Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000588Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +0000589Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +0000590
jsgf855d93d2003-10-13 22:26:55 +0000591static Bool VG_(clo_wait_for_gdb) = False;
592
593/* If we're doing signal routing, poll for signals every 50mS by
594 default. */
595Int VG_(clo_signal_polltime) = 50;
596
597/* These flags reduce thread wakeup latency on syscall completion and
598 signal delivery, respectively. The downside is possible unfairness. */
599Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
600Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
601
sewardjde4a1d02002-03-22 01:27:54 +0000602/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
603 to behave. Initially we say False. */
604Bool VG_(running_on_simd_CPU) = False;
605
606/* Holds client's %esp at the point we gained control. */
607Addr VG_(esp_at_startup);
608
sewardjd5815ec2003-04-06 12:23:27 +0000609/* Indicates presence, and holds address of client's sysinfo page, a
610 feature of some modern kernels used to provide vsyscalls, etc. */
611Bool VG_(sysinfo_page_exists) = False;
612Addr VG_(sysinfo_page_addr) = 0;
613
sewardjde4a1d02002-03-22 01:27:54 +0000614/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
615 envp[] as extracted from the client's stack at startup-time. */
616Int VG_(client_argc);
617Char** VG_(client_argv);
618Char** VG_(client_envp);
619
sewardjde4a1d02002-03-22 01:27:54 +0000620/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000621 Processing of command-line options.
622 ------------------------------------------------------------------ */
623
njn25e49d8e72002-09-23 09:36:25 +0000624void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000625{
626 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000627 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000628 VG_(clo_logfile_fd) = 2; /* stderr */
629 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
630 VG_(exit)(1);
631}
632
633static void config_error ( Char* msg )
634{
635 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000636 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000637 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000638 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +0000639 "valgrind: Startup or configuration error:\n %s\n", msg);
sewardj19d81412002-06-03 01:10:40 +0000640 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +0000641 "valgrind: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000642 VG_(exit)(1);
643}
644
fitzhardinge98abfc72003-12-16 02:05:15 +0000645void VG_(usage) ( void )
njn7cf0bd32002-06-08 13:36:03 +0000646{
njn25e49d8e72002-09-23 09:36:25 +0000647 Char* usage1 =
648"usage: valgrind [options] prog-and-args\n"
649"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000650" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote137bc552003-11-14 17:47:54 +0000651" --tool=<name> Use the Valgrind tool named <name> [memcheck]\n"
njn25e49d8e72002-09-23 09:36:25 +0000652" --help show this message\n"
653" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000654" -q --quiet run silently; only print error msgs\n"
655" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000656" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +0000657" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000658"\n"
659" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +0000660" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
661" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +0000662" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000663" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
664" Only applies for older kernels which need\n"
665" signal routing [50]\n"
666" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
667" a signal [no]\n"
668" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
669" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000670" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000671"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000672" user options for Valgrind tools that report errors:\n"
673" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
674" --logfile=<file> log messages to <file>.pid<pid>\n"
675" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
676" --demangle=no|yes automatically demangle C++ names? [yes]\n"
677" --num-callers=<number> show <num> callers in stack traces [4]\n"
678" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
679" --show-below-main=no|yes continue stack traces below main() [no]\n"
680" --suppressions=<filename> suppress errors described in <filename>\n"
681" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +0000682
nethercote2b0793f2003-12-02 10:41:18 +0000683" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
684" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
685" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000686"\n";
njn7cf0bd32002-06-08 13:36:03 +0000687
njn25e49d8e72002-09-23 09:36:25 +0000688 Char* usage2 =
689"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000690" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000691" --sanity-level=<number> level of sanity checking to do [1]\n"
692" --single-step=no|yes translate each instr separately? [no]\n"
693" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +0000694" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000695" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +0000696" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000697" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
698" --trace-syscalls=no|yes show all system calls? [no]\n"
699" --trace-signals=no|yes show signal handling details? [no]\n"
700" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000701" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000702" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000703" --stop-after=<number> switch to real CPU after executing\n"
704" <number> basic blocks [infinity]\n"
jsgf855d93d2003-10-13 22:26:55 +0000705" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000706"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000707" debugging options for Valgrind tools that report errors\n"
708" --dump-error=<number> show translation for basic block associated\n"
709" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000710"\n";
njn3e884182003-04-15 13:03:23 +0000711
712 Char* usage3 =
713"\n"
njn25e49d8e72002-09-23 09:36:25 +0000714" Extra options are read from env variable $VALGRIND_OPTS\n"
715"\n"
njn0e1b5142003-04-15 14:58:06 +0000716" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000717" and licensed under the GNU General Public License, version 2.\n"
718" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000719"\n"
nethercote137bc552003-11-14 17:47:54 +0000720" Tools are copyright and licensed by their authors. See each\n"
721" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000722"\n";
njn7cf0bd32002-06-08 13:36:03 +0000723
fitzhardinge98abfc72003-12-16 02:05:15 +0000724 VG_(printf)(usage1);
725 if (VG_(details).name) {
726 VG_(printf)(" user options for %s:\n", VG_(details).name);
727 /* Don't print skin string directly for security, ha! */
728 if (VG_(needs).command_line_options)
729 SK_(print_usage)();
730 else
731 VG_(printf)(" (none)\n");
732 }
733 VG_(printf)(usage2);
734
735 if (VG_(details).name) {
736 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
737
738 if (VG_(needs).command_line_options)
739 SK_(print_debug_usage)();
740 else
741 VG_(printf)(" (none)\n");
742 }
nethercote421281e2003-11-20 16:20:55 +0000743 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +0000744
njn25e49d8e72002-09-23 09:36:25 +0000745 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000746 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000747 VG_(clo_logfile_fd) = 2; /* stderr */
748 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000749}
sewardjde4a1d02002-03-22 01:27:54 +0000750
sewardj1c1b1162003-02-23 01:25:51 +0000751
fitzhardinge98abfc72003-12-16 02:05:15 +0000752static void process_cmd_line_options ( const KickstartParams *kp )
sewardj1c1b1162003-02-23 01:25:51 +0000753{
fitzhardinge98abfc72003-12-16 02:05:15 +0000754 Int argc;
755 Char **argv;
756 Int i, eventually_logfile_fd;
757 Int *auxp;
sewardjde4a1d02002-03-22 01:27:54 +0000758
759# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000760
nethercotee1730692003-11-20 10:38:07 +0000761 /* log to stderr by default, but usage message goes to stdout */
762 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +0000763
764 /* Once logging is started, we can safely send messages pertaining
765 to failures in initialisation. */
766 VG_(startup_logging)();
767
sewardj19d81412002-06-03 01:10:40 +0000768 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +0000769 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +0000770 config_error("Please use absolute paths in "
771 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000772
fitzhardinge98abfc72003-12-16 02:05:15 +0000773 for(auxp = kp->client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
774 switch(auxp[0]) {
775 case VKI_AT_SYSINFO:
776 VG_(sysinfo_page_exists) = True;
777 VG_(sysinfo_page_addr) = auxp[1];
778 break;
sewardjde4a1d02002-03-22 01:27:54 +0000779 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000780 }
sewardjde4a1d02002-03-22 01:27:54 +0000781
fitzhardinge98abfc72003-12-16 02:05:15 +0000782 VG_(client_envp) = kp->client_envp;
sewardjde4a1d02002-03-22 01:27:54 +0000783
fitzhardinge98abfc72003-12-16 02:05:15 +0000784 argc = kp->argc;
785 argv = kp->argv;
786
787 VG_(vg_argc) = argc;
788 VG_(vg_argv) = argv;
789
790 /* We know the initial ESP is pointing at argc/argv */
791 VG_(client_argc) = *(Int *)kp->client_esp;
792 VG_(client_argv) = (Char **)(kp->client_esp + sizeof(Int));
793
794 for (i = 1; i < argc; i++) {
795 /* Ignore these options - they've already been handled */
796 if (VG_CLO_STREQN(7, argv[i], "--tool=") ||
797 VG_CLO_STREQN(7, argv[i], "--skin="))
798 continue;
799 if (VG_CLO_STREQN(7, argv[i], "--exec="))
800 continue;
801
802 if ( VG_CLO_STREQ(argv[i], "--"))
803 continue;
804 else if (VG_CLO_STREQ(argv[i], "-v") ||
njn43c799e2003-04-08 00:08:52 +0000805 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000806 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000807 else if (VG_CLO_STREQ(argv[i], "-q") ||
808 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000809 VG_(clo_verbosity)--;
810
njn43c799e2003-04-08 00:08:52 +0000811 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000812 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000813 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000814 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000815
njn43c799e2003-04-08 00:08:52 +0000816 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000817 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000818 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000819 VG_(clo_GDB_attach) = False;
820
sewardj6024b212003-07-13 10:54:33 +0000821 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
822 VG_(clo_GDB_path) = &argv[i][11];
823
njn43c799e2003-04-08 00:08:52 +0000824 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
825 VG_(clo_gen_suppressions) = True;
826 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
827 VG_(clo_gen_suppressions) = False;
828
nethercote77eba602003-11-13 17:35:04 +0000829 else if (VG_CLO_STREQ(argv[i], "--show-below-main=yes"))
830 VG_(clo_show_below_main) = True;
831 else if (VG_CLO_STREQ(argv[i], "--show-below-main=no"))
832 VG_(clo_show_below_main) = False;
833
fitzhardinge98abfc72003-12-16 02:05:15 +0000834 else if (VG_CLO_STREQ(argv[i], "--pointercheck=yes"))
835 VG_(clo_pointercheck) = True;
836 else if (VG_CLO_STREQ(argv[i], "--pointercheck=no"))
837 VG_(clo_pointercheck) = False;
838
njn43c799e2003-04-08 00:08:52 +0000839 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000840 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000841 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000842 VG_(clo_demangle) = False;
843
njn43c799e2003-04-08 00:08:52 +0000844 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000845 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000846 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000847 VG_(clo_trace_children) = False;
848
njn43c799e2003-04-08 00:08:52 +0000849 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000850 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000851 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000852 VG_(clo_run_libc_freeres) = False;
853
rjwalshf5f536f2003-11-17 17:45:00 +0000854 else if (VG_CLO_STREQ(argv[i], "--track-fds=yes"))
855 VG_(clo_track_fds) = True;
856 else if (VG_CLO_STREQ(argv[i], "--track-fds=no"))
857 VG_(clo_track_fds) = False;
858
njn43c799e2003-04-08 00:08:52 +0000859 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000860 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
861
njn43c799e2003-04-08 00:08:52 +0000862 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000863 VG_(clo_log_to) = VgLogTo_Fd;
864 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000865 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000866 }
867
njn43c799e2003-04-08 00:08:52 +0000868 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000869 VG_(clo_log_to) = VgLogTo_File;
870 VG_(clo_logfile_name) = &argv[i][10];
871 }
sewardjde4a1d02002-03-22 01:27:54 +0000872
njn43c799e2003-04-08 00:08:52 +0000873 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000874 VG_(clo_log_to) = VgLogTo_Socket;
875 VG_(clo_logfile_name) = &argv[i][12];
876 }
877
sewardj6024b212003-07-13 10:54:33 +0000878 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
879 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
880
njn43c799e2003-04-08 00:08:52 +0000881 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000882 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000883 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000884 VG_(message)(Vg_UserMsg,
885 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000886 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000887 }
888 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
889 VG_(clo_n_suppressions)++;
890 }
njn43c799e2003-04-08 00:08:52 +0000891 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000892 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000893 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000894 VG_(clo_profile) = False;
895
njn43c799e2003-04-08 00:08:52 +0000896 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000897 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000898 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000899 VG_(clo_chain_bb) = False;
900
fitzhardinge462f4f92003-12-18 02:10:54 +0000901 else if (VG_CLO_STREQ(argv[i], "--branchpred=yes"))
902 VG_(clo_branchpred) = True;
903 else if (VG_CLO_STREQ(argv[i], "--branchpred=no"))
904 VG_(clo_branchpred) = False;
905
njn43c799e2003-04-08 00:08:52 +0000906 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000907 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000908 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000909 VG_(clo_single_step) = False;
910
njn43c799e2003-04-08 00:08:52 +0000911 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000912 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000913 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000914 VG_(clo_optimise) = False;
915
njn25e49d8e72002-09-23 09:36:25 +0000916 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +0000917 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +0000918 Int j;
919 char* opt = & argv[i][16];
920
921 if (5 != VG_(strlen)(opt)) {
922 VG_(message)(Vg_UserMsg,
923 "--trace-codegen argument must have 5 digits");
924 VG_(bad_option)(argv[i]);
925 }
926 for (j = 0; j < 5; j++) {
927 if ('0' == opt[j]) { /* do nothing */ }
928 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
929 else {
930 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
931 "contain 0s and 1s");
932 VG_(bad_option)(argv[i]);
933 }
934 }
935 }
sewardjde4a1d02002-03-22 01:27:54 +0000936
njn43c799e2003-04-08 00:08:52 +0000937 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000938 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +0000939 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000940 VG_(clo_trace_syscalls) = False;
941
njn43c799e2003-04-08 00:08:52 +0000942 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000943 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +0000944 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000945 VG_(clo_trace_signals) = False;
946
njn43c799e2003-04-08 00:08:52 +0000947 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000948 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +0000949 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000950 VG_(clo_trace_symtab) = False;
951
njn43c799e2003-04-08 00:08:52 +0000952 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +0000953 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +0000954 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +0000955 VG_(clo_trace_sched) = False;
956
njn43c799e2003-04-08 00:08:52 +0000957 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +0000958 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +0000959 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +0000960 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +0000961 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +0000962 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000963
njn43c799e2003-04-08 00:08:52 +0000964 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +0000965 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000966
jsgf855d93d2003-10-13 22:26:55 +0000967 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
968 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
969
970 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
971 VG_(clo_lowlat_signals) = True;
972 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
973 VG_(clo_lowlat_signals) = False;
974
975 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
976 VG_(clo_lowlat_syscalls) = True;
977 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
978 VG_(clo_lowlat_syscalls) = False;
979
njn43c799e2003-04-08 00:08:52 +0000980 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +0000981 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
982
njn43c799e2003-04-08 00:08:52 +0000983 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +0000984 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
985
jsgf855d93d2003-10-13 22:26:55 +0000986 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
987 VG_(clo_wait_for_gdb) = True;
988 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
989 VG_(clo_wait_for_gdb) = False;
990
njn43c799e2003-04-08 00:08:52 +0000991 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000992 /* Make sure it's sane. */
993 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +0000994 if (VG_(clo_backtrace_size) < 1)
995 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +0000996 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
997 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
998 }
999
njn25e49d8e72002-09-23 09:36:25 +00001000 else if (VG_(needs).command_line_options) {
1001 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1002 if (!ok)
fitzhardinge98abfc72003-12-16 02:05:15 +00001003 VG_(usage)();
njn25e49d8e72002-09-23 09:36:25 +00001004 }
sewardjde4a1d02002-03-22 01:27:54 +00001005 else
fitzhardinge98abfc72003-12-16 02:05:15 +00001006 VG_(usage)();
sewardjde4a1d02002-03-22 01:27:54 +00001007 }
1008
1009# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001010
njnf9ebf672003-05-12 21:41:30 +00001011 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001012 VG_(clo_verbosity) = 0;
1013
1014 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1015 VG_(message)(Vg_UserMsg, "");
1016 VG_(message)(Vg_UserMsg,
1017 "--gdb-attach=yes conflicts with --trace-children=yes");
1018 VG_(message)(Vg_UserMsg,
1019 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001020 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001021 }
1022
sewardj4cf05692002-10-27 20:28:29 +00001023 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1024 should be connected to whatever sink has been selected, and we
1025 indiscriminately chuck stuff into it without worrying what the
1026 nature of it is. Oh the wonder of Unix streams. */
1027
nethercotee1730692003-11-20 10:38:07 +00001028 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001029 the terminal any problems to do with processing command line
1030 opts. */
nethercotee1730692003-11-20 10:38:07 +00001031 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001032 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001033
1034 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001035
sewardj4cf05692002-10-27 20:28:29 +00001036 case VgLogTo_Fd:
1037 vg_assert(VG_(clo_logfile_name) == NULL);
1038 VG_(clo_logfile_fd) = eventually_logfile_fd;
1039 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001040
sewardj4cf05692002-10-27 20:28:29 +00001041 case VgLogTo_File: {
1042 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001043 Int seq = 0;
1044 Int pid = VG_(getpid)();
1045
sewardj4cf05692002-10-27 20:28:29 +00001046 vg_assert(VG_(clo_logfile_name) != NULL);
1047 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001048
1049 for(;;) {
1050 if (seq == 0)
1051 VG_(sprintf)(logfilename, "%s.pid%d",
1052 VG_(clo_logfile_name), pid );
1053 else
1054 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1055 VG_(clo_logfile_name), pid, seq );
1056 seq++;
1057
1058 eventually_logfile_fd
1059 = VG_(open)(logfilename,
1060 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1061 VKI_S_IRUSR|VKI_S_IWUSR);
1062 if (eventually_logfile_fd >= 0) {
1063 VG_(clo_logfile_fd) = eventually_logfile_fd;
1064 break;
1065 } else {
1066 if (eventually_logfile_fd != -VKI_EEXIST) {
1067 VG_(message)(Vg_UserMsg,
1068 "Can't create/open log file `%s.pid%d'; giving up!",
1069 VG_(clo_logfile_name), pid);
1070 VG_(bad_option)(
1071 "--logfile=<file> didn't work out for some reason.");
1072 break;
1073 }
1074 }
1075 }
sewardj4cf05692002-10-27 20:28:29 +00001076 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001077 }
1078
1079 case VgLogTo_Socket: {
1080 vg_assert(VG_(clo_logfile_name) != NULL);
1081 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1082 eventually_logfile_fd
1083 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1084 if (eventually_logfile_fd == -1) {
1085 VG_(message)(Vg_UserMsg,
1086 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1087 VG_(message)(Vg_UserMsg,
1088 "of `%s'; giving up!", VG_(clo_logfile_name) );
1089 VG_(bad_option)(
1090 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001091 }
sewardj73cf3bc2002-11-03 03:20:15 +00001092 if (eventually_logfile_fd == -2) {
1093 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001094 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001095 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001096 VG_(message)(Vg_UserMsg,
1097 "Log messages will sent to stderr instead." );
1098 VG_(message)(Vg_UserMsg,
1099 "" );
1100 /* We don't change anything here. */
1101 } else {
1102 vg_assert(eventually_logfile_fd > 0);
1103 VG_(clo_logfile_fd) = eventually_logfile_fd;
1104 VG_(logging_to_filedes) = False;
1105 }
sewardj73cf3bc2002-11-03 03:20:15 +00001106 break;
1107 }
1108
sewardj4cf05692002-10-27 20:28:29 +00001109 }
1110
jsgf855d93d2003-10-13 22:26:55 +00001111 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
1112 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_MAX_FD+1);
1113 if (eventually_logfile_fd < 0)
1114 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1115 else {
1116 VG_(clo_logfile_fd) = eventually_logfile_fd;
1117 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1118 }
1119
sewardj4cf05692002-10-27 20:28:29 +00001120 /* Ok, the logging sink is running now. Print a suitable preamble.
1121 If logging to file or a socket, write details of parent PID and
1122 command line args, to help people trying to interpret the
1123 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001124
sewardj83adf412002-05-01 01:25:45 +00001125 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001126 /* Skin details */
1127 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1128 VG_(details).name,
1129 NULL == VG_(details).version ? "" : "-",
1130 NULL == VG_(details).version
1131 ? (Char*)"" : VG_(details).version,
1132 VG_(details).description);
1133 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001134
njnd04b7c62002-10-03 14:05:52 +00001135 /* Core details */
1136 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001137 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001138 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001139 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001140 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001141 }
1142
nethercotec1e395d2003-11-10 13:26:49 +00001143 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001144 VG_(message)(Vg_UserMsg, "");
1145 VG_(message)(Vg_UserMsg,
1146 "My PID = %d, parent PID = %d. Prog and args are:",
1147 VG_(getpid)(), VG_(getppid)() );
1148 for (i = 0; i < VG_(client_argc); i++)
1149 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1150 }
1151
sewardjde4a1d02002-03-22 01:27:54 +00001152 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001153 if (VG_(clo_log_to) != VgLogTo_Fd)
1154 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001155 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001156 VG_(message)(Vg_UserMsg, "Command line");
1157 for (i = 0; i < VG_(client_argc); i++)
1158 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1159
sewardjde4a1d02002-03-22 01:27:54 +00001160 VG_(message)(Vg_UserMsg, "Startup, with flags:");
fitzhardinge98abfc72003-12-16 02:05:15 +00001161 for (i = 1; i < argc; i++) {
sewardjde4a1d02002-03-22 01:27:54 +00001162 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1163 }
1164 }
1165
fitzhardinge98abfc72003-12-16 02:05:15 +00001166 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001167 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001168 /* If there are no suppression files specified and the skin
1169 needs one, load the default */
1170 static const Char default_supp[] = "default.supp";
1171 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1172 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1173 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1174 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1175 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001176 }
sewardj4cf05692002-10-27 20:28:29 +00001177
njn6a230532003-07-21 10:38:23 +00001178 if (VG_(clo_gen_suppressions) &&
1179 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1180 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1181 " as it doesn't generate errors.");
1182 }
1183
sewardjde4a1d02002-03-22 01:27:54 +00001184}
1185
sewardjde4a1d02002-03-22 01:27:54 +00001186/* ---------------------------------------------------------------------
1187 Copying to/from m_state_static.
1188 ------------------------------------------------------------------ */
1189
sewardjb91ae7f2003-04-29 23:50:00 +00001190/* See comment about this in vg_include.h. Change only with
1191 great care.
1192*/
1193__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001194UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1195 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001196 + 1 /* %eflags */
1197 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001198 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001199 ];
1200
sewardjfa492d42002-12-08 18:20:01 +00001201UInt VG_(insertDflag)(UInt eflags, Int d)
1202{
1203 vg_assert(d == 1 || d == -1);
1204 eflags &= ~EFlagD;
1205
1206 if (d < 0)
1207 eflags |= EFlagD;
1208
1209 return eflags;
1210}
1211
1212Int VG_(extractDflag)(UInt eflags)
1213{
1214 Int ret;
1215
1216 if (eflags & EFlagD)
1217 ret = -1;
1218 else
1219 ret = 1;
1220
1221 return ret;
1222}
1223
sewardjde4a1d02002-03-22 01:27:54 +00001224void VG_(copy_baseBlock_to_m_state_static) ( void )
1225{
1226 Int i;
sewardj92a59562002-09-30 00:53:10 +00001227 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1228 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1229 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1230 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1231 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1232 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001233
sewardj92a59562002-09-30 00:53:10 +00001234 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1235 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1236 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1237 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1238 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1239 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1240 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1241 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1242
sewardjb91ae7f2003-04-29 23:50:00 +00001243 VG_(m_state_static)[56/4]
1244 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1245 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001246 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001247
sewardjb91ae7f2003-04-29 23:50:00 +00001248 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001249 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001250 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001251}
1252
1253
1254void VG_(copy_m_state_static_to_baseBlock) ( void )
1255{
1256 Int i;
sewardj92a59562002-09-30 00:53:10 +00001257 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1258 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1259 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1260 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1261 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1262 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001263
sewardj92a59562002-09-30 00:53:10 +00001264 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1265 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1266 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1267 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1268 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1269 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1270 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1271 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1272
sewardjb91ae7f2003-04-29 23:50:00 +00001273 VG_(baseBlock)[VGOFF_(m_eflags)]
1274 = VG_(m_state_static)[56/4] & ~EFlagD;
1275 VG_(baseBlock)[VGOFF_(m_dflag)]
1276 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001277
sewardj92a59562002-09-30 00:53:10 +00001278 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001279
sewardjb91ae7f2003-04-29 23:50:00 +00001280 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1281 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001282 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001283}
1284
njn25e49d8e72002-09-23 09:36:25 +00001285Addr VG_(get_stack_pointer) ( void )
1286{
1287 return VG_(baseBlock)[VGOFF_(m_esp)];
1288}
1289
sewardjde4a1d02002-03-22 01:27:54 +00001290/* ---------------------------------------------------------------------
1291 Show accumulated counts.
1292 ------------------------------------------------------------------ */
1293
njn25e49d8e72002-09-23 09:36:25 +00001294static __inline__ Int safe_idiv(Int a, Int b)
1295{
1296 return (b == 0 ? 0 : a / b);
1297}
1298
sewardjde4a1d02002-03-22 01:27:54 +00001299static void vg_show_counts ( void )
1300{
1301 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001302 " TT/TC: %d tc sectors discarded.",
1303 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001304 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001305 " %d chainings, %d unchainings.",
1306 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1307 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001308 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001309 VG_(overall_in_count),
1310 VG_(overall_in_osize),
1311 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001312 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1313 VG_(message)(Vg_DebugMsg,
1314 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001315 VG_(overall_out_count),
1316 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001317 VG_(overall_out_tsize),
1318 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001319 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001320 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001321 VG_(bbs_done),
1322 VG_(unchained_jumps_done),
1323 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1324 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1325 );
1326
1327 VG_(message)(Vg_DebugMsg,
1328 " %d/%d major/minor sched events. %d tt_fast misses.",
1329 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001330 VG_(num_scheduling_events_MINOR),
1331 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001332
sewardjde4a1d02002-03-22 01:27:54 +00001333 VG_(message)(Vg_DebugMsg,
1334 "reg-alloc: %d t-req-spill, "
1335 "%d+%d orig+spill uis, %d total-reg-r.",
1336 VG_(translations_needing_spill),
1337 VG_(uinstrs_prealloc),
1338 VG_(uinstrs_spill),
1339 VG_(total_reg_rank) );
1340 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001341 " sanity: %d cheap, %d expensive checks.",
1342 VG_(sanity_fast_count),
1343 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001344 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001345}
1346
1347
1348/* ---------------------------------------------------------------------
1349 Main!
1350 ------------------------------------------------------------------ */
1351
jsgf855d93d2003-10-13 22:26:55 +00001352/* Initialize the PID and PGRP of scheduler LWP; this is also called
1353 in any new children after fork. */
1354static void newpid(ThreadId unused)
1355{
1356 /* PID of scheduler LWP */
1357 VG_(main_pid) = VG_(getpid)();
1358 VG_(main_pgrp) = VG_(getpgrp)();
1359}
1360
sewardjde4a1d02002-03-22 01:27:54 +00001361/* Where we jump to once Valgrind has got control, and the real
1362 machine's state has been copied to the m_state_static. */
1363
fitzhardinge98abfc72003-12-16 02:05:15 +00001364void VG_(main) ( const KickstartParams *kp, void (*tool_init)(void), void *tool_dlhandle )
sewardjde4a1d02002-03-22 01:27:54 +00001365{
sewardj2e93c502002-04-12 11:12:52 +00001366 VgSchedReturnCode src;
sewardjde4a1d02002-03-22 01:27:54 +00001367
fitzhardinge98abfc72003-12-16 02:05:15 +00001368 /* initial state */
1369 if (0)
1370 VG_(printf)("starting esp=%p eip=%p, esp=%p\n", kp->client_esp, kp->client_eip, &src);
1371 VG_(esp_at_startup) = kp->client_esp;
1372 VG_(memset)(&VG_(m_state_static), 0, sizeof(VG_(m_state_static)));
1373 VG_(m_state_static)[40/4] = kp->client_esp;
1374 VG_(m_state_static)[60/4] = kp->client_eip;
1375
1376 /* set up an initial FPU state (doesn't really matter what it is,
1377 so long as it's somewhat valid) */
1378 if (!VG_(have_ssestate))
1379 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
1380 : : "m" (VG_(m_state_static)[64/4]) : "cc", "memory");
1381 else
1382 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1; fxrstor %0; fwait"
1383 : : "m" (VG_(m_state_static)[64/4]), "m" (VG_(m_state_static)[(64+24)/4]) : "cc", "memory");
1384
1385 VG_(brk_base) = VG_(brk_limit) = kp->client_brkbase;
1386 VG_(client_base) = kp->client_base;
1387 VG_(client_end) = kp->client_end;
1388 VG_(client_mapbase) = kp->client_mapbase;
1389 VG_(clstk_base) = kp->clstk_base;
1390 VG_(clstk_end) = kp->clstk_end;
1391
1392 VG_(shadow_base) = kp->shadow_base;
1393 VG_(shadow_end) = kp->shadow_end;
1394 VG_(valgrind_base) = kp->vg_base;
1395 VG_(valgrind_mmap_end) = kp->vg_mmap_end;
1396 VG_(valgrind_end) = kp->vg_end;
1397
1398 VG_(libdir) = kp->libdir;
1399
1400 vg_assert(VG_(clstk_end) == VG_(client_end));
1401
fitzhardingea49f9b52003-12-16 22:26:45 +00001402 if (kp->vgexecfd != -1)
1403 VG_(vgexecfd) = VG_(safe_fd)(kp->vgexecfd);
1404 if (kp->clexecfd != -1)
1405 VG_(clexecfd) = VG_(safe_fd)(kp->clexecfd);
fitzhardinge98abfc72003-12-16 02:05:15 +00001406
njn0c7a5b52003-04-30 09:00:33 +00001407 if (0) {
1408 if (VG_(have_ssestate))
1409 VG_(printf)("Looks like a SSE-capable CPU\n");
1410 else
1411 VG_(printf)("Looks like a MMX-only CPU\n");
1412 }
sewardjb91ae7f2003-04-29 23:50:00 +00001413
jsgf855d93d2003-10-13 22:26:55 +00001414 VG_(atfork)(NULL, NULL, newpid);
1415 newpid(VG_INVALID_THREADID);
1416
njn3e884182003-04-15 13:03:23 +00001417 /* Read /proc/self/maps into a buffer. Must be before:
1418 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1419 superblocks are not erroneously identified as being owned by the
1420 client, which would be bad.
1421 - init_memory(): that's where the buffer is parsed
1422 - init_tt_tc(): so the anonymous mmaps for the translation table and
1423 translation cache aren't identified as part of the client, which would
1424 waste > 20M of virtual address space, and be bad.
1425 */
njnfa1016e2003-09-25 17:54:11 +00001426 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001427
njn25e49d8e72002-09-23 09:36:25 +00001428 /* Setup stuff that depends on the skin. Must be before:
1429 - vg_init_baseBlock(): to register helpers
1430 - process_cmd_line_options(): to register skin name and description,
1431 and turn on/off 'command_line_options' need
1432 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001433 */
fitzhardinge98abfc72003-12-16 02:05:15 +00001434 (*tool_init)();
1435 VG_(tool_init_dlsym)(tool_dlhandle);
1436
njn810086f2002-11-14 12:42:47 +00001437 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001438
fitzhardinge98abfc72003-12-16 02:05:15 +00001439 /* Process Valgrind's command-line opts */
1440 process_cmd_line_options(kp);
sewardjde4a1d02002-03-22 01:27:54 +00001441
jsgf855d93d2003-10-13 22:26:55 +00001442 /* Hook to delay things long enough so we can get the pid and
1443 attach GDB in another shell. */
1444 if (VG_(clo_wait_for_gdb)) {
1445 VG_(printf)("pid=%d\n", VG_(getpid)());
1446 /* do "jump *$eip" to skip this in gdb */
1447 VG_(do_syscall)(__NR_pause);
1448 }
1449
njn3e884182003-04-15 13:03:23 +00001450 /* Do post command-line processing initialisation. Must be before:
1451 - vg_init_baseBlock(): to register any more helpers
1452 */
njncc7bb472002-10-14 09:25:19 +00001453 SK_(post_clo_init)();
1454
njn3e884182003-04-15 13:03:23 +00001455 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001456 vg_init_baseBlock();
1457
rjwalshf5f536f2003-11-17 17:45:00 +00001458 /* Search for file descriptors that are inherited from our parent. */
1459 if (VG_(clo_track_fds))
1460 VG_(init_preopened_fds)();
1461
sewardj018f7622002-05-15 21:13:39 +00001462 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001463 baseBlock into VG_(threads)[1]. Must be before:
1464 - VG_(sigstartup_actions)()
1465 */
sewardj018f7622002-05-15 21:13:39 +00001466 VG_(scheduler_init)();
1467
jsgf855d93d2003-10-13 22:26:55 +00001468 /* Set up the ProxyLWP machinery */
1469 VG_(proxy_init)();
1470
sewardj018f7622002-05-15 21:13:39 +00001471 /* Initialise the signal handling subsystem, temporarily parking
1472 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001473 VG_(sigstartup_actions)();
1474
sewardj018f7622002-05-15 21:13:39 +00001475 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001476 if (VG_(clo_profile))
1477 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001478
sewardj5f07b662002-04-23 16:52:51 +00001479 /* Start calibration of our RDTSC-based clock. */
1480 VG_(start_rdtsc_calibration)();
1481
njn3e884182003-04-15 13:03:23 +00001482 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001483 VGP_PUSHCC(VgpInitMem);
1484 VG_(init_memory)();
1485 VGP_POPCC(VgpInitMem);
1486
1487 /* Read the list of errors to suppress. This should be found in
1488 the file specified by vg_clo_suppressions. */
1489 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1490 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001491
sewardj5f07b662002-04-23 16:52:51 +00001492 /* End calibration of our RDTSC-based clock, leaving it as long as
1493 we can. */
1494 VG_(end_rdtsc_calibration)();
1495
njn3e884182003-04-15 13:03:23 +00001496 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001497 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001498
1499 if (VG_(clo_verbosity) == 1) {
1500 VG_(message)(Vg_UserMsg,
1501 "For more details, rerun with: -v");
1502 }
1503
sewardj25c7c3a2003-07-10 00:17:58 +00001504 /* Force a read of the debug info so that we can look for
1505 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001506 VG_(setup_code_redirect_table)();
1507
sewardjde4a1d02002-03-22 01:27:54 +00001508 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1509 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001510 if (VG_(clo_verbosity) > 0)
1511 VG_(message)(Vg_UserMsg, "");
1512
1513 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001514
fitzhardinge98abfc72003-12-16 02:05:15 +00001515 if (VG_(clo_pointercheck)) {
1516 vki_modify_ldt_t ldt = { VG_POINTERCHECK_SEGIDX,
1517 VG_(client_base),
1518 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE,
1519 1, /* 32 bit */
1520 0, /* contents: data, RW, non-expanding */
1521 0, /* not read-exec only */
1522 1, /* limit in pages */
1523 0, /* !seg not present */
1524 1, /* usable */
1525 };
1526 Int ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
1527
1528 if (ret < 0) {
1529 VG_(message)(Vg_UserMsg,
1530 "Warning: ignoring --pointercheck=yes, "
1531 "because modify_ldt failed (errno=%d)", -ret);
1532 VG_(clo_pointercheck) = False;
1533 }
1534 }
1535
sewardj018f7622002-05-15 21:13:39 +00001536 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001537 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001538 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001539
1540 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1541 VG_(fatal_signal_set) = True;
1542 src = VG_(scheduler)();
1543 } else
1544 src = VgSrc_FatalSig;
1545
njn25e49d8e72002-09-23 09:36:25 +00001546 VGP_POPCC(VgpSched);
1547 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001548
1549 if (VG_(clo_verbosity) > 0)
1550 VG_(message)(Vg_UserMsg, "");
1551
sewardj2e93c502002-04-12 11:12:52 +00001552 if (src == VgSrc_Deadlock) {
1553 VG_(message)(Vg_UserMsg,
1554 "Warning: pthread scheduler exited due to deadlock");
1555 }
1556
rjwalshf5f536f2003-11-17 17:45:00 +00001557 /* Print out file descriptor summary and stats. */
1558 if(VG_(clo_track_fds))
1559 VG_(fd_stats)();
1560
njn25e49d8e72002-09-23 09:36:25 +00001561 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001562 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001563
njn7d9f94d2003-04-22 21:41:40 +00001564 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001565
sewardj0c3b53f2002-05-01 01:58:35 +00001566 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001567
1568 if (VG_(clo_verbosity) > 1)
1569 vg_show_counts();
1570
sewardjc0d8f682002-11-30 00:49:43 +00001571 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001572 VG_(print_UInstr_histogram)();
1573
sewardjde4a1d02002-03-22 01:27:54 +00001574 if (0) {
1575 VG_(message)(Vg_DebugMsg, "");
1576 VG_(message)(Vg_DebugMsg,
1577 "------ Valgrind's internal memory use stats follow ------" );
1578 VG_(mallocSanityCheckAll)();
1579 VG_(show_all_arena_stats)();
1580 VG_(message)(Vg_DebugMsg,
1581 "------ Valgrind's ExeContext management stats follow ------" );
1582 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001583 }
1584
njn25e49d8e72002-09-23 09:36:25 +00001585 if (VG_(clo_profile))
1586 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001587
1588 VG_(shutdown_logging)();
1589
jsgf855d93d2003-10-13 22:26:55 +00001590 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1591 vg_assert(src == VgSrc_FatalSig ||
1592 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1593 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1594 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1595
sewardj7e87e382002-05-03 19:09:05 +00001596 /* Decide how to exit. This depends on what the scheduler
1597 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001598
sewardj7e87e382002-05-03 19:09:05 +00001599 switch (src) {
1600 case VgSrc_ExitSyscall: /* the normal way out */
1601 vg_assert(VG_(last_run_tid) > 0
1602 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001603 VG_(proxy_shutdown)();
1604
njn25e49d8e72002-09-23 09:36:25 +00001605 /* The thread's %EBX at the time it did __NR_exit() will hold
1606 the arg to __NR_exit(), so we just do __NR_exit() with
1607 that arg. */
1608 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001609 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001610 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001611 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001612
sewardj7e87e382002-05-03 19:09:05 +00001613 case VgSrc_Deadlock:
1614 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001615 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001616 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001617 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001618 break;
1619
1620 case VgSrc_BbsDone:
1621 /* Tricky; we have to try and switch back to the real CPU.
1622 This is all very dodgy and won't work at all in the
1623 presence of threads, or if the client happened to be
1624 running a signal handler. */
1625 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001626 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001627 VG_(load_thread_state)(1 /* root thread */ );
1628 VG_(copy_baseBlock_to_m_state_static)();
1629
jsgf855d93d2003-10-13 22:26:55 +00001630 VG_(proxy_shutdown)();
1631
sewardj7e87e382002-05-03 19:09:05 +00001632 /* This pushes a return address on the simulator's stack,
1633 which is abandoned. We call vg_sigshutdown_actions() at
1634 the end of vg_switch_to_real_CPU(), so as to ensure that
1635 the original stack and machine state is restored before
1636 the real signal mechanism is restored. */
1637 VG_(switch_to_real_CPU)();
1638
jsgf855d93d2003-10-13 22:26:55 +00001639 case VgSrc_FatalSig:
1640 /* We were killed by a fatal signal, so replicate the effect */
1641 vg_assert(VG_(fatal_sigNo) != -1);
1642 VG_(kill_self)(VG_(fatal_sigNo));
1643 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1644 break;
1645
sewardj7e87e382002-05-03 19:09:05 +00001646 default:
njne427a662002-10-02 11:08:25 +00001647 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001648 }
sewardjde4a1d02002-03-22 01:27:54 +00001649}
1650
1651
1652/* Debugging thing .. can be called from assembly with OYNK macro. */
1653void VG_(oynk) ( Int n )
1654{
1655 OINK(n);
1656}
1657
1658
fitzhardinge98abfc72003-12-16 02:05:15 +00001659/* Walk through a colon-separated environment variable, and remove the
1660 entries which matches file_pattern. It slides everything down over
1661 the removed entries, and pads the remaining space with '\0'. It
1662 modifies the entries in place (in the client address space), but it
1663 shouldn't matter too much, since we only do this just before an
1664 execve().
sewardj78e25c92002-05-20 23:38:33 +00001665
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 This is also careful to mop up any excess ':'s, since empty strings
1667 delimited by ':' are considered to be '.' in a path.
sewardjde4a1d02002-03-22 01:27:54 +00001668*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001669void VG_(mash_colon_env)(Char *varp, const Char *remove_pattern)
sewardj45b672d2003-07-25 19:58:11 +00001670{
fitzhardinge98abfc72003-12-16 02:05:15 +00001671 Char *const start = varp;
1672 Char *entry_start = varp;
1673 Char *output = varp;
sewardj45b672d2003-07-25 19:58:11 +00001674
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 if (varp == NULL)
sewardjde4a1d02002-03-22 01:27:54 +00001676 return;
fitzhardinge98abfc72003-12-16 02:05:15 +00001677
1678 while(*varp) {
1679 if (*varp == ':') {
1680 Char prev;
1681 Bool match;
1682
1683 /* This is a bit subtle: we want to match against the entry
1684 we just copied, because it may have overlapped with
1685 itself, junking the original. */
1686
1687 prev = *output;
1688 *output = '\0';
1689
1690 match = VG_(string_match)(remove_pattern, entry_start);
1691
1692 *output = prev;
1693
1694 if (match) {
1695 output = entry_start;
1696 varp++; /* skip ':' after removed entry */
1697 } else
1698 entry_start = output+1; /* entry starts after ':' */
1699 }
1700
1701 *output++ = *varp++;
sewardj3e1eb1f2002-05-18 13:14:17 +00001702 }
1703
fitzhardinge98abfc72003-12-16 02:05:15 +00001704 /* match against the last entry */
1705 if (VG_(string_match)(remove_pattern, entry_start)) {
1706 output = entry_start;
1707 if (output > start) {
1708 /* remove trailing ':' */
1709 output--;
1710 vg_assert(*output == ':');
1711 }
1712 }
njn25e49d8e72002-09-23 09:36:25 +00001713
fitzhardinge98abfc72003-12-16 02:05:15 +00001714 /* pad out the left-overs with '\0' */
1715 while(output < varp)
1716 *output++ = '\0';
sewardjde4a1d02002-03-22 01:27:54 +00001717}
1718
1719/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1720 it to attach to this process. Called if the user requests this
1721 service after an error has been shown, so she can poke around and
1722 look at parameters, memory, etc. You can't meaningfully get GDB to
1723 continue the program, though; to continue, quit GDB. */
fitzhardingea49f9b52003-12-16 22:26:45 +00001724void VG_(start_GDB_whilst_on_client_stack) ( void )
sewardjde4a1d02002-03-22 01:27:54 +00001725{
sewardje6a25242002-04-21 22:03:07 +00001726 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001727 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001728
fitzhardingea49f9b52003-12-16 22:26:45 +00001729 VG_(sprintf)(buf, "%s -nw /proc/%d/fd/%d %d",
1730 VG_(clo_GDB_path), VG_(getpid)(), VG_(clexecfd), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001731 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1732 res = VG_(system)(buf);
1733 if (res == 0) {
1734 VG_(message)(Vg_UserMsg, "");
1735 VG_(message)(Vg_UserMsg,
1736 "GDB has detached. Valgrind regains control. We continue.");
1737 } else {
1738 VG_(message)(Vg_UserMsg, "Apparently failed!");
1739 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001740 }
sewardjde4a1d02002-03-22 01:27:54 +00001741}
1742
1743
1744/* Print some helpful-ish text about unimplemented things, and give
1745 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001746void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001747{
1748 VG_(message)(Vg_UserMsg, "");
1749 VG_(message)(Vg_UserMsg,
1750 "Valgrind detected that your program requires");
1751 VG_(message)(Vg_UserMsg,
1752 "the following unimplemented functionality:");
1753 VG_(message)(Vg_UserMsg, " %s", msg);
1754 VG_(message)(Vg_UserMsg,
1755 "This may be because the functionality is hard to implement,");
1756 VG_(message)(Vg_UserMsg,
1757 "or because no reasonable program would behave this way,");
1758 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001759 "or because nobody has yet needed it. In any case, let us know at");
sewardjde4a1d02002-03-22 01:27:54 +00001760 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001761 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
sewardjde4a1d02002-03-22 01:27:54 +00001762 VG_(message)(Vg_UserMsg,
1763 "");
1764 VG_(message)(Vg_UserMsg,
1765 "Valgrind has to exit now. Sorry. Bye!");
1766 VG_(message)(Vg_UserMsg,
1767 "");
sewardj15a43e12002-04-17 19:35:12 +00001768 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001769 VG_(exit)(1);
1770}
1771
1772
njn25e49d8e72002-09-23 09:36:25 +00001773/* ---------------------------------------------------------------------
1774 Sanity check machinery (permanently engaged).
1775 ------------------------------------------------------------------ */
1776
1777/* A fast sanity check -- suitable for calling circa once per
1778 millisecond. */
1779
1780void VG_(do_sanity_checks) ( Bool force_expensive )
1781{
njn37cea302002-09-30 11:24:00 +00001782 VGP_PUSHCC(VgpCoreCheapSanity);
1783
njn25e49d8e72002-09-23 09:36:25 +00001784 if (VG_(sanity_level) < 1) return;
1785
1786 /* --- First do all the tests that we can do quickly. ---*/
1787
1788 VG_(sanity_fast_count)++;
1789
njn25e49d8e72002-09-23 09:36:25 +00001790 /* Check stuff pertaining to the memory check system. */
1791
1792 /* Check that nobody has spuriously claimed that the first or
1793 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001794 if (VG_(needs).sanity_checks) {
1795 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001796 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001797 VGP_POPCC(VgpSkinCheapSanity);
1798 }
njn25e49d8e72002-09-23 09:36:25 +00001799
1800 /* --- Now some more expensive checks. ---*/
1801
1802 /* Once every 25 times, check some more expensive stuff. */
1803 if ( force_expensive
1804 || VG_(sanity_level) > 1
1805 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1806
njn37cea302002-09-30 11:24:00 +00001807 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001808 VG_(sanity_slow_count)++;
1809
jsgf855d93d2003-10-13 22:26:55 +00001810 VG_(proxy_sanity)();
1811
njn25e49d8e72002-09-23 09:36:25 +00001812# if 0
1813 { void zzzmemscan(void); zzzmemscan(); }
1814# endif
1815
1816 if ((VG_(sanity_fast_count) % 250) == 0)
1817 VG_(sanity_check_tc_tt)();
1818
1819 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001820 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001821 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001822 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001823 }
1824 /*
1825 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1826 */
njn37cea302002-09-30 11:24:00 +00001827 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001828 }
1829
1830 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001831 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001832 /* Check sanity of the low-level memory manager. Note that bugs
1833 in the client's code can cause this to fail, so we don't do
1834 this check unless specially asked for. And because it's
1835 potentially very expensive. */
1836 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001837 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001838 }
njn37cea302002-09-30 11:24:00 +00001839 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001840}
sewardjde4a1d02002-03-22 01:27:54 +00001841/*--------------------------------------------------------------------*/
1842/*--- end vg_main.c ---*/
1843/*--------------------------------------------------------------------*/