blob: d11a4265f287ce9565ff14c8bc65fbecf7a41a05 [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;
rjwalshf5f536f2003-11-17 17:45:00 +0000560Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +0000561Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +0000562Bool VG_(clo_show_below_main) = False;
sewardj2370f3b2002-11-30 15:01:01 +0000563
jsgf855d93d2003-10-13 22:26:55 +0000564static Bool VG_(clo_wait_for_gdb) = False;
565
566/* If we're doing signal routing, poll for signals every 50mS by
567 default. */
568Int VG_(clo_signal_polltime) = 50;
569
fitzhardinge89f9a322003-10-30 07:25:59 +0000570/* If true, assume we're running on a plain 2.4 kernel */
571Bool VG_(clo_assume_24) = False;
572
jsgf855d93d2003-10-13 22:26:55 +0000573/* These flags reduce thread wakeup latency on syscall completion and
574 signal delivery, respectively. The downside is possible unfairness. */
575Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
576Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
577
sewardjde4a1d02002-03-22 01:27:54 +0000578/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
579 to behave. Initially we say False. */
580Bool VG_(running_on_simd_CPU) = False;
581
582/* Holds client's %esp at the point we gained control. */
583Addr VG_(esp_at_startup);
584
sewardjd5815ec2003-04-06 12:23:27 +0000585/* Indicates presence, and holds address of client's sysinfo page, a
586 feature of some modern kernels used to provide vsyscalls, etc. */
587Bool VG_(sysinfo_page_exists) = False;
588Addr VG_(sysinfo_page_addr) = 0;
589
sewardjde4a1d02002-03-22 01:27:54 +0000590/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
591 envp[] as extracted from the client's stack at startup-time. */
592Int VG_(client_argc);
593Char** VG_(client_argv);
594Char** VG_(client_envp);
595
596/* A place into which to copy the value of env var VG_ARGS, so we
597 don't have to modify the original. */
598static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
599
sewardjde4a1d02002-03-22 01:27:54 +0000600/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000601 Processing of command-line options.
602 ------------------------------------------------------------------ */
603
njn25e49d8e72002-09-23 09:36:25 +0000604void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000605{
606 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000607 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000608 VG_(clo_logfile_fd) = 2; /* stderr */
609 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
610 VG_(exit)(1);
611}
612
613static void config_error ( Char* msg )
614{
615 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000616 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000617 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000618 VG_(printf)(
619 "valgrind.so: Startup or configuration error:\n %s\n", msg);
620 VG_(printf)(
621 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000622 VG_(exit)(1);
623}
624
sewardja1679dd2002-05-10 22:31:40 +0000625static void args_grok_error ( Char* msg )
626{
627 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000628 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000629 VG_(clo_logfile_fd) = 2; /* stderr */
630 VG_(printf)("valgrind.so: When searching for "
631 "client's argc/argc/envp:\n\t%s\n", msg);
632 config_error("couldn't find client's argc/argc/envp");
633}
634
njn25e49d8e72002-09-23 09:36:25 +0000635static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000636{
njn25e49d8e72002-09-23 09:36:25 +0000637 Char* usage1 =
638"usage: valgrind [options] prog-and-args\n"
639"\n"
640" core user options, with defaults in [ ], are:\n"
nethercote137bc552003-11-14 17:47:54 +0000641" --tool=<name> Use the Valgrind tool named <name> [memcheck]\n"
nethercote77eba602003-11-13 17:35:04 +0000642
njn25e49d8e72002-09-23 09:36:25 +0000643" --help show this message\n"
644" --version show version\n"
nethercote77eba602003-11-13 17:35:04 +0000645
njn25e49d8e72002-09-23 09:36:25 +0000646" -q --quiet run silently; only print error msgs\n"
647" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000648
649" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
650
651" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
652" --logfile=<file> log messages to <file>.pid<pid>\n"
653" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
654
njn25e49d8e72002-09-23 09:36:25 +0000655" --demangle=no|yes automatically demangle C++ names? [yes]\n"
656" --num-callers=<number> show <num> callers in stack traces [4]\n"
657" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
nethercote77eba602003-11-13 17:35:04 +0000658" --show-below-main=no|yes continue stack traces below main() [no]\n"
659" --suppressions=<filename> suppress errors described in <filename>\n"
660" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
661
rjwalshf5f536f2003-11-17 17:45:00 +0000662" --track-fds=no|yes Track open file descriptors? [no]\n"
663
nethercote77eba602003-11-13 17:35:04 +0000664" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
665" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
sewardj6024b212003-07-13 10:54:33 +0000666" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
nethercote77eba602003-11-13 17:35:04 +0000667
668" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
669" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +0000670" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000671" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
672" Only applies for older kernels which need\n"
673" signal routing [50]\n"
674" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
675" a signal [no]\n"
676" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
677" syscall completes [no]\n"
fitzhardinge89f9a322003-10-30 07:25:59 +0000678" --assume-2.4=no|yes assume we're running on a 2.4 kernel [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000679"\n"
nethercote137bc552003-11-14 17:47:54 +0000680" %s tool user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000681
njn7cf0bd32002-06-08 13:36:03 +0000682
njn25e49d8e72002-09-23 09:36:25 +0000683 Char* usage2 =
684"\n"
685" core options for debugging Valgrind itself are:\n"
686" --sanity-level=<number> level of sanity checking to do [1]\n"
687" --single-step=no|yes translate each instr separately? [no]\n"
688" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +0000689" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000690" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000691" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
692" --trace-syscalls=no|yes show all system calls? [no]\n"
693" --trace-signals=no|yes show signal handling details? [no]\n"
694" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000695" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000696" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000697" --stop-after=<number> switch to real CPU after executing\n"
698" <number> basic blocks [infinity]\n"
699" --dump-error=<number> show translation for basic block\n"
700" associated with <number>'th\n"
701" error context [0=don't show any]\n"
jsgf855d93d2003-10-13 22:26:55 +0000702" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000703"\n"
nethercote137bc552003-11-14 17:47:54 +0000704" %s tool debugging options:\n";
njn3e884182003-04-15 13:03:23 +0000705
706 Char* usage3 =
707"\n"
njn25e49d8e72002-09-23 09:36:25 +0000708" Extra options are read from env variable $VALGRIND_OPTS\n"
709"\n"
njn0e1b5142003-04-15 14:58:06 +0000710" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000711" and licensed under the GNU General Public License, version 2.\n"
712" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000713"\n"
nethercote137bc552003-11-14 17:47:54 +0000714" Tools are copyright and licensed by their authors. See each\n"
715" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000716"\n";
njn7cf0bd32002-06-08 13:36:03 +0000717
njnd04b7c62002-10-03 14:05:52 +0000718 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000719 /* Don't print skin string directly for security, ha! */
720 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000721 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000722 else
723 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000724 VG_(printf)(usage2, VG_(details).name);
725 if (VG_(needs).command_line_options)
726 SK_(print_debug_usage)();
727 else
728 VG_(printf)(" (none)\n");
729 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000730
njn25e49d8e72002-09-23 09:36:25 +0000731 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000732 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000733 VG_(clo_logfile_fd) = 2; /* stderr */
734 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000735}
sewardjde4a1d02002-03-22 01:27:54 +0000736
sewardj1c1b1162003-02-23 01:25:51 +0000737
sewardj49e630d2003-04-23 21:18:52 +0000738/* Callback for looking for the stack segment. */
739Addr VG_(foundstack_start) = (Addr)NULL;
740UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000741
742static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000743 Char r, Char w, Char x,
744 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000745{
746 Addr lastword;
747 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000748 if (r != 'r' || w != 'w'
749 /* || x != 'x' --not necessarily so on x86-64*/
750 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000751 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000752 if (start <= VG_(esp_at_startup)
753 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000754 VG_(foundstack_start) = start;
755 VG_(foundstack_size) = size;
756 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000757 }
758}
759
760
761
sewardjde4a1d02002-03-22 01:27:54 +0000762static void process_cmd_line_options ( void )
763{
njn25e49d8e72002-09-23 09:36:25 +0000764 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000765 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000766 Char* p;
767 Char* str;
768 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000769
770# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000771
sewardjde4a1d02002-03-22 01:27:54 +0000772 eventually_logfile_fd = VG_(clo_logfile_fd);
773
774 /* Once logging is started, we can safely send messages pertaining
775 to failures in initialisation. */
776 VG_(startup_logging)();
777
sewardj19d81412002-06-03 01:10:40 +0000778 /* Check for sane path in ./configure --prefix=... */
779 if (VG_(strlen)(VG_LIBDIR) < 1
780 || VG_LIBDIR[0] != '/')
781 config_error("Please use absolute paths in "
782 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000783
sewardja1679dd2002-05-10 22:31:40 +0000784 /* (Suggested by Fabrice Bellard ... )
785 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000786 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000787 change less often than the libc ones. */
788 {
sewardj05bcdcb2003-05-18 10:05:38 +0000789 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000790
njn3e884182003-04-15 13:03:23 +0000791 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000792 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000793 has rwx permissions and no associated file. Note that this uses
794 the /proc/self/maps contents read at the start of VG_(main)(),
795 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000796
njnfa1016e2003-09-25 17:54:11 +0000797 VG_(parse_procselfmaps)( vg_findstack_callback );
sewardj53fe4582003-02-23 01:41:17 +0000798
sewardj49e630d2003-04-23 21:18:52 +0000799 /* Now foundstack_start and foundstack_size should delimit the stack. */
800 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000801 args_grok_error("Cannot determine stack segment "
802 "from /proc/self/maps");
803 }
sewardj1c1b1162003-02-23 01:25:51 +0000804
805 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000806 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000807 VG_(foundstack_start),
808 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000809
sewardj49e630d2003-04-23 21:18:52 +0000810 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000811 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
812 args_grok_error("Stack segment is not page aligned?!");
813 }
sewardj1c1b1162003-02-23 01:25:51 +0000814
sewardj53fe4582003-02-23 01:41:17 +0000815 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
816 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000817
sewardj38170912002-05-10 21:07:22 +0000818 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000819 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000820 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000821 sp--;
822 }
sewardj38170912002-05-10 21:07:22 +0000823
824 if (sp[2] == VKI_AT_BASE
825 && sp[0] == VKI_AT_PAGESZ
826 && sp[-2] == VKI_AT_PHNUM
827 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000828 && sp[-6] == VKI_AT_PHDR
829 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000830 if (0)
831 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000832 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000833 } else
834 if (sp[2] == VKI_AT_CLKTCK
835 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000836 && sp[-2] == VKI_AT_HWCAP
837 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000838 if (0)
839 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
840 sp -= 2;
841 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000842 if (sp[2] == VKI_AT_CLKTCK
843 && sp[0] == VKI_AT_PAGESZ
844 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000845 && sp[-4] == VKI_AT_SYSINFO
846 && sp[-4-1] == 0) {
847 if (0)
848 VG_(printf)("Looks like you've got a 2.4.X kernel with "
849 "a sysinfo page at %x here.\n", sp[-3]);
850 VG_(sysinfo_page_exists) = True;
851 VG_(sysinfo_page_addr) = sp[-3];
852 sp -= 4;
853 } else
854 if (sp[2] == VKI_AT_CLKTCK
855 && sp[0] == VKI_AT_PAGESZ
856 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000857 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
858 && sp[-4-1] == 0) {
859 if (0)
860 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
861 "kernel here.\n");
862 sp -= 4;
863 } else
864 if (sp[2] == VKI_AT_CLKTCK
865 && sp[0] == VKI_AT_PAGESZ
866 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000867 && sp[-2-20-1] == 0) {
868 if (0)
869 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
870 sp -= 22;
871 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000872 if (sp[2] == VKI_AT_CLKTCK
873 && sp[0] == VKI_AT_PAGESZ
874 && sp[-2] == VKI_AT_HWCAP
875 && sp[-4-1] == 0) {
876 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000877 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000878 sp -= 4;
879 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000880 if (sp[2] == VKI_AT_CLKTCK
881 && sp[0] == VKI_AT_PAGESZ
882 && sp[-2] == VKI_AT_HWCAP
883 && sp[-6] == VKI_AT_SYSINFO
884 && sp[-6-1] == 0) {
885 if (0)
886 VG_(printf)("Looks like a >= 2.5.68 kernel with "
887 "a sysinfo page at %x here.\n", sp[-5]);
888 VG_(sysinfo_page_exists) = True;
889 VG_(sysinfo_page_addr) = sp[-5];
890 sp -= 6;
891 } else
sewardja1679dd2002-05-10 22:31:40 +0000892 args_grok_error(
893 "ELF frame does not look like 2.2.X or 2.4.X.\n "
894 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
895 );
sewardj38170912002-05-10 21:07:22 +0000896
897 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000898 if (*sp != 0)
899 args_grok_error("can't find NULL at end of env[]");
900
sewardj38170912002-05-10 21:07:22 +0000901 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000902 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000903 while (True) {
904 sp --;
905 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000906 if (++ctr >= 1000)
907 args_grok_error(
908 "suspiciously many (1000) env[] entries; giving up");
909
sewardj38170912002-05-10 21:07:22 +0000910 }
911 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000912 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000913
sewardja1679dd2002-05-10 22:31:40 +0000914 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000915 VG_(client_argc) = 0;
916 while (True) {
917 sp--;
918 if (*sp == VG_(client_argc))
919 break;
920 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000921 if (++ctr >= 1000)
922 args_grok_error(
923 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000924 }
925
sewardja1679dd2002-05-10 22:31:40 +0000926 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000927 }
928
sewardjde4a1d02002-03-22 01:27:54 +0000929 /* Now that VG_(client_envp) has been set, we can extract the args
930 for Valgrind itself. Copy into global var so that we don't have to
931 write zeroes to the getenv'd value itself. */
932 str = VG_(getenv)("VG_ARGS");
933 argc = 0;
934
935 if (!str) {
936 config_error("Can't read options from env var VG_ARGS.");
937 }
938
939 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
940 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
941 }
942 VG_(strcpy)(vg_cmdline_copy, str);
943 str = NULL;
944
945 p = &vg_cmdline_copy[0];
946 while (True) {
947 while (ISSPACE(*p)) { *p = 0; p++; }
948 if (*p == 0) break;
949 if (argc < M_VG_CMDLINE_OPTS-1) {
950 argv[argc] = p; argc++;
951 } else {
952 config_error(
953 "Found more than M_CMDLINE_OPTS command-line opts.");
954 }
955 while (*p != 0 && !ISSPACE(*p)) p++;
956 }
957
958 for (i = 0; i < argc; i++) {
959
njn43c799e2003-04-08 00:08:52 +0000960 if (VG_CLO_STREQ(argv[i], "-v") ||
961 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000962 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000963 else if (VG_CLO_STREQ(argv[i], "-q") ||
964 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000965 VG_(clo_verbosity)--;
966
njn43c799e2003-04-08 00:08:52 +0000967 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000968 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000969 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000970 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000971
njn43c799e2003-04-08 00:08:52 +0000972 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000973 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000974 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000975 VG_(clo_GDB_attach) = False;
976
sewardj6024b212003-07-13 10:54:33 +0000977 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
978 VG_(clo_GDB_path) = &argv[i][11];
979
njn43c799e2003-04-08 00:08:52 +0000980 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
981 VG_(clo_gen_suppressions) = True;
982 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
983 VG_(clo_gen_suppressions) = False;
984
nethercote77eba602003-11-13 17:35:04 +0000985 else if (VG_CLO_STREQ(argv[i], "--show-below-main=yes"))
986 VG_(clo_show_below_main) = True;
987 else if (VG_CLO_STREQ(argv[i], "--show-below-main=no"))
988 VG_(clo_show_below_main) = False;
989
njn43c799e2003-04-08 00:08:52 +0000990 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000991 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000992 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000993 VG_(clo_demangle) = False;
994
njn43c799e2003-04-08 00:08:52 +0000995 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000996 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000997 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000998 VG_(clo_trace_children) = False;
999
njn43c799e2003-04-08 00:08:52 +00001000 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001001 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +00001002 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001003 VG_(clo_run_libc_freeres) = False;
1004
rjwalshf5f536f2003-11-17 17:45:00 +00001005 else if (VG_CLO_STREQ(argv[i], "--track-fds=yes"))
1006 VG_(clo_track_fds) = True;
1007 else if (VG_CLO_STREQ(argv[i], "--track-fds=no"))
1008 VG_(clo_track_fds) = False;
1009
njn43c799e2003-04-08 00:08:52 +00001010 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +00001011 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
1012
njn43c799e2003-04-08 00:08:52 +00001013 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001014 VG_(clo_log_to) = VgLogTo_Fd;
1015 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001016 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +00001017 }
1018
njn43c799e2003-04-08 00:08:52 +00001019 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001020 VG_(clo_log_to) = VgLogTo_File;
1021 VG_(clo_logfile_name) = &argv[i][10];
1022 }
sewardjde4a1d02002-03-22 01:27:54 +00001023
njn43c799e2003-04-08 00:08:52 +00001024 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001025 VG_(clo_log_to) = VgLogTo_Socket;
1026 VG_(clo_logfile_name) = &argv[i][12];
1027 }
1028
sewardj6024b212003-07-13 10:54:33 +00001029 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
1030 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
1031
njn43c799e2003-04-08 00:08:52 +00001032 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001033 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001034 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001035 VG_(message)(Vg_UserMsg,
1036 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +00001037 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001038 }
1039 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
1040 VG_(clo_n_suppressions)++;
1041 }
njn43c799e2003-04-08 00:08:52 +00001042 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001043 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +00001044 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001045 VG_(clo_profile) = False;
1046
njn43c799e2003-04-08 00:08:52 +00001047 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001048 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +00001049 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001050 VG_(clo_chain_bb) = False;
1051
njn43c799e2003-04-08 00:08:52 +00001052 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001053 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +00001054 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001055 VG_(clo_single_step) = False;
1056
njn43c799e2003-04-08 00:08:52 +00001057 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001058 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +00001059 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001060 VG_(clo_optimise) = False;
1061
njn25e49d8e72002-09-23 09:36:25 +00001062 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +00001063 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001064 Int j;
1065 char* opt = & argv[i][16];
1066
1067 if (5 != VG_(strlen)(opt)) {
1068 VG_(message)(Vg_UserMsg,
1069 "--trace-codegen argument must have 5 digits");
1070 VG_(bad_option)(argv[i]);
1071 }
1072 for (j = 0; j < 5; j++) {
1073 if ('0' == opt[j]) { /* do nothing */ }
1074 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1075 else {
1076 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1077 "contain 0s and 1s");
1078 VG_(bad_option)(argv[i]);
1079 }
1080 }
1081 }
sewardjde4a1d02002-03-22 01:27:54 +00001082
njn43c799e2003-04-08 00:08:52 +00001083 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001084 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001085 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001086 VG_(clo_trace_syscalls) = False;
1087
njn43c799e2003-04-08 00:08:52 +00001088 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001089 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001090 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001091 VG_(clo_trace_signals) = False;
1092
njn43c799e2003-04-08 00:08:52 +00001093 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001094 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001095 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001096 VG_(clo_trace_symtab) = False;
1097
njn43c799e2003-04-08 00:08:52 +00001098 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001099 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001100 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001101 VG_(clo_trace_sched) = False;
1102
njn43c799e2003-04-08 00:08:52 +00001103 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001104 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001105 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001106 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001107 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001108 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001109
njn43c799e2003-04-08 00:08:52 +00001110 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001111 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001112
jsgf855d93d2003-10-13 22:26:55 +00001113 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
1114 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
1115
1116 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
1117 VG_(clo_lowlat_signals) = True;
1118 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
1119 VG_(clo_lowlat_signals) = False;
1120
1121 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
1122 VG_(clo_lowlat_syscalls) = True;
1123 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
1124 VG_(clo_lowlat_syscalls) = False;
1125
fitzhardinge89f9a322003-10-30 07:25:59 +00001126 else if (VG_CLO_STREQ(argv[i], "--assume-2.4=yes"))
1127 VG_(clo_assume_24) = True;
1128 else if (VG_CLO_STREQ(argv[i], "--assume-2.4=no"))
1129 VG_(clo_assume_24) = False;
1130
njn43c799e2003-04-08 00:08:52 +00001131 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001132 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1133
njn43c799e2003-04-08 00:08:52 +00001134 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001135 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1136
jsgf855d93d2003-10-13 22:26:55 +00001137 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
1138 VG_(clo_wait_for_gdb) = True;
1139 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
1140 VG_(clo_wait_for_gdb) = False;
1141
njn43c799e2003-04-08 00:08:52 +00001142 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001143 /* Make sure it's sane. */
1144 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +00001145 if (VG_(clo_backtrace_size) < 1)
1146 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001147 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1148 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1149 }
1150
njn25e49d8e72002-09-23 09:36:25 +00001151 else if (VG_(needs).command_line_options) {
1152 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1153 if (!ok)
1154 usage();
1155 }
sewardjde4a1d02002-03-22 01:27:54 +00001156 else
njn25e49d8e72002-09-23 09:36:25 +00001157 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001158 }
1159
1160# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001161
njnf9ebf672003-05-12 21:41:30 +00001162 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001163 VG_(clo_verbosity) = 0;
1164
1165 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1166 VG_(message)(Vg_UserMsg, "");
1167 VG_(message)(Vg_UserMsg,
1168 "--gdb-attach=yes conflicts with --trace-children=yes");
1169 VG_(message)(Vg_UserMsg,
1170 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001171 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001172 }
1173
sewardj4cf05692002-10-27 20:28:29 +00001174 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1175 should be connected to whatever sink has been selected, and we
1176 indiscriminately chuck stuff into it without worrying what the
1177 nature of it is. Oh the wonder of Unix streams. */
1178
1179 /* So far we should be still attached to stderr, so we can show on
1180 the terminal any problems to do with processing command line
1181 opts. */
1182 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001183 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001184
1185 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001186
sewardj4cf05692002-10-27 20:28:29 +00001187 case VgLogTo_Fd:
1188 vg_assert(VG_(clo_logfile_name) == NULL);
1189 VG_(clo_logfile_fd) = eventually_logfile_fd;
1190 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001191
sewardj4cf05692002-10-27 20:28:29 +00001192 case VgLogTo_File: {
1193 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001194 Int seq = 0;
1195 Int pid = VG_(getpid)();
1196
sewardj4cf05692002-10-27 20:28:29 +00001197 vg_assert(VG_(clo_logfile_name) != NULL);
1198 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001199
1200 for(;;) {
1201 if (seq == 0)
1202 VG_(sprintf)(logfilename, "%s.pid%d",
1203 VG_(clo_logfile_name), pid );
1204 else
1205 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1206 VG_(clo_logfile_name), pid, seq );
1207 seq++;
1208
1209 eventually_logfile_fd
1210 = VG_(open)(logfilename,
1211 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1212 VKI_S_IRUSR|VKI_S_IWUSR);
1213 if (eventually_logfile_fd >= 0) {
1214 VG_(clo_logfile_fd) = eventually_logfile_fd;
1215 break;
1216 } else {
1217 if (eventually_logfile_fd != -VKI_EEXIST) {
1218 VG_(message)(Vg_UserMsg,
1219 "Can't create/open log file `%s.pid%d'; giving up!",
1220 VG_(clo_logfile_name), pid);
1221 VG_(bad_option)(
1222 "--logfile=<file> didn't work out for some reason.");
1223 break;
1224 }
1225 }
1226 }
sewardj4cf05692002-10-27 20:28:29 +00001227 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001228 }
1229
1230 case VgLogTo_Socket: {
1231 vg_assert(VG_(clo_logfile_name) != NULL);
1232 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1233 eventually_logfile_fd
1234 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1235 if (eventually_logfile_fd == -1) {
1236 VG_(message)(Vg_UserMsg,
1237 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1238 VG_(message)(Vg_UserMsg,
1239 "of `%s'; giving up!", VG_(clo_logfile_name) );
1240 VG_(bad_option)(
1241 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001242 }
sewardj73cf3bc2002-11-03 03:20:15 +00001243 if (eventually_logfile_fd == -2) {
1244 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001245 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001246 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001247 VG_(message)(Vg_UserMsg,
1248 "Log messages will sent to stderr instead." );
1249 VG_(message)(Vg_UserMsg,
1250 "" );
1251 /* We don't change anything here. */
1252 } else {
1253 vg_assert(eventually_logfile_fd > 0);
1254 VG_(clo_logfile_fd) = eventually_logfile_fd;
1255 VG_(logging_to_filedes) = False;
1256 }
sewardj73cf3bc2002-11-03 03:20:15 +00001257 break;
1258 }
1259
sewardj4cf05692002-10-27 20:28:29 +00001260 }
1261
jsgf855d93d2003-10-13 22:26:55 +00001262 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
1263 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_MAX_FD+1);
1264 if (eventually_logfile_fd < 0)
1265 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1266 else {
1267 VG_(clo_logfile_fd) = eventually_logfile_fd;
1268 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1269 }
1270
sewardj4cf05692002-10-27 20:28:29 +00001271 /* Ok, the logging sink is running now. Print a suitable preamble.
1272 If logging to file or a socket, write details of parent PID and
1273 command line args, to help people trying to interpret the
1274 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001275
sewardj83adf412002-05-01 01:25:45 +00001276 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001277 /* Skin details */
1278 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1279 VG_(details).name,
1280 NULL == VG_(details).version ? "" : "-",
1281 NULL == VG_(details).version
1282 ? (Char*)"" : VG_(details).version,
1283 VG_(details).description);
1284 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001285
njnd04b7c62002-10-03 14:05:52 +00001286 /* Core details */
1287 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001288 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001289 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001290 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001291 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001292 }
1293
nethercotec1e395d2003-11-10 13:26:49 +00001294 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001295 VG_(message)(Vg_UserMsg, "");
1296 VG_(message)(Vg_UserMsg,
1297 "My PID = %d, parent PID = %d. Prog and args are:",
1298 VG_(getpid)(), VG_(getppid)() );
1299 for (i = 0; i < VG_(client_argc); i++)
1300 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1301 }
1302
sewardjde4a1d02002-03-22 01:27:54 +00001303 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001304 if (VG_(clo_log_to) != VgLogTo_Fd)
1305 VG_(message)(Vg_UserMsg, "");
njn86dc2bc2003-09-09 07:26:21 +00001306 VG_(message)(Vg_UserMsg, "Command line");
1307 for (i = 0; i < VG_(client_argc); i++)
1308 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1309
sewardjde4a1d02002-03-22 01:27:54 +00001310 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1311 for (i = 0; i < argc; i++) {
1312 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1313 }
1314 }
1315
njn25e49d8e72002-09-23 09:36:25 +00001316 if (VG_(clo_n_suppressions) == 0 &&
1317 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001318 config_error("No error-suppression files were specified.");
1319 }
sewardj4cf05692002-10-27 20:28:29 +00001320
njn6a230532003-07-21 10:38:23 +00001321 if (VG_(clo_gen_suppressions) &&
1322 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1323 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1324 " as it doesn't generate errors.");
1325 }
1326
sewardjde4a1d02002-03-22 01:27:54 +00001327}
1328
sewardjde4a1d02002-03-22 01:27:54 +00001329/* ---------------------------------------------------------------------
1330 Copying to/from m_state_static.
1331 ------------------------------------------------------------------ */
1332
sewardjb91ae7f2003-04-29 23:50:00 +00001333/* See comment about this in vg_include.h. Change only with
1334 great care.
1335*/
1336__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001337UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1338 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001339 + 1 /* %eflags */
1340 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001341 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001342 ];
1343
sewardjfa492d42002-12-08 18:20:01 +00001344UInt VG_(insertDflag)(UInt eflags, Int d)
1345{
1346 vg_assert(d == 1 || d == -1);
1347 eflags &= ~EFlagD;
1348
1349 if (d < 0)
1350 eflags |= EFlagD;
1351
1352 return eflags;
1353}
1354
1355Int VG_(extractDflag)(UInt eflags)
1356{
1357 Int ret;
1358
1359 if (eflags & EFlagD)
1360 ret = -1;
1361 else
1362 ret = 1;
1363
1364 return ret;
1365}
1366
sewardjde4a1d02002-03-22 01:27:54 +00001367void VG_(copy_baseBlock_to_m_state_static) ( void )
1368{
1369 Int i;
sewardj92a59562002-09-30 00:53:10 +00001370 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1371 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1372 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1373 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1374 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1375 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001376
sewardj92a59562002-09-30 00:53:10 +00001377 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1378 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1379 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1380 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1381 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1382 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1383 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1384 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1385
sewardjb91ae7f2003-04-29 23:50:00 +00001386 VG_(m_state_static)[56/4]
1387 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1388 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001389 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001390
sewardjb91ae7f2003-04-29 23:50:00 +00001391 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001392 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001393 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001394}
1395
1396
1397void VG_(copy_m_state_static_to_baseBlock) ( void )
1398{
1399 Int i;
sewardj92a59562002-09-30 00:53:10 +00001400 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1401 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1402 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1403 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1404 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1405 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001406
sewardj92a59562002-09-30 00:53:10 +00001407 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1408 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1409 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1410 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1411 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1412 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1413 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1414 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1415
sewardjb91ae7f2003-04-29 23:50:00 +00001416 VG_(baseBlock)[VGOFF_(m_eflags)]
1417 = VG_(m_state_static)[56/4] & ~EFlagD;
1418 VG_(baseBlock)[VGOFF_(m_dflag)]
1419 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001420
sewardj92a59562002-09-30 00:53:10 +00001421 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001422
sewardjb91ae7f2003-04-29 23:50:00 +00001423 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1424 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001425 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001426}
1427
njn25e49d8e72002-09-23 09:36:25 +00001428Addr VG_(get_stack_pointer) ( void )
1429{
1430 return VG_(baseBlock)[VGOFF_(m_esp)];
1431}
1432
1433/* Some random tests needed for leak checking */
1434
1435Bool VG_(within_stack)(Addr a)
1436{
1437 if (a >= ((Addr)(&VG_(stack)))
1438 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1439 return True;
1440 else
1441 return False;
1442}
1443
sewardjecf8e102003-07-12 12:11:39 +00001444Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001445{
1446 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001447 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001448 return True;
sewardjecf8e102003-07-12 12:11:39 +00001449
1450 if (a >= ((Addr)(&VG_(threads)[0]))
1451 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1452 return True;
1453
1454 return False;
njn25e49d8e72002-09-23 09:36:25 +00001455}
sewardjde4a1d02002-03-22 01:27:54 +00001456
1457/* ---------------------------------------------------------------------
1458 Show accumulated counts.
1459 ------------------------------------------------------------------ */
1460
njn25e49d8e72002-09-23 09:36:25 +00001461static __inline__ Int safe_idiv(Int a, Int b)
1462{
1463 return (b == 0 ? 0 : a / b);
1464}
1465
sewardjde4a1d02002-03-22 01:27:54 +00001466static void vg_show_counts ( void )
1467{
1468 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001469 " TT/TC: %d tc sectors discarded.",
1470 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001471 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001472 " %d chainings, %d unchainings.",
1473 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1474 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001475 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001476 VG_(overall_in_count),
1477 VG_(overall_in_osize),
1478 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001479 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1480 VG_(message)(Vg_DebugMsg,
1481 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001482 VG_(overall_out_count),
1483 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001484 VG_(overall_out_tsize),
1485 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001486 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001487 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001488 VG_(bbs_done),
1489 VG_(unchained_jumps_done),
1490 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1491 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1492 );
1493
1494 VG_(message)(Vg_DebugMsg,
1495 " %d/%d major/minor sched events. %d tt_fast misses.",
1496 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001497 VG_(num_scheduling_events_MINOR),
1498 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001499
sewardjde4a1d02002-03-22 01:27:54 +00001500 VG_(message)(Vg_DebugMsg,
1501 "reg-alloc: %d t-req-spill, "
1502 "%d+%d orig+spill uis, %d total-reg-r.",
1503 VG_(translations_needing_spill),
1504 VG_(uinstrs_prealloc),
1505 VG_(uinstrs_spill),
1506 VG_(total_reg_rank) );
1507 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001508 " sanity: %d cheap, %d expensive checks.",
1509 VG_(sanity_fast_count),
1510 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001511 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001512}
1513
1514
1515/* ---------------------------------------------------------------------
1516 Main!
1517 ------------------------------------------------------------------ */
1518
jsgf855d93d2003-10-13 22:26:55 +00001519/* Initialize the PID and PGRP of scheduler LWP; this is also called
1520 in any new children after fork. */
1521static void newpid(ThreadId unused)
1522{
1523 /* PID of scheduler LWP */
1524 VG_(main_pid) = VG_(getpid)();
1525 VG_(main_pgrp) = VG_(getpgrp)();
1526}
1527
sewardjde4a1d02002-03-22 01:27:54 +00001528/* Where we jump to once Valgrind has got control, and the real
1529 machine's state has been copied to the m_state_static. */
1530
1531void VG_(main) ( void )
1532{
sewardj2e93c502002-04-12 11:12:52 +00001533 Int i;
1534 VgSchedReturnCode src;
sewardjde4a1d02002-03-22 01:27:54 +00001535
njn0c7a5b52003-04-30 09:00:33 +00001536 if (0) {
1537 if (VG_(have_ssestate))
1538 VG_(printf)("Looks like a SSE-capable CPU\n");
1539 else
1540 VG_(printf)("Looks like a MMX-only CPU\n");
1541 }
sewardjb91ae7f2003-04-29 23:50:00 +00001542
njn27f1a382002-11-08 15:48:16 +00001543 /* Check skin and core versions are compatible */
1544 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1545 VG_(printf)("Error:\n"
nethercote137bc552003-11-14 17:47:54 +00001546 " Tool and core interface versions do not match.\n"
njn27f1a382002-11-08 15:48:16 +00001547 " Interface version used by core is: %d.%d\n"
nethercote137bc552003-11-14 17:47:54 +00001548 " Interface version used by tool is: %d.%d\n"
njn27f1a382002-11-08 15:48:16 +00001549 " The major version numbers must match.\n",
1550 VG_CORE_INTERFACE_MAJOR_VERSION,
1551 VG_CORE_INTERFACE_MINOR_VERSION,
1552 VG_(skin_interface_major_version),
1553 VG_(skin_interface_minor_version));
1554 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1555 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1556 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1557 else
1558 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1559 VG_(printf)(" Aborting, sorry.\n");
1560 VG_(exit)(1);
1561 }
1562
jsgf855d93d2003-10-13 22:26:55 +00001563 VG_(atfork)(NULL, NULL, newpid);
1564 newpid(VG_INVALID_THREADID);
1565
sewardjde4a1d02002-03-22 01:27:54 +00001566 /* Set up our stack sanity-check words. */
1567 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001568 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1569 VG_(stack)[VG_STACK_SIZE_W-1-i]
1570 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001571 }
1572
njn3e884182003-04-15 13:03:23 +00001573 /* Read /proc/self/maps into a buffer. Must be before:
1574 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1575 superblocks are not erroneously identified as being owned by the
1576 client, which would be bad.
1577 - init_memory(): that's where the buffer is parsed
1578 - init_tt_tc(): so the anonymous mmaps for the translation table and
1579 translation cache aren't identified as part of the client, which would
1580 waste > 20M of virtual address space, and be bad.
1581 */
njnfa1016e2003-09-25 17:54:11 +00001582 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001583
njn25e49d8e72002-09-23 09:36:25 +00001584 /* Setup stuff that depends on the skin. Must be before:
1585 - vg_init_baseBlock(): to register helpers
1586 - process_cmd_line_options(): to register skin name and description,
1587 and turn on/off 'command_line_options' need
1588 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001589 */
njn810086f2002-11-14 12:42:47 +00001590 SK_(pre_clo_init)();
1591 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001592
njncc7bb472002-10-14 09:25:19 +00001593 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001594 process_cmd_line_options();
1595
jsgf855d93d2003-10-13 22:26:55 +00001596 /* Hook to delay things long enough so we can get the pid and
1597 attach GDB in another shell. */
1598 if (VG_(clo_wait_for_gdb)) {
1599 VG_(printf)("pid=%d\n", VG_(getpid)());
1600 /* do "jump *$eip" to skip this in gdb */
1601 VG_(do_syscall)(__NR_pause);
1602 }
1603
njn3e884182003-04-15 13:03:23 +00001604 /* Do post command-line processing initialisation. Must be before:
1605 - vg_init_baseBlock(): to register any more helpers
1606 */
njncc7bb472002-10-14 09:25:19 +00001607 SK_(post_clo_init)();
1608
njn3e884182003-04-15 13:03:23 +00001609 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001610 vg_init_baseBlock();
1611
rjwalshf5f536f2003-11-17 17:45:00 +00001612 /* Search for file descriptors that are inherited from our parent. */
1613 if (VG_(clo_track_fds))
1614 VG_(init_preopened_fds)();
1615
sewardj018f7622002-05-15 21:13:39 +00001616 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001617 baseBlock into VG_(threads)[1]. Must be before:
1618 - VG_(sigstartup_actions)()
1619 */
sewardj018f7622002-05-15 21:13:39 +00001620 VG_(scheduler_init)();
1621
jsgf855d93d2003-10-13 22:26:55 +00001622 /* Set up the ProxyLWP machinery */
1623 VG_(proxy_init)();
1624
sewardj018f7622002-05-15 21:13:39 +00001625 /* Initialise the signal handling subsystem, temporarily parking
1626 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001627 VG_(sigstartup_actions)();
1628
sewardj018f7622002-05-15 21:13:39 +00001629 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001630 if (VG_(clo_profile))
1631 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001632
sewardj5f07b662002-04-23 16:52:51 +00001633 /* Start calibration of our RDTSC-based clock. */
1634 VG_(start_rdtsc_calibration)();
1635
njn3e884182003-04-15 13:03:23 +00001636 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001637 VGP_PUSHCC(VgpInitMem);
1638 VG_(init_memory)();
1639 VGP_POPCC(VgpInitMem);
1640
1641 /* Read the list of errors to suppress. This should be found in
1642 the file specified by vg_clo_suppressions. */
1643 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1644 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001645
sewardj5f07b662002-04-23 16:52:51 +00001646 /* End calibration of our RDTSC-based clock, leaving it as long as
1647 we can. */
1648 VG_(end_rdtsc_calibration)();
1649
njn3e884182003-04-15 13:03:23 +00001650 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001651 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001652
1653 if (VG_(clo_verbosity) == 1) {
1654 VG_(message)(Vg_UserMsg,
1655 "For more details, rerun with: -v");
1656 }
1657
sewardj25c7c3a2003-07-10 00:17:58 +00001658 /* Force a read of the debug info so that we can look for
1659 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001660 VG_(setup_code_redirect_table)();
1661
sewardjde4a1d02002-03-22 01:27:54 +00001662 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1663 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001664 if (VG_(clo_verbosity) > 0)
1665 VG_(message)(Vg_UserMsg, "");
1666
1667 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001668
sewardj018f7622002-05-15 21:13:39 +00001669 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001670 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001671 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001672
1673 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1674 VG_(fatal_signal_set) = True;
1675 src = VG_(scheduler)();
1676 } else
1677 src = VgSrc_FatalSig;
1678
njn25e49d8e72002-09-23 09:36:25 +00001679 VGP_POPCC(VgpSched);
1680 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001681
1682 if (VG_(clo_verbosity) > 0)
1683 VG_(message)(Vg_UserMsg, "");
1684
sewardj2e93c502002-04-12 11:12:52 +00001685 if (src == VgSrc_Deadlock) {
1686 VG_(message)(Vg_UserMsg,
1687 "Warning: pthread scheduler exited due to deadlock");
1688 }
1689
rjwalshf5f536f2003-11-17 17:45:00 +00001690 /* Print out file descriptor summary and stats. */
1691 if(VG_(clo_track_fds))
1692 VG_(fd_stats)();
1693
njn25e49d8e72002-09-23 09:36:25 +00001694 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001695 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001696
njn7d9f94d2003-04-22 21:41:40 +00001697 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001698
sewardj0c3b53f2002-05-01 01:58:35 +00001699 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001700
1701 if (VG_(clo_verbosity) > 1)
1702 vg_show_counts();
1703
sewardjc0d8f682002-11-30 00:49:43 +00001704 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001705 VG_(print_UInstr_histogram)();
1706
sewardjde4a1d02002-03-22 01:27:54 +00001707 if (0) {
1708 VG_(message)(Vg_DebugMsg, "");
1709 VG_(message)(Vg_DebugMsg,
1710 "------ Valgrind's internal memory use stats follow ------" );
1711 VG_(mallocSanityCheckAll)();
1712 VG_(show_all_arena_stats)();
1713 VG_(message)(Vg_DebugMsg,
1714 "------ Valgrind's ExeContext management stats follow ------" );
1715 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001716 }
1717
njn25e49d8e72002-09-23 09:36:25 +00001718 if (VG_(clo_profile))
1719 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001720
1721 VG_(shutdown_logging)();
1722
sewardj3e1eb1f2002-05-18 13:14:17 +00001723 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1724 processes don't get traced into. Also mess up $libdir/valgrind
1725 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001726 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1727 pointless when we are just about to VgSrc_ExitSyscall. So don't
1728 bother in that case. */
1729 if ((!VG_(clo_trace_children))
1730 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001731 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1732 VG_(getenv)("LD_PRELOAD"),
1733 VG_(getenv)("LD_LIBRARY_PATH")
1734 );
sewardjde4a1d02002-03-22 01:27:54 +00001735 }
1736
jsgf855d93d2003-10-13 22:26:55 +00001737 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1738 vg_assert(src == VgSrc_FatalSig ||
1739 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1740 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1741 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1742
sewardj7e87e382002-05-03 19:09:05 +00001743 /* Decide how to exit. This depends on what the scheduler
1744 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001745
sewardj7e87e382002-05-03 19:09:05 +00001746 switch (src) {
1747 case VgSrc_ExitSyscall: /* the normal way out */
1748 vg_assert(VG_(last_run_tid) > 0
1749 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001750 VG_(proxy_shutdown)();
1751
njn25e49d8e72002-09-23 09:36:25 +00001752 /* The thread's %EBX at the time it did __NR_exit() will hold
1753 the arg to __NR_exit(), so we just do __NR_exit() with
1754 that arg. */
1755 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001756 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001757 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001758 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001759
sewardj7e87e382002-05-03 19:09:05 +00001760 case VgSrc_Deadlock:
1761 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001762 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001763 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001764 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001765 break;
1766
1767 case VgSrc_BbsDone:
1768 /* Tricky; we have to try and switch back to the real CPU.
1769 This is all very dodgy and won't work at all in the
1770 presence of threads, or if the client happened to be
1771 running a signal handler. */
1772 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001773 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001774 VG_(load_thread_state)(1 /* root thread */ );
1775 VG_(copy_baseBlock_to_m_state_static)();
1776
jsgf855d93d2003-10-13 22:26:55 +00001777 VG_(proxy_shutdown)();
1778
sewardj7e87e382002-05-03 19:09:05 +00001779 /* This pushes a return address on the simulator's stack,
1780 which is abandoned. We call vg_sigshutdown_actions() at
1781 the end of vg_switch_to_real_CPU(), so as to ensure that
1782 the original stack and machine state is restored before
1783 the real signal mechanism is restored. */
1784 VG_(switch_to_real_CPU)();
1785
jsgf855d93d2003-10-13 22:26:55 +00001786 case VgSrc_FatalSig:
1787 /* We were killed by a fatal signal, so replicate the effect */
1788 vg_assert(VG_(fatal_sigNo) != -1);
1789 VG_(kill_self)(VG_(fatal_sigNo));
1790 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1791 break;
1792
sewardj7e87e382002-05-03 19:09:05 +00001793 default:
njne427a662002-10-02 11:08:25 +00001794 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001795 }
sewardjde4a1d02002-03-22 01:27:54 +00001796}
1797
1798
1799/* Debugging thing .. can be called from assembly with OYNK macro. */
1800void VG_(oynk) ( Int n )
1801{
1802 OINK(n);
1803}
1804
1805
1806/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1807 "valgrinq.so", which doesn't do anything. This is used to avoid
1808 tracing into child processes. To make this work the build system
1809 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001810
njn25e49d8e72002-09-23 09:36:25 +00001811 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1812 without it, child processes try to find valgrind.so symbols in the
1813 skin .so.
1814
sewardj78e25c92002-05-20 23:38:33 +00001815 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1816 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1817 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001818*/
sewardj45b672d2003-07-25 19:58:11 +00001819static void slideleft ( Char* s )
1820{
1821 vg_assert(s && (*s == ' ' || *s == ':'));
1822 while (True) {
1823 s[0] = s[1];
1824 if (s[0] == '\0') break;
1825 s++;
1826 }
1827}
1828
1829
sewardj3e1eb1f2002-05-18 13:14:17 +00001830void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1831 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001832{
njn42e23f22003-05-05 12:47:25 +00001833 Char* vg_prel = NULL;
1834 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001835 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001836 Char* p;
1837 Char* coredir_first;
1838 Char* coredir_last;
1839 Int coredir_len;
1840 Int i;
1841 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001842
njn42e23f22003-05-05 12:47:25 +00001843#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001844
njn42e23f22003-05-05 12:47:25 +00001845 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001846
njn42e23f22003-05-05 12:47:25 +00001847 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1848
njnc2f5bb02003-07-23 09:40:50 +00001849 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1850 LD_LIBRARY_PATH = "<coredir>:Y" */
1851
njn42e23f22003-05-05 12:47:25 +00001852 /* Setting up, finding things */
1853
1854 /* LD_PRELOAD: Search for "valgrind.so" */
1855 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1856
1857 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001858 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001859 if (NULL == vg_prel) {
1860 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001861 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001862 }
1863
njnc2f5bb02003-07-23 09:40:50 +00001864 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001865 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001866
njn42e23f22003-05-05 12:47:25 +00001867 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1868 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1869 coredir_first = p+1;
1870 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001871 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001872
1873 /* LD_PRELOAD: find "vgskin_foo.so" */
1874 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1875 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001876
njnc2f5bb02003-07-23 09:40:50 +00001877 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001878 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001879 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1880 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001881 *coredir_last = '/'; /* Undo zero-termination */
1882
1883 /* Changing things */
1884
1885 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1886 if (vg_prel[7] != 'd') MUTANCY(6);
1887 vg_prel[7] = 'q';
1888
njnc2f5bb02003-07-23 09:40:50 +00001889 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1890 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1891 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001892 while (*p != ':' && p >= ld_preload_str) {
1893 *p = ' ';
1894 p--;
njn25e49d8e72002-09-23 09:36:25 +00001895 }
njnc2f5bb02003-07-23 09:40:50 +00001896 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1897 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001898 p = sk_prel;
1899 while (*p != ':' && *p != '\0') {
1900 *p = ' ';
1901 p++;
1902 }
1903 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001904
njnc2f5bb02003-07-23 09:40:50 +00001905 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001906 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001907 coredir2[i] = ' ';
sewardj45b672d2003-07-25 19:58:11 +00001908
1909 /* Zap the leading spaces and : in both strings. */
1910 while (ld_preload_str[0] == ' ') slideleft(ld_preload_str);
1911 if (ld_preload_str[0] == ':') slideleft(ld_preload_str);
1912
1913 while (ld_library_path_str[0] == ' ') slideleft(ld_library_path_str);
1914 if (ld_library_path_str[0] == ':') slideleft(ld_library_path_str);
1915
njn42e23f22003-05-05 12:47:25 +00001916 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001917
sewardj78e25c92002-05-20 23:38:33 +00001918 return;
1919
njn42e23f22003-05-05 12:47:25 +00001920
1921mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001922 VG_(printf)(
1923 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1924 " what = %d\n"
1925 " ld_preload_str = `%s'\n"
1926 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001927 " vg_prel = `%s'\n"
1928 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001929 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001930 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001931 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001932 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001933 );
sewardjc26b4482002-07-13 12:20:35 +00001934 VG_(printf)(
1935 "\n"
1936 "Note that this is often caused by mis-installation of valgrind.\n"
1937 "Correct installation procedure is:\n"
1938 " ./configure --prefix=/install/dir\n"
1939 " make install\n"
1940 "And then use /install/dir/bin/valgrind\n"
1941 "Moving the installation directory elsewhere after 'make install'\n"
1942 "will cause the above error. Hand-editing the paths in the shell\n"
1943 "scripts is also likely to cause problems.\n"
1944 "\n"
1945 );
njne427a662002-10-02 11:08:25 +00001946 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001947}
1948
sewardj3e1eb1f2002-05-18 13:14:17 +00001949
sewardjde4a1d02002-03-22 01:27:54 +00001950/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1951 it to attach to this process. Called if the user requests this
1952 service after an error has been shown, so she can poke around and
1953 look at parameters, memory, etc. You can't meaningfully get GDB to
1954 continue the program, though; to continue, quit GDB. */
1955extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1956{
sewardje6a25242002-04-21 22:03:07 +00001957 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001958 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001959
njn9315df32003-04-16 20:50:50 +00001960 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001961 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001962 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1963 res = VG_(system)(buf);
1964 if (res == 0) {
1965 VG_(message)(Vg_UserMsg, "");
1966 VG_(message)(Vg_UserMsg,
1967 "GDB has detached. Valgrind regains control. We continue.");
1968 } else {
1969 VG_(message)(Vg_UserMsg, "Apparently failed!");
1970 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001971 }
sewardjde4a1d02002-03-22 01:27:54 +00001972}
1973
1974
1975/* Print some helpful-ish text about unimplemented things, and give
1976 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001977void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001978{
1979 VG_(message)(Vg_UserMsg, "");
1980 VG_(message)(Vg_UserMsg,
1981 "Valgrind detected that your program requires");
1982 VG_(message)(Vg_UserMsg,
1983 "the following unimplemented functionality:");
1984 VG_(message)(Vg_UserMsg, " %s", msg);
1985 VG_(message)(Vg_UserMsg,
1986 "This may be because the functionality is hard to implement,");
1987 VG_(message)(Vg_UserMsg,
1988 "or because no reasonable program would behave this way,");
1989 VG_(message)(Vg_UserMsg,
1990 "or because nobody has yet needed it. In any case, let me know");
1991 VG_(message)(Vg_UserMsg,
1992 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1993 VG_(message)(Vg_UserMsg,
1994 "");
1995 VG_(message)(Vg_UserMsg,
1996 "Valgrind has to exit now. Sorry. Bye!");
1997 VG_(message)(Vg_UserMsg,
1998 "");
sewardj15a43e12002-04-17 19:35:12 +00001999 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00002000 VG_(exit)(1);
2001}
2002
2003
njn25e49d8e72002-09-23 09:36:25 +00002004/* ---------------------------------------------------------------------
2005 Sanity check machinery (permanently engaged).
2006 ------------------------------------------------------------------ */
2007
2008/* A fast sanity check -- suitable for calling circa once per
2009 millisecond. */
2010
2011void VG_(do_sanity_checks) ( Bool force_expensive )
2012{
2013 Int i;
2014
njn37cea302002-09-30 11:24:00 +00002015 VGP_PUSHCC(VgpCoreCheapSanity);
2016
njn25e49d8e72002-09-23 09:36:25 +00002017 if (VG_(sanity_level) < 1) return;
2018
2019 /* --- First do all the tests that we can do quickly. ---*/
2020
2021 VG_(sanity_fast_count)++;
2022
2023 /* Check that we haven't overrun our private stack. */
2024 for (i = 0; i < 10; i++) {
2025 vg_assert(VG_(stack)[i]
2026 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00002027 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
2028 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00002029 }
2030
2031 /* Check stuff pertaining to the memory check system. */
2032
2033 /* Check that nobody has spuriously claimed that the first or
2034 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002035 if (VG_(needs).sanity_checks) {
2036 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002037 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002038 VGP_POPCC(VgpSkinCheapSanity);
2039 }
njn25e49d8e72002-09-23 09:36:25 +00002040
2041 /* --- Now some more expensive checks. ---*/
2042
2043 /* Once every 25 times, check some more expensive stuff. */
2044 if ( force_expensive
2045 || VG_(sanity_level) > 1
2046 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2047
njn37cea302002-09-30 11:24:00 +00002048 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002049 VG_(sanity_slow_count)++;
2050
jsgf855d93d2003-10-13 22:26:55 +00002051 VG_(proxy_sanity)();
2052
njn25e49d8e72002-09-23 09:36:25 +00002053# if 0
2054 { void zzzmemscan(void); zzzmemscan(); }
2055# endif
2056
2057 if ((VG_(sanity_fast_count) % 250) == 0)
2058 VG_(sanity_check_tc_tt)();
2059
2060 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002061 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002062 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002063 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002064 }
2065 /*
2066 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2067 */
njn37cea302002-09-30 11:24:00 +00002068 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002069 }
2070
2071 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002072 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002073 /* Check sanity of the low-level memory manager. Note that bugs
2074 in the client's code can cause this to fail, so we don't do
2075 this check unless specially asked for. And because it's
2076 potentially very expensive. */
2077 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002078 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002079 }
njn37cea302002-09-30 11:24:00 +00002080 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002081}
sewardjde4a1d02002-03-22 01:27:54 +00002082/*--------------------------------------------------------------------*/
2083/*--- end vg_main.c ---*/
2084/*--------------------------------------------------------------------*/