blob: 0ddbd1be17794335a09b538ba386db2b28cb8fd7 [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
jsgf855d93d2003-10-13 22:26:55 +0000123/* PID of the main thread */
124Int VG_(main_pid);
125
126/* PGRP of process */
127Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000128
sewardjde4a1d02002-03-22 01:27:54 +0000129/* Words. */
130static Int baB_off = 0;
131
jsgf855d93d2003-10-13 22:26:55 +0000132/* jmp_buf for fatal signals */
133Int VG_(fatal_sigNo) = -1;
134Bool VG_(fatal_signal_set) = False;
135jmp_buf VG_(fatal_signal_jmpbuf);
136
sewardjde4a1d02002-03-22 01:27:54 +0000137/* Returns the offset, in words. */
138static Int alloc_BaB ( Int words )
139{
140 Int off = baB_off;
141 baB_off += words;
142 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000143 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000144
145 return off;
146}
147
njn0c7a5b52003-04-30 09:00:33 +0000148/* Align offset, in *bytes* */
149static void align_BaB ( UInt align )
150{
151 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
152 baB_off += (align-1);
153 baB_off &= ~(align-1);
154}
155
sewardjde4a1d02002-03-22 01:27:54 +0000156/* Allocate 1 word in baseBlock and set it to the given value. */
daywalkerb106c422003-09-29 10:56:24 +0000157static Int alloc_BaB_1_set ( Addr a )
sewardjde4a1d02002-03-22 01:27:54 +0000158{
159 Int off = alloc_BaB(1);
160 VG_(baseBlock)[off] = (UInt)a;
161 return off;
162}
163
njn25e49d8e72002-09-23 09:36:25 +0000164/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000165 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000166void VG_(register_compact_helper)(Addr a)
167{
168 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
169 VG_(printf)("Can only register %d compact helpers\n",
170 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000171 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000172 }
173 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
174 VG_(n_compact_helpers)++;
175}
176
177/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
178 * is filled in later.
179 */
180void VG_(register_noncompact_helper)(Addr a)
181{
182 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
183 VG_(printf)("Can only register %d non-compact helpers\n",
184 MAX_NONCOMPACT_HELPERS);
185 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000186 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000187 }
188 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
189 VG_(n_noncompact_helpers)++;
190}
191
192/* Allocate offsets in baseBlock for the skin helpers */
sewardj05bcdcb2003-05-18 10:05:38 +0000193static
194void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
njn25e49d8e72002-09-23 09:36:25 +0000195{
sewardj05bcdcb2003-05-18 10:05:38 +0000196 UInt i;
197 for (i = 0; i < n; i++)
daywalkerb106c422003-09-29 10:56:24 +0000198 offsets[i] = alloc_BaB_1_set( addrs[i] );
njn25e49d8e72002-09-23 09:36:25 +0000199}
sewardjde4a1d02002-03-22 01:27:54 +0000200
njnf4ce3d32003-02-10 10:17:26 +0000201Bool VG_(need_to_handle_esp_assignment)(void)
202{
njn9b007f62003-04-07 14:40:25 +0000203 return ( VG_(track_events).new_mem_stack_4 ||
204 VG_(track_events).die_mem_stack_4 ||
205 VG_(track_events).new_mem_stack_8 ||
206 VG_(track_events).die_mem_stack_8 ||
207 VG_(track_events).new_mem_stack_12 ||
208 VG_(track_events).die_mem_stack_12 ||
209 VG_(track_events).new_mem_stack_16 ||
210 VG_(track_events).die_mem_stack_16 ||
211 VG_(track_events).new_mem_stack_32 ||
212 VG_(track_events).die_mem_stack_32 ||
213 VG_(track_events).new_mem_stack ||
214 VG_(track_events).die_mem_stack
215 );
njnf4ce3d32003-02-10 10:17:26 +0000216}
217
sewardjde4a1d02002-03-22 01:27:54 +0000218/* Here we assign actual offsets. It's important to get the most
219 popular referents within 128 bytes of the start, so we can take
220 advantage of short addressing modes relative to %ebp. Popularity
221 of offsets was measured on 22 Feb 02 running a KDE application, and
222 the slots rearranged accordingly, with a 1.5% reduction in total
223 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000224static void vg_init_baseBlock ( void )
225{
sewardjde4a1d02002-03-22 01:27:54 +0000226 /* Those with offsets under 128 are carefully chosen. */
227
228 /* WORD offsets in this column */
229 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
230 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
231 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
232 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
233 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
234 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
235 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
236 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
237 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
238
njn25e49d8e72002-09-23 09:36:25 +0000239 if (VG_(needs).shadow_regs) {
240 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
241 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
242 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
243 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
244 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
245 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
246 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
247 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
248 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
249 }
sewardjde4a1d02002-03-22 01:27:54 +0000250
njn25e49d8e72002-09-23 09:36:25 +0000251 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
252 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000253
njn9b007f62003-04-07 14:40:25 +0000254 /* Make these most-frequently-called specialised ones compact, if they
255 are used. */
256 if (VG_(track_events).new_mem_stack_4)
257 VG_(register_compact_helper)( (Addr) VG_(track_events).new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000258
njn9b007f62003-04-07 14:40:25 +0000259 if (VG_(track_events).die_mem_stack_4)
260 VG_(register_compact_helper)( (Addr) VG_(track_events).die_mem_stack_4);
261
262 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000263 /* Allocate slots for compact helpers */
264 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
265 VG_(compact_helper_offsets),
266 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000267
njn25e49d8e72002-09-23 09:36:25 +0000268 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000269 VGOFF_(m_eip) = alloc_BaB(1);
270
271 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000272 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
273 * boundary at >= 32 words, but most spills are to low numbered spill
274 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000275 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
276
njn25e49d8e72002-09-23 09:36:25 +0000277 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000278 short-amode-boundary, there's no point. */
279
sewardjfa492d42002-12-08 18:20:01 +0000280 VGOFF_(m_dflag) = alloc_BaB(1);
281
sewardjb91ae7f2003-04-29 23:50:00 +0000282 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000283 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000284 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
285 vg_assert(
286 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
287 % 16 )
288 == 0
289 );
sewardjde4a1d02002-03-22 01:27:54 +0000290
sewardj92a59562002-09-30 00:53:10 +0000291 /* This thread's LDT pointer, and segment registers. */
292 VGOFF_(ldt) = alloc_BaB(1);
293 VGOFF_(m_cs) = alloc_BaB(1);
294 VGOFF_(m_ss) = alloc_BaB(1);
295 VGOFF_(m_ds) = alloc_BaB(1);
296 VGOFF_(m_es) = alloc_BaB(1);
297 VGOFF_(m_fs) = alloc_BaB(1);
298 VGOFF_(m_gs) = alloc_BaB(1);
299
sewardje1042472002-09-30 12:33:11 +0000300 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
301
njn9b007f62003-04-07 14:40:25 +0000302#define REG(kind, size) \
303 if (VG_(track_events).kind##_mem_stack##size) \
304 VG_(register_noncompact_helper)( \
305 (Addr) VG_(track_events).kind##_mem_stack##size );
306
307 REG(new, _8);
308 REG(new, _12);
309 REG(new, _16);
310 REG(new, _32);
311 REG(new, );
312 REG(die, _8);
313 REG(die, _12);
314 REG(die, _16);
315 REG(die, _32);
316 REG(die, );
317#undef REG
318
319 if (VG_(need_to_handle_esp_assignment)())
320 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
321
sewardj92a59562002-09-30 00:53:10 +0000322 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000323 VGOFF_(helper_idiv_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000324 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000325 VGOFF_(helper_div_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000326 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000327 VGOFF_(helper_idiv_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000328 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000329 VGOFF_(helper_div_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000330 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000331 VGOFF_(helper_idiv_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000332 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000333 VGOFF_(helper_div_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000334 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000335
336 VGOFF_(helper_imul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000337 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000338 VGOFF_(helper_mul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000339 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000340 VGOFF_(helper_imul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000341 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000342 VGOFF_(helper_mul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000343 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000344 VGOFF_(helper_imul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000345 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000346 VGOFF_(helper_mul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000347 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000348
349 VGOFF_(helper_CLD)
daywalkerb106c422003-09-29 10:56:24 +0000350 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD));
sewardjde4a1d02002-03-22 01:27:54 +0000351 VGOFF_(helper_STD)
daywalkerb106c422003-09-29 10:56:24 +0000352 = alloc_BaB_1_set( (Addr) & VG_(helper_STD));
sewardjde4a1d02002-03-22 01:27:54 +0000353 VGOFF_(helper_get_dirflag)
daywalkerb106c422003-09-29 10:56:24 +0000354 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag));
sewardjde4a1d02002-03-22 01:27:54 +0000355
sewardj7d78e782002-06-02 00:04:00 +0000356 VGOFF_(helper_CLC)
daywalkerb106c422003-09-29 10:56:24 +0000357 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC));
sewardj73cf3bc2002-11-03 03:20:15 +0000358 VGOFF_(helper_STC)
daywalkerb106c422003-09-29 10:56:24 +0000359 = alloc_BaB_1_set( (Addr) & VG_(helper_STC));
sewardj7d78e782002-06-02 00:04:00 +0000360
sewardjde4a1d02002-03-22 01:27:54 +0000361 VGOFF_(helper_shldl)
daywalkerb106c422003-09-29 10:56:24 +0000362 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl));
sewardjde4a1d02002-03-22 01:27:54 +0000363 VGOFF_(helper_shldw)
daywalkerb106c422003-09-29 10:56:24 +0000364 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw));
sewardjde4a1d02002-03-22 01:27:54 +0000365 VGOFF_(helper_shrdl)
daywalkerb106c422003-09-29 10:56:24 +0000366 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl));
sewardjde4a1d02002-03-22 01:27:54 +0000367 VGOFF_(helper_shrdw)
daywalkerb106c422003-09-29 10:56:24 +0000368 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw));
sewardjde4a1d02002-03-22 01:27:54 +0000369
370 VGOFF_(helper_RDTSC)
daywalkerb106c422003-09-29 10:56:24 +0000371 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC));
sewardjde4a1d02002-03-22 01:27:54 +0000372 VGOFF_(helper_CPUID)
daywalkerb106c422003-09-29 10:56:24 +0000373 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID));
sewardjde4a1d02002-03-22 01:27:54 +0000374
sewardjde4a1d02002-03-22 01:27:54 +0000375 VGOFF_(helper_bsf)
daywalkerb106c422003-09-29 10:56:24 +0000376 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf));
sewardjde4a1d02002-03-22 01:27:54 +0000377 VGOFF_(helper_bsr)
daywalkerb106c422003-09-29 10:56:24 +0000378 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr));
sewardjde4a1d02002-03-22 01:27:54 +0000379
380 VGOFF_(helper_fstsw_AX)
daywalkerb106c422003-09-29 10:56:24 +0000381 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX));
sewardjde4a1d02002-03-22 01:27:54 +0000382 VGOFF_(helper_SAHF)
daywalkerb106c422003-09-29 10:56:24 +0000383 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF));
njnd6251f12003-06-03 13:38:51 +0000384 VGOFF_(helper_LAHF)
daywalkerb106c422003-09-29 10:56:24 +0000385 = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF));
sewardj4d0ab1f2002-03-24 10:00:09 +0000386 VGOFF_(helper_DAS)
daywalkerb106c422003-09-29 10:56:24 +0000387 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS));
sewardjfe8a1662002-03-24 11:54:07 +0000388 VGOFF_(helper_DAA)
daywalkerb106c422003-09-29 10:56:24 +0000389 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA));
daywalkerb18d2532003-09-27 20:15:01 +0000390 VGOFF_(helper_IN)
daywalkerb106c422003-09-29 10:56:24 +0000391 = alloc_BaB_1_set( (Addr) & VG_(helper_IN));
daywalkerb18d2532003-09-27 20:15:01 +0000392 VGOFF_(helper_OUT)
daywalkerb106c422003-09-29 10:56:24 +0000393 = alloc_BaB_1_set( (Addr) & VG_(helper_OUT));
njn25e49d8e72002-09-23 09:36:25 +0000394
sewardj51096432002-12-14 23:59:09 +0000395 VGOFF_(helper_undefined_instruction)
daywalkerb106c422003-09-29 10:56:24 +0000396 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction));
sewardj51096432002-12-14 23:59:09 +0000397
sewardj92a59562002-09-30 00:53:10 +0000398 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000399 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
400 VG_(noncompact_helper_offsets),
401 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000402
njncc7bb472002-10-14 09:25:19 +0000403
404 /* Initialise slots that require it */
405 VG_(copy_m_state_static_to_baseBlock)();
406
407 /* Pretend the root thread has a completely empty LDT to start with. */
408 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
409
410 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000411 if (VG_(needs).shadow_regs) {
njn25e49d8e72002-09-23 09:36:25 +0000412 VG_(baseBlock)[VGOFF_(sh_esp)] =
413 VG_(baseBlock)[VGOFF_(sh_ebp)] =
414 VG_(baseBlock)[VGOFF_(sh_eax)] =
415 VG_(baseBlock)[VGOFF_(sh_ecx)] =
416 VG_(baseBlock)[VGOFF_(sh_edx)] =
417 VG_(baseBlock)[VGOFF_(sh_ebx)] =
418 VG_(baseBlock)[VGOFF_(sh_esi)] =
njnd3040452003-05-19 15:04:06 +0000419 VG_(baseBlock)[VGOFF_(sh_edi)] = 0;
420 VG_(baseBlock)[VGOFF_(sh_eflags)] = 0;
421 VG_TRACK( post_regs_write_init );
njncc7bb472002-10-14 09:25:19 +0000422 }
sewardjde4a1d02002-03-22 01:27:54 +0000423}
424
425
426/* ---------------------------------------------------------------------
427 Global entities which are not referenced from generated code.
428 ------------------------------------------------------------------ */
429
430/* The stack on which Valgrind runs. We can't use the same stack as
431 the simulatee -- that's an important design decision. */
njn6eba4ef2003-05-01 08:06:41 +0000432UInt VG_(stack)[VG_STACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000433
434/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000435UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000436
437/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000438__attribute__ ((aligned (16)))
439UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000440Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000441
442/* Counts downwards in vg_run_innerloop. */
443UInt VG_(dispatch_ctr);
444
sewardjde4a1d02002-03-22 01:27:54 +0000445
446/* 64-bit counter for the number of basic blocks done. */
447ULong VG_(bbs_done);
448/* 64-bit counter for the number of bbs to go before a debug exit. */
449ULong VG_(bbs_to_go);
450
sewardj7e87e382002-05-03 19:09:05 +0000451/* This is the ThreadId of the last thread the scheduler ran. */
452ThreadId VG_(last_run_tid) = 0;
453
njn25e49d8e72002-09-23 09:36:25 +0000454/* This is the argument to __NR_exit() supplied by the first thread to
455 call that syscall. We eventually pass that to __NR_exit() for
456 real. */
njn633de322003-05-12 20:40:13 +0000457Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000458
sewardj73cf3bc2002-11-03 03:20:15 +0000459/* Tell the logging mechanism whether we are logging to a file
460 descriptor or a socket descriptor. */
461Bool VG_(logging_to_filedes) = True;
462
sewardjb91ae7f2003-04-29 23:50:00 +0000463/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
464 the SSE state all over the place. This is set up very early, in
465 vg_startup.S. We have to determine it early since we can't even
466 correctly snapshot the startup machine state without it. */
467/* Initially True. Safer to err on the side of SSEness and get SIGILL
daywalker7e73e5f2003-07-04 16:18:15 +0000468 than to not notice for some reason that we have SSE and get weird
sewardjb91ae7f2003-04-29 23:50:00 +0000469 errors later on. */
470Bool VG_(have_ssestate) = True;
471
sewardjde4a1d02002-03-22 01:27:54 +0000472
473/* ---------------------------------------------------------------------
474 Counters, for informational purposes only.
475 ------------------------------------------------------------------ */
476
477/* Number of lookups which miss the fast tt helper. */
478UInt VG_(tt_fast_misses) = 0;
479
480
sewardjc0d8f682002-11-30 00:49:43 +0000481/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000482
sewardjde4a1d02002-03-22 01:27:54 +0000483/* Number and total o/t size of translations overall. */
484UInt VG_(overall_in_count) = 0;
485UInt VG_(overall_in_osize) = 0;
486UInt VG_(overall_in_tsize) = 0;
487/* Number and total o/t size of discards overall. */
488UInt VG_(overall_out_count) = 0;
489UInt VG_(overall_out_osize) = 0;
490UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000491/* The number of discards of TT/TC. */
492UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000493/* Counts of chain and unchain operations done. */
494UInt VG_(bb_enchain_count) = 0;
495UInt VG_(bb_dechain_count) = 0;
496/* Number of unchained jumps performed. */
497UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000498
499
500/* Counts pertaining to the register allocator. */
501
502/* total number of uinstrs input to reg-alloc */
503UInt VG_(uinstrs_prealloc) = 0;
504
505/* total number of uinstrs added due to spill code */
506UInt VG_(uinstrs_spill) = 0;
507
508/* number of bbs requiring spill code */
509UInt VG_(translations_needing_spill) = 0;
510
511/* total of register ranks over all translations */
512UInt VG_(total_reg_rank) = 0;
513
514
sewardjde4a1d02002-03-22 01:27:54 +0000515/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000516UInt VG_(sanity_fast_count) = 0;
517UInt VG_(sanity_slow_count) = 0;
518
sewardj2e93c502002-04-12 11:12:52 +0000519/* Counts pertaining to the scheduler. */
520UInt VG_(num_scheduling_events_MINOR) = 0;
521UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000522
523
524/* ---------------------------------------------------------------------
525 Values derived from command-line options.
526 ------------------------------------------------------------------ */
527
njn25e49d8e72002-09-23 09:36:25 +0000528/* Define, and set defaults. */
529Bool VG_(clo_error_limit) = True;
530Bool VG_(clo_GDB_attach) = False;
sewardj6024b212003-07-13 10:54:33 +0000531Char* VG_(clo_GDB_path) = GDB_PATH;
njn43c799e2003-04-08 00:08:52 +0000532Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000533Int VG_(sanity_level) = 1;
534Int VG_(clo_verbosity) = 1;
535Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000536Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000537
nethercotee1730692003-11-20 10:38:07 +0000538/* See big comment in vg_include.h for meaning of these three.
539 fd is initially stdout, for --help, but gets moved to stderr by default
540 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +0000541VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +0000542Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +0000543Char* VG_(clo_logfile_name) = NULL;
544
sewardj6024b212003-07-13 10:54:33 +0000545Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +0000546Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000547Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000548Bool VG_(clo_profile) = False;
549Bool VG_(clo_single_step) = False;
550Bool VG_(clo_optimise) = True;
551UChar VG_(clo_trace_codegen) = 0; // 00000000b
552Bool VG_(clo_trace_syscalls) = False;
553Bool VG_(clo_trace_signals) = False;
554Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000555Bool VG_(clo_trace_sched) = False;
556Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000557ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000558Int VG_(clo_dump_error) = 0;
559Int VG_(clo_backtrace_size) = 4;
560Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000561Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +0000562Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +0000563Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +0000564Bool VG_(clo_show_below_main) = False;
sewardj2370f3b2002-11-30 15:01:01 +0000565
jsgf855d93d2003-10-13 22:26:55 +0000566static Bool VG_(clo_wait_for_gdb) = False;
567
568/* If we're doing signal routing, poll for signals every 50mS by
569 default. */
570Int VG_(clo_signal_polltime) = 50;
571
fitzhardinge89f9a322003-10-30 07:25:59 +0000572/* If true, assume we're running on a plain 2.4 kernel */
573Bool VG_(clo_assume_24) = False;
574
jsgf855d93d2003-10-13 22:26:55 +0000575/* These flags reduce thread wakeup latency on syscall completion and
576 signal delivery, respectively. The downside is possible unfairness. */
577Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
578Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
579
sewardjde4a1d02002-03-22 01:27:54 +0000580/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
581 to behave. Initially we say False. */
582Bool VG_(running_on_simd_CPU) = False;
583
584/* Holds client's %esp at the point we gained control. */
585Addr VG_(esp_at_startup);
586
sewardjd5815ec2003-04-06 12:23:27 +0000587/* Indicates presence, and holds address of client's sysinfo page, a
588 feature of some modern kernels used to provide vsyscalls, etc. */
589Bool VG_(sysinfo_page_exists) = False;
590Addr VG_(sysinfo_page_addr) = 0;
591
sewardjde4a1d02002-03-22 01:27:54 +0000592/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
593 envp[] as extracted from the client's stack at startup-time. */
594Int VG_(client_argc);
595Char** VG_(client_argv);
596Char** VG_(client_envp);
597
598/* A place into which to copy the value of env var VG_ARGS, so we
599 don't have to modify the original. */
600static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
601
sewardjde4a1d02002-03-22 01:27:54 +0000602/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000603 Processing of command-line options.
604 ------------------------------------------------------------------ */
605
njn25e49d8e72002-09-23 09:36:25 +0000606void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000607{
608 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000609 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000610 VG_(clo_logfile_fd) = 2; /* stderr */
611 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
612 VG_(exit)(1);
613}
614
615static void config_error ( Char* msg )
616{
617 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000618 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000619 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000620 VG_(printf)(
621 "valgrind.so: Startup or configuration error:\n %s\n", msg);
622 VG_(printf)(
623 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000624 VG_(exit)(1);
625}
626
sewardja1679dd2002-05-10 22:31:40 +0000627static void args_grok_error ( Char* msg )
628{
629 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000630 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000631 VG_(clo_logfile_fd) = 2; /* stderr */
632 VG_(printf)("valgrind.so: When searching for "
633 "client's argc/argc/envp:\n\t%s\n", msg);
634 config_error("couldn't find client's argc/argc/envp");
635}
636
njn25e49d8e72002-09-23 09:36:25 +0000637static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000638{
njn25e49d8e72002-09-23 09:36:25 +0000639 Char* usage1 =
640"usage: valgrind [options] prog-and-args\n"
641"\n"
642" core user options, with defaults in [ ], are:\n"
nethercote137bc552003-11-14 17:47:54 +0000643" --tool=<name> Use the Valgrind tool named <name> [memcheck]\n"
nethercote77eba602003-11-13 17:35:04 +0000644
njn25e49d8e72002-09-23 09:36:25 +0000645" --help show this message\n"
646" --version show version\n"
nethercote77eba602003-11-13 17:35:04 +0000647
njn25e49d8e72002-09-23 09:36:25 +0000648" -q --quiet run silently; only print error msgs\n"
649" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000650
651" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
652
653" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
654" --logfile=<file> log messages to <file>.pid<pid>\n"
655" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
656
njn25e49d8e72002-09-23 09:36:25 +0000657" --demangle=no|yes automatically demangle C++ names? [yes]\n"
658" --num-callers=<number> show <num> callers in stack traces [4]\n"
659" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
nethercote77eba602003-11-13 17:35:04 +0000660" --show-below-main=no|yes continue stack traces below main() [no]\n"
661" --suppressions=<filename> suppress errors described in <filename>\n"
662" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
663
rjwalshf5f536f2003-11-17 17:45:00 +0000664" --track-fds=no|yes Track open file descriptors? [no]\n"
665
nethercote77eba602003-11-13 17:35:04 +0000666" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
667" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
sewardj6024b212003-07-13 10:54:33 +0000668" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
nethercote77eba602003-11-13 17:35:04 +0000669
670" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
671" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +0000672" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000673" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
674" Only applies for older kernels which need\n"
675" signal routing [50]\n"
676" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
677" a signal [no]\n"
678" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
679" syscall completes [no]\n"
fitzhardinge89f9a322003-10-30 07:25:59 +0000680" --assume-2.4=no|yes assume we're running on a 2.4 kernel [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000681"\n"
nethercote137bc552003-11-14 17:47:54 +0000682" %s tool user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000683
njn7cf0bd32002-06-08 13:36:03 +0000684
njn25e49d8e72002-09-23 09:36:25 +0000685 Char* usage2 =
686"\n"
687" core options for debugging Valgrind itself are:\n"
688" --sanity-level=<number> level of sanity checking to do [1]\n"
689" --single-step=no|yes translate each instr separately? [no]\n"
690" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +0000691" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000692" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000693" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
694" --trace-syscalls=no|yes show all system calls? [no]\n"
695" --trace-signals=no|yes show signal handling details? [no]\n"
696" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000697" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000698" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000699" --stop-after=<number> switch to real CPU after executing\n"
700" <number> basic blocks [infinity]\n"
701" --dump-error=<number> show translation for basic block\n"
702" associated with <number>'th\n"
703" error context [0=don't show any]\n"
jsgf855d93d2003-10-13 22:26:55 +0000704" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000705"\n"
nethercote137bc552003-11-14 17:47:54 +0000706" %s tool debugging options:\n";
njn3e884182003-04-15 13:03:23 +0000707
708 Char* usage3 =
709"\n"
njn25e49d8e72002-09-23 09:36:25 +0000710" Extra options are read from env variable $VALGRIND_OPTS\n"
711"\n"
njn0e1b5142003-04-15 14:58:06 +0000712" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000713" and licensed under the GNU General Public License, version 2.\n"
714" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000715"\n"
nethercote137bc552003-11-14 17:47:54 +0000716" Tools are copyright and licensed by their authors. See each\n"
717" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000718"\n";
njn7cf0bd32002-06-08 13:36:03 +0000719
njnd04b7c62002-10-03 14:05:52 +0000720 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000721 /* Don't print skin string directly for security, ha! */
722 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000723 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000724 else
725 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000726 VG_(printf)(usage2, VG_(details).name);
727 if (VG_(needs).command_line_options)
728 SK_(print_debug_usage)();
729 else
730 VG_(printf)(" (none)\n");
nethercote421281e2003-11-20 16:20:55 +0000731 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +0000732
njn25e49d8e72002-09-23 09:36:25 +0000733 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000734 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000735 VG_(clo_logfile_fd) = 2; /* stderr */
736 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000737}
sewardjde4a1d02002-03-22 01:27:54 +0000738
sewardj1c1b1162003-02-23 01:25:51 +0000739
sewardj49e630d2003-04-23 21:18:52 +0000740/* Callback for looking for the stack segment. */
741Addr VG_(foundstack_start) = (Addr)NULL;
742UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000743
744static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000745 Char r, Char w, Char x,
746 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000747{
748 Addr lastword;
749 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000750 if (r != 'r' || w != 'w'
751 /* || x != 'x' --not necessarily so on x86-64*/
752 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000753 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000754 if (start <= VG_(esp_at_startup)
755 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000756 VG_(foundstack_start) = start;
757 VG_(foundstack_size) = size;
758 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000759 }
760}
761
762
763
sewardjde4a1d02002-03-22 01:27:54 +0000764static void process_cmd_line_options ( void )
765{
njn25e49d8e72002-09-23 09:36:25 +0000766 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000767 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000768 Char* p;
769 Char* str;
770 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000771
772# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000773
nethercotee1730692003-11-20 10:38:07 +0000774 /* log to stderr by default, but usage message goes to stdout */
775 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +0000776
777 /* Once logging is started, we can safely send messages pertaining
778 to failures in initialisation. */
779 VG_(startup_logging)();
780
sewardj19d81412002-06-03 01:10:40 +0000781 /* Check for sane path in ./configure --prefix=... */
782 if (VG_(strlen)(VG_LIBDIR) < 1
783 || VG_LIBDIR[0] != '/')
784 config_error("Please use absolute paths in "
785 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000786
sewardja1679dd2002-05-10 22:31:40 +0000787 /* (Suggested by Fabrice Bellard ... )
788 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000789 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000790 change less often than the libc ones. */
791 {
sewardj05bcdcb2003-05-18 10:05:38 +0000792 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000793
njn3e884182003-04-15 13:03:23 +0000794 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000795 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000796 has rwx permissions and no associated file. Note that this uses
797 the /proc/self/maps contents read at the start of VG_(main)(),
798 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000799
njnfa1016e2003-09-25 17:54:11 +0000800 VG_(parse_procselfmaps)( vg_findstack_callback );
sewardj53fe4582003-02-23 01:41:17 +0000801
sewardj49e630d2003-04-23 21:18:52 +0000802 /* Now foundstack_start and foundstack_size should delimit the stack. */
803 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000804 args_grok_error("Cannot determine stack segment "
805 "from /proc/self/maps");
806 }
sewardj1c1b1162003-02-23 01:25:51 +0000807
808 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000809 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000810 VG_(foundstack_start),
811 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000812
sewardj49e630d2003-04-23 21:18:52 +0000813 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000814 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
815 args_grok_error("Stack segment is not page aligned?!");
816 }
sewardj1c1b1162003-02-23 01:25:51 +0000817
sewardj53fe4582003-02-23 01:41:17 +0000818 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
819 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000820
sewardj38170912002-05-10 21:07:22 +0000821 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000822 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000823 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000824 sp--;
825 }
sewardj38170912002-05-10 21:07:22 +0000826
827 if (sp[2] == VKI_AT_BASE
828 && sp[0] == VKI_AT_PAGESZ
829 && sp[-2] == VKI_AT_PHNUM
830 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000831 && sp[-6] == VKI_AT_PHDR
832 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000833 if (0)
834 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000835 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000836 } else
837 if (sp[2] == VKI_AT_CLKTCK
838 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000839 && sp[-2] == VKI_AT_HWCAP
840 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000841 if (0)
842 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
843 sp -= 2;
844 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000845 if (sp[2] == VKI_AT_CLKTCK
846 && sp[0] == VKI_AT_PAGESZ
847 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000848 && sp[-4] == VKI_AT_SYSINFO
849 && sp[-4-1] == 0) {
850 if (0)
851 VG_(printf)("Looks like you've got a 2.4.X kernel with "
852 "a sysinfo page at %x here.\n", sp[-3]);
853 VG_(sysinfo_page_exists) = True;
854 VG_(sysinfo_page_addr) = sp[-3];
855 sp -= 4;
856 } else
857 if (sp[2] == VKI_AT_CLKTCK
858 && sp[0] == VKI_AT_PAGESZ
859 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000860 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
861 && sp[-4-1] == 0) {
862 if (0)
863 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
864 "kernel here.\n");
865 sp -= 4;
866 } else
867 if (sp[2] == VKI_AT_CLKTCK
868 && sp[0] == VKI_AT_PAGESZ
869 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000870 && sp[-2-20-1] == 0) {
871 if (0)
872 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
873 sp -= 22;
874 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000875 if (sp[2] == VKI_AT_CLKTCK
876 && sp[0] == VKI_AT_PAGESZ
877 && sp[-2] == VKI_AT_HWCAP
878 && sp[-4-1] == 0) {
879 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000880 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000881 sp -= 4;
882 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000883 if (sp[2] == VKI_AT_CLKTCK
884 && sp[0] == VKI_AT_PAGESZ
885 && sp[-2] == VKI_AT_HWCAP
886 && sp[-6] == VKI_AT_SYSINFO
887 && sp[-6-1] == 0) {
888 if (0)
889 VG_(printf)("Looks like a >= 2.5.68 kernel with "
890 "a sysinfo page at %x here.\n", sp[-5]);
891 VG_(sysinfo_page_exists) = True;
892 VG_(sysinfo_page_addr) = sp[-5];
893 sp -= 6;
894 } else
sewardja1679dd2002-05-10 22:31:40 +0000895 args_grok_error(
896 "ELF frame does not look like 2.2.X or 2.4.X.\n "
897 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
898 );
sewardj38170912002-05-10 21:07:22 +0000899
900 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000901 if (*sp != 0)
902 args_grok_error("can't find NULL at end of env[]");
903
sewardj38170912002-05-10 21:07:22 +0000904 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000905 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000906 while (True) {
907 sp --;
908 if (*sp == 0) break;
mueller0be67ff2003-11-19 00:45:13 +0000909 if (++ctr >= 2000)
sewardja1679dd2002-05-10 22:31:40 +0000910 args_grok_error(
mueller0be67ff2003-11-19 00:45:13 +0000911 "suspiciously many (2000) env[] entries; giving up");
sewardja1679dd2002-05-10 22:31:40 +0000912
sewardj38170912002-05-10 21:07:22 +0000913 }
914 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000915 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000916
sewardja1679dd2002-05-10 22:31:40 +0000917 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000918 VG_(client_argc) = 0;
919 while (True) {
920 sp--;
921 if (*sp == VG_(client_argc))
922 break;
923 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000924 if (++ctr >= 1000)
925 args_grok_error(
926 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000927 }
928
sewardja1679dd2002-05-10 22:31:40 +0000929 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000930 }
931
sewardjde4a1d02002-03-22 01:27:54 +0000932 /* Now that VG_(client_envp) has been set, we can extract the args
933 for Valgrind itself. Copy into global var so that we don't have to
934 write zeroes to the getenv'd value itself. */
935 str = VG_(getenv)("VG_ARGS");
936 argc = 0;
937
938 if (!str) {
939 config_error("Can't read options from env var VG_ARGS.");
940 }
941
942 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
943 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
944 }
945 VG_(strcpy)(vg_cmdline_copy, str);
946 str = NULL;
947
948 p = &vg_cmdline_copy[0];
949 while (True) {
950 while (ISSPACE(*p)) { *p = 0; p++; }
951 if (*p == 0) break;
952 if (argc < M_VG_CMDLINE_OPTS-1) {
953 argv[argc] = p; argc++;
954 } else {
955 config_error(
956 "Found more than M_CMDLINE_OPTS command-line opts.");
957 }
958 while (*p != 0 && !ISSPACE(*p)) p++;
959 }
960
961 for (i = 0; i < argc; i++) {
962
njn43c799e2003-04-08 00:08:52 +0000963 if (VG_CLO_STREQ(argv[i], "-v") ||
964 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000965 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000966 else if (VG_CLO_STREQ(argv[i], "-q") ||
967 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000968 VG_(clo_verbosity)--;
969
njn43c799e2003-04-08 00:08:52 +0000970 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000971 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000972 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000973 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000974
njn43c799e2003-04-08 00:08:52 +0000975 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000976 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000977 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000978 VG_(clo_GDB_attach) = False;
979
sewardj6024b212003-07-13 10:54:33 +0000980 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
981 VG_(clo_GDB_path) = &argv[i][11];
982
njn43c799e2003-04-08 00:08:52 +0000983 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
984 VG_(clo_gen_suppressions) = True;
985 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
986 VG_(clo_gen_suppressions) = False;
987
nethercote77eba602003-11-13 17:35:04 +0000988 else if (VG_CLO_STREQ(argv[i], "--show-below-main=yes"))
989 VG_(clo_show_below_main) = True;
990 else if (VG_CLO_STREQ(argv[i], "--show-below-main=no"))
991 VG_(clo_show_below_main) = False;
992
njn43c799e2003-04-08 00:08:52 +0000993 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000994 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000995 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000996 VG_(clo_demangle) = False;
997
njn43c799e2003-04-08 00:08:52 +0000998 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000999 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +00001000 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001001 VG_(clo_trace_children) = False;
1002
njn43c799e2003-04-08 00:08:52 +00001003 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001004 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +00001005 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001006 VG_(clo_run_libc_freeres) = False;
1007
rjwalshf5f536f2003-11-17 17:45:00 +00001008 else if (VG_CLO_STREQ(argv[i], "--track-fds=yes"))
1009 VG_(clo_track_fds) = True;
1010 else if (VG_CLO_STREQ(argv[i], "--track-fds=no"))
1011 VG_(clo_track_fds) = False;
1012
njn43c799e2003-04-08 00:08:52 +00001013 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +00001014 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
1015
njn43c799e2003-04-08 00:08:52 +00001016 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001017 VG_(clo_log_to) = VgLogTo_Fd;
1018 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001019 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +00001020 }
1021
njn43c799e2003-04-08 00:08:52 +00001022 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001023 VG_(clo_log_to) = VgLogTo_File;
1024 VG_(clo_logfile_name) = &argv[i][10];
1025 }
sewardjde4a1d02002-03-22 01:27:54 +00001026
njn43c799e2003-04-08 00:08:52 +00001027 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001028 VG_(clo_log_to) = VgLogTo_Socket;
1029 VG_(clo_logfile_name) = &argv[i][12];
1030 }
1031
sewardj6024b212003-07-13 10:54:33 +00001032 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
1033 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
1034
njn43c799e2003-04-08 00:08:52 +00001035 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001036 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001037 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001038 VG_(message)(Vg_UserMsg,
1039 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +00001040 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001041 }
1042 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
1043 VG_(clo_n_suppressions)++;
1044 }
njn43c799e2003-04-08 00:08:52 +00001045 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001046 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +00001047 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001048 VG_(clo_profile) = False;
1049
njn43c799e2003-04-08 00:08:52 +00001050 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001051 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +00001052 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001053 VG_(clo_chain_bb) = False;
1054
njn43c799e2003-04-08 00:08:52 +00001055 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001056 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +00001057 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001058 VG_(clo_single_step) = False;
1059
njn43c799e2003-04-08 00:08:52 +00001060 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001061 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +00001062 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001063 VG_(clo_optimise) = False;
1064
njn25e49d8e72002-09-23 09:36:25 +00001065 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +00001066 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001067 Int j;
1068 char* opt = & argv[i][16];
1069
1070 if (5 != VG_(strlen)(opt)) {
1071 VG_(message)(Vg_UserMsg,
1072 "--trace-codegen argument must have 5 digits");
1073 VG_(bad_option)(argv[i]);
1074 }
1075 for (j = 0; j < 5; j++) {
1076 if ('0' == opt[j]) { /* do nothing */ }
1077 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1078 else {
1079 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1080 "contain 0s and 1s");
1081 VG_(bad_option)(argv[i]);
1082 }
1083 }
1084 }
sewardjde4a1d02002-03-22 01:27:54 +00001085
njn43c799e2003-04-08 00:08:52 +00001086 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001087 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001088 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001089 VG_(clo_trace_syscalls) = False;
1090
njn43c799e2003-04-08 00:08:52 +00001091 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001092 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001093 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001094 VG_(clo_trace_signals) = False;
1095
njn43c799e2003-04-08 00:08:52 +00001096 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001097 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001098 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001099 VG_(clo_trace_symtab) = False;
1100
njn43c799e2003-04-08 00:08:52 +00001101 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001102 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001103 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001104 VG_(clo_trace_sched) = False;
1105
njn43c799e2003-04-08 00:08:52 +00001106 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001107 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001108 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001109 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001110 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001111 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001112
njn43c799e2003-04-08 00:08:52 +00001113 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001114 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001115
jsgf855d93d2003-10-13 22:26:55 +00001116 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
1117 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
1118
1119 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
1120 VG_(clo_lowlat_signals) = True;
1121 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
1122 VG_(clo_lowlat_signals) = False;
1123
1124 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
1125 VG_(clo_lowlat_syscalls) = True;
1126 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
1127 VG_(clo_lowlat_syscalls) = False;
1128
fitzhardinge89f9a322003-10-30 07:25:59 +00001129 else if (VG_CLO_STREQ(argv[i], "--assume-2.4=yes"))
1130 VG_(clo_assume_24) = True;
1131 else if (VG_CLO_STREQ(argv[i], "--assume-2.4=no"))
1132 VG_(clo_assume_24) = False;
1133
njn43c799e2003-04-08 00:08:52 +00001134 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001135 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1136
njn43c799e2003-04-08 00:08:52 +00001137 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001138 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1139
jsgf855d93d2003-10-13 22:26:55 +00001140 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
1141 VG_(clo_wait_for_gdb) = True;
1142 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
1143 VG_(clo_wait_for_gdb) = False;
1144
njn43c799e2003-04-08 00:08:52 +00001145 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001146 /* Make sure it's sane. */
1147 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +00001148 if (VG_(clo_backtrace_size) < 1)
1149 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001150 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1151 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1152 }
1153
njn25e49d8e72002-09-23 09:36:25 +00001154 else if (VG_(needs).command_line_options) {
1155 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1156 if (!ok)
1157 usage();
1158 }
sewardjde4a1d02002-03-22 01:27:54 +00001159 else
njn25e49d8e72002-09-23 09:36:25 +00001160 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001161 }
1162
1163# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001164
njnf9ebf672003-05-12 21:41:30 +00001165 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001166 VG_(clo_verbosity) = 0;
1167
1168 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1169 VG_(message)(Vg_UserMsg, "");
1170 VG_(message)(Vg_UserMsg,
1171 "--gdb-attach=yes conflicts with --trace-children=yes");
1172 VG_(message)(Vg_UserMsg,
1173 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001174 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001175 }
1176
sewardj4cf05692002-10-27 20:28:29 +00001177 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1178 should be connected to whatever sink has been selected, and we
1179 indiscriminately chuck stuff into it without worrying what the
1180 nature of it is. Oh the wonder of Unix streams. */
1181
nethercotee1730692003-11-20 10:38:07 +00001182 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001183 the terminal any problems to do with processing command line
1184 opts. */
nethercotee1730692003-11-20 10:38:07 +00001185 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001186 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001187
1188 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001189
sewardj4cf05692002-10-27 20:28:29 +00001190 case VgLogTo_Fd:
1191 vg_assert(VG_(clo_logfile_name) == NULL);
1192 VG_(clo_logfile_fd) = eventually_logfile_fd;
1193 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001194
sewardj4cf05692002-10-27 20:28:29 +00001195 case VgLogTo_File: {
1196 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001197 Int seq = 0;
1198 Int pid = VG_(getpid)();
1199
sewardj4cf05692002-10-27 20:28:29 +00001200 vg_assert(VG_(clo_logfile_name) != NULL);
1201 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001202
1203 for(;;) {
1204 if (seq == 0)
1205 VG_(sprintf)(logfilename, "%s.pid%d",
1206 VG_(clo_logfile_name), pid );
1207 else
1208 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1209 VG_(clo_logfile_name), pid, seq );
1210 seq++;
1211
1212 eventually_logfile_fd
1213 = VG_(open)(logfilename,
1214 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1215 VKI_S_IRUSR|VKI_S_IWUSR);
1216 if (eventually_logfile_fd >= 0) {
1217 VG_(clo_logfile_fd) = eventually_logfile_fd;
1218 break;
1219 } else {
1220 if (eventually_logfile_fd != -VKI_EEXIST) {
1221 VG_(message)(Vg_UserMsg,
1222 "Can't create/open log file `%s.pid%d'; giving up!",
1223 VG_(clo_logfile_name), pid);
1224 VG_(bad_option)(
1225 "--logfile=<file> didn't work out for some reason.");
1226 break;
1227 }
1228 }
1229 }
sewardj4cf05692002-10-27 20:28:29 +00001230 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001231 }
1232
1233 case VgLogTo_Socket: {
1234 vg_assert(VG_(clo_logfile_name) != NULL);
1235 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1236 eventually_logfile_fd
1237 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1238 if (eventually_logfile_fd == -1) {
1239 VG_(message)(Vg_UserMsg,
1240 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1241 VG_(message)(Vg_UserMsg,
1242 "of `%s'; giving up!", VG_(clo_logfile_name) );
1243 VG_(bad_option)(
1244 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001245 }
sewardj73cf3bc2002-11-03 03:20:15 +00001246 if (eventually_logfile_fd == -2) {
1247 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001248 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001249 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001250 VG_(message)(Vg_UserMsg,
1251 "Log messages will sent to stderr instead." );
1252 VG_(message)(Vg_UserMsg,
1253 "" );
1254 /* We don't change anything here. */
1255 } else {
1256 vg_assert(eventually_logfile_fd > 0);
1257 VG_(clo_logfile_fd) = eventually_logfile_fd;
1258 VG_(logging_to_filedes) = False;
1259 }
sewardj73cf3bc2002-11-03 03:20:15 +00001260 break;
1261 }
1262
sewardj4cf05692002-10-27 20:28:29 +00001263 }
1264
jsgf855d93d2003-10-13 22:26:55 +00001265 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
1266 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_MAX_FD+1);
1267 if (eventually_logfile_fd < 0)
1268 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1269 else {
1270 VG_(clo_logfile_fd) = eventually_logfile_fd;
1271 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1272 }
1273
sewardj4cf05692002-10-27 20:28:29 +00001274 /* Ok, the logging sink is running now. Print a suitable preamble.
1275 If logging to file or a socket, write details of parent PID and
1276 command line args, to help people trying to interpret the
1277 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001278
sewardj83adf412002-05-01 01:25:45 +00001279 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001280 /* Skin details */
1281 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1282 VG_(details).name,
1283 NULL == VG_(details).version ? "" : "-",
1284 NULL == VG_(details).version
1285 ? (Char*)"" : VG_(details).version,
1286 VG_(details).description);
1287 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001288
njnd04b7c62002-10-03 14:05:52 +00001289 /* Core details */
1290 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001291 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001292 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001293 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001294 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001295 }
1296
nethercotec1e395d2003-11-10 13:26:49 +00001297 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001298 VG_(message)(Vg_UserMsg, "");
1299 VG_(message)(Vg_UserMsg,
1300 "My PID = %d, parent PID = %d. Prog and args are:",
1301 VG_(getpid)(), VG_(getppid)() );
1302 for (i = 0; i < VG_(client_argc); i++)
1303 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1304 }
1305
sewardjde4a1d02002-03-22 01:27:54 +00001306 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001307 if (VG_(clo_log_to) != VgLogTo_Fd)
1308 VG_(message)(Vg_UserMsg, "");
njn86dc2bc2003-09-09 07:26:21 +00001309 VG_(message)(Vg_UserMsg, "Command line");
1310 for (i = 0; i < VG_(client_argc); i++)
1311 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1312
sewardjde4a1d02002-03-22 01:27:54 +00001313 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1314 for (i = 0; i < argc; i++) {
1315 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1316 }
1317 }
1318
njn25e49d8e72002-09-23 09:36:25 +00001319 if (VG_(clo_n_suppressions) == 0 &&
1320 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001321 config_error("No error-suppression files were specified.");
1322 }
sewardj4cf05692002-10-27 20:28:29 +00001323
njn6a230532003-07-21 10:38:23 +00001324 if (VG_(clo_gen_suppressions) &&
1325 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1326 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1327 " as it doesn't generate errors.");
1328 }
1329
sewardjde4a1d02002-03-22 01:27:54 +00001330}
1331
sewardjde4a1d02002-03-22 01:27:54 +00001332/* ---------------------------------------------------------------------
1333 Copying to/from m_state_static.
1334 ------------------------------------------------------------------ */
1335
sewardjb91ae7f2003-04-29 23:50:00 +00001336/* See comment about this in vg_include.h. Change only with
1337 great care.
1338*/
1339__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001340UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1341 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001342 + 1 /* %eflags */
1343 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001344 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001345 ];
1346
sewardjfa492d42002-12-08 18:20:01 +00001347UInt VG_(insertDflag)(UInt eflags, Int d)
1348{
1349 vg_assert(d == 1 || d == -1);
1350 eflags &= ~EFlagD;
1351
1352 if (d < 0)
1353 eflags |= EFlagD;
1354
1355 return eflags;
1356}
1357
1358Int VG_(extractDflag)(UInt eflags)
1359{
1360 Int ret;
1361
1362 if (eflags & EFlagD)
1363 ret = -1;
1364 else
1365 ret = 1;
1366
1367 return ret;
1368}
1369
sewardjde4a1d02002-03-22 01:27:54 +00001370void VG_(copy_baseBlock_to_m_state_static) ( void )
1371{
1372 Int i;
sewardj92a59562002-09-30 00:53:10 +00001373 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1374 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1375 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1376 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1377 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1378 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001379
sewardj92a59562002-09-30 00:53:10 +00001380 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1381 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1382 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1383 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1384 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1385 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1386 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1387 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1388
sewardjb91ae7f2003-04-29 23:50:00 +00001389 VG_(m_state_static)[56/4]
1390 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1391 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001392 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001393
sewardjb91ae7f2003-04-29 23:50:00 +00001394 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001395 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001396 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001397}
1398
1399
1400void VG_(copy_m_state_static_to_baseBlock) ( void )
1401{
1402 Int i;
sewardj92a59562002-09-30 00:53:10 +00001403 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1404 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1405 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1406 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1407 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1408 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001409
sewardj92a59562002-09-30 00:53:10 +00001410 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1411 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1412 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1413 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1414 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1415 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1416 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1417 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1418
sewardjb91ae7f2003-04-29 23:50:00 +00001419 VG_(baseBlock)[VGOFF_(m_eflags)]
1420 = VG_(m_state_static)[56/4] & ~EFlagD;
1421 VG_(baseBlock)[VGOFF_(m_dflag)]
1422 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001423
sewardj92a59562002-09-30 00:53:10 +00001424 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001425
sewardjb91ae7f2003-04-29 23:50:00 +00001426 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1427 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001428 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001429}
1430
njn25e49d8e72002-09-23 09:36:25 +00001431Addr VG_(get_stack_pointer) ( void )
1432{
1433 return VG_(baseBlock)[VGOFF_(m_esp)];
1434}
1435
1436/* Some random tests needed for leak checking */
1437
1438Bool VG_(within_stack)(Addr a)
1439{
1440 if (a >= ((Addr)(&VG_(stack)))
1441 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1442 return True;
1443 else
1444 return False;
1445}
1446
sewardjecf8e102003-07-12 12:11:39 +00001447Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001448{
1449 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001450 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001451 return True;
sewardjecf8e102003-07-12 12:11:39 +00001452
1453 if (a >= ((Addr)(&VG_(threads)[0]))
1454 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1455 return True;
1456
1457 return False;
njn25e49d8e72002-09-23 09:36:25 +00001458}
sewardjde4a1d02002-03-22 01:27:54 +00001459
1460/* ---------------------------------------------------------------------
1461 Show accumulated counts.
1462 ------------------------------------------------------------------ */
1463
njn25e49d8e72002-09-23 09:36:25 +00001464static __inline__ Int safe_idiv(Int a, Int b)
1465{
1466 return (b == 0 ? 0 : a / b);
1467}
1468
sewardjde4a1d02002-03-22 01:27:54 +00001469static void vg_show_counts ( void )
1470{
1471 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001472 " TT/TC: %d tc sectors discarded.",
1473 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001474 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001475 " %d chainings, %d unchainings.",
1476 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1477 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001478 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001479 VG_(overall_in_count),
1480 VG_(overall_in_osize),
1481 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001482 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1483 VG_(message)(Vg_DebugMsg,
1484 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001485 VG_(overall_out_count),
1486 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001487 VG_(overall_out_tsize),
1488 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001489 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001490 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001491 VG_(bbs_done),
1492 VG_(unchained_jumps_done),
1493 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1494 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1495 );
1496
1497 VG_(message)(Vg_DebugMsg,
1498 " %d/%d major/minor sched events. %d tt_fast misses.",
1499 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001500 VG_(num_scheduling_events_MINOR),
1501 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001502
sewardjde4a1d02002-03-22 01:27:54 +00001503 VG_(message)(Vg_DebugMsg,
1504 "reg-alloc: %d t-req-spill, "
1505 "%d+%d orig+spill uis, %d total-reg-r.",
1506 VG_(translations_needing_spill),
1507 VG_(uinstrs_prealloc),
1508 VG_(uinstrs_spill),
1509 VG_(total_reg_rank) );
1510 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001511 " sanity: %d cheap, %d expensive checks.",
1512 VG_(sanity_fast_count),
1513 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001514 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001515}
1516
1517
1518/* ---------------------------------------------------------------------
1519 Main!
1520 ------------------------------------------------------------------ */
1521
jsgf855d93d2003-10-13 22:26:55 +00001522/* Initialize the PID and PGRP of scheduler LWP; this is also called
1523 in any new children after fork. */
1524static void newpid(ThreadId unused)
1525{
1526 /* PID of scheduler LWP */
1527 VG_(main_pid) = VG_(getpid)();
1528 VG_(main_pgrp) = VG_(getpgrp)();
1529}
1530
sewardjde4a1d02002-03-22 01:27:54 +00001531/* Where we jump to once Valgrind has got control, and the real
1532 machine's state has been copied to the m_state_static. */
1533
1534void VG_(main) ( void )
1535{
sewardj2e93c502002-04-12 11:12:52 +00001536 Int i;
1537 VgSchedReturnCode src;
sewardjde4a1d02002-03-22 01:27:54 +00001538
njn0c7a5b52003-04-30 09:00:33 +00001539 if (0) {
1540 if (VG_(have_ssestate))
1541 VG_(printf)("Looks like a SSE-capable CPU\n");
1542 else
1543 VG_(printf)("Looks like a MMX-only CPU\n");
1544 }
sewardjb91ae7f2003-04-29 23:50:00 +00001545
njn27f1a382002-11-08 15:48:16 +00001546 /* Check skin and core versions are compatible */
1547 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1548 VG_(printf)("Error:\n"
nethercote137bc552003-11-14 17:47:54 +00001549 " Tool and core interface versions do not match.\n"
njn27f1a382002-11-08 15:48:16 +00001550 " Interface version used by core is: %d.%d\n"
nethercote137bc552003-11-14 17:47:54 +00001551 " Interface version used by tool is: %d.%d\n"
njn27f1a382002-11-08 15:48:16 +00001552 " The major version numbers must match.\n",
1553 VG_CORE_INTERFACE_MAJOR_VERSION,
1554 VG_CORE_INTERFACE_MINOR_VERSION,
1555 VG_(skin_interface_major_version),
1556 VG_(skin_interface_minor_version));
1557 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1558 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1559 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1560 else
1561 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1562 VG_(printf)(" Aborting, sorry.\n");
1563 VG_(exit)(1);
1564 }
1565
jsgf855d93d2003-10-13 22:26:55 +00001566 VG_(atfork)(NULL, NULL, newpid);
1567 newpid(VG_INVALID_THREADID);
1568
sewardjde4a1d02002-03-22 01:27:54 +00001569 /* Set up our stack sanity-check words. */
1570 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001571 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1572 VG_(stack)[VG_STACK_SIZE_W-1-i]
1573 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001574 }
1575
njn3e884182003-04-15 13:03:23 +00001576 /* Read /proc/self/maps into a buffer. Must be before:
1577 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1578 superblocks are not erroneously identified as being owned by the
1579 client, which would be bad.
1580 - init_memory(): that's where the buffer is parsed
1581 - init_tt_tc(): so the anonymous mmaps for the translation table and
1582 translation cache aren't identified as part of the client, which would
1583 waste > 20M of virtual address space, and be bad.
1584 */
njnfa1016e2003-09-25 17:54:11 +00001585 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001586
njn25e49d8e72002-09-23 09:36:25 +00001587 /* Setup stuff that depends on the skin. Must be before:
1588 - vg_init_baseBlock(): to register helpers
1589 - process_cmd_line_options(): to register skin name and description,
1590 and turn on/off 'command_line_options' need
1591 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001592 */
njn810086f2002-11-14 12:42:47 +00001593 SK_(pre_clo_init)();
1594 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001595
njncc7bb472002-10-14 09:25:19 +00001596 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001597 process_cmd_line_options();
1598
jsgf855d93d2003-10-13 22:26:55 +00001599 /* Hook to delay things long enough so we can get the pid and
1600 attach GDB in another shell. */
1601 if (VG_(clo_wait_for_gdb)) {
1602 VG_(printf)("pid=%d\n", VG_(getpid)());
1603 /* do "jump *$eip" to skip this in gdb */
1604 VG_(do_syscall)(__NR_pause);
1605 }
1606
njn3e884182003-04-15 13:03:23 +00001607 /* Do post command-line processing initialisation. Must be before:
1608 - vg_init_baseBlock(): to register any more helpers
1609 */
njncc7bb472002-10-14 09:25:19 +00001610 SK_(post_clo_init)();
1611
njn3e884182003-04-15 13:03:23 +00001612 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001613 vg_init_baseBlock();
1614
rjwalshf5f536f2003-11-17 17:45:00 +00001615 /* Search for file descriptors that are inherited from our parent. */
1616 if (VG_(clo_track_fds))
1617 VG_(init_preopened_fds)();
1618
sewardj018f7622002-05-15 21:13:39 +00001619 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001620 baseBlock into VG_(threads)[1]. Must be before:
1621 - VG_(sigstartup_actions)()
1622 */
sewardj018f7622002-05-15 21:13:39 +00001623 VG_(scheduler_init)();
1624
jsgf855d93d2003-10-13 22:26:55 +00001625 /* Set up the ProxyLWP machinery */
1626 VG_(proxy_init)();
1627
sewardj018f7622002-05-15 21:13:39 +00001628 /* Initialise the signal handling subsystem, temporarily parking
1629 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001630 VG_(sigstartup_actions)();
1631
sewardj018f7622002-05-15 21:13:39 +00001632 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001633 if (VG_(clo_profile))
1634 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001635
sewardj5f07b662002-04-23 16:52:51 +00001636 /* Start calibration of our RDTSC-based clock. */
1637 VG_(start_rdtsc_calibration)();
1638
njn3e884182003-04-15 13:03:23 +00001639 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001640 VGP_PUSHCC(VgpInitMem);
1641 VG_(init_memory)();
1642 VGP_POPCC(VgpInitMem);
1643
1644 /* Read the list of errors to suppress. This should be found in
1645 the file specified by vg_clo_suppressions. */
1646 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1647 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001648
sewardj5f07b662002-04-23 16:52:51 +00001649 /* End calibration of our RDTSC-based clock, leaving it as long as
1650 we can. */
1651 VG_(end_rdtsc_calibration)();
1652
njn3e884182003-04-15 13:03:23 +00001653 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001654 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001655
1656 if (VG_(clo_verbosity) == 1) {
1657 VG_(message)(Vg_UserMsg,
1658 "For more details, rerun with: -v");
1659 }
1660
sewardj25c7c3a2003-07-10 00:17:58 +00001661 /* Force a read of the debug info so that we can look for
1662 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001663 VG_(setup_code_redirect_table)();
1664
sewardjde4a1d02002-03-22 01:27:54 +00001665 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1666 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001667 if (VG_(clo_verbosity) > 0)
1668 VG_(message)(Vg_UserMsg, "");
1669
1670 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001671
sewardj018f7622002-05-15 21:13:39 +00001672 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001673 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001674 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001675
1676 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1677 VG_(fatal_signal_set) = True;
1678 src = VG_(scheduler)();
1679 } else
1680 src = VgSrc_FatalSig;
1681
njn25e49d8e72002-09-23 09:36:25 +00001682 VGP_POPCC(VgpSched);
1683 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001684
1685 if (VG_(clo_verbosity) > 0)
1686 VG_(message)(Vg_UserMsg, "");
1687
sewardj2e93c502002-04-12 11:12:52 +00001688 if (src == VgSrc_Deadlock) {
1689 VG_(message)(Vg_UserMsg,
1690 "Warning: pthread scheduler exited due to deadlock");
1691 }
1692
rjwalshf5f536f2003-11-17 17:45:00 +00001693 /* Print out file descriptor summary and stats. */
1694 if(VG_(clo_track_fds))
1695 VG_(fd_stats)();
1696
njn25e49d8e72002-09-23 09:36:25 +00001697 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001698 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001699
njn7d9f94d2003-04-22 21:41:40 +00001700 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001701
sewardj0c3b53f2002-05-01 01:58:35 +00001702 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001703
1704 if (VG_(clo_verbosity) > 1)
1705 vg_show_counts();
1706
sewardjc0d8f682002-11-30 00:49:43 +00001707 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001708 VG_(print_UInstr_histogram)();
1709
sewardjde4a1d02002-03-22 01:27:54 +00001710 if (0) {
1711 VG_(message)(Vg_DebugMsg, "");
1712 VG_(message)(Vg_DebugMsg,
1713 "------ Valgrind's internal memory use stats follow ------" );
1714 VG_(mallocSanityCheckAll)();
1715 VG_(show_all_arena_stats)();
1716 VG_(message)(Vg_DebugMsg,
1717 "------ Valgrind's ExeContext management stats follow ------" );
1718 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001719 }
1720
njn25e49d8e72002-09-23 09:36:25 +00001721 if (VG_(clo_profile))
1722 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001723
1724 VG_(shutdown_logging)();
1725
sewardj3e1eb1f2002-05-18 13:14:17 +00001726 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1727 processes don't get traced into. Also mess up $libdir/valgrind
1728 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001729 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1730 pointless when we are just about to VgSrc_ExitSyscall. So don't
1731 bother in that case. */
1732 if ((!VG_(clo_trace_children))
1733 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001734 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1735 VG_(getenv)("LD_PRELOAD"),
1736 VG_(getenv)("LD_LIBRARY_PATH")
1737 );
sewardjde4a1d02002-03-22 01:27:54 +00001738 }
1739
jsgf855d93d2003-10-13 22:26:55 +00001740 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1741 vg_assert(src == VgSrc_FatalSig ||
1742 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1743 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1744 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1745
sewardj7e87e382002-05-03 19:09:05 +00001746 /* Decide how to exit. This depends on what the scheduler
1747 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001748
sewardj7e87e382002-05-03 19:09:05 +00001749 switch (src) {
1750 case VgSrc_ExitSyscall: /* the normal way out */
1751 vg_assert(VG_(last_run_tid) > 0
1752 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001753 VG_(proxy_shutdown)();
1754
njn25e49d8e72002-09-23 09:36:25 +00001755 /* The thread's %EBX at the time it did __NR_exit() will hold
1756 the arg to __NR_exit(), so we just do __NR_exit() with
1757 that arg. */
1758 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001759 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001760 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001761 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001762
sewardj7e87e382002-05-03 19:09:05 +00001763 case VgSrc_Deadlock:
1764 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001765 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001766 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001767 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001768 break;
1769
1770 case VgSrc_BbsDone:
1771 /* Tricky; we have to try and switch back to the real CPU.
1772 This is all very dodgy and won't work at all in the
1773 presence of threads, or if the client happened to be
1774 running a signal handler. */
1775 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001776 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001777 VG_(load_thread_state)(1 /* root thread */ );
1778 VG_(copy_baseBlock_to_m_state_static)();
1779
jsgf855d93d2003-10-13 22:26:55 +00001780 VG_(proxy_shutdown)();
1781
sewardj7e87e382002-05-03 19:09:05 +00001782 /* This pushes a return address on the simulator's stack,
1783 which is abandoned. We call vg_sigshutdown_actions() at
1784 the end of vg_switch_to_real_CPU(), so as to ensure that
1785 the original stack and machine state is restored before
1786 the real signal mechanism is restored. */
1787 VG_(switch_to_real_CPU)();
1788
jsgf855d93d2003-10-13 22:26:55 +00001789 case VgSrc_FatalSig:
1790 /* We were killed by a fatal signal, so replicate the effect */
1791 vg_assert(VG_(fatal_sigNo) != -1);
1792 VG_(kill_self)(VG_(fatal_sigNo));
1793 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1794 break;
1795
sewardj7e87e382002-05-03 19:09:05 +00001796 default:
njne427a662002-10-02 11:08:25 +00001797 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001798 }
sewardjde4a1d02002-03-22 01:27:54 +00001799}
1800
1801
1802/* Debugging thing .. can be called from assembly with OYNK macro. */
1803void VG_(oynk) ( Int n )
1804{
1805 OINK(n);
1806}
1807
1808
1809/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1810 "valgrinq.so", which doesn't do anything. This is used to avoid
1811 tracing into child processes. To make this work the build system
1812 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001813
njn25e49d8e72002-09-23 09:36:25 +00001814 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1815 without it, child processes try to find valgrind.so symbols in the
1816 skin .so.
1817
sewardj78e25c92002-05-20 23:38:33 +00001818 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1819 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1820 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001821*/
sewardj45b672d2003-07-25 19:58:11 +00001822static void slideleft ( Char* s )
1823{
1824 vg_assert(s && (*s == ' ' || *s == ':'));
1825 while (True) {
1826 s[0] = s[1];
1827 if (s[0] == '\0') break;
1828 s++;
1829 }
1830}
1831
1832
sewardj3e1eb1f2002-05-18 13:14:17 +00001833void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1834 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001835{
njn42e23f22003-05-05 12:47:25 +00001836 Char* vg_prel = NULL;
1837 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001838 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001839 Char* p;
1840 Char* coredir_first;
1841 Char* coredir_last;
1842 Int coredir_len;
1843 Int i;
1844 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001845
njn42e23f22003-05-05 12:47:25 +00001846#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001847
njn42e23f22003-05-05 12:47:25 +00001848 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001849
njn42e23f22003-05-05 12:47:25 +00001850 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1851
njnc2f5bb02003-07-23 09:40:50 +00001852 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1853 LD_LIBRARY_PATH = "<coredir>:Y" */
1854
njn42e23f22003-05-05 12:47:25 +00001855 /* Setting up, finding things */
1856
1857 /* LD_PRELOAD: Search for "valgrind.so" */
1858 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1859
1860 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001861 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001862 if (NULL == vg_prel) {
1863 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001864 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001865 }
1866
njnc2f5bb02003-07-23 09:40:50 +00001867 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001868 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001869
njn42e23f22003-05-05 12:47:25 +00001870 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1871 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1872 coredir_first = p+1;
1873 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001874 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001875
1876 /* LD_PRELOAD: find "vgskin_foo.so" */
1877 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1878 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001879
njnc2f5bb02003-07-23 09:40:50 +00001880 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001881 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001882 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1883 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001884 *coredir_last = '/'; /* Undo zero-termination */
1885
1886 /* Changing things */
1887
1888 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1889 if (vg_prel[7] != 'd') MUTANCY(6);
1890 vg_prel[7] = 'q';
1891
njnc2f5bb02003-07-23 09:40:50 +00001892 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1893 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1894 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001895 while (*p != ':' && p >= ld_preload_str) {
1896 *p = ' ';
1897 p--;
njn25e49d8e72002-09-23 09:36:25 +00001898 }
njnc2f5bb02003-07-23 09:40:50 +00001899 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1900 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001901 p = sk_prel;
1902 while (*p != ':' && *p != '\0') {
1903 *p = ' ';
1904 p++;
1905 }
1906 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001907
njnc2f5bb02003-07-23 09:40:50 +00001908 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001909 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001910 coredir2[i] = ' ';
sewardj45b672d2003-07-25 19:58:11 +00001911
1912 /* Zap the leading spaces and : in both strings. */
1913 while (ld_preload_str[0] == ' ') slideleft(ld_preload_str);
1914 if (ld_preload_str[0] == ':') slideleft(ld_preload_str);
1915
1916 while (ld_library_path_str[0] == ' ') slideleft(ld_library_path_str);
1917 if (ld_library_path_str[0] == ':') slideleft(ld_library_path_str);
1918
njn42e23f22003-05-05 12:47:25 +00001919 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001920
sewardj78e25c92002-05-20 23:38:33 +00001921 return;
1922
njn42e23f22003-05-05 12:47:25 +00001923
1924mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001925 VG_(printf)(
1926 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1927 " what = %d\n"
1928 " ld_preload_str = `%s'\n"
1929 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001930 " vg_prel = `%s'\n"
1931 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001932 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001933 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001934 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001935 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001936 );
sewardjc26b4482002-07-13 12:20:35 +00001937 VG_(printf)(
1938 "\n"
1939 "Note that this is often caused by mis-installation of valgrind.\n"
1940 "Correct installation procedure is:\n"
1941 " ./configure --prefix=/install/dir\n"
1942 " make install\n"
1943 "And then use /install/dir/bin/valgrind\n"
1944 "Moving the installation directory elsewhere after 'make install'\n"
1945 "will cause the above error. Hand-editing the paths in the shell\n"
1946 "scripts is also likely to cause problems.\n"
1947 "\n"
1948 );
njne427a662002-10-02 11:08:25 +00001949 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001950}
1951
sewardj3e1eb1f2002-05-18 13:14:17 +00001952
sewardjde4a1d02002-03-22 01:27:54 +00001953/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1954 it to attach to this process. Called if the user requests this
1955 service after an error has been shown, so she can poke around and
1956 look at parameters, memory, etc. You can't meaningfully get GDB to
1957 continue the program, though; to continue, quit GDB. */
1958extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1959{
sewardje6a25242002-04-21 22:03:07 +00001960 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001961 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001962
njn9315df32003-04-16 20:50:50 +00001963 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001964 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001965 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1966 res = VG_(system)(buf);
1967 if (res == 0) {
1968 VG_(message)(Vg_UserMsg, "");
1969 VG_(message)(Vg_UserMsg,
1970 "GDB has detached. Valgrind regains control. We continue.");
1971 } else {
1972 VG_(message)(Vg_UserMsg, "Apparently failed!");
1973 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001974 }
sewardjde4a1d02002-03-22 01:27:54 +00001975}
1976
1977
1978/* Print some helpful-ish text about unimplemented things, and give
1979 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001980void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001981{
1982 VG_(message)(Vg_UserMsg, "");
1983 VG_(message)(Vg_UserMsg,
1984 "Valgrind detected that your program requires");
1985 VG_(message)(Vg_UserMsg,
1986 "the following unimplemented functionality:");
1987 VG_(message)(Vg_UserMsg, " %s", msg);
1988 VG_(message)(Vg_UserMsg,
1989 "This may be because the functionality is hard to implement,");
1990 VG_(message)(Vg_UserMsg,
1991 "or because no reasonable program would behave this way,");
1992 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001993 "or because nobody has yet needed it. In any case, let us know at");
sewardjde4a1d02002-03-22 01:27:54 +00001994 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001995 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
sewardjde4a1d02002-03-22 01:27:54 +00001996 VG_(message)(Vg_UserMsg,
1997 "");
1998 VG_(message)(Vg_UserMsg,
1999 "Valgrind has to exit now. Sorry. Bye!");
2000 VG_(message)(Vg_UserMsg,
2001 "");
sewardj15a43e12002-04-17 19:35:12 +00002002 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00002003 VG_(exit)(1);
2004}
2005
2006
njn25e49d8e72002-09-23 09:36:25 +00002007/* ---------------------------------------------------------------------
2008 Sanity check machinery (permanently engaged).
2009 ------------------------------------------------------------------ */
2010
2011/* A fast sanity check -- suitable for calling circa once per
2012 millisecond. */
2013
2014void VG_(do_sanity_checks) ( Bool force_expensive )
2015{
2016 Int i;
2017
njn37cea302002-09-30 11:24:00 +00002018 VGP_PUSHCC(VgpCoreCheapSanity);
2019
njn25e49d8e72002-09-23 09:36:25 +00002020 if (VG_(sanity_level) < 1) return;
2021
2022 /* --- First do all the tests that we can do quickly. ---*/
2023
2024 VG_(sanity_fast_count)++;
2025
2026 /* Check that we haven't overrun our private stack. */
2027 for (i = 0; i < 10; i++) {
2028 vg_assert(VG_(stack)[i]
2029 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00002030 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
2031 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00002032 }
2033
2034 /* Check stuff pertaining to the memory check system. */
2035
2036 /* Check that nobody has spuriously claimed that the first or
2037 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002038 if (VG_(needs).sanity_checks) {
2039 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002040 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002041 VGP_POPCC(VgpSkinCheapSanity);
2042 }
njn25e49d8e72002-09-23 09:36:25 +00002043
2044 /* --- Now some more expensive checks. ---*/
2045
2046 /* Once every 25 times, check some more expensive stuff. */
2047 if ( force_expensive
2048 || VG_(sanity_level) > 1
2049 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2050
njn37cea302002-09-30 11:24:00 +00002051 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002052 VG_(sanity_slow_count)++;
2053
jsgf855d93d2003-10-13 22:26:55 +00002054 VG_(proxy_sanity)();
2055
njn25e49d8e72002-09-23 09:36:25 +00002056# if 0
2057 { void zzzmemscan(void); zzzmemscan(); }
2058# endif
2059
2060 if ((VG_(sanity_fast_count) % 250) == 0)
2061 VG_(sanity_check_tc_tt)();
2062
2063 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002064 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002065 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002066 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002067 }
2068 /*
2069 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2070 */
njn37cea302002-09-30 11:24:00 +00002071 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002072 }
2073
2074 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002075 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002076 /* Check sanity of the low-level memory manager. Note that bugs
2077 in the client's code can cause this to fail, so we don't do
2078 this check unless specially asked for. And because it's
2079 potentially very expensive. */
2080 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002081 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002082 }
njn37cea302002-09-30 11:24:00 +00002083 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002084}
sewardjde4a1d02002-03-22 01:27:54 +00002085/*--------------------------------------------------------------------*/
2086/*--- end vg_main.c ---*/
2087/*--------------------------------------------------------------------*/