blob: 8680af074526284a6b3cb1f340aa3c502fb5dde2 [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;
sewardj2370f3b2002-11-30 15:01:01 +0000561
jsgf855d93d2003-10-13 22:26:55 +0000562static Bool VG_(clo_wait_for_gdb) = False;
563
564/* If we're doing signal routing, poll for signals every 50mS by
565 default. */
566Int VG_(clo_signal_polltime) = 50;
567
568/* These flags reduce thread wakeup latency on syscall completion and
569 signal delivery, respectively. The downside is possible unfairness. */
570Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
571Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
572
sewardjde4a1d02002-03-22 01:27:54 +0000573/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
574 to behave. Initially we say False. */
575Bool VG_(running_on_simd_CPU) = False;
576
577/* Holds client's %esp at the point we gained control. */
578Addr VG_(esp_at_startup);
579
sewardjd5815ec2003-04-06 12:23:27 +0000580/* Indicates presence, and holds address of client's sysinfo page, a
581 feature of some modern kernels used to provide vsyscalls, etc. */
582Bool VG_(sysinfo_page_exists) = False;
583Addr VG_(sysinfo_page_addr) = 0;
584
sewardjde4a1d02002-03-22 01:27:54 +0000585/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
586 envp[] as extracted from the client's stack at startup-time. */
587Int VG_(client_argc);
588Char** VG_(client_argv);
589Char** VG_(client_envp);
590
591/* A place into which to copy the value of env var VG_ARGS, so we
592 don't have to modify the original. */
593static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
594
sewardjde4a1d02002-03-22 01:27:54 +0000595/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000596 Processing of command-line options.
597 ------------------------------------------------------------------ */
598
njn25e49d8e72002-09-23 09:36:25 +0000599void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000600{
601 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000602 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000603 VG_(clo_logfile_fd) = 2; /* stderr */
604 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
605 VG_(exit)(1);
606}
607
608static void config_error ( Char* msg )
609{
610 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000611 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000612 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000613 VG_(printf)(
614 "valgrind.so: Startup or configuration error:\n %s\n", msg);
615 VG_(printf)(
616 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000617 VG_(exit)(1);
618}
619
sewardja1679dd2002-05-10 22:31:40 +0000620static void args_grok_error ( Char* msg )
621{
622 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000623 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000624 VG_(clo_logfile_fd) = 2; /* stderr */
625 VG_(printf)("valgrind.so: When searching for "
626 "client's argc/argc/envp:\n\t%s\n", msg);
627 config_error("couldn't find client's argc/argc/envp");
628}
629
njn25e49d8e72002-09-23 09:36:25 +0000630static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000631{
njn25e49d8e72002-09-23 09:36:25 +0000632 Char* usage1 =
633"usage: valgrind [options] prog-and-args\n"
634"\n"
635" core user options, with defaults in [ ], are:\n"
636" --help show this message\n"
637" --version show version\n"
638" --skin=<name> main task (skin to use) [Valgrind]\n"
639" -q --quiet run silently; only print error msgs\n"
640" -v --verbose be more verbose, incl counts of errors\n"
641" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
sewardj6024b212003-07-13 10:54:33 +0000642" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
njn43c799e2003-04-08 00:08:52 +0000643" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000644" --demangle=no|yes automatically demangle C++ names? [yes]\n"
645" --num-callers=<number> show <num> callers in stack traces [4]\n"
646" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000647" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000648" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000649" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000650" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj6024b212003-07-13 10:54:33 +0000651" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000652" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000653" --suppressions=<filename> suppress errors described in\n"
654" suppressions file <filename>\n"
655" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000656" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000657" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
658" Only applies for older kernels which need\n"
659" signal routing [50]\n"
660" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
661" a signal [no]\n"
662" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
663" syscall completes [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000664"\n"
665" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000666
njn7cf0bd32002-06-08 13:36:03 +0000667
njn25e49d8e72002-09-23 09:36:25 +0000668 Char* usage2 =
669"\n"
670" core options for debugging Valgrind itself are:\n"
671" --sanity-level=<number> level of sanity checking to do [1]\n"
672" --single-step=no|yes translate each instr separately? [no]\n"
673" --optimise=no|yes improve intermediate code? [yes]\n"
674" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000675" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000676" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
677" --trace-syscalls=no|yes show all system calls? [no]\n"
678" --trace-signals=no|yes show signal handling details? [no]\n"
679" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000680" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000681" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000682" --stop-after=<number> switch to real CPU after executing\n"
683" <number> basic blocks [infinity]\n"
684" --dump-error=<number> show translation for basic block\n"
685" associated with <number>'th\n"
686" error context [0=don't show any]\n"
jsgf855d93d2003-10-13 22:26:55 +0000687" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000688"\n"
njn3e884182003-04-15 13:03:23 +0000689" %s skin debugging options:\n";
690
691 Char* usage3 =
692"\n"
njn25e49d8e72002-09-23 09:36:25 +0000693" Extra options are read from env variable $VALGRIND_OPTS\n"
694"\n"
njn0e1b5142003-04-15 14:58:06 +0000695" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000696" and licensed under the GNU General Public License, version 2.\n"
697" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000698"\n"
699" Skins are copyright and licensed by their authors. See each\n"
700" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000701"\n";
njn7cf0bd32002-06-08 13:36:03 +0000702
njnd04b7c62002-10-03 14:05:52 +0000703 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000704 /* Don't print skin string directly for security, ha! */
705 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000706 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000707 else
708 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000709 VG_(printf)(usage2, VG_(details).name);
710 if (VG_(needs).command_line_options)
711 SK_(print_debug_usage)();
712 else
713 VG_(printf)(" (none)\n");
714 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000715
njn25e49d8e72002-09-23 09:36:25 +0000716 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000717 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000718 VG_(clo_logfile_fd) = 2; /* stderr */
719 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000720}
sewardjde4a1d02002-03-22 01:27:54 +0000721
sewardj1c1b1162003-02-23 01:25:51 +0000722
sewardj49e630d2003-04-23 21:18:52 +0000723/* Callback for looking for the stack segment. */
724Addr VG_(foundstack_start) = (Addr)NULL;
725UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000726
727static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000728 Char r, Char w, Char x,
729 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000730{
731 Addr lastword;
732 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000733 if (r != 'r' || w != 'w'
734 /* || x != 'x' --not necessarily so on x86-64*/
735 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000736 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000737 if (start <= VG_(esp_at_startup)
738 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000739 VG_(foundstack_start) = start;
740 VG_(foundstack_size) = size;
741 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000742 }
743}
744
745
746
sewardjde4a1d02002-03-22 01:27:54 +0000747static void process_cmd_line_options ( void )
748{
njn25e49d8e72002-09-23 09:36:25 +0000749 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000750 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000751 Char* p;
752 Char* str;
753 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000754
755# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000756
sewardjde4a1d02002-03-22 01:27:54 +0000757 eventually_logfile_fd = VG_(clo_logfile_fd);
758
759 /* Once logging is started, we can safely send messages pertaining
760 to failures in initialisation. */
761 VG_(startup_logging)();
762
sewardj19d81412002-06-03 01:10:40 +0000763 /* Check for sane path in ./configure --prefix=... */
764 if (VG_(strlen)(VG_LIBDIR) < 1
765 || VG_LIBDIR[0] != '/')
766 config_error("Please use absolute paths in "
767 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000768
sewardja1679dd2002-05-10 22:31:40 +0000769 /* (Suggested by Fabrice Bellard ... )
770 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000771 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000772 change less often than the libc ones. */
773 {
sewardj05bcdcb2003-05-18 10:05:38 +0000774 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000775
njn3e884182003-04-15 13:03:23 +0000776 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000777 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000778 has rwx permissions and no associated file. Note that this uses
779 the /proc/self/maps contents read at the start of VG_(main)(),
780 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000781
njnfa1016e2003-09-25 17:54:11 +0000782 VG_(parse_procselfmaps)( vg_findstack_callback );
sewardj53fe4582003-02-23 01:41:17 +0000783
sewardj49e630d2003-04-23 21:18:52 +0000784 /* Now foundstack_start and foundstack_size should delimit the stack. */
785 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000786 args_grok_error("Cannot determine stack segment "
787 "from /proc/self/maps");
788 }
sewardj1c1b1162003-02-23 01:25:51 +0000789
790 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000791 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000792 VG_(foundstack_start),
793 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000794
sewardj49e630d2003-04-23 21:18:52 +0000795 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000796 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
797 args_grok_error("Stack segment is not page aligned?!");
798 }
sewardj1c1b1162003-02-23 01:25:51 +0000799
sewardj53fe4582003-02-23 01:41:17 +0000800 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
801 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000802
sewardj38170912002-05-10 21:07:22 +0000803 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000804 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000805 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000806 sp--;
807 }
sewardj38170912002-05-10 21:07:22 +0000808
809 if (sp[2] == VKI_AT_BASE
810 && sp[0] == VKI_AT_PAGESZ
811 && sp[-2] == VKI_AT_PHNUM
812 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000813 && sp[-6] == VKI_AT_PHDR
814 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000815 if (0)
816 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000817 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000818 } else
819 if (sp[2] == VKI_AT_CLKTCK
820 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000821 && sp[-2] == VKI_AT_HWCAP
822 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000823 if (0)
824 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
825 sp -= 2;
826 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000827 if (sp[2] == VKI_AT_CLKTCK
828 && sp[0] == VKI_AT_PAGESZ
829 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000830 && sp[-4] == VKI_AT_SYSINFO
831 && sp[-4-1] == 0) {
832 if (0)
833 VG_(printf)("Looks like you've got a 2.4.X kernel with "
834 "a sysinfo page at %x here.\n", sp[-3]);
835 VG_(sysinfo_page_exists) = True;
836 VG_(sysinfo_page_addr) = sp[-3];
837 sp -= 4;
838 } else
839 if (sp[2] == VKI_AT_CLKTCK
840 && sp[0] == VKI_AT_PAGESZ
841 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000842 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
843 && sp[-4-1] == 0) {
844 if (0)
845 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
846 "kernel here.\n");
847 sp -= 4;
848 } else
849 if (sp[2] == VKI_AT_CLKTCK
850 && sp[0] == VKI_AT_PAGESZ
851 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000852 && sp[-2-20-1] == 0) {
853 if (0)
854 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
855 sp -= 22;
856 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000857 if (sp[2] == VKI_AT_CLKTCK
858 && sp[0] == VKI_AT_PAGESZ
859 && sp[-2] == VKI_AT_HWCAP
860 && sp[-4-1] == 0) {
861 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000862 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000863 sp -= 4;
864 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000865 if (sp[2] == VKI_AT_CLKTCK
866 && sp[0] == VKI_AT_PAGESZ
867 && sp[-2] == VKI_AT_HWCAP
868 && sp[-6] == VKI_AT_SYSINFO
869 && sp[-6-1] == 0) {
870 if (0)
871 VG_(printf)("Looks like a >= 2.5.68 kernel with "
872 "a sysinfo page at %x here.\n", sp[-5]);
873 VG_(sysinfo_page_exists) = True;
874 VG_(sysinfo_page_addr) = sp[-5];
875 sp -= 6;
876 } else
sewardja1679dd2002-05-10 22:31:40 +0000877 args_grok_error(
878 "ELF frame does not look like 2.2.X or 2.4.X.\n "
879 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
880 );
sewardj38170912002-05-10 21:07:22 +0000881
882 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000883 if (*sp != 0)
884 args_grok_error("can't find NULL at end of env[]");
885
sewardj38170912002-05-10 21:07:22 +0000886 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000887 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000888 while (True) {
889 sp --;
890 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000891 if (++ctr >= 1000)
892 args_grok_error(
893 "suspiciously many (1000) env[] entries; giving up");
894
sewardj38170912002-05-10 21:07:22 +0000895 }
896 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000897 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000898
sewardja1679dd2002-05-10 22:31:40 +0000899 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000900 VG_(client_argc) = 0;
901 while (True) {
902 sp--;
903 if (*sp == VG_(client_argc))
904 break;
905 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000906 if (++ctr >= 1000)
907 args_grok_error(
908 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000909 }
910
sewardja1679dd2002-05-10 22:31:40 +0000911 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000912 }
913
sewardjde4a1d02002-03-22 01:27:54 +0000914 /* Now that VG_(client_envp) has been set, we can extract the args
915 for Valgrind itself. Copy into global var so that we don't have to
916 write zeroes to the getenv'd value itself. */
917 str = VG_(getenv)("VG_ARGS");
918 argc = 0;
919
920 if (!str) {
921 config_error("Can't read options from env var VG_ARGS.");
922 }
923
924 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
925 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
926 }
927 VG_(strcpy)(vg_cmdline_copy, str);
928 str = NULL;
929
930 p = &vg_cmdline_copy[0];
931 while (True) {
932 while (ISSPACE(*p)) { *p = 0; p++; }
933 if (*p == 0) break;
934 if (argc < M_VG_CMDLINE_OPTS-1) {
935 argv[argc] = p; argc++;
936 } else {
937 config_error(
938 "Found more than M_CMDLINE_OPTS command-line opts.");
939 }
940 while (*p != 0 && !ISSPACE(*p)) p++;
941 }
942
943 for (i = 0; i < argc; i++) {
944
njn43c799e2003-04-08 00:08:52 +0000945 if (VG_CLO_STREQ(argv[i], "-v") ||
946 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000947 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000948 else if (VG_CLO_STREQ(argv[i], "-q") ||
949 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000950 VG_(clo_verbosity)--;
951
njn43c799e2003-04-08 00:08:52 +0000952 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000953 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000954 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000955 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000956
njn43c799e2003-04-08 00:08:52 +0000957 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000958 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000959 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000960 VG_(clo_GDB_attach) = False;
961
sewardj6024b212003-07-13 10:54:33 +0000962 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
963 VG_(clo_GDB_path) = &argv[i][11];
964
njn43c799e2003-04-08 00:08:52 +0000965 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
966 VG_(clo_gen_suppressions) = True;
967 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
968 VG_(clo_gen_suppressions) = False;
969
970 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000971 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000972 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000973 VG_(clo_demangle) = False;
974
njn43c799e2003-04-08 00:08:52 +0000975 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000976 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000977 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000978 VG_(clo_trace_children) = False;
979
njn43c799e2003-04-08 00:08:52 +0000980 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000981 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000982 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000983 VG_(clo_run_libc_freeres) = False;
984
njn43c799e2003-04-08 00:08:52 +0000985 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000986 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
987
njn43c799e2003-04-08 00:08:52 +0000988 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000989 VG_(clo_log_to) = VgLogTo_Fd;
990 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000991 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000992 }
993
njn43c799e2003-04-08 00:08:52 +0000994 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000995 VG_(clo_log_to) = VgLogTo_File;
996 VG_(clo_logfile_name) = &argv[i][10];
997 }
sewardjde4a1d02002-03-22 01:27:54 +0000998
njn43c799e2003-04-08 00:08:52 +0000999 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001000 VG_(clo_log_to) = VgLogTo_Socket;
1001 VG_(clo_logfile_name) = &argv[i][12];
1002 }
1003
sewardj6024b212003-07-13 10:54:33 +00001004 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
1005 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
1006
njn43c799e2003-04-08 00:08:52 +00001007 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001008 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001009 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001010 VG_(message)(Vg_UserMsg,
1011 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +00001012 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001013 }
1014 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
1015 VG_(clo_n_suppressions)++;
1016 }
njn43c799e2003-04-08 00:08:52 +00001017 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001018 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +00001019 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001020 VG_(clo_profile) = False;
1021
njn43c799e2003-04-08 00:08:52 +00001022 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001023 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +00001024 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001025 VG_(clo_chain_bb) = False;
1026
njn43c799e2003-04-08 00:08:52 +00001027 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001028 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +00001029 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001030 VG_(clo_single_step) = False;
1031
njn43c799e2003-04-08 00:08:52 +00001032 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001033 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +00001034 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001035 VG_(clo_optimise) = False;
1036
njn25e49d8e72002-09-23 09:36:25 +00001037 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +00001038 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001039 Int j;
1040 char* opt = & argv[i][16];
1041
1042 if (5 != VG_(strlen)(opt)) {
1043 VG_(message)(Vg_UserMsg,
1044 "--trace-codegen argument must have 5 digits");
1045 VG_(bad_option)(argv[i]);
1046 }
1047 for (j = 0; j < 5; j++) {
1048 if ('0' == opt[j]) { /* do nothing */ }
1049 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1050 else {
1051 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1052 "contain 0s and 1s");
1053 VG_(bad_option)(argv[i]);
1054 }
1055 }
1056 }
sewardjde4a1d02002-03-22 01:27:54 +00001057
njn43c799e2003-04-08 00:08:52 +00001058 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001059 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001060 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001061 VG_(clo_trace_syscalls) = False;
1062
njn43c799e2003-04-08 00:08:52 +00001063 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001064 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001065 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001066 VG_(clo_trace_signals) = False;
1067
njn43c799e2003-04-08 00:08:52 +00001068 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001069 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001070 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001071 VG_(clo_trace_symtab) = False;
1072
njn43c799e2003-04-08 00:08:52 +00001073 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001074 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001075 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001076 VG_(clo_trace_sched) = False;
1077
njn43c799e2003-04-08 00:08:52 +00001078 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001079 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001080 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001081 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001082 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001083 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001084
njn43c799e2003-04-08 00:08:52 +00001085 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001086 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001087
jsgf855d93d2003-10-13 22:26:55 +00001088 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
1089 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
1090
1091 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
1092 VG_(clo_lowlat_signals) = True;
1093 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
1094 VG_(clo_lowlat_signals) = False;
1095
1096 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
1097 VG_(clo_lowlat_syscalls) = True;
1098 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
1099 VG_(clo_lowlat_syscalls) = False;
1100
njn43c799e2003-04-08 00:08:52 +00001101 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001102 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1103
njn43c799e2003-04-08 00:08:52 +00001104 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001105 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1106
jsgf855d93d2003-10-13 22:26:55 +00001107 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
1108 VG_(clo_wait_for_gdb) = True;
1109 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
1110 VG_(clo_wait_for_gdb) = False;
1111
njn43c799e2003-04-08 00:08:52 +00001112 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001113 /* Make sure it's sane. */
1114 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +00001115 if (VG_(clo_backtrace_size) < 1)
1116 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001117 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1118 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1119 }
1120
njn25e49d8e72002-09-23 09:36:25 +00001121 else if (VG_(needs).command_line_options) {
1122 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1123 if (!ok)
1124 usage();
1125 }
sewardjde4a1d02002-03-22 01:27:54 +00001126 else
njn25e49d8e72002-09-23 09:36:25 +00001127 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001128 }
1129
1130# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001131
njnf9ebf672003-05-12 21:41:30 +00001132 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001133 VG_(clo_verbosity) = 0;
1134
1135 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1136 VG_(message)(Vg_UserMsg, "");
1137 VG_(message)(Vg_UserMsg,
1138 "--gdb-attach=yes conflicts with --trace-children=yes");
1139 VG_(message)(Vg_UserMsg,
1140 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001141 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001142 }
1143
sewardj4cf05692002-10-27 20:28:29 +00001144 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1145 should be connected to whatever sink has been selected, and we
1146 indiscriminately chuck stuff into it without worrying what the
1147 nature of it is. Oh the wonder of Unix streams. */
1148
1149 /* So far we should be still attached to stderr, so we can show on
1150 the terminal any problems to do with processing command line
1151 opts. */
1152 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001153 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001154
1155 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001156
sewardj4cf05692002-10-27 20:28:29 +00001157 case VgLogTo_Fd:
1158 vg_assert(VG_(clo_logfile_name) == NULL);
1159 VG_(clo_logfile_fd) = eventually_logfile_fd;
1160 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001161
sewardj4cf05692002-10-27 20:28:29 +00001162 case VgLogTo_File: {
1163 Char logfilename[1000];
1164 vg_assert(VG_(clo_logfile_name) != NULL);
1165 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1166 VG_(sprintf)(logfilename, "%s.pid%d",
1167 VG_(clo_logfile_name), VG_(getpid)() );
1168 eventually_logfile_fd
1169 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1170 VKI_S_IRUSR|VKI_S_IWUSR);
1171 if (eventually_logfile_fd != -1) {
1172 VG_(clo_logfile_fd) = eventually_logfile_fd;
1173 } else {
1174 VG_(message)(Vg_UserMsg,
1175 "Can't create/open log file `%s.pid%d'; giving up!",
1176 VG_(clo_logfile_name), VG_(getpid)());
1177 VG_(bad_option)(
1178 "--logfile=<file> didn't work out for some reason.");
1179 }
1180 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001181 }
1182
1183 case VgLogTo_Socket: {
1184 vg_assert(VG_(clo_logfile_name) != NULL);
1185 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1186 eventually_logfile_fd
1187 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1188 if (eventually_logfile_fd == -1) {
1189 VG_(message)(Vg_UserMsg,
1190 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1191 VG_(message)(Vg_UserMsg,
1192 "of `%s'; giving up!", VG_(clo_logfile_name) );
1193 VG_(bad_option)(
1194 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001195 }
sewardj73cf3bc2002-11-03 03:20:15 +00001196 if (eventually_logfile_fd == -2) {
1197 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001198 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001199 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001200 VG_(message)(Vg_UserMsg,
1201 "Log messages will sent to stderr instead." );
1202 VG_(message)(Vg_UserMsg,
1203 "" );
1204 /* We don't change anything here. */
1205 } else {
1206 vg_assert(eventually_logfile_fd > 0);
1207 VG_(clo_logfile_fd) = eventually_logfile_fd;
1208 VG_(logging_to_filedes) = False;
1209 }
sewardj73cf3bc2002-11-03 03:20:15 +00001210 break;
1211 }
1212
sewardj4cf05692002-10-27 20:28:29 +00001213 }
1214
jsgf855d93d2003-10-13 22:26:55 +00001215 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
1216 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_MAX_FD+1);
1217 if (eventually_logfile_fd < 0)
1218 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1219 else {
1220 VG_(clo_logfile_fd) = eventually_logfile_fd;
1221 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1222 }
1223
sewardj4cf05692002-10-27 20:28:29 +00001224 /* Ok, the logging sink is running now. Print a suitable preamble.
1225 If logging to file or a socket, write details of parent PID and
1226 command line args, to help people trying to interpret the
1227 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001228
sewardj83adf412002-05-01 01:25:45 +00001229 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001230 /* Skin details */
1231 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1232 VG_(details).name,
1233 NULL == VG_(details).version ? "" : "-",
1234 NULL == VG_(details).version
1235 ? (Char*)"" : VG_(details).version,
1236 VG_(details).description);
1237 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001238
njnd04b7c62002-10-03 14:05:52 +00001239 /* Core details */
1240 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001241 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001242 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001243 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001244 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001245 }
1246
sewardj4cf05692002-10-27 20:28:29 +00001247 if (VG_(clo_log_to) != VgLogTo_Fd) {
1248 VG_(message)(Vg_UserMsg, "");
1249 VG_(message)(Vg_UserMsg,
1250 "My PID = %d, parent PID = %d. Prog and args are:",
1251 VG_(getpid)(), VG_(getppid)() );
1252 for (i = 0; i < VG_(client_argc); i++)
1253 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1254 }
1255
sewardjde4a1d02002-03-22 01:27:54 +00001256 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001257 if (VG_(clo_log_to) != VgLogTo_Fd)
1258 VG_(message)(Vg_UserMsg, "");
njn86dc2bc2003-09-09 07:26:21 +00001259 VG_(message)(Vg_UserMsg, "Command line");
1260 for (i = 0; i < VG_(client_argc); i++)
1261 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1262
sewardjde4a1d02002-03-22 01:27:54 +00001263 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1264 for (i = 0; i < argc; i++) {
1265 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1266 }
1267 }
1268
njn25e49d8e72002-09-23 09:36:25 +00001269 if (VG_(clo_n_suppressions) == 0 &&
1270 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001271 config_error("No error-suppression files were specified.");
1272 }
sewardj4cf05692002-10-27 20:28:29 +00001273
njn6a230532003-07-21 10:38:23 +00001274 if (VG_(clo_gen_suppressions) &&
1275 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1276 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1277 " as it doesn't generate errors.");
1278 }
1279
sewardjde4a1d02002-03-22 01:27:54 +00001280}
1281
sewardjde4a1d02002-03-22 01:27:54 +00001282/* ---------------------------------------------------------------------
1283 Copying to/from m_state_static.
1284 ------------------------------------------------------------------ */
1285
sewardjb91ae7f2003-04-29 23:50:00 +00001286/* See comment about this in vg_include.h. Change only with
1287 great care.
1288*/
1289__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001290UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1291 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001292 + 1 /* %eflags */
1293 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001294 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001295 ];
1296
sewardjfa492d42002-12-08 18:20:01 +00001297UInt VG_(insertDflag)(UInt eflags, Int d)
1298{
1299 vg_assert(d == 1 || d == -1);
1300 eflags &= ~EFlagD;
1301
1302 if (d < 0)
1303 eflags |= EFlagD;
1304
1305 return eflags;
1306}
1307
1308Int VG_(extractDflag)(UInt eflags)
1309{
1310 Int ret;
1311
1312 if (eflags & EFlagD)
1313 ret = -1;
1314 else
1315 ret = 1;
1316
1317 return ret;
1318}
1319
sewardjde4a1d02002-03-22 01:27:54 +00001320void VG_(copy_baseBlock_to_m_state_static) ( void )
1321{
1322 Int i;
sewardj92a59562002-09-30 00:53:10 +00001323 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1324 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1325 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1326 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1327 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1328 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001329
sewardj92a59562002-09-30 00:53:10 +00001330 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1331 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1332 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1333 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1334 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1335 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1336 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1337 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1338
sewardjb91ae7f2003-04-29 23:50:00 +00001339 VG_(m_state_static)[56/4]
1340 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1341 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001342 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001343
sewardjb91ae7f2003-04-29 23:50:00 +00001344 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001345 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001346 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001347}
1348
1349
1350void VG_(copy_m_state_static_to_baseBlock) ( void )
1351{
1352 Int i;
sewardj92a59562002-09-30 00:53:10 +00001353 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1354 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1355 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1356 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1357 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1358 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001359
sewardj92a59562002-09-30 00:53:10 +00001360 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1361 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1362 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1363 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1364 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1365 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1366 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1367 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1368
sewardjb91ae7f2003-04-29 23:50:00 +00001369 VG_(baseBlock)[VGOFF_(m_eflags)]
1370 = VG_(m_state_static)[56/4] & ~EFlagD;
1371 VG_(baseBlock)[VGOFF_(m_dflag)]
1372 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001373
sewardj92a59562002-09-30 00:53:10 +00001374 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001375
sewardjb91ae7f2003-04-29 23:50:00 +00001376 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1377 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001378 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001379}
1380
njn25e49d8e72002-09-23 09:36:25 +00001381Addr VG_(get_stack_pointer) ( void )
1382{
1383 return VG_(baseBlock)[VGOFF_(m_esp)];
1384}
1385
1386/* Some random tests needed for leak checking */
1387
1388Bool VG_(within_stack)(Addr a)
1389{
1390 if (a >= ((Addr)(&VG_(stack)))
1391 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1392 return True;
1393 else
1394 return False;
1395}
1396
sewardjecf8e102003-07-12 12:11:39 +00001397Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001398{
1399 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001400 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001401 return True;
sewardjecf8e102003-07-12 12:11:39 +00001402
1403 if (a >= ((Addr)(&VG_(threads)[0]))
1404 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1405 return True;
1406
1407 return False;
njn25e49d8e72002-09-23 09:36:25 +00001408}
sewardjde4a1d02002-03-22 01:27:54 +00001409
1410/* ---------------------------------------------------------------------
1411 Show accumulated counts.
1412 ------------------------------------------------------------------ */
1413
njn25e49d8e72002-09-23 09:36:25 +00001414static __inline__ Int safe_idiv(Int a, Int b)
1415{
1416 return (b == 0 ? 0 : a / b);
1417}
1418
sewardjde4a1d02002-03-22 01:27:54 +00001419static void vg_show_counts ( void )
1420{
1421 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001422 " TT/TC: %d tc sectors discarded.",
1423 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001424 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001425 " %d chainings, %d unchainings.",
1426 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1427 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001428 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001429 VG_(overall_in_count),
1430 VG_(overall_in_osize),
1431 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001432 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1433 VG_(message)(Vg_DebugMsg,
1434 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001435 VG_(overall_out_count),
1436 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001437 VG_(overall_out_tsize),
1438 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001439 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001440 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001441 VG_(bbs_done),
1442 VG_(unchained_jumps_done),
1443 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1444 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1445 );
1446
1447 VG_(message)(Vg_DebugMsg,
1448 " %d/%d major/minor sched events. %d tt_fast misses.",
1449 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001450 VG_(num_scheduling_events_MINOR),
1451 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001452
sewardjde4a1d02002-03-22 01:27:54 +00001453 VG_(message)(Vg_DebugMsg,
1454 "reg-alloc: %d t-req-spill, "
1455 "%d+%d orig+spill uis, %d total-reg-r.",
1456 VG_(translations_needing_spill),
1457 VG_(uinstrs_prealloc),
1458 VG_(uinstrs_spill),
1459 VG_(total_reg_rank) );
1460 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001461 " sanity: %d cheap, %d expensive checks.",
1462 VG_(sanity_fast_count),
1463 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001464 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001465}
1466
1467
1468/* ---------------------------------------------------------------------
1469 Main!
1470 ------------------------------------------------------------------ */
1471
jsgf855d93d2003-10-13 22:26:55 +00001472/* Initialize the PID and PGRP of scheduler LWP; this is also called
1473 in any new children after fork. */
1474static void newpid(ThreadId unused)
1475{
1476 /* PID of scheduler LWP */
1477 VG_(main_pid) = VG_(getpid)();
1478 VG_(main_pgrp) = VG_(getpgrp)();
1479}
1480
sewardjde4a1d02002-03-22 01:27:54 +00001481/* Where we jump to once Valgrind has got control, and the real
1482 machine's state has been copied to the m_state_static. */
1483
1484void VG_(main) ( void )
1485{
sewardj2e93c502002-04-12 11:12:52 +00001486 Int i;
1487 VgSchedReturnCode src;
sewardjde4a1d02002-03-22 01:27:54 +00001488
njn0c7a5b52003-04-30 09:00:33 +00001489 if (0) {
1490 if (VG_(have_ssestate))
1491 VG_(printf)("Looks like a SSE-capable CPU\n");
1492 else
1493 VG_(printf)("Looks like a MMX-only CPU\n");
1494 }
sewardjb91ae7f2003-04-29 23:50:00 +00001495
njn27f1a382002-11-08 15:48:16 +00001496 /* Check skin and core versions are compatible */
1497 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1498 VG_(printf)("Error:\n"
1499 " Skin and core interface versions do not match.\n"
1500 " Interface version used by core is: %d.%d\n"
1501 " Interface version used by skin is: %d.%d\n"
1502 " The major version numbers must match.\n",
1503 VG_CORE_INTERFACE_MAJOR_VERSION,
1504 VG_CORE_INTERFACE_MINOR_VERSION,
1505 VG_(skin_interface_major_version),
1506 VG_(skin_interface_minor_version));
1507 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1508 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1509 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1510 else
1511 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1512 VG_(printf)(" Aborting, sorry.\n");
1513 VG_(exit)(1);
1514 }
1515
jsgf855d93d2003-10-13 22:26:55 +00001516 VG_(atfork)(NULL, NULL, newpid);
1517 newpid(VG_INVALID_THREADID);
1518
sewardjde4a1d02002-03-22 01:27:54 +00001519 /* Set up our stack sanity-check words. */
1520 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001521 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1522 VG_(stack)[VG_STACK_SIZE_W-1-i]
1523 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001524 }
1525
njn3e884182003-04-15 13:03:23 +00001526 /* Read /proc/self/maps into a buffer. Must be before:
1527 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1528 superblocks are not erroneously identified as being owned by the
1529 client, which would be bad.
1530 - init_memory(): that's where the buffer is parsed
1531 - init_tt_tc(): so the anonymous mmaps for the translation table and
1532 translation cache aren't identified as part of the client, which would
1533 waste > 20M of virtual address space, and be bad.
1534 */
njnfa1016e2003-09-25 17:54:11 +00001535 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001536
njn25e49d8e72002-09-23 09:36:25 +00001537 /* Setup stuff that depends on the skin. Must be before:
1538 - vg_init_baseBlock(): to register helpers
1539 - process_cmd_line_options(): to register skin name and description,
1540 and turn on/off 'command_line_options' need
1541 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001542 */
njn810086f2002-11-14 12:42:47 +00001543 SK_(pre_clo_init)();
1544 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001545
njncc7bb472002-10-14 09:25:19 +00001546 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001547 process_cmd_line_options();
1548
jsgf855d93d2003-10-13 22:26:55 +00001549 /* Hook to delay things long enough so we can get the pid and
1550 attach GDB in another shell. */
1551 if (VG_(clo_wait_for_gdb)) {
1552 VG_(printf)("pid=%d\n", VG_(getpid)());
1553 /* do "jump *$eip" to skip this in gdb */
1554 VG_(do_syscall)(__NR_pause);
1555 }
1556
njn3e884182003-04-15 13:03:23 +00001557 /* Do post command-line processing initialisation. Must be before:
1558 - vg_init_baseBlock(): to register any more helpers
1559 */
njncc7bb472002-10-14 09:25:19 +00001560 SK_(post_clo_init)();
1561
njn3e884182003-04-15 13:03:23 +00001562 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001563 vg_init_baseBlock();
1564
sewardj018f7622002-05-15 21:13:39 +00001565 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001566 baseBlock into VG_(threads)[1]. Must be before:
1567 - VG_(sigstartup_actions)()
1568 */
sewardj018f7622002-05-15 21:13:39 +00001569 VG_(scheduler_init)();
1570
jsgf855d93d2003-10-13 22:26:55 +00001571 /* Set up the ProxyLWP machinery */
1572 VG_(proxy_init)();
1573
sewardj018f7622002-05-15 21:13:39 +00001574 /* Initialise the signal handling subsystem, temporarily parking
1575 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001576 VG_(sigstartup_actions)();
1577
sewardj018f7622002-05-15 21:13:39 +00001578 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001579 if (VG_(clo_profile))
1580 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001581
sewardj5f07b662002-04-23 16:52:51 +00001582 /* Start calibration of our RDTSC-based clock. */
1583 VG_(start_rdtsc_calibration)();
1584
njn3e884182003-04-15 13:03:23 +00001585 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001586 VGP_PUSHCC(VgpInitMem);
1587 VG_(init_memory)();
1588 VGP_POPCC(VgpInitMem);
1589
1590 /* Read the list of errors to suppress. This should be found in
1591 the file specified by vg_clo_suppressions. */
1592 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1593 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001594
sewardj5f07b662002-04-23 16:52:51 +00001595 /* End calibration of our RDTSC-based clock, leaving it as long as
1596 we can. */
1597 VG_(end_rdtsc_calibration)();
1598
njn3e884182003-04-15 13:03:23 +00001599 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001600 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001601
1602 if (VG_(clo_verbosity) == 1) {
1603 VG_(message)(Vg_UserMsg,
1604 "For more details, rerun with: -v");
1605 }
1606
sewardj25c7c3a2003-07-10 00:17:58 +00001607 /* Force a read of the debug info so that we can look for
1608 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001609 VG_(setup_code_redirect_table)();
1610
sewardjde4a1d02002-03-22 01:27:54 +00001611 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1612 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001613 if (VG_(clo_verbosity) > 0)
1614 VG_(message)(Vg_UserMsg, "");
1615
1616 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001617
sewardj018f7622002-05-15 21:13:39 +00001618 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001619 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001620 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001621
1622 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1623 VG_(fatal_signal_set) = True;
1624 src = VG_(scheduler)();
1625 } else
1626 src = VgSrc_FatalSig;
1627
njn25e49d8e72002-09-23 09:36:25 +00001628 VGP_POPCC(VgpSched);
1629 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001630
1631 if (VG_(clo_verbosity) > 0)
1632 VG_(message)(Vg_UserMsg, "");
1633
sewardj2e93c502002-04-12 11:12:52 +00001634 if (src == VgSrc_Deadlock) {
1635 VG_(message)(Vg_UserMsg,
1636 "Warning: pthread scheduler exited due to deadlock");
1637 }
1638
njn25e49d8e72002-09-23 09:36:25 +00001639 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001640 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001641
njn7d9f94d2003-04-22 21:41:40 +00001642 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001643
sewardj0c3b53f2002-05-01 01:58:35 +00001644 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001645
1646 if (VG_(clo_verbosity) > 1)
1647 vg_show_counts();
1648
sewardjc0d8f682002-11-30 00:49:43 +00001649 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001650 VG_(print_UInstr_histogram)();
1651
sewardjde4a1d02002-03-22 01:27:54 +00001652 if (0) {
1653 VG_(message)(Vg_DebugMsg, "");
1654 VG_(message)(Vg_DebugMsg,
1655 "------ Valgrind's internal memory use stats follow ------" );
1656 VG_(mallocSanityCheckAll)();
1657 VG_(show_all_arena_stats)();
1658 VG_(message)(Vg_DebugMsg,
1659 "------ Valgrind's ExeContext management stats follow ------" );
1660 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001661 }
1662
njn25e49d8e72002-09-23 09:36:25 +00001663 if (VG_(clo_profile))
1664 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001665
1666 VG_(shutdown_logging)();
1667
sewardj3e1eb1f2002-05-18 13:14:17 +00001668 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1669 processes don't get traced into. Also mess up $libdir/valgrind
1670 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001671 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1672 pointless when we are just about to VgSrc_ExitSyscall. So don't
1673 bother in that case. */
1674 if ((!VG_(clo_trace_children))
1675 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001676 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1677 VG_(getenv)("LD_PRELOAD"),
1678 VG_(getenv)("LD_LIBRARY_PATH")
1679 );
sewardjde4a1d02002-03-22 01:27:54 +00001680 }
1681
jsgf855d93d2003-10-13 22:26:55 +00001682 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1683 vg_assert(src == VgSrc_FatalSig ||
1684 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1685 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1686 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1687
sewardj7e87e382002-05-03 19:09:05 +00001688 /* Decide how to exit. This depends on what the scheduler
1689 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001690
sewardj7e87e382002-05-03 19:09:05 +00001691 switch (src) {
1692 case VgSrc_ExitSyscall: /* the normal way out */
1693 vg_assert(VG_(last_run_tid) > 0
1694 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001695 VG_(proxy_shutdown)();
1696
njn25e49d8e72002-09-23 09:36:25 +00001697 /* The thread's %EBX at the time it did __NR_exit() will hold
1698 the arg to __NR_exit(), so we just do __NR_exit() with
1699 that arg. */
1700 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001701 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001702 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001703 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001704
sewardj7e87e382002-05-03 19:09:05 +00001705 case VgSrc_Deadlock:
1706 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001707 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001708 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001709 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001710 break;
1711
1712 case VgSrc_BbsDone:
1713 /* Tricky; we have to try and switch back to the real CPU.
1714 This is all very dodgy and won't work at all in the
1715 presence of threads, or if the client happened to be
1716 running a signal handler. */
1717 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001718 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001719 VG_(load_thread_state)(1 /* root thread */ );
1720 VG_(copy_baseBlock_to_m_state_static)();
1721
jsgf855d93d2003-10-13 22:26:55 +00001722 VG_(proxy_shutdown)();
1723
sewardj7e87e382002-05-03 19:09:05 +00001724 /* This pushes a return address on the simulator's stack,
1725 which is abandoned. We call vg_sigshutdown_actions() at
1726 the end of vg_switch_to_real_CPU(), so as to ensure that
1727 the original stack and machine state is restored before
1728 the real signal mechanism is restored. */
1729 VG_(switch_to_real_CPU)();
1730
jsgf855d93d2003-10-13 22:26:55 +00001731 case VgSrc_FatalSig:
1732 /* We were killed by a fatal signal, so replicate the effect */
1733 vg_assert(VG_(fatal_sigNo) != -1);
1734 VG_(kill_self)(VG_(fatal_sigNo));
1735 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1736 break;
1737
sewardj7e87e382002-05-03 19:09:05 +00001738 default:
njne427a662002-10-02 11:08:25 +00001739 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001740 }
sewardjde4a1d02002-03-22 01:27:54 +00001741}
1742
1743
1744/* Debugging thing .. can be called from assembly with OYNK macro. */
1745void VG_(oynk) ( Int n )
1746{
1747 OINK(n);
1748}
1749
1750
1751/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1752 "valgrinq.so", which doesn't do anything. This is used to avoid
1753 tracing into child processes. To make this work the build system
1754 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001755
njn25e49d8e72002-09-23 09:36:25 +00001756 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1757 without it, child processes try to find valgrind.so symbols in the
1758 skin .so.
1759
sewardj78e25c92002-05-20 23:38:33 +00001760 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1761 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1762 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001763*/
sewardj45b672d2003-07-25 19:58:11 +00001764static void slideleft ( Char* s )
1765{
1766 vg_assert(s && (*s == ' ' || *s == ':'));
1767 while (True) {
1768 s[0] = s[1];
1769 if (s[0] == '\0') break;
1770 s++;
1771 }
1772}
1773
1774
sewardj3e1eb1f2002-05-18 13:14:17 +00001775void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1776 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001777{
njn42e23f22003-05-05 12:47:25 +00001778 Char* vg_prel = NULL;
1779 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001780 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001781 Char* p;
1782 Char* coredir_first;
1783 Char* coredir_last;
1784 Int coredir_len;
1785 Int i;
1786 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001787
njn42e23f22003-05-05 12:47:25 +00001788#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001789
njn42e23f22003-05-05 12:47:25 +00001790 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001791
njn42e23f22003-05-05 12:47:25 +00001792 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1793
njnc2f5bb02003-07-23 09:40:50 +00001794 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1795 LD_LIBRARY_PATH = "<coredir>:Y" */
1796
njn42e23f22003-05-05 12:47:25 +00001797 /* Setting up, finding things */
1798
1799 /* LD_PRELOAD: Search for "valgrind.so" */
1800 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1801
1802 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001803 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001804 if (NULL == vg_prel) {
1805 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001806 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001807 }
1808
njnc2f5bb02003-07-23 09:40:50 +00001809 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001810 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001811
njn42e23f22003-05-05 12:47:25 +00001812 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1813 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1814 coredir_first = p+1;
1815 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001816 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001817
1818 /* LD_PRELOAD: find "vgskin_foo.so" */
1819 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1820 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001821
njnc2f5bb02003-07-23 09:40:50 +00001822 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001823 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001824 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1825 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001826 *coredir_last = '/'; /* Undo zero-termination */
1827
1828 /* Changing things */
1829
1830 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1831 if (vg_prel[7] != 'd') MUTANCY(6);
1832 vg_prel[7] = 'q';
1833
njnc2f5bb02003-07-23 09:40:50 +00001834 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1835 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1836 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001837 while (*p != ':' && p >= ld_preload_str) {
1838 *p = ' ';
1839 p--;
njn25e49d8e72002-09-23 09:36:25 +00001840 }
njnc2f5bb02003-07-23 09:40:50 +00001841 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1842 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001843 p = sk_prel;
1844 while (*p != ':' && *p != '\0') {
1845 *p = ' ';
1846 p++;
1847 }
1848 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001849
njnc2f5bb02003-07-23 09:40:50 +00001850 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001851 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001852 coredir2[i] = ' ';
sewardj45b672d2003-07-25 19:58:11 +00001853
1854 /* Zap the leading spaces and : in both strings. */
1855 while (ld_preload_str[0] == ' ') slideleft(ld_preload_str);
1856 if (ld_preload_str[0] == ':') slideleft(ld_preload_str);
1857
1858 while (ld_library_path_str[0] == ' ') slideleft(ld_library_path_str);
1859 if (ld_library_path_str[0] == ':') slideleft(ld_library_path_str);
1860
njn42e23f22003-05-05 12:47:25 +00001861 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001862
sewardj78e25c92002-05-20 23:38:33 +00001863 return;
1864
njn42e23f22003-05-05 12:47:25 +00001865
1866mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001867 VG_(printf)(
1868 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1869 " what = %d\n"
1870 " ld_preload_str = `%s'\n"
1871 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001872 " vg_prel = `%s'\n"
1873 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001874 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001875 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001876 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001877 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001878 );
sewardjc26b4482002-07-13 12:20:35 +00001879 VG_(printf)(
1880 "\n"
1881 "Note that this is often caused by mis-installation of valgrind.\n"
1882 "Correct installation procedure is:\n"
1883 " ./configure --prefix=/install/dir\n"
1884 " make install\n"
1885 "And then use /install/dir/bin/valgrind\n"
1886 "Moving the installation directory elsewhere after 'make install'\n"
1887 "will cause the above error. Hand-editing the paths in the shell\n"
1888 "scripts is also likely to cause problems.\n"
1889 "\n"
1890 );
njne427a662002-10-02 11:08:25 +00001891 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001892}
1893
sewardj3e1eb1f2002-05-18 13:14:17 +00001894
sewardjde4a1d02002-03-22 01:27:54 +00001895/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1896 it to attach to this process. Called if the user requests this
1897 service after an error has been shown, so she can poke around and
1898 look at parameters, memory, etc. You can't meaningfully get GDB to
1899 continue the program, though; to continue, quit GDB. */
1900extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1901{
sewardje6a25242002-04-21 22:03:07 +00001902 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001903 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001904
njn9315df32003-04-16 20:50:50 +00001905 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001906 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001907 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1908 res = VG_(system)(buf);
1909 if (res == 0) {
1910 VG_(message)(Vg_UserMsg, "");
1911 VG_(message)(Vg_UserMsg,
1912 "GDB has detached. Valgrind regains control. We continue.");
1913 } else {
1914 VG_(message)(Vg_UserMsg, "Apparently failed!");
1915 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001916 }
sewardjde4a1d02002-03-22 01:27:54 +00001917}
1918
1919
1920/* Print some helpful-ish text about unimplemented things, and give
1921 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001922void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001923{
1924 VG_(message)(Vg_UserMsg, "");
1925 VG_(message)(Vg_UserMsg,
1926 "Valgrind detected that your program requires");
1927 VG_(message)(Vg_UserMsg,
1928 "the following unimplemented functionality:");
1929 VG_(message)(Vg_UserMsg, " %s", msg);
1930 VG_(message)(Vg_UserMsg,
1931 "This may be because the functionality is hard to implement,");
1932 VG_(message)(Vg_UserMsg,
1933 "or because no reasonable program would behave this way,");
1934 VG_(message)(Vg_UserMsg,
1935 "or because nobody has yet needed it. In any case, let me know");
1936 VG_(message)(Vg_UserMsg,
1937 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1938 VG_(message)(Vg_UserMsg,
1939 "");
1940 VG_(message)(Vg_UserMsg,
1941 "Valgrind has to exit now. Sorry. Bye!");
1942 VG_(message)(Vg_UserMsg,
1943 "");
sewardj15a43e12002-04-17 19:35:12 +00001944 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001945 VG_(exit)(1);
1946}
1947
1948
njn25e49d8e72002-09-23 09:36:25 +00001949/* ---------------------------------------------------------------------
1950 Sanity check machinery (permanently engaged).
1951 ------------------------------------------------------------------ */
1952
1953/* A fast sanity check -- suitable for calling circa once per
1954 millisecond. */
1955
1956void VG_(do_sanity_checks) ( Bool force_expensive )
1957{
1958 Int i;
1959
njn37cea302002-09-30 11:24:00 +00001960 VGP_PUSHCC(VgpCoreCheapSanity);
1961
njn25e49d8e72002-09-23 09:36:25 +00001962 if (VG_(sanity_level) < 1) return;
1963
1964 /* --- First do all the tests that we can do quickly. ---*/
1965
1966 VG_(sanity_fast_count)++;
1967
1968 /* Check that we haven't overrun our private stack. */
1969 for (i = 0; i < 10; i++) {
1970 vg_assert(VG_(stack)[i]
1971 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00001972 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
1973 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00001974 }
1975
1976 /* Check stuff pertaining to the memory check system. */
1977
1978 /* Check that nobody has spuriously claimed that the first or
1979 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001980 if (VG_(needs).sanity_checks) {
1981 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001982 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001983 VGP_POPCC(VgpSkinCheapSanity);
1984 }
njn25e49d8e72002-09-23 09:36:25 +00001985
1986 /* --- Now some more expensive checks. ---*/
1987
1988 /* Once every 25 times, check some more expensive stuff. */
1989 if ( force_expensive
1990 || VG_(sanity_level) > 1
1991 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1992
njn37cea302002-09-30 11:24:00 +00001993 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001994 VG_(sanity_slow_count)++;
1995
jsgf855d93d2003-10-13 22:26:55 +00001996 VG_(proxy_sanity)();
1997
njn25e49d8e72002-09-23 09:36:25 +00001998# if 0
1999 { void zzzmemscan(void); zzzmemscan(); }
2000# endif
2001
2002 if ((VG_(sanity_fast_count) % 250) == 0)
2003 VG_(sanity_check_tc_tt)();
2004
2005 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002006 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002007 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002008 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002009 }
2010 /*
2011 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2012 */
njn37cea302002-09-30 11:24:00 +00002013 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002014 }
2015
2016 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002017 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002018 /* Check sanity of the low-level memory manager. Note that bugs
2019 in the client's code can cause this to fail, so we don't do
2020 this check unless specially asked for. And because it's
2021 potentially very expensive. */
2022 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002023 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002024 }
njn37cea302002-09-30 11:24:00 +00002025 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002026}
sewardjde4a1d02002-03-22 01:27:54 +00002027/*--------------------------------------------------------------------*/
2028/*--- end vg_main.c ---*/
2029/*--------------------------------------------------------------------*/