blob: edea109b22f386cf1fd3a52a264ab365e513e338 [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
538/* See big comment in vg_include.h for meaning of these three. */
539VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
540Int VG_(clo_logfile_fd) = 2;
541Char* VG_(clo_logfile_name) = NULL;
542
sewardj6024b212003-07-13 10:54:33 +0000543Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +0000544Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000545Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000546Bool VG_(clo_profile) = False;
547Bool VG_(clo_single_step) = False;
548Bool VG_(clo_optimise) = True;
549UChar VG_(clo_trace_codegen) = 0; // 00000000b
550Bool VG_(clo_trace_syscalls) = False;
551Bool VG_(clo_trace_signals) = False;
552Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000553Bool VG_(clo_trace_sched) = False;
554Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000555ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000556Int VG_(clo_dump_error) = 0;
557Int VG_(clo_backtrace_size) = 4;
558Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000559Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000560Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +0000561Bool VG_(clo_show_below_main) = False;
sewardj2370f3b2002-11-30 15:01:01 +0000562
jsgf855d93d2003-10-13 22:26:55 +0000563static Bool VG_(clo_wait_for_gdb) = False;
564
565/* If we're doing signal routing, poll for signals every 50mS by
566 default. */
567Int VG_(clo_signal_polltime) = 50;
568
fitzhardinge89f9a322003-10-30 07:25:59 +0000569/* If true, assume we're running on a plain 2.4 kernel */
570Bool VG_(clo_assume_24) = False;
571
jsgf855d93d2003-10-13 22:26:55 +0000572/* These flags reduce thread wakeup latency on syscall completion and
573 signal delivery, respectively. The downside is possible unfairness. */
574Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
575Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
576
sewardjde4a1d02002-03-22 01:27:54 +0000577/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
578 to behave. Initially we say False. */
579Bool VG_(running_on_simd_CPU) = False;
580
581/* Holds client's %esp at the point we gained control. */
582Addr VG_(esp_at_startup);
583
sewardjd5815ec2003-04-06 12:23:27 +0000584/* Indicates presence, and holds address of client's sysinfo page, a
585 feature of some modern kernels used to provide vsyscalls, etc. */
586Bool VG_(sysinfo_page_exists) = False;
587Addr VG_(sysinfo_page_addr) = 0;
588
sewardjde4a1d02002-03-22 01:27:54 +0000589/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
590 envp[] as extracted from the client's stack at startup-time. */
591Int VG_(client_argc);
592Char** VG_(client_argv);
593Char** VG_(client_envp);
594
595/* A place into which to copy the value of env var VG_ARGS, so we
596 don't have to modify the original. */
597static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
598
sewardjde4a1d02002-03-22 01:27:54 +0000599/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000600 Processing of command-line options.
601 ------------------------------------------------------------------ */
602
njn25e49d8e72002-09-23 09:36:25 +0000603void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000604{
605 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000606 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000607 VG_(clo_logfile_fd) = 2; /* stderr */
608 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
609 VG_(exit)(1);
610}
611
612static void config_error ( Char* msg )
613{
614 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000615 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000616 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000617 VG_(printf)(
618 "valgrind.so: Startup or configuration error:\n %s\n", msg);
619 VG_(printf)(
620 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000621 VG_(exit)(1);
622}
623
sewardja1679dd2002-05-10 22:31:40 +0000624static void args_grok_error ( Char* msg )
625{
626 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000627 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000628 VG_(clo_logfile_fd) = 2; /* stderr */
629 VG_(printf)("valgrind.so: When searching for "
630 "client's argc/argc/envp:\n\t%s\n", msg);
631 config_error("couldn't find client's argc/argc/envp");
632}
633
njn25e49d8e72002-09-23 09:36:25 +0000634static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000635{
njn25e49d8e72002-09-23 09:36:25 +0000636 Char* usage1 =
637"usage: valgrind [options] prog-and-args\n"
638"\n"
639" core user options, with defaults in [ ], are:\n"
nethercote137bc552003-11-14 17:47:54 +0000640" --tool=<name> Use the Valgrind tool named <name> [memcheck]\n"
nethercote77eba602003-11-13 17:35:04 +0000641
njn25e49d8e72002-09-23 09:36:25 +0000642" --help show this message\n"
643" --version show version\n"
nethercote77eba602003-11-13 17:35:04 +0000644
njn25e49d8e72002-09-23 09:36:25 +0000645" -q --quiet run silently; only print error msgs\n"
646" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000647
648" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
649
650" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
651" --logfile=<file> log messages to <file>.pid<pid>\n"
652" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
653
njn25e49d8e72002-09-23 09:36:25 +0000654" --demangle=no|yes automatically demangle C++ names? [yes]\n"
655" --num-callers=<number> show <num> callers in stack traces [4]\n"
656" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
nethercote77eba602003-11-13 17:35:04 +0000657" --show-below-main=no|yes continue stack traces below main() [no]\n"
658" --suppressions=<filename> suppress errors described in <filename>\n"
659" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
660
661" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
662" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
sewardj6024b212003-07-13 10:54:33 +0000663" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
nethercote77eba602003-11-13 17:35:04 +0000664
665" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
666" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +0000667" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000668" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
669" Only applies for older kernels which need\n"
670" signal routing [50]\n"
671" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
672" a signal [no]\n"
673" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
674" syscall completes [no]\n"
fitzhardinge89f9a322003-10-30 07:25:59 +0000675" --assume-2.4=no|yes assume we're running on a 2.4 kernel [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000676"\n"
nethercote137bc552003-11-14 17:47:54 +0000677" %s tool user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000678
njn7cf0bd32002-06-08 13:36:03 +0000679
njn25e49d8e72002-09-23 09:36:25 +0000680 Char* usage2 =
681"\n"
682" core options for debugging Valgrind itself are:\n"
683" --sanity-level=<number> level of sanity checking to do [1]\n"
684" --single-step=no|yes translate each instr separately? [no]\n"
685" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +0000686" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000687" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000688" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
689" --trace-syscalls=no|yes show all system calls? [no]\n"
690" --trace-signals=no|yes show signal handling details? [no]\n"
691" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000692" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000693" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000694" --stop-after=<number> switch to real CPU after executing\n"
695" <number> basic blocks [infinity]\n"
696" --dump-error=<number> show translation for basic block\n"
697" associated with <number>'th\n"
698" error context [0=don't show any]\n"
jsgf855d93d2003-10-13 22:26:55 +0000699" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000700"\n"
nethercote137bc552003-11-14 17:47:54 +0000701" %s tool debugging options:\n";
njn3e884182003-04-15 13:03:23 +0000702
703 Char* usage3 =
704"\n"
njn25e49d8e72002-09-23 09:36:25 +0000705" Extra options are read from env variable $VALGRIND_OPTS\n"
706"\n"
njn0e1b5142003-04-15 14:58:06 +0000707" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000708" and licensed under the GNU General Public License, version 2.\n"
709" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000710"\n"
nethercote137bc552003-11-14 17:47:54 +0000711" Tools are copyright and licensed by their authors. See each\n"
712" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000713"\n";
njn7cf0bd32002-06-08 13:36:03 +0000714
njnd04b7c62002-10-03 14:05:52 +0000715 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000716 /* Don't print skin string directly for security, ha! */
717 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000718 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000719 else
720 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000721 VG_(printf)(usage2, VG_(details).name);
722 if (VG_(needs).command_line_options)
723 SK_(print_debug_usage)();
724 else
725 VG_(printf)(" (none)\n");
726 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000727
njn25e49d8e72002-09-23 09:36:25 +0000728 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000729 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000730 VG_(clo_logfile_fd) = 2; /* stderr */
731 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000732}
sewardjde4a1d02002-03-22 01:27:54 +0000733
sewardj1c1b1162003-02-23 01:25:51 +0000734
sewardj49e630d2003-04-23 21:18:52 +0000735/* Callback for looking for the stack segment. */
736Addr VG_(foundstack_start) = (Addr)NULL;
737UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000738
739static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000740 Char r, Char w, Char x,
741 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000742{
743 Addr lastword;
744 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000745 if (r != 'r' || w != 'w'
746 /* || x != 'x' --not necessarily so on x86-64*/
747 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000748 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000749 if (start <= VG_(esp_at_startup)
750 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000751 VG_(foundstack_start) = start;
752 VG_(foundstack_size) = size;
753 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000754 }
755}
756
757
758
sewardjde4a1d02002-03-22 01:27:54 +0000759static void process_cmd_line_options ( void )
760{
njn25e49d8e72002-09-23 09:36:25 +0000761 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000762 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000763 Char* p;
764 Char* str;
765 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000766
767# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000768
sewardjde4a1d02002-03-22 01:27:54 +0000769 eventually_logfile_fd = VG_(clo_logfile_fd);
770
771 /* Once logging is started, we can safely send messages pertaining
772 to failures in initialisation. */
773 VG_(startup_logging)();
774
sewardj19d81412002-06-03 01:10:40 +0000775 /* Check for sane path in ./configure --prefix=... */
776 if (VG_(strlen)(VG_LIBDIR) < 1
777 || VG_LIBDIR[0] != '/')
778 config_error("Please use absolute paths in "
779 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000780
sewardja1679dd2002-05-10 22:31:40 +0000781 /* (Suggested by Fabrice Bellard ... )
782 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000783 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000784 change less often than the libc ones. */
785 {
sewardj05bcdcb2003-05-18 10:05:38 +0000786 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000787
njn3e884182003-04-15 13:03:23 +0000788 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000789 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000790 has rwx permissions and no associated file. Note that this uses
791 the /proc/self/maps contents read at the start of VG_(main)(),
792 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000793
njnfa1016e2003-09-25 17:54:11 +0000794 VG_(parse_procselfmaps)( vg_findstack_callback );
sewardj53fe4582003-02-23 01:41:17 +0000795
sewardj49e630d2003-04-23 21:18:52 +0000796 /* Now foundstack_start and foundstack_size should delimit the stack. */
797 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000798 args_grok_error("Cannot determine stack segment "
799 "from /proc/self/maps");
800 }
sewardj1c1b1162003-02-23 01:25:51 +0000801
802 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000803 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000804 VG_(foundstack_start),
805 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000806
sewardj49e630d2003-04-23 21:18:52 +0000807 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000808 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
809 args_grok_error("Stack segment is not page aligned?!");
810 }
sewardj1c1b1162003-02-23 01:25:51 +0000811
sewardj53fe4582003-02-23 01:41:17 +0000812 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
813 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000814
sewardj38170912002-05-10 21:07:22 +0000815 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000816 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000817 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000818 sp--;
819 }
sewardj38170912002-05-10 21:07:22 +0000820
821 if (sp[2] == VKI_AT_BASE
822 && sp[0] == VKI_AT_PAGESZ
823 && sp[-2] == VKI_AT_PHNUM
824 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000825 && sp[-6] == VKI_AT_PHDR
826 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000827 if (0)
828 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000829 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000830 } else
831 if (sp[2] == VKI_AT_CLKTCK
832 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000833 && sp[-2] == VKI_AT_HWCAP
834 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000835 if (0)
836 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
837 sp -= 2;
838 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000839 if (sp[2] == VKI_AT_CLKTCK
840 && sp[0] == VKI_AT_PAGESZ
841 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000842 && sp[-4] == VKI_AT_SYSINFO
843 && sp[-4-1] == 0) {
844 if (0)
845 VG_(printf)("Looks like you've got a 2.4.X kernel with "
846 "a sysinfo page at %x here.\n", sp[-3]);
847 VG_(sysinfo_page_exists) = True;
848 VG_(sysinfo_page_addr) = sp[-3];
849 sp -= 4;
850 } else
851 if (sp[2] == VKI_AT_CLKTCK
852 && sp[0] == VKI_AT_PAGESZ
853 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000854 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
855 && sp[-4-1] == 0) {
856 if (0)
857 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
858 "kernel here.\n");
859 sp -= 4;
860 } else
861 if (sp[2] == VKI_AT_CLKTCK
862 && sp[0] == VKI_AT_PAGESZ
863 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000864 && sp[-2-20-1] == 0) {
865 if (0)
866 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
867 sp -= 22;
868 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000869 if (sp[2] == VKI_AT_CLKTCK
870 && sp[0] == VKI_AT_PAGESZ
871 && sp[-2] == VKI_AT_HWCAP
872 && sp[-4-1] == 0) {
873 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000874 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000875 sp -= 4;
876 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000877 if (sp[2] == VKI_AT_CLKTCK
878 && sp[0] == VKI_AT_PAGESZ
879 && sp[-2] == VKI_AT_HWCAP
880 && sp[-6] == VKI_AT_SYSINFO
881 && sp[-6-1] == 0) {
882 if (0)
883 VG_(printf)("Looks like a >= 2.5.68 kernel with "
884 "a sysinfo page at %x here.\n", sp[-5]);
885 VG_(sysinfo_page_exists) = True;
886 VG_(sysinfo_page_addr) = sp[-5];
887 sp -= 6;
888 } else
sewardja1679dd2002-05-10 22:31:40 +0000889 args_grok_error(
890 "ELF frame does not look like 2.2.X or 2.4.X.\n "
891 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
892 );
sewardj38170912002-05-10 21:07:22 +0000893
894 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000895 if (*sp != 0)
896 args_grok_error("can't find NULL at end of env[]");
897
sewardj38170912002-05-10 21:07:22 +0000898 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000899 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000900 while (True) {
901 sp --;
902 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000903 if (++ctr >= 1000)
904 args_grok_error(
905 "suspiciously many (1000) env[] entries; giving up");
906
sewardj38170912002-05-10 21:07:22 +0000907 }
908 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000909 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000910
sewardja1679dd2002-05-10 22:31:40 +0000911 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000912 VG_(client_argc) = 0;
913 while (True) {
914 sp--;
915 if (*sp == VG_(client_argc))
916 break;
917 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000918 if (++ctr >= 1000)
919 args_grok_error(
920 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000921 }
922
sewardja1679dd2002-05-10 22:31:40 +0000923 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000924 }
925
sewardjde4a1d02002-03-22 01:27:54 +0000926 /* Now that VG_(client_envp) has been set, we can extract the args
927 for Valgrind itself. Copy into global var so that we don't have to
928 write zeroes to the getenv'd value itself. */
929 str = VG_(getenv)("VG_ARGS");
930 argc = 0;
931
932 if (!str) {
933 config_error("Can't read options from env var VG_ARGS.");
934 }
935
936 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
937 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
938 }
939 VG_(strcpy)(vg_cmdline_copy, str);
940 str = NULL;
941
942 p = &vg_cmdline_copy[0];
943 while (True) {
944 while (ISSPACE(*p)) { *p = 0; p++; }
945 if (*p == 0) break;
946 if (argc < M_VG_CMDLINE_OPTS-1) {
947 argv[argc] = p; argc++;
948 } else {
949 config_error(
950 "Found more than M_CMDLINE_OPTS command-line opts.");
951 }
952 while (*p != 0 && !ISSPACE(*p)) p++;
953 }
954
955 for (i = 0; i < argc; i++) {
956
njn43c799e2003-04-08 00:08:52 +0000957 if (VG_CLO_STREQ(argv[i], "-v") ||
958 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000959 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000960 else if (VG_CLO_STREQ(argv[i], "-q") ||
961 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000962 VG_(clo_verbosity)--;
963
njn43c799e2003-04-08 00:08:52 +0000964 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000965 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000966 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000967 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000968
njn43c799e2003-04-08 00:08:52 +0000969 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000970 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000971 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000972 VG_(clo_GDB_attach) = False;
973
sewardj6024b212003-07-13 10:54:33 +0000974 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
975 VG_(clo_GDB_path) = &argv[i][11];
976
njn43c799e2003-04-08 00:08:52 +0000977 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
978 VG_(clo_gen_suppressions) = True;
979 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
980 VG_(clo_gen_suppressions) = False;
981
nethercote77eba602003-11-13 17:35:04 +0000982 else if (VG_CLO_STREQ(argv[i], "--show-below-main=yes"))
983 VG_(clo_show_below_main) = True;
984 else if (VG_CLO_STREQ(argv[i], "--show-below-main=no"))
985 VG_(clo_show_below_main) = False;
986
njn43c799e2003-04-08 00:08:52 +0000987 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000988 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000989 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000990 VG_(clo_demangle) = False;
991
njn43c799e2003-04-08 00:08:52 +0000992 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000993 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000994 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000995 VG_(clo_trace_children) = False;
996
njn43c799e2003-04-08 00:08:52 +0000997 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000998 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000999 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001000 VG_(clo_run_libc_freeres) = False;
1001
njn43c799e2003-04-08 00:08:52 +00001002 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +00001003 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
1004
njn43c799e2003-04-08 00:08:52 +00001005 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001006 VG_(clo_log_to) = VgLogTo_Fd;
1007 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001008 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +00001009 }
1010
njn43c799e2003-04-08 00:08:52 +00001011 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001012 VG_(clo_log_to) = VgLogTo_File;
1013 VG_(clo_logfile_name) = &argv[i][10];
1014 }
sewardjde4a1d02002-03-22 01:27:54 +00001015
njn43c799e2003-04-08 00:08:52 +00001016 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001017 VG_(clo_log_to) = VgLogTo_Socket;
1018 VG_(clo_logfile_name) = &argv[i][12];
1019 }
1020
sewardj6024b212003-07-13 10:54:33 +00001021 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
1022 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
1023
njn43c799e2003-04-08 00:08:52 +00001024 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001025 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001026 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001027 VG_(message)(Vg_UserMsg,
1028 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +00001029 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001030 }
1031 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
1032 VG_(clo_n_suppressions)++;
1033 }
njn43c799e2003-04-08 00:08:52 +00001034 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001035 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +00001036 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001037 VG_(clo_profile) = False;
1038
njn43c799e2003-04-08 00:08:52 +00001039 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001040 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +00001041 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001042 VG_(clo_chain_bb) = False;
1043
njn43c799e2003-04-08 00:08:52 +00001044 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001045 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +00001046 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001047 VG_(clo_single_step) = False;
1048
njn43c799e2003-04-08 00:08:52 +00001049 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001050 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +00001051 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001052 VG_(clo_optimise) = False;
1053
njn25e49d8e72002-09-23 09:36:25 +00001054 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +00001055 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001056 Int j;
1057 char* opt = & argv[i][16];
1058
1059 if (5 != VG_(strlen)(opt)) {
1060 VG_(message)(Vg_UserMsg,
1061 "--trace-codegen argument must have 5 digits");
1062 VG_(bad_option)(argv[i]);
1063 }
1064 for (j = 0; j < 5; j++) {
1065 if ('0' == opt[j]) { /* do nothing */ }
1066 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1067 else {
1068 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1069 "contain 0s and 1s");
1070 VG_(bad_option)(argv[i]);
1071 }
1072 }
1073 }
sewardjde4a1d02002-03-22 01:27:54 +00001074
njn43c799e2003-04-08 00:08:52 +00001075 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001076 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001077 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001078 VG_(clo_trace_syscalls) = False;
1079
njn43c799e2003-04-08 00:08:52 +00001080 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001081 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001082 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001083 VG_(clo_trace_signals) = False;
1084
njn43c799e2003-04-08 00:08:52 +00001085 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001086 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001087 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001088 VG_(clo_trace_symtab) = False;
1089
njn43c799e2003-04-08 00:08:52 +00001090 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001091 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001092 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001093 VG_(clo_trace_sched) = False;
1094
njn43c799e2003-04-08 00:08:52 +00001095 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001096 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001097 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001098 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001099 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001100 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001101
njn43c799e2003-04-08 00:08:52 +00001102 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001103 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001104
jsgf855d93d2003-10-13 22:26:55 +00001105 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
1106 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
1107
1108 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
1109 VG_(clo_lowlat_signals) = True;
1110 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
1111 VG_(clo_lowlat_signals) = False;
1112
1113 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
1114 VG_(clo_lowlat_syscalls) = True;
1115 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
1116 VG_(clo_lowlat_syscalls) = False;
1117
fitzhardinge89f9a322003-10-30 07:25:59 +00001118 else if (VG_CLO_STREQ(argv[i], "--assume-2.4=yes"))
1119 VG_(clo_assume_24) = True;
1120 else if (VG_CLO_STREQ(argv[i], "--assume-2.4=no"))
1121 VG_(clo_assume_24) = False;
1122
njn43c799e2003-04-08 00:08:52 +00001123 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001124 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1125
njn43c799e2003-04-08 00:08:52 +00001126 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001127 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1128
jsgf855d93d2003-10-13 22:26:55 +00001129 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
1130 VG_(clo_wait_for_gdb) = True;
1131 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
1132 VG_(clo_wait_for_gdb) = False;
1133
njn43c799e2003-04-08 00:08:52 +00001134 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001135 /* Make sure it's sane. */
1136 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +00001137 if (VG_(clo_backtrace_size) < 1)
1138 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001139 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1140 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1141 }
1142
njn25e49d8e72002-09-23 09:36:25 +00001143 else if (VG_(needs).command_line_options) {
1144 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1145 if (!ok)
1146 usage();
1147 }
sewardjde4a1d02002-03-22 01:27:54 +00001148 else
njn25e49d8e72002-09-23 09:36:25 +00001149 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001150 }
1151
1152# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001153
njnf9ebf672003-05-12 21:41:30 +00001154 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001155 VG_(clo_verbosity) = 0;
1156
1157 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1158 VG_(message)(Vg_UserMsg, "");
1159 VG_(message)(Vg_UserMsg,
1160 "--gdb-attach=yes conflicts with --trace-children=yes");
1161 VG_(message)(Vg_UserMsg,
1162 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001163 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001164 }
1165
sewardj4cf05692002-10-27 20:28:29 +00001166 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1167 should be connected to whatever sink has been selected, and we
1168 indiscriminately chuck stuff into it without worrying what the
1169 nature of it is. Oh the wonder of Unix streams. */
1170
1171 /* So far we should be still attached to stderr, so we can show on
1172 the terminal any problems to do with processing command line
1173 opts. */
1174 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001175 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001176
1177 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001178
sewardj4cf05692002-10-27 20:28:29 +00001179 case VgLogTo_Fd:
1180 vg_assert(VG_(clo_logfile_name) == NULL);
1181 VG_(clo_logfile_fd) = eventually_logfile_fd;
1182 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001183
sewardj4cf05692002-10-27 20:28:29 +00001184 case VgLogTo_File: {
1185 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001186 Int seq = 0;
1187 Int pid = VG_(getpid)();
1188
sewardj4cf05692002-10-27 20:28:29 +00001189 vg_assert(VG_(clo_logfile_name) != NULL);
1190 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001191
1192 for(;;) {
1193 if (seq == 0)
1194 VG_(sprintf)(logfilename, "%s.pid%d",
1195 VG_(clo_logfile_name), pid );
1196 else
1197 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1198 VG_(clo_logfile_name), pid, seq );
1199 seq++;
1200
1201 eventually_logfile_fd
1202 = VG_(open)(logfilename,
1203 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1204 VKI_S_IRUSR|VKI_S_IWUSR);
1205 if (eventually_logfile_fd >= 0) {
1206 VG_(clo_logfile_fd) = eventually_logfile_fd;
1207 break;
1208 } else {
1209 if (eventually_logfile_fd != -VKI_EEXIST) {
1210 VG_(message)(Vg_UserMsg,
1211 "Can't create/open log file `%s.pid%d'; giving up!",
1212 VG_(clo_logfile_name), pid);
1213 VG_(bad_option)(
1214 "--logfile=<file> didn't work out for some reason.");
1215 break;
1216 }
1217 }
1218 }
sewardj4cf05692002-10-27 20:28:29 +00001219 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001220 }
1221
1222 case VgLogTo_Socket: {
1223 vg_assert(VG_(clo_logfile_name) != NULL);
1224 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1225 eventually_logfile_fd
1226 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1227 if (eventually_logfile_fd == -1) {
1228 VG_(message)(Vg_UserMsg,
1229 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1230 VG_(message)(Vg_UserMsg,
1231 "of `%s'; giving up!", VG_(clo_logfile_name) );
1232 VG_(bad_option)(
1233 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001234 }
sewardj73cf3bc2002-11-03 03:20:15 +00001235 if (eventually_logfile_fd == -2) {
1236 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001237 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001238 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001239 VG_(message)(Vg_UserMsg,
1240 "Log messages will sent to stderr instead." );
1241 VG_(message)(Vg_UserMsg,
1242 "" );
1243 /* We don't change anything here. */
1244 } else {
1245 vg_assert(eventually_logfile_fd > 0);
1246 VG_(clo_logfile_fd) = eventually_logfile_fd;
1247 VG_(logging_to_filedes) = False;
1248 }
sewardj73cf3bc2002-11-03 03:20:15 +00001249 break;
1250 }
1251
sewardj4cf05692002-10-27 20:28:29 +00001252 }
1253
jsgf855d93d2003-10-13 22:26:55 +00001254 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
1255 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_MAX_FD+1);
1256 if (eventually_logfile_fd < 0)
1257 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1258 else {
1259 VG_(clo_logfile_fd) = eventually_logfile_fd;
1260 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1261 }
1262
sewardj4cf05692002-10-27 20:28:29 +00001263 /* Ok, the logging sink is running now. Print a suitable preamble.
1264 If logging to file or a socket, write details of parent PID and
1265 command line args, to help people trying to interpret the
1266 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001267
sewardj83adf412002-05-01 01:25:45 +00001268 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001269 /* Skin details */
1270 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1271 VG_(details).name,
1272 NULL == VG_(details).version ? "" : "-",
1273 NULL == VG_(details).version
1274 ? (Char*)"" : VG_(details).version,
1275 VG_(details).description);
1276 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001277
njnd04b7c62002-10-03 14:05:52 +00001278 /* Core details */
1279 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001280 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001281 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001282 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001283 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001284 }
1285
nethercotec1e395d2003-11-10 13:26:49 +00001286 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001287 VG_(message)(Vg_UserMsg, "");
1288 VG_(message)(Vg_UserMsg,
1289 "My PID = %d, parent PID = %d. Prog and args are:",
1290 VG_(getpid)(), VG_(getppid)() );
1291 for (i = 0; i < VG_(client_argc); i++)
1292 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1293 }
1294
sewardjde4a1d02002-03-22 01:27:54 +00001295 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001296 if (VG_(clo_log_to) != VgLogTo_Fd)
1297 VG_(message)(Vg_UserMsg, "");
njn86dc2bc2003-09-09 07:26:21 +00001298 VG_(message)(Vg_UserMsg, "Command line");
1299 for (i = 0; i < VG_(client_argc); i++)
1300 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1301
sewardjde4a1d02002-03-22 01:27:54 +00001302 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1303 for (i = 0; i < argc; i++) {
1304 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1305 }
1306 }
1307
njn25e49d8e72002-09-23 09:36:25 +00001308 if (VG_(clo_n_suppressions) == 0 &&
1309 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001310 config_error("No error-suppression files were specified.");
1311 }
sewardj4cf05692002-10-27 20:28:29 +00001312
njn6a230532003-07-21 10:38:23 +00001313 if (VG_(clo_gen_suppressions) &&
1314 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1315 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1316 " as it doesn't generate errors.");
1317 }
1318
sewardjde4a1d02002-03-22 01:27:54 +00001319}
1320
sewardjde4a1d02002-03-22 01:27:54 +00001321/* ---------------------------------------------------------------------
1322 Copying to/from m_state_static.
1323 ------------------------------------------------------------------ */
1324
sewardjb91ae7f2003-04-29 23:50:00 +00001325/* See comment about this in vg_include.h. Change only with
1326 great care.
1327*/
1328__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001329UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1330 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001331 + 1 /* %eflags */
1332 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001333 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001334 ];
1335
sewardjfa492d42002-12-08 18:20:01 +00001336UInt VG_(insertDflag)(UInt eflags, Int d)
1337{
1338 vg_assert(d == 1 || d == -1);
1339 eflags &= ~EFlagD;
1340
1341 if (d < 0)
1342 eflags |= EFlagD;
1343
1344 return eflags;
1345}
1346
1347Int VG_(extractDflag)(UInt eflags)
1348{
1349 Int ret;
1350
1351 if (eflags & EFlagD)
1352 ret = -1;
1353 else
1354 ret = 1;
1355
1356 return ret;
1357}
1358
sewardjde4a1d02002-03-22 01:27:54 +00001359void VG_(copy_baseBlock_to_m_state_static) ( void )
1360{
1361 Int i;
sewardj92a59562002-09-30 00:53:10 +00001362 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1363 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1364 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1365 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1366 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1367 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001368
sewardj92a59562002-09-30 00:53:10 +00001369 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1370 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1371 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1372 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1373 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1374 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1375 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1376 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1377
sewardjb91ae7f2003-04-29 23:50:00 +00001378 VG_(m_state_static)[56/4]
1379 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1380 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001381 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001382
sewardjb91ae7f2003-04-29 23:50:00 +00001383 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001384 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001385 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001386}
1387
1388
1389void VG_(copy_m_state_static_to_baseBlock) ( void )
1390{
1391 Int i;
sewardj92a59562002-09-30 00:53:10 +00001392 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1393 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1394 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1395 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1396 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1397 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001398
sewardj92a59562002-09-30 00:53:10 +00001399 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1400 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1401 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1402 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1403 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1404 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1405 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1406 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1407
sewardjb91ae7f2003-04-29 23:50:00 +00001408 VG_(baseBlock)[VGOFF_(m_eflags)]
1409 = VG_(m_state_static)[56/4] & ~EFlagD;
1410 VG_(baseBlock)[VGOFF_(m_dflag)]
1411 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001412
sewardj92a59562002-09-30 00:53:10 +00001413 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001414
sewardjb91ae7f2003-04-29 23:50:00 +00001415 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1416 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001417 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001418}
1419
njn25e49d8e72002-09-23 09:36:25 +00001420Addr VG_(get_stack_pointer) ( void )
1421{
1422 return VG_(baseBlock)[VGOFF_(m_esp)];
1423}
1424
1425/* Some random tests needed for leak checking */
1426
1427Bool VG_(within_stack)(Addr a)
1428{
1429 if (a >= ((Addr)(&VG_(stack)))
1430 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1431 return True;
1432 else
1433 return False;
1434}
1435
sewardjecf8e102003-07-12 12:11:39 +00001436Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001437{
1438 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001439 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001440 return True;
sewardjecf8e102003-07-12 12:11:39 +00001441
1442 if (a >= ((Addr)(&VG_(threads)[0]))
1443 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1444 return True;
1445
1446 return False;
njn25e49d8e72002-09-23 09:36:25 +00001447}
sewardjde4a1d02002-03-22 01:27:54 +00001448
1449/* ---------------------------------------------------------------------
1450 Show accumulated counts.
1451 ------------------------------------------------------------------ */
1452
njn25e49d8e72002-09-23 09:36:25 +00001453static __inline__ Int safe_idiv(Int a, Int b)
1454{
1455 return (b == 0 ? 0 : a / b);
1456}
1457
sewardjde4a1d02002-03-22 01:27:54 +00001458static void vg_show_counts ( void )
1459{
1460 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001461 " TT/TC: %d tc sectors discarded.",
1462 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001463 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001464 " %d chainings, %d unchainings.",
1465 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1466 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001467 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001468 VG_(overall_in_count),
1469 VG_(overall_in_osize),
1470 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001471 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1472 VG_(message)(Vg_DebugMsg,
1473 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001474 VG_(overall_out_count),
1475 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001476 VG_(overall_out_tsize),
1477 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001478 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001479 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001480 VG_(bbs_done),
1481 VG_(unchained_jumps_done),
1482 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1483 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1484 );
1485
1486 VG_(message)(Vg_DebugMsg,
1487 " %d/%d major/minor sched events. %d tt_fast misses.",
1488 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001489 VG_(num_scheduling_events_MINOR),
1490 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001491
sewardjde4a1d02002-03-22 01:27:54 +00001492 VG_(message)(Vg_DebugMsg,
1493 "reg-alloc: %d t-req-spill, "
1494 "%d+%d orig+spill uis, %d total-reg-r.",
1495 VG_(translations_needing_spill),
1496 VG_(uinstrs_prealloc),
1497 VG_(uinstrs_spill),
1498 VG_(total_reg_rank) );
1499 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001500 " sanity: %d cheap, %d expensive checks.",
1501 VG_(sanity_fast_count),
1502 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001503 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001504}
1505
1506
1507/* ---------------------------------------------------------------------
1508 Main!
1509 ------------------------------------------------------------------ */
1510
jsgf855d93d2003-10-13 22:26:55 +00001511/* Initialize the PID and PGRP of scheduler LWP; this is also called
1512 in any new children after fork. */
1513static void newpid(ThreadId unused)
1514{
1515 /* PID of scheduler LWP */
1516 VG_(main_pid) = VG_(getpid)();
1517 VG_(main_pgrp) = VG_(getpgrp)();
1518}
1519
sewardjde4a1d02002-03-22 01:27:54 +00001520/* Where we jump to once Valgrind has got control, and the real
1521 machine's state has been copied to the m_state_static. */
1522
1523void VG_(main) ( void )
1524{
sewardj2e93c502002-04-12 11:12:52 +00001525 Int i;
1526 VgSchedReturnCode src;
sewardjde4a1d02002-03-22 01:27:54 +00001527
njn0c7a5b52003-04-30 09:00:33 +00001528 if (0) {
1529 if (VG_(have_ssestate))
1530 VG_(printf)("Looks like a SSE-capable CPU\n");
1531 else
1532 VG_(printf)("Looks like a MMX-only CPU\n");
1533 }
sewardjb91ae7f2003-04-29 23:50:00 +00001534
njn27f1a382002-11-08 15:48:16 +00001535 /* Check skin and core versions are compatible */
1536 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1537 VG_(printf)("Error:\n"
nethercote137bc552003-11-14 17:47:54 +00001538 " Tool and core interface versions do not match.\n"
njn27f1a382002-11-08 15:48:16 +00001539 " Interface version used by core is: %d.%d\n"
nethercote137bc552003-11-14 17:47:54 +00001540 " Interface version used by tool is: %d.%d\n"
njn27f1a382002-11-08 15:48:16 +00001541 " The major version numbers must match.\n",
1542 VG_CORE_INTERFACE_MAJOR_VERSION,
1543 VG_CORE_INTERFACE_MINOR_VERSION,
1544 VG_(skin_interface_major_version),
1545 VG_(skin_interface_minor_version));
1546 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1547 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1548 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1549 else
1550 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1551 VG_(printf)(" Aborting, sorry.\n");
1552 VG_(exit)(1);
1553 }
1554
jsgf855d93d2003-10-13 22:26:55 +00001555 VG_(atfork)(NULL, NULL, newpid);
1556 newpid(VG_INVALID_THREADID);
1557
sewardjde4a1d02002-03-22 01:27:54 +00001558 /* Set up our stack sanity-check words. */
1559 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001560 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1561 VG_(stack)[VG_STACK_SIZE_W-1-i]
1562 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001563 }
1564
njn3e884182003-04-15 13:03:23 +00001565 /* Read /proc/self/maps into a buffer. Must be before:
1566 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1567 superblocks are not erroneously identified as being owned by the
1568 client, which would be bad.
1569 - init_memory(): that's where the buffer is parsed
1570 - init_tt_tc(): so the anonymous mmaps for the translation table and
1571 translation cache aren't identified as part of the client, which would
1572 waste > 20M of virtual address space, and be bad.
1573 */
njnfa1016e2003-09-25 17:54:11 +00001574 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001575
njn25e49d8e72002-09-23 09:36:25 +00001576 /* Setup stuff that depends on the skin. Must be before:
1577 - vg_init_baseBlock(): to register helpers
1578 - process_cmd_line_options(): to register skin name and description,
1579 and turn on/off 'command_line_options' need
1580 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001581 */
njn810086f2002-11-14 12:42:47 +00001582 SK_(pre_clo_init)();
1583 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001584
njncc7bb472002-10-14 09:25:19 +00001585 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001586 process_cmd_line_options();
1587
jsgf855d93d2003-10-13 22:26:55 +00001588 /* Hook to delay things long enough so we can get the pid and
1589 attach GDB in another shell. */
1590 if (VG_(clo_wait_for_gdb)) {
1591 VG_(printf)("pid=%d\n", VG_(getpid)());
1592 /* do "jump *$eip" to skip this in gdb */
1593 VG_(do_syscall)(__NR_pause);
1594 }
1595
njn3e884182003-04-15 13:03:23 +00001596 /* Do post command-line processing initialisation. Must be before:
1597 - vg_init_baseBlock(): to register any more helpers
1598 */
njncc7bb472002-10-14 09:25:19 +00001599 SK_(post_clo_init)();
1600
njn3e884182003-04-15 13:03:23 +00001601 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001602 vg_init_baseBlock();
1603
sewardj018f7622002-05-15 21:13:39 +00001604 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001605 baseBlock into VG_(threads)[1]. Must be before:
1606 - VG_(sigstartup_actions)()
1607 */
sewardj018f7622002-05-15 21:13:39 +00001608 VG_(scheduler_init)();
1609
jsgf855d93d2003-10-13 22:26:55 +00001610 /* Set up the ProxyLWP machinery */
1611 VG_(proxy_init)();
1612
sewardj018f7622002-05-15 21:13:39 +00001613 /* Initialise the signal handling subsystem, temporarily parking
1614 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001615 VG_(sigstartup_actions)();
1616
sewardj018f7622002-05-15 21:13:39 +00001617 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001618 if (VG_(clo_profile))
1619 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001620
sewardj5f07b662002-04-23 16:52:51 +00001621 /* Start calibration of our RDTSC-based clock. */
1622 VG_(start_rdtsc_calibration)();
1623
njn3e884182003-04-15 13:03:23 +00001624 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001625 VGP_PUSHCC(VgpInitMem);
1626 VG_(init_memory)();
1627 VGP_POPCC(VgpInitMem);
1628
1629 /* Read the list of errors to suppress. This should be found in
1630 the file specified by vg_clo_suppressions. */
1631 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1632 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001633
sewardj5f07b662002-04-23 16:52:51 +00001634 /* End calibration of our RDTSC-based clock, leaving it as long as
1635 we can. */
1636 VG_(end_rdtsc_calibration)();
1637
njn3e884182003-04-15 13:03:23 +00001638 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001639 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001640
1641 if (VG_(clo_verbosity) == 1) {
1642 VG_(message)(Vg_UserMsg,
1643 "For more details, rerun with: -v");
1644 }
1645
sewardj25c7c3a2003-07-10 00:17:58 +00001646 /* Force a read of the debug info so that we can look for
1647 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001648 VG_(setup_code_redirect_table)();
1649
sewardjde4a1d02002-03-22 01:27:54 +00001650 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1651 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001652 if (VG_(clo_verbosity) > 0)
1653 VG_(message)(Vg_UserMsg, "");
1654
1655 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001656
sewardj018f7622002-05-15 21:13:39 +00001657 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001658 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001659 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001660
1661 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1662 VG_(fatal_signal_set) = True;
1663 src = VG_(scheduler)();
1664 } else
1665 src = VgSrc_FatalSig;
1666
njn25e49d8e72002-09-23 09:36:25 +00001667 VGP_POPCC(VgpSched);
1668 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001669
1670 if (VG_(clo_verbosity) > 0)
1671 VG_(message)(Vg_UserMsg, "");
1672
sewardj2e93c502002-04-12 11:12:52 +00001673 if (src == VgSrc_Deadlock) {
1674 VG_(message)(Vg_UserMsg,
1675 "Warning: pthread scheduler exited due to deadlock");
1676 }
1677
njn25e49d8e72002-09-23 09:36:25 +00001678 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001679 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001680
njn7d9f94d2003-04-22 21:41:40 +00001681 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001682
sewardj0c3b53f2002-05-01 01:58:35 +00001683 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001684
1685 if (VG_(clo_verbosity) > 1)
1686 vg_show_counts();
1687
sewardjc0d8f682002-11-30 00:49:43 +00001688 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001689 VG_(print_UInstr_histogram)();
1690
sewardjde4a1d02002-03-22 01:27:54 +00001691 if (0) {
1692 VG_(message)(Vg_DebugMsg, "");
1693 VG_(message)(Vg_DebugMsg,
1694 "------ Valgrind's internal memory use stats follow ------" );
1695 VG_(mallocSanityCheckAll)();
1696 VG_(show_all_arena_stats)();
1697 VG_(message)(Vg_DebugMsg,
1698 "------ Valgrind's ExeContext management stats follow ------" );
1699 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001700 }
1701
njn25e49d8e72002-09-23 09:36:25 +00001702 if (VG_(clo_profile))
1703 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001704
1705 VG_(shutdown_logging)();
1706
sewardj3e1eb1f2002-05-18 13:14:17 +00001707 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1708 processes don't get traced into. Also mess up $libdir/valgrind
1709 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001710 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1711 pointless when we are just about to VgSrc_ExitSyscall. So don't
1712 bother in that case. */
1713 if ((!VG_(clo_trace_children))
1714 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001715 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1716 VG_(getenv)("LD_PRELOAD"),
1717 VG_(getenv)("LD_LIBRARY_PATH")
1718 );
sewardjde4a1d02002-03-22 01:27:54 +00001719 }
1720
jsgf855d93d2003-10-13 22:26:55 +00001721 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1722 vg_assert(src == VgSrc_FatalSig ||
1723 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1724 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1725 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1726
sewardj7e87e382002-05-03 19:09:05 +00001727 /* Decide how to exit. This depends on what the scheduler
1728 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001729
sewardj7e87e382002-05-03 19:09:05 +00001730 switch (src) {
1731 case VgSrc_ExitSyscall: /* the normal way out */
1732 vg_assert(VG_(last_run_tid) > 0
1733 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001734 VG_(proxy_shutdown)();
1735
njn25e49d8e72002-09-23 09:36:25 +00001736 /* The thread's %EBX at the time it did __NR_exit() will hold
1737 the arg to __NR_exit(), so we just do __NR_exit() with
1738 that arg. */
1739 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001740 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001741 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001742 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001743
sewardj7e87e382002-05-03 19:09:05 +00001744 case VgSrc_Deadlock:
1745 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001746 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001747 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001748 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001749 break;
1750
1751 case VgSrc_BbsDone:
1752 /* Tricky; we have to try and switch back to the real CPU.
1753 This is all very dodgy and won't work at all in the
1754 presence of threads, or if the client happened to be
1755 running a signal handler. */
1756 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001757 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001758 VG_(load_thread_state)(1 /* root thread */ );
1759 VG_(copy_baseBlock_to_m_state_static)();
1760
jsgf855d93d2003-10-13 22:26:55 +00001761 VG_(proxy_shutdown)();
1762
sewardj7e87e382002-05-03 19:09:05 +00001763 /* This pushes a return address on the simulator's stack,
1764 which is abandoned. We call vg_sigshutdown_actions() at
1765 the end of vg_switch_to_real_CPU(), so as to ensure that
1766 the original stack and machine state is restored before
1767 the real signal mechanism is restored. */
1768 VG_(switch_to_real_CPU)();
1769
jsgf855d93d2003-10-13 22:26:55 +00001770 case VgSrc_FatalSig:
1771 /* We were killed by a fatal signal, so replicate the effect */
1772 vg_assert(VG_(fatal_sigNo) != -1);
1773 VG_(kill_self)(VG_(fatal_sigNo));
1774 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1775 break;
1776
sewardj7e87e382002-05-03 19:09:05 +00001777 default:
njne427a662002-10-02 11:08:25 +00001778 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001779 }
sewardjde4a1d02002-03-22 01:27:54 +00001780}
1781
1782
1783/* Debugging thing .. can be called from assembly with OYNK macro. */
1784void VG_(oynk) ( Int n )
1785{
1786 OINK(n);
1787}
1788
1789
1790/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1791 "valgrinq.so", which doesn't do anything. This is used to avoid
1792 tracing into child processes. To make this work the build system
1793 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001794
njn25e49d8e72002-09-23 09:36:25 +00001795 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1796 without it, child processes try to find valgrind.so symbols in the
1797 skin .so.
1798
sewardj78e25c92002-05-20 23:38:33 +00001799 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1800 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1801 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001802*/
sewardj45b672d2003-07-25 19:58:11 +00001803static void slideleft ( Char* s )
1804{
1805 vg_assert(s && (*s == ' ' || *s == ':'));
1806 while (True) {
1807 s[0] = s[1];
1808 if (s[0] == '\0') break;
1809 s++;
1810 }
1811}
1812
1813
sewardj3e1eb1f2002-05-18 13:14:17 +00001814void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1815 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001816{
njn42e23f22003-05-05 12:47:25 +00001817 Char* vg_prel = NULL;
1818 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001819 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001820 Char* p;
1821 Char* coredir_first;
1822 Char* coredir_last;
1823 Int coredir_len;
1824 Int i;
1825 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001826
njn42e23f22003-05-05 12:47:25 +00001827#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001828
njn42e23f22003-05-05 12:47:25 +00001829 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001830
njn42e23f22003-05-05 12:47:25 +00001831 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1832
njnc2f5bb02003-07-23 09:40:50 +00001833 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1834 LD_LIBRARY_PATH = "<coredir>:Y" */
1835
njn42e23f22003-05-05 12:47:25 +00001836 /* Setting up, finding things */
1837
1838 /* LD_PRELOAD: Search for "valgrind.so" */
1839 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1840
1841 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001842 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001843 if (NULL == vg_prel) {
1844 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001845 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001846 }
1847
njnc2f5bb02003-07-23 09:40:50 +00001848 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001849 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001850
njn42e23f22003-05-05 12:47:25 +00001851 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1852 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1853 coredir_first = p+1;
1854 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001855 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001856
1857 /* LD_PRELOAD: find "vgskin_foo.so" */
1858 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1859 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001860
njnc2f5bb02003-07-23 09:40:50 +00001861 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001862 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001863 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1864 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001865 *coredir_last = '/'; /* Undo zero-termination */
1866
1867 /* Changing things */
1868
1869 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1870 if (vg_prel[7] != 'd') MUTANCY(6);
1871 vg_prel[7] = 'q';
1872
njnc2f5bb02003-07-23 09:40:50 +00001873 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1874 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1875 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001876 while (*p != ':' && p >= ld_preload_str) {
1877 *p = ' ';
1878 p--;
njn25e49d8e72002-09-23 09:36:25 +00001879 }
njnc2f5bb02003-07-23 09:40:50 +00001880 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1881 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001882 p = sk_prel;
1883 while (*p != ':' && *p != '\0') {
1884 *p = ' ';
1885 p++;
1886 }
1887 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001888
njnc2f5bb02003-07-23 09:40:50 +00001889 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001890 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001891 coredir2[i] = ' ';
sewardj45b672d2003-07-25 19:58:11 +00001892
1893 /* Zap the leading spaces and : in both strings. */
1894 while (ld_preload_str[0] == ' ') slideleft(ld_preload_str);
1895 if (ld_preload_str[0] == ':') slideleft(ld_preload_str);
1896
1897 while (ld_library_path_str[0] == ' ') slideleft(ld_library_path_str);
1898 if (ld_library_path_str[0] == ':') slideleft(ld_library_path_str);
1899
njn42e23f22003-05-05 12:47:25 +00001900 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001901
sewardj78e25c92002-05-20 23:38:33 +00001902 return;
1903
njn42e23f22003-05-05 12:47:25 +00001904
1905mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001906 VG_(printf)(
1907 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1908 " what = %d\n"
1909 " ld_preload_str = `%s'\n"
1910 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001911 " vg_prel = `%s'\n"
1912 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001913 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001914 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001915 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001916 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001917 );
sewardjc26b4482002-07-13 12:20:35 +00001918 VG_(printf)(
1919 "\n"
1920 "Note that this is often caused by mis-installation of valgrind.\n"
1921 "Correct installation procedure is:\n"
1922 " ./configure --prefix=/install/dir\n"
1923 " make install\n"
1924 "And then use /install/dir/bin/valgrind\n"
1925 "Moving the installation directory elsewhere after 'make install'\n"
1926 "will cause the above error. Hand-editing the paths in the shell\n"
1927 "scripts is also likely to cause problems.\n"
1928 "\n"
1929 );
njne427a662002-10-02 11:08:25 +00001930 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001931}
1932
sewardj3e1eb1f2002-05-18 13:14:17 +00001933
sewardjde4a1d02002-03-22 01:27:54 +00001934/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1935 it to attach to this process. Called if the user requests this
1936 service after an error has been shown, so she can poke around and
1937 look at parameters, memory, etc. You can't meaningfully get GDB to
1938 continue the program, though; to continue, quit GDB. */
1939extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1940{
sewardje6a25242002-04-21 22:03:07 +00001941 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001942 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001943
njn9315df32003-04-16 20:50:50 +00001944 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001945 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001946 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1947 res = VG_(system)(buf);
1948 if (res == 0) {
1949 VG_(message)(Vg_UserMsg, "");
1950 VG_(message)(Vg_UserMsg,
1951 "GDB has detached. Valgrind regains control. We continue.");
1952 } else {
1953 VG_(message)(Vg_UserMsg, "Apparently failed!");
1954 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001955 }
sewardjde4a1d02002-03-22 01:27:54 +00001956}
1957
1958
1959/* Print some helpful-ish text about unimplemented things, and give
1960 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001961void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001962{
1963 VG_(message)(Vg_UserMsg, "");
1964 VG_(message)(Vg_UserMsg,
1965 "Valgrind detected that your program requires");
1966 VG_(message)(Vg_UserMsg,
1967 "the following unimplemented functionality:");
1968 VG_(message)(Vg_UserMsg, " %s", msg);
1969 VG_(message)(Vg_UserMsg,
1970 "This may be because the functionality is hard to implement,");
1971 VG_(message)(Vg_UserMsg,
1972 "or because no reasonable program would behave this way,");
1973 VG_(message)(Vg_UserMsg,
1974 "or because nobody has yet needed it. In any case, let me know");
1975 VG_(message)(Vg_UserMsg,
1976 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1977 VG_(message)(Vg_UserMsg,
1978 "");
1979 VG_(message)(Vg_UserMsg,
1980 "Valgrind has to exit now. Sorry. Bye!");
1981 VG_(message)(Vg_UserMsg,
1982 "");
sewardj15a43e12002-04-17 19:35:12 +00001983 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001984 VG_(exit)(1);
1985}
1986
1987
njn25e49d8e72002-09-23 09:36:25 +00001988/* ---------------------------------------------------------------------
1989 Sanity check machinery (permanently engaged).
1990 ------------------------------------------------------------------ */
1991
1992/* A fast sanity check -- suitable for calling circa once per
1993 millisecond. */
1994
1995void VG_(do_sanity_checks) ( Bool force_expensive )
1996{
1997 Int i;
1998
njn37cea302002-09-30 11:24:00 +00001999 VGP_PUSHCC(VgpCoreCheapSanity);
2000
njn25e49d8e72002-09-23 09:36:25 +00002001 if (VG_(sanity_level) < 1) return;
2002
2003 /* --- First do all the tests that we can do quickly. ---*/
2004
2005 VG_(sanity_fast_count)++;
2006
2007 /* Check that we haven't overrun our private stack. */
2008 for (i = 0; i < 10; i++) {
2009 vg_assert(VG_(stack)[i]
2010 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00002011 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
2012 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00002013 }
2014
2015 /* Check stuff pertaining to the memory check system. */
2016
2017 /* Check that nobody has spuriously claimed that the first or
2018 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002019 if (VG_(needs).sanity_checks) {
2020 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002021 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002022 VGP_POPCC(VgpSkinCheapSanity);
2023 }
njn25e49d8e72002-09-23 09:36:25 +00002024
2025 /* --- Now some more expensive checks. ---*/
2026
2027 /* Once every 25 times, check some more expensive stuff. */
2028 if ( force_expensive
2029 || VG_(sanity_level) > 1
2030 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2031
njn37cea302002-09-30 11:24:00 +00002032 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002033 VG_(sanity_slow_count)++;
2034
jsgf855d93d2003-10-13 22:26:55 +00002035 VG_(proxy_sanity)();
2036
njn25e49d8e72002-09-23 09:36:25 +00002037# if 0
2038 { void zzzmemscan(void); zzzmemscan(); }
2039# endif
2040
2041 if ((VG_(sanity_fast_count) % 250) == 0)
2042 VG_(sanity_check_tc_tt)();
2043
2044 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002045 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002046 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002047 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002048 }
2049 /*
2050 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2051 */
njn37cea302002-09-30 11:24:00 +00002052 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002053 }
2054
2055 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002056 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002057 /* Check sanity of the low-level memory manager. Note that bugs
2058 in the client's code can cause this to fail, so we don't do
2059 this check unless specially asked for. And because it's
2060 potentially very expensive. */
2061 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002062 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002063 }
njn37cea302002-09-30 11:24:00 +00002064 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002065}
sewardjde4a1d02002-03-22 01:27:54 +00002066/*--------------------------------------------------------------------*/
2067/*--- end vg_main.c ---*/
2068/*--------------------------------------------------------------------*/