blob: 91c0d1199e7fd7a77d4ed7e19b2bf59db190051f [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- C startup stuff, reached from vg_startup.S. ---*/
4/*--- vg_main.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32#include "vg_include.h"
sewardjde4a1d02002-03-22 01:27:54 +000033
34/* ---------------------------------------------------------------------
35 Compute offsets into baseBlock. See comments in vg_include.h.
36 ------------------------------------------------------------------ */
37
38/* The variables storing offsets. */
39
40#define INVALID_OFFSET (-1)
41
42Int VGOFF_(m_eax) = INVALID_OFFSET;
43Int VGOFF_(m_ecx) = INVALID_OFFSET;
44Int VGOFF_(m_edx) = INVALID_OFFSET;
45Int VGOFF_(m_ebx) = INVALID_OFFSET;
46Int VGOFF_(m_esp) = INVALID_OFFSET;
47Int VGOFF_(m_ebp) = INVALID_OFFSET;
48Int VGOFF_(m_esi) = INVALID_OFFSET;
49Int VGOFF_(m_edi) = INVALID_OFFSET;
50Int VGOFF_(m_eflags) = INVALID_OFFSET;
sewardjfa492d42002-12-08 18:20:01 +000051Int VGOFF_(m_dflag) = INVALID_OFFSET;
sewardjb91ae7f2003-04-29 23:50:00 +000052Int VGOFF_(m_ssestate) = INVALID_OFFSET;
sewardj92a59562002-09-30 00:53:10 +000053Int VGOFF_(ldt) = INVALID_OFFSET;
54Int VGOFF_(m_cs) = INVALID_OFFSET;
55Int VGOFF_(m_ss) = INVALID_OFFSET;
56Int VGOFF_(m_ds) = INVALID_OFFSET;
57Int VGOFF_(m_es) = INVALID_OFFSET;
58Int VGOFF_(m_fs) = INVALID_OFFSET;
59Int VGOFF_(m_gs) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000060Int VGOFF_(m_eip) = INVALID_OFFSET;
61Int VGOFF_(spillslots) = INVALID_OFFSET;
62Int VGOFF_(sh_eax) = INVALID_OFFSET;
63Int VGOFF_(sh_ecx) = INVALID_OFFSET;
64Int VGOFF_(sh_edx) = INVALID_OFFSET;
65Int VGOFF_(sh_ebx) = INVALID_OFFSET;
66Int VGOFF_(sh_esp) = INVALID_OFFSET;
67Int VGOFF_(sh_ebp) = INVALID_OFFSET;
68Int VGOFF_(sh_esi) = INVALID_OFFSET;
69Int VGOFF_(sh_edi) = INVALID_OFFSET;
70Int VGOFF_(sh_eflags) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +000071
sewardjde4a1d02002-03-22 01:27:54 +000072Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
73Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
74Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
75Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
76Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
77Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
78Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
79Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
80Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
81Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
82Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
83Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
84Int VGOFF_(helper_CLD) = INVALID_OFFSET;
85Int VGOFF_(helper_STD) = INVALID_OFFSET;
86Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
sewardj7d78e782002-06-02 00:04:00 +000087Int VGOFF_(helper_CLC) = INVALID_OFFSET;
88Int VGOFF_(helper_STC) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000089Int VGOFF_(helper_shldl) = INVALID_OFFSET;
90Int VGOFF_(helper_shldw) = INVALID_OFFSET;
91Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
92Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
daywalkerb18d2532003-09-27 20:15:01 +000093Int VGOFF_(helper_IN) = INVALID_OFFSET;
94Int VGOFF_(helper_OUT) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000095Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
96Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
97Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000098Int VGOFF_(helper_bsf) = INVALID_OFFSET;
99Int VGOFF_(helper_bsr) = INVALID_OFFSET;
100Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
101Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
njnd6251f12003-06-03 13:38:51 +0000102Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +0000103Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +0000104Int VGOFF_(helper_DAA) = INVALID_OFFSET;
sewardj51096432002-12-14 23:59:09 +0000105Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +0000106
107/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
108 * increased too much, they won't really be compact any more... */
109#define MAX_COMPACT_HELPERS 8
njnfedb7362003-02-24 10:21:45 +0000110#define MAX_NONCOMPACT_HELPERS 50
njn25e49d8e72002-09-23 09:36:25 +0000111
112UInt VG_(n_compact_helpers) = 0;
113UInt VG_(n_noncompact_helpers) = 0;
114
115Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
116Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
117Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
118Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
sewardjde4a1d02002-03-22 01:27:54 +0000119
120/* This is the actual defn of baseblock. */
121UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
122
jsgf855d93d2003-10-13 22:26:55 +0000123/* PID of the main thread */
124Int VG_(main_pid);
125
126/* PGRP of process */
127Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000128
sewardjde4a1d02002-03-22 01:27:54 +0000129/* Words. */
130static Int baB_off = 0;
131
jsgf855d93d2003-10-13 22:26:55 +0000132/* jmp_buf for fatal signals */
133Int VG_(fatal_sigNo) = -1;
134Bool VG_(fatal_signal_set) = False;
135jmp_buf VG_(fatal_signal_jmpbuf);
136
sewardjde4a1d02002-03-22 01:27:54 +0000137/* Returns the offset, in words. */
138static Int alloc_BaB ( Int words )
139{
140 Int off = baB_off;
141 baB_off += words;
142 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000143 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000144
145 return off;
146}
147
njn0c7a5b52003-04-30 09:00:33 +0000148/* Align offset, in *bytes* */
149static void align_BaB ( UInt align )
150{
151 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
152 baB_off += (align-1);
153 baB_off &= ~(align-1);
154}
155
sewardjde4a1d02002-03-22 01:27:54 +0000156/* Allocate 1 word in baseBlock and set it to the given value. */
daywalkerb106c422003-09-29 10:56:24 +0000157static Int alloc_BaB_1_set ( Addr a )
sewardjde4a1d02002-03-22 01:27:54 +0000158{
159 Int off = alloc_BaB(1);
160 VG_(baseBlock)[off] = (UInt)a;
161 return off;
162}
163
njn25e49d8e72002-09-23 09:36:25 +0000164/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000165 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000166void VG_(register_compact_helper)(Addr a)
167{
168 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
169 VG_(printf)("Can only register %d compact helpers\n",
170 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000171 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000172 }
173 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
174 VG_(n_compact_helpers)++;
175}
176
177/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
178 * is filled in later.
179 */
180void VG_(register_noncompact_helper)(Addr a)
181{
182 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
183 VG_(printf)("Can only register %d non-compact helpers\n",
184 MAX_NONCOMPACT_HELPERS);
185 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000186 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000187 }
188 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
189 VG_(n_noncompact_helpers)++;
190}
191
192/* Allocate offsets in baseBlock for the skin helpers */
sewardj05bcdcb2003-05-18 10:05:38 +0000193static
194void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
njn25e49d8e72002-09-23 09:36:25 +0000195{
sewardj05bcdcb2003-05-18 10:05:38 +0000196 UInt i;
197 for (i = 0; i < n; i++)
daywalkerb106c422003-09-29 10:56:24 +0000198 offsets[i] = alloc_BaB_1_set( addrs[i] );
njn25e49d8e72002-09-23 09:36:25 +0000199}
sewardjde4a1d02002-03-22 01:27:54 +0000200
njnf4ce3d32003-02-10 10:17:26 +0000201Bool VG_(need_to_handle_esp_assignment)(void)
202{
njn9b007f62003-04-07 14:40:25 +0000203 return ( VG_(track_events).new_mem_stack_4 ||
204 VG_(track_events).die_mem_stack_4 ||
205 VG_(track_events).new_mem_stack_8 ||
206 VG_(track_events).die_mem_stack_8 ||
207 VG_(track_events).new_mem_stack_12 ||
208 VG_(track_events).die_mem_stack_12 ||
209 VG_(track_events).new_mem_stack_16 ||
210 VG_(track_events).die_mem_stack_16 ||
211 VG_(track_events).new_mem_stack_32 ||
212 VG_(track_events).die_mem_stack_32 ||
213 VG_(track_events).new_mem_stack ||
214 VG_(track_events).die_mem_stack
215 );
njnf4ce3d32003-02-10 10:17:26 +0000216}
217
sewardjde4a1d02002-03-22 01:27:54 +0000218/* Here we assign actual offsets. It's important to get the most
219 popular referents within 128 bytes of the start, so we can take
220 advantage of short addressing modes relative to %ebp. Popularity
221 of offsets was measured on 22 Feb 02 running a KDE application, and
222 the slots rearranged accordingly, with a 1.5% reduction in total
223 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000224static void vg_init_baseBlock ( void )
225{
sewardjde4a1d02002-03-22 01:27:54 +0000226 /* Those with offsets under 128 are carefully chosen. */
227
228 /* WORD offsets in this column */
229 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
230 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
231 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
232 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
233 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
234 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
235 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
236 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
237 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
238
njn25e49d8e72002-09-23 09:36:25 +0000239 if (VG_(needs).shadow_regs) {
240 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
241 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
242 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
243 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
244 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
245 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
246 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
247 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
248 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
249 }
sewardjde4a1d02002-03-22 01:27:54 +0000250
njn25e49d8e72002-09-23 09:36:25 +0000251 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
252 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000253
njn9b007f62003-04-07 14:40:25 +0000254 /* Make these most-frequently-called specialised ones compact, if they
255 are used. */
256 if (VG_(track_events).new_mem_stack_4)
257 VG_(register_compact_helper)( (Addr) VG_(track_events).new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000258
njn9b007f62003-04-07 14:40:25 +0000259 if (VG_(track_events).die_mem_stack_4)
260 VG_(register_compact_helper)( (Addr) VG_(track_events).die_mem_stack_4);
261
262 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000263 /* Allocate slots for compact helpers */
264 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
265 VG_(compact_helper_offsets),
266 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000267
njn25e49d8e72002-09-23 09:36:25 +0000268 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000269 VGOFF_(m_eip) = alloc_BaB(1);
270
271 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000272 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
273 * boundary at >= 32 words, but most spills are to low numbered spill
274 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000275 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
276
njn25e49d8e72002-09-23 09:36:25 +0000277 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000278 short-amode-boundary, there's no point. */
279
sewardjfa492d42002-12-08 18:20:01 +0000280 VGOFF_(m_dflag) = alloc_BaB(1);
281
sewardjb91ae7f2003-04-29 23:50:00 +0000282 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000283 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000284 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
285 vg_assert(
286 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
287 % 16 )
288 == 0
289 );
sewardjde4a1d02002-03-22 01:27:54 +0000290
sewardj92a59562002-09-30 00:53:10 +0000291 /* This thread's LDT pointer, and segment registers. */
292 VGOFF_(ldt) = alloc_BaB(1);
293 VGOFF_(m_cs) = alloc_BaB(1);
294 VGOFF_(m_ss) = alloc_BaB(1);
295 VGOFF_(m_ds) = alloc_BaB(1);
296 VGOFF_(m_es) = alloc_BaB(1);
297 VGOFF_(m_fs) = alloc_BaB(1);
298 VGOFF_(m_gs) = alloc_BaB(1);
299
sewardje1042472002-09-30 12:33:11 +0000300 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
301
njn9b007f62003-04-07 14:40:25 +0000302#define REG(kind, size) \
303 if (VG_(track_events).kind##_mem_stack##size) \
304 VG_(register_noncompact_helper)( \
305 (Addr) VG_(track_events).kind##_mem_stack##size );
306
307 REG(new, _8);
308 REG(new, _12);
309 REG(new, _16);
310 REG(new, _32);
311 REG(new, );
312 REG(die, _8);
313 REG(die, _12);
314 REG(die, _16);
315 REG(die, _32);
316 REG(die, );
317#undef REG
318
319 if (VG_(need_to_handle_esp_assignment)())
320 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
321
sewardj92a59562002-09-30 00:53:10 +0000322 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000323 VGOFF_(helper_idiv_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000324 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000325 VGOFF_(helper_div_64_32)
daywalkerb106c422003-09-29 10:56:24 +0000326 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32));
sewardjde4a1d02002-03-22 01:27:54 +0000327 VGOFF_(helper_idiv_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000328 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000329 VGOFF_(helper_div_32_16)
daywalkerb106c422003-09-29 10:56:24 +0000330 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16));
sewardjde4a1d02002-03-22 01:27:54 +0000331 VGOFF_(helper_idiv_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000332 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000333 VGOFF_(helper_div_16_8)
daywalkerb106c422003-09-29 10:56:24 +0000334 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8));
sewardjde4a1d02002-03-22 01:27:54 +0000335
336 VGOFF_(helper_imul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000337 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000338 VGOFF_(helper_mul_32_64)
daywalkerb106c422003-09-29 10:56:24 +0000339 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64));
sewardjde4a1d02002-03-22 01:27:54 +0000340 VGOFF_(helper_imul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000341 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000342 VGOFF_(helper_mul_16_32)
daywalkerb106c422003-09-29 10:56:24 +0000343 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32));
sewardjde4a1d02002-03-22 01:27:54 +0000344 VGOFF_(helper_imul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000345 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000346 VGOFF_(helper_mul_8_16)
daywalkerb106c422003-09-29 10:56:24 +0000347 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16));
sewardjde4a1d02002-03-22 01:27:54 +0000348
349 VGOFF_(helper_CLD)
daywalkerb106c422003-09-29 10:56:24 +0000350 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD));
sewardjde4a1d02002-03-22 01:27:54 +0000351 VGOFF_(helper_STD)
daywalkerb106c422003-09-29 10:56:24 +0000352 = alloc_BaB_1_set( (Addr) & VG_(helper_STD));
sewardjde4a1d02002-03-22 01:27:54 +0000353 VGOFF_(helper_get_dirflag)
daywalkerb106c422003-09-29 10:56:24 +0000354 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag));
sewardjde4a1d02002-03-22 01:27:54 +0000355
sewardj7d78e782002-06-02 00:04:00 +0000356 VGOFF_(helper_CLC)
daywalkerb106c422003-09-29 10:56:24 +0000357 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC));
sewardj73cf3bc2002-11-03 03:20:15 +0000358 VGOFF_(helper_STC)
daywalkerb106c422003-09-29 10:56:24 +0000359 = alloc_BaB_1_set( (Addr) & VG_(helper_STC));
sewardj7d78e782002-06-02 00:04:00 +0000360
sewardjde4a1d02002-03-22 01:27:54 +0000361 VGOFF_(helper_shldl)
daywalkerb106c422003-09-29 10:56:24 +0000362 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl));
sewardjde4a1d02002-03-22 01:27:54 +0000363 VGOFF_(helper_shldw)
daywalkerb106c422003-09-29 10:56:24 +0000364 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw));
sewardjde4a1d02002-03-22 01:27:54 +0000365 VGOFF_(helper_shrdl)
daywalkerb106c422003-09-29 10:56:24 +0000366 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl));
sewardjde4a1d02002-03-22 01:27:54 +0000367 VGOFF_(helper_shrdw)
daywalkerb106c422003-09-29 10:56:24 +0000368 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw));
sewardjde4a1d02002-03-22 01:27:54 +0000369
370 VGOFF_(helper_RDTSC)
daywalkerb106c422003-09-29 10:56:24 +0000371 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC));
sewardjde4a1d02002-03-22 01:27:54 +0000372 VGOFF_(helper_CPUID)
daywalkerb106c422003-09-29 10:56:24 +0000373 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID));
sewardjde4a1d02002-03-22 01:27:54 +0000374
sewardjde4a1d02002-03-22 01:27:54 +0000375 VGOFF_(helper_bsf)
daywalkerb106c422003-09-29 10:56:24 +0000376 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf));
sewardjde4a1d02002-03-22 01:27:54 +0000377 VGOFF_(helper_bsr)
daywalkerb106c422003-09-29 10:56:24 +0000378 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr));
sewardjde4a1d02002-03-22 01:27:54 +0000379
380 VGOFF_(helper_fstsw_AX)
daywalkerb106c422003-09-29 10:56:24 +0000381 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX));
sewardjde4a1d02002-03-22 01:27:54 +0000382 VGOFF_(helper_SAHF)
daywalkerb106c422003-09-29 10:56:24 +0000383 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF));
njnd6251f12003-06-03 13:38:51 +0000384 VGOFF_(helper_LAHF)
daywalkerb106c422003-09-29 10:56:24 +0000385 = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF));
sewardj4d0ab1f2002-03-24 10:00:09 +0000386 VGOFF_(helper_DAS)
daywalkerb106c422003-09-29 10:56:24 +0000387 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS));
sewardjfe8a1662002-03-24 11:54:07 +0000388 VGOFF_(helper_DAA)
daywalkerb106c422003-09-29 10:56:24 +0000389 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA));
daywalkerb18d2532003-09-27 20:15:01 +0000390 VGOFF_(helper_IN)
daywalkerb106c422003-09-29 10:56:24 +0000391 = alloc_BaB_1_set( (Addr) & VG_(helper_IN));
daywalkerb18d2532003-09-27 20:15:01 +0000392 VGOFF_(helper_OUT)
daywalkerb106c422003-09-29 10:56:24 +0000393 = alloc_BaB_1_set( (Addr) & VG_(helper_OUT));
njn25e49d8e72002-09-23 09:36:25 +0000394
sewardj51096432002-12-14 23:59:09 +0000395 VGOFF_(helper_undefined_instruction)
daywalkerb106c422003-09-29 10:56:24 +0000396 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction));
sewardj51096432002-12-14 23:59:09 +0000397
sewardj92a59562002-09-30 00:53:10 +0000398 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000399 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
400 VG_(noncompact_helper_offsets),
401 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000402
njncc7bb472002-10-14 09:25:19 +0000403
404 /* Initialise slots that require it */
405 VG_(copy_m_state_static_to_baseBlock)();
406
407 /* Pretend the root thread has a completely empty LDT to start with. */
408 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
409
410 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000411 if (VG_(needs).shadow_regs) {
njn25e49d8e72002-09-23 09:36:25 +0000412 VG_(baseBlock)[VGOFF_(sh_esp)] =
413 VG_(baseBlock)[VGOFF_(sh_ebp)] =
414 VG_(baseBlock)[VGOFF_(sh_eax)] =
415 VG_(baseBlock)[VGOFF_(sh_ecx)] =
416 VG_(baseBlock)[VGOFF_(sh_edx)] =
417 VG_(baseBlock)[VGOFF_(sh_ebx)] =
418 VG_(baseBlock)[VGOFF_(sh_esi)] =
njnd3040452003-05-19 15:04:06 +0000419 VG_(baseBlock)[VGOFF_(sh_edi)] = 0;
420 VG_(baseBlock)[VGOFF_(sh_eflags)] = 0;
421 VG_TRACK( post_regs_write_init );
njncc7bb472002-10-14 09:25:19 +0000422 }
sewardjde4a1d02002-03-22 01:27:54 +0000423}
424
425
426/* ---------------------------------------------------------------------
427 Global entities which are not referenced from generated code.
428 ------------------------------------------------------------------ */
429
430/* The stack on which Valgrind runs. We can't use the same stack as
431 the simulatee -- that's an important design decision. */
njn6eba4ef2003-05-01 08:06:41 +0000432UInt VG_(stack)[VG_STACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000433
434/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000435UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000436
437/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000438__attribute__ ((aligned (16)))
439UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000440Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000441
442/* Counts downwards in vg_run_innerloop. */
443UInt VG_(dispatch_ctr);
444
sewardjde4a1d02002-03-22 01:27:54 +0000445
446/* 64-bit counter for the number of basic blocks done. */
447ULong VG_(bbs_done);
448/* 64-bit counter for the number of bbs to go before a debug exit. */
449ULong VG_(bbs_to_go);
450
sewardj7e87e382002-05-03 19:09:05 +0000451/* This is the ThreadId of the last thread the scheduler ran. */
452ThreadId VG_(last_run_tid) = 0;
453
njn25e49d8e72002-09-23 09:36:25 +0000454/* This is the argument to __NR_exit() supplied by the first thread to
455 call that syscall. We eventually pass that to __NR_exit() for
456 real. */
njn633de322003-05-12 20:40:13 +0000457Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000458
sewardj73cf3bc2002-11-03 03:20:15 +0000459/* Tell the logging mechanism whether we are logging to a file
460 descriptor or a socket descriptor. */
461Bool VG_(logging_to_filedes) = True;
462
sewardjb91ae7f2003-04-29 23:50:00 +0000463/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
464 the SSE state all over the place. This is set up very early, in
465 vg_startup.S. We have to determine it early since we can't even
466 correctly snapshot the startup machine state without it. */
467/* Initially True. Safer to err on the side of SSEness and get SIGILL
daywalker7e73e5f2003-07-04 16:18:15 +0000468 than to not notice for some reason that we have SSE and get weird
sewardjb91ae7f2003-04-29 23:50:00 +0000469 errors later on. */
470Bool VG_(have_ssestate) = True;
471
sewardjde4a1d02002-03-22 01:27:54 +0000472
473/* ---------------------------------------------------------------------
474 Counters, for informational purposes only.
475 ------------------------------------------------------------------ */
476
477/* Number of lookups which miss the fast tt helper. */
478UInt VG_(tt_fast_misses) = 0;
479
480
sewardjc0d8f682002-11-30 00:49:43 +0000481/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000482
sewardjde4a1d02002-03-22 01:27:54 +0000483/* Number and total o/t size of translations overall. */
484UInt VG_(overall_in_count) = 0;
485UInt VG_(overall_in_osize) = 0;
486UInt VG_(overall_in_tsize) = 0;
487/* Number and total o/t size of discards overall. */
488UInt VG_(overall_out_count) = 0;
489UInt VG_(overall_out_osize) = 0;
490UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000491/* The number of discards of TT/TC. */
492UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000493/* Counts of chain and unchain operations done. */
494UInt VG_(bb_enchain_count) = 0;
495UInt VG_(bb_dechain_count) = 0;
496/* Number of unchained jumps performed. */
497UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000498
499
500/* Counts pertaining to the register allocator. */
501
502/* total number of uinstrs input to reg-alloc */
503UInt VG_(uinstrs_prealloc) = 0;
504
505/* total number of uinstrs added due to spill code */
506UInt VG_(uinstrs_spill) = 0;
507
508/* number of bbs requiring spill code */
509UInt VG_(translations_needing_spill) = 0;
510
511/* total of register ranks over all translations */
512UInt VG_(total_reg_rank) = 0;
513
514
sewardjde4a1d02002-03-22 01:27:54 +0000515/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000516UInt VG_(sanity_fast_count) = 0;
517UInt VG_(sanity_slow_count) = 0;
518
sewardj2e93c502002-04-12 11:12:52 +0000519/* Counts pertaining to the scheduler. */
520UInt VG_(num_scheduling_events_MINOR) = 0;
521UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000522
523
524/* ---------------------------------------------------------------------
525 Values derived from command-line options.
526 ------------------------------------------------------------------ */
527
njn25e49d8e72002-09-23 09:36:25 +0000528/* Define, and set defaults. */
529Bool VG_(clo_error_limit) = True;
530Bool VG_(clo_GDB_attach) = False;
sewardj6024b212003-07-13 10:54:33 +0000531Char* VG_(clo_GDB_path) = GDB_PATH;
njn43c799e2003-04-08 00:08:52 +0000532Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000533Int VG_(sanity_level) = 1;
534Int VG_(clo_verbosity) = 1;
535Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000536Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000537
nethercotee1730692003-11-20 10:38:07 +0000538/* See big comment in vg_include.h for meaning of these three.
539 fd is initially stdout, for --help, but gets moved to stderr by default
540 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +0000541VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +0000542Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +0000543Char* VG_(clo_logfile_name) = NULL;
544
sewardj6024b212003-07-13 10:54:33 +0000545Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +0000546Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000547Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000548Bool VG_(clo_profile) = False;
549Bool VG_(clo_single_step) = False;
550Bool VG_(clo_optimise) = True;
551UChar VG_(clo_trace_codegen) = 0; // 00000000b
552Bool VG_(clo_trace_syscalls) = False;
553Bool VG_(clo_trace_signals) = False;
554Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000555Bool VG_(clo_trace_sched) = False;
556Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000557ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000558Int VG_(clo_dump_error) = 0;
559Int VG_(clo_backtrace_size) = 4;
560Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000561Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +0000562Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +0000563Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +0000564Bool VG_(clo_show_below_main) = False;
sewardj2370f3b2002-11-30 15:01:01 +0000565
jsgf855d93d2003-10-13 22:26:55 +0000566static Bool VG_(clo_wait_for_gdb) = False;
567
568/* If we're doing signal routing, poll for signals every 50mS by
569 default. */
570Int VG_(clo_signal_polltime) = 50;
571
572/* These flags reduce thread wakeup latency on syscall completion and
573 signal delivery, respectively. The downside is possible unfairness. */
574Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
575Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
576
sewardjde4a1d02002-03-22 01:27:54 +0000577/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
578 to behave. Initially we say False. */
579Bool VG_(running_on_simd_CPU) = False;
580
581/* Holds client's %esp at the point we gained control. */
582Addr VG_(esp_at_startup);
583
sewardjd5815ec2003-04-06 12:23:27 +0000584/* Indicates presence, and holds address of client's sysinfo page, a
585 feature of some modern kernels used to provide vsyscalls, etc. */
586Bool VG_(sysinfo_page_exists) = False;
587Addr VG_(sysinfo_page_addr) = 0;
588
sewardjde4a1d02002-03-22 01:27:54 +0000589/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
590 envp[] as extracted from the client's stack at startup-time. */
591Int VG_(client_argc);
592Char** VG_(client_argv);
593Char** VG_(client_envp);
594
595/* A place into which to copy the value of env var VG_ARGS, so we
596 don't have to modify the original. */
597static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
598
sewardjde4a1d02002-03-22 01:27:54 +0000599/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000600 Processing of command-line options.
601 ------------------------------------------------------------------ */
602
njn25e49d8e72002-09-23 09:36:25 +0000603void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000604{
605 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000606 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000607 VG_(clo_logfile_fd) = 2; /* stderr */
608 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
609 VG_(exit)(1);
610}
611
612static void config_error ( Char* msg )
613{
614 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000615 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000616 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000617 VG_(printf)(
618 "valgrind.so: Startup or configuration error:\n %s\n", msg);
619 VG_(printf)(
620 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000621 VG_(exit)(1);
622}
623
sewardja1679dd2002-05-10 22:31:40 +0000624static void args_grok_error ( Char* msg )
625{
626 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000627 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000628 VG_(clo_logfile_fd) = 2; /* stderr */
629 VG_(printf)("valgrind.so: When searching for "
630 "client's argc/argc/envp:\n\t%s\n", msg);
631 config_error("couldn't find client's argc/argc/envp");
632}
633
njn25e49d8e72002-09-23 09:36:25 +0000634static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000635{
njn25e49d8e72002-09-23 09:36:25 +0000636 Char* usage1 =
637"usage: valgrind [options] prog-and-args\n"
638"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000639" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote137bc552003-11-14 17:47:54 +0000640" --tool=<name> Use the Valgrind tool named <name> [memcheck]\n"
njn25e49d8e72002-09-23 09:36:25 +0000641" --help show this message\n"
642" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000643" -q --quiet run silently; only print error msgs\n"
644" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000645" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +0000646" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000647"\n"
648" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +0000649" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
650" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +0000651" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +0000652" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
653" Only applies for older kernels which need\n"
654" signal routing [50]\n"
655" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
656" a signal [no]\n"
657" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
658" syscall completes [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000659"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000660" user options for Valgrind tools that report errors:\n"
661" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
662" --logfile=<file> log messages to <file>.pid<pid>\n"
663" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
664" --demangle=no|yes automatically demangle C++ names? [yes]\n"
665" --num-callers=<number> show <num> callers in stack traces [4]\n"
666" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
667" --show-below-main=no|yes continue stack traces below main() [no]\n"
668" --suppressions=<filename> suppress errors described in <filename>\n"
669" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +0000670
nethercote2b0793f2003-12-02 10:41:18 +0000671" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
672" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
673" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
674"\n"
675" user options for %s:\n";
njn7cf0bd32002-06-08 13:36:03 +0000676
njn25e49d8e72002-09-23 09:36:25 +0000677 Char* usage2 =
678"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000679" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000680" --sanity-level=<number> level of sanity checking to do [1]\n"
681" --single-step=no|yes translate each instr separately? [no]\n"
682" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +0000683" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000684" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000685" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
686" --trace-syscalls=no|yes show all system calls? [no]\n"
687" --trace-signals=no|yes show signal handling details? [no]\n"
688" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000689" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000690" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000691" --stop-after=<number> switch to real CPU after executing\n"
692" <number> basic blocks [infinity]\n"
jsgf855d93d2003-10-13 22:26:55 +0000693" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +0000694"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000695" debugging options for Valgrind tools that report errors\n"
696" --dump-error=<number> show translation for basic block associated\n"
697" with <number>'th error context [0=show none]\n"
698"\n"
699" debugging options for %s:\n";
njn3e884182003-04-15 13:03:23 +0000700
701 Char* usage3 =
702"\n"
njn25e49d8e72002-09-23 09:36:25 +0000703" Extra options are read from env variable $VALGRIND_OPTS\n"
704"\n"
njn0e1b5142003-04-15 14:58:06 +0000705" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000706" and licensed under the GNU General Public License, version 2.\n"
707" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000708"\n"
nethercote137bc552003-11-14 17:47:54 +0000709" Tools are copyright and licensed by their authors. See each\n"
710" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000711"\n";
njn7cf0bd32002-06-08 13:36:03 +0000712
njnd04b7c62002-10-03 14:05:52 +0000713 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000714 /* Don't print skin string directly for security, ha! */
715 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000716 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000717 else
718 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000719 VG_(printf)(usage2, VG_(details).name);
720 if (VG_(needs).command_line_options)
721 SK_(print_debug_usage)();
722 else
723 VG_(printf)(" (none)\n");
nethercote421281e2003-11-20 16:20:55 +0000724 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +0000725
njn25e49d8e72002-09-23 09:36:25 +0000726 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000727 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000728 VG_(clo_logfile_fd) = 2; /* stderr */
729 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000730}
sewardjde4a1d02002-03-22 01:27:54 +0000731
sewardj1c1b1162003-02-23 01:25:51 +0000732
sewardj49e630d2003-04-23 21:18:52 +0000733/* Callback for looking for the stack segment. */
734Addr VG_(foundstack_start) = (Addr)NULL;
735UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000736
737static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000738 Char r, Char w, Char x,
739 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000740{
741 Addr lastword;
742 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000743 if (r != 'r' || w != 'w'
744 /* || x != 'x' --not necessarily so on x86-64*/
745 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000746 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000747 if (start <= VG_(esp_at_startup)
748 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000749 VG_(foundstack_start) = start;
750 VG_(foundstack_size) = size;
751 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000752 }
753}
754
755
756
sewardjde4a1d02002-03-22 01:27:54 +0000757static void process_cmd_line_options ( void )
758{
njn25e49d8e72002-09-23 09:36:25 +0000759 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000760 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000761 Char* p;
762 Char* str;
763 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000764
765# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000766
nethercotee1730692003-11-20 10:38:07 +0000767 /* log to stderr by default, but usage message goes to stdout */
768 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +0000769
770 /* Once logging is started, we can safely send messages pertaining
771 to failures in initialisation. */
772 VG_(startup_logging)();
773
sewardj19d81412002-06-03 01:10:40 +0000774 /* Check for sane path in ./configure --prefix=... */
775 if (VG_(strlen)(VG_LIBDIR) < 1
776 || VG_LIBDIR[0] != '/')
777 config_error("Please use absolute paths in "
778 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000779
sewardja1679dd2002-05-10 22:31:40 +0000780 /* (Suggested by Fabrice Bellard ... )
781 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000782 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000783 change less often than the libc ones. */
784 {
sewardj05bcdcb2003-05-18 10:05:38 +0000785 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000786
njn3e884182003-04-15 13:03:23 +0000787 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000788 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000789 has rwx permissions and no associated file. Note that this uses
790 the /proc/self/maps contents read at the start of VG_(main)(),
791 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000792
njnfa1016e2003-09-25 17:54:11 +0000793 VG_(parse_procselfmaps)( vg_findstack_callback );
sewardj53fe4582003-02-23 01:41:17 +0000794
sewardj49e630d2003-04-23 21:18:52 +0000795 /* Now foundstack_start and foundstack_size should delimit the stack. */
796 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000797 args_grok_error("Cannot determine stack segment "
798 "from /proc/self/maps");
799 }
sewardj1c1b1162003-02-23 01:25:51 +0000800
801 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000802 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000803 VG_(foundstack_start),
804 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000805
sewardj49e630d2003-04-23 21:18:52 +0000806 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000807 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
808 args_grok_error("Stack segment is not page aligned?!");
809 }
sewardj1c1b1162003-02-23 01:25:51 +0000810
sewardj53fe4582003-02-23 01:41:17 +0000811 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
812 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000813
sewardj38170912002-05-10 21:07:22 +0000814 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000815 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000816 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000817 sp--;
818 }
sewardj38170912002-05-10 21:07:22 +0000819
820 if (sp[2] == VKI_AT_BASE
821 && sp[0] == VKI_AT_PAGESZ
822 && sp[-2] == VKI_AT_PHNUM
823 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000824 && sp[-6] == VKI_AT_PHDR
825 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000826 if (0)
827 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000828 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000829 } else
830 if (sp[2] == VKI_AT_CLKTCK
831 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000832 && sp[-2] == VKI_AT_HWCAP
833 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000834 if (0)
835 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
836 sp -= 2;
837 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000838 if (sp[2] == VKI_AT_CLKTCK
839 && sp[0] == VKI_AT_PAGESZ
840 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000841 && sp[-4] == VKI_AT_SYSINFO
842 && sp[-4-1] == 0) {
843 if (0)
844 VG_(printf)("Looks like you've got a 2.4.X kernel with "
845 "a sysinfo page at %x here.\n", sp[-3]);
846 VG_(sysinfo_page_exists) = True;
847 VG_(sysinfo_page_addr) = sp[-3];
848 sp -= 4;
849 } else
850 if (sp[2] == VKI_AT_CLKTCK
851 && sp[0] == VKI_AT_PAGESZ
852 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000853 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
854 && sp[-4-1] == 0) {
855 if (0)
856 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
857 "kernel here.\n");
858 sp -= 4;
859 } else
860 if (sp[2] == VKI_AT_CLKTCK
861 && sp[0] == VKI_AT_PAGESZ
862 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000863 && sp[-2-20-1] == 0) {
864 if (0)
865 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
866 sp -= 22;
867 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000868 if (sp[2] == VKI_AT_CLKTCK
869 && sp[0] == VKI_AT_PAGESZ
870 && sp[-2] == VKI_AT_HWCAP
871 && sp[-4-1] == 0) {
872 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000873 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000874 sp -= 4;
875 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000876 if (sp[2] == VKI_AT_CLKTCK
877 && sp[0] == VKI_AT_PAGESZ
878 && sp[-2] == VKI_AT_HWCAP
879 && sp[-6] == VKI_AT_SYSINFO
880 && sp[-6-1] == 0) {
881 if (0)
882 VG_(printf)("Looks like a >= 2.5.68 kernel with "
883 "a sysinfo page at %x here.\n", sp[-5]);
884 VG_(sysinfo_page_exists) = True;
885 VG_(sysinfo_page_addr) = sp[-5];
886 sp -= 6;
887 } else
sewardja1679dd2002-05-10 22:31:40 +0000888 args_grok_error(
889 "ELF frame does not look like 2.2.X or 2.4.X.\n "
890 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
891 );
sewardj38170912002-05-10 21:07:22 +0000892
893 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000894 if (*sp != 0)
895 args_grok_error("can't find NULL at end of env[]");
896
sewardj38170912002-05-10 21:07:22 +0000897 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000898 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000899 while (True) {
900 sp --;
901 if (*sp == 0) break;
mueller0be67ff2003-11-19 00:45:13 +0000902 if (++ctr >= 2000)
sewardja1679dd2002-05-10 22:31:40 +0000903 args_grok_error(
mueller0be67ff2003-11-19 00:45:13 +0000904 "suspiciously many (2000) env[] entries; giving up");
sewardja1679dd2002-05-10 22:31:40 +0000905
sewardj38170912002-05-10 21:07:22 +0000906 }
907 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000908 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000909
sewardja1679dd2002-05-10 22:31:40 +0000910 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000911 VG_(client_argc) = 0;
912 while (True) {
913 sp--;
914 if (*sp == VG_(client_argc))
915 break;
916 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000917 if (++ctr >= 1000)
918 args_grok_error(
919 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000920 }
921
sewardja1679dd2002-05-10 22:31:40 +0000922 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000923 }
924
sewardjde4a1d02002-03-22 01:27:54 +0000925 /* Now that VG_(client_envp) has been set, we can extract the args
926 for Valgrind itself. Copy into global var so that we don't have to
927 write zeroes to the getenv'd value itself. */
928 str = VG_(getenv)("VG_ARGS");
929 argc = 0;
930
931 if (!str) {
932 config_error("Can't read options from env var VG_ARGS.");
933 }
934
935 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
936 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
937 }
938 VG_(strcpy)(vg_cmdline_copy, str);
939 str = NULL;
940
941 p = &vg_cmdline_copy[0];
942 while (True) {
943 while (ISSPACE(*p)) { *p = 0; p++; }
944 if (*p == 0) break;
945 if (argc < M_VG_CMDLINE_OPTS-1) {
946 argv[argc] = p; argc++;
947 } else {
948 config_error(
949 "Found more than M_CMDLINE_OPTS command-line opts.");
950 }
951 while (*p != 0 && !ISSPACE(*p)) p++;
952 }
953
954 for (i = 0; i < argc; i++) {
955
njn43c799e2003-04-08 00:08:52 +0000956 if (VG_CLO_STREQ(argv[i], "-v") ||
957 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000958 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000959 else if (VG_CLO_STREQ(argv[i], "-q") ||
960 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000961 VG_(clo_verbosity)--;
962
njn43c799e2003-04-08 00:08:52 +0000963 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000964 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000965 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000966 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000967
njn43c799e2003-04-08 00:08:52 +0000968 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000969 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000970 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000971 VG_(clo_GDB_attach) = False;
972
sewardj6024b212003-07-13 10:54:33 +0000973 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
974 VG_(clo_GDB_path) = &argv[i][11];
975
njn43c799e2003-04-08 00:08:52 +0000976 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
977 VG_(clo_gen_suppressions) = True;
978 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
979 VG_(clo_gen_suppressions) = False;
980
nethercote77eba602003-11-13 17:35:04 +0000981 else if (VG_CLO_STREQ(argv[i], "--show-below-main=yes"))
982 VG_(clo_show_below_main) = True;
983 else if (VG_CLO_STREQ(argv[i], "--show-below-main=no"))
984 VG_(clo_show_below_main) = False;
985
njn43c799e2003-04-08 00:08:52 +0000986 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000987 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000988 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000989 VG_(clo_demangle) = False;
990
njn43c799e2003-04-08 00:08:52 +0000991 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000992 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000993 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000994 VG_(clo_trace_children) = False;
995
njn43c799e2003-04-08 00:08:52 +0000996 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000997 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000998 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000999 VG_(clo_run_libc_freeres) = False;
1000
rjwalshf5f536f2003-11-17 17:45:00 +00001001 else if (VG_CLO_STREQ(argv[i], "--track-fds=yes"))
1002 VG_(clo_track_fds) = True;
1003 else if (VG_CLO_STREQ(argv[i], "--track-fds=no"))
1004 VG_(clo_track_fds) = False;
1005
njn43c799e2003-04-08 00:08:52 +00001006 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +00001007 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
1008
njn43c799e2003-04-08 00:08:52 +00001009 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001010 VG_(clo_log_to) = VgLogTo_Fd;
1011 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001012 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +00001013 }
1014
njn43c799e2003-04-08 00:08:52 +00001015 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001016 VG_(clo_log_to) = VgLogTo_File;
1017 VG_(clo_logfile_name) = &argv[i][10];
1018 }
sewardjde4a1d02002-03-22 01:27:54 +00001019
njn43c799e2003-04-08 00:08:52 +00001020 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001021 VG_(clo_log_to) = VgLogTo_Socket;
1022 VG_(clo_logfile_name) = &argv[i][12];
1023 }
1024
sewardj6024b212003-07-13 10:54:33 +00001025 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
1026 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
1027
njn43c799e2003-04-08 00:08:52 +00001028 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001029 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001030 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001031 VG_(message)(Vg_UserMsg,
1032 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +00001033 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001034 }
1035 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
1036 VG_(clo_n_suppressions)++;
1037 }
njn43c799e2003-04-08 00:08:52 +00001038 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001039 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +00001040 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001041 VG_(clo_profile) = False;
1042
njn43c799e2003-04-08 00:08:52 +00001043 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001044 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +00001045 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001046 VG_(clo_chain_bb) = False;
1047
njn43c799e2003-04-08 00:08:52 +00001048 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001049 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +00001050 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001051 VG_(clo_single_step) = False;
1052
njn43c799e2003-04-08 00:08:52 +00001053 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001054 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +00001055 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001056 VG_(clo_optimise) = False;
1057
njn25e49d8e72002-09-23 09:36:25 +00001058 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +00001059 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001060 Int j;
1061 char* opt = & argv[i][16];
1062
1063 if (5 != VG_(strlen)(opt)) {
1064 VG_(message)(Vg_UserMsg,
1065 "--trace-codegen argument must have 5 digits");
1066 VG_(bad_option)(argv[i]);
1067 }
1068 for (j = 0; j < 5; j++) {
1069 if ('0' == opt[j]) { /* do nothing */ }
1070 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1071 else {
1072 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1073 "contain 0s and 1s");
1074 VG_(bad_option)(argv[i]);
1075 }
1076 }
1077 }
sewardjde4a1d02002-03-22 01:27:54 +00001078
njn43c799e2003-04-08 00:08:52 +00001079 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001080 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001081 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001082 VG_(clo_trace_syscalls) = False;
1083
njn43c799e2003-04-08 00:08:52 +00001084 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001085 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001086 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001087 VG_(clo_trace_signals) = False;
1088
njn43c799e2003-04-08 00:08:52 +00001089 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001090 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001091 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001092 VG_(clo_trace_symtab) = False;
1093
njn43c799e2003-04-08 00:08:52 +00001094 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001095 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001096 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001097 VG_(clo_trace_sched) = False;
1098
njn43c799e2003-04-08 00:08:52 +00001099 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001100 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001101 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001102 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001103 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001104 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001105
njn43c799e2003-04-08 00:08:52 +00001106 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001107 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001108
jsgf855d93d2003-10-13 22:26:55 +00001109 else if (VG_CLO_STREQN(17, argv[i], "--signal-polltime="))
1110 VG_(clo_signal_polltime) = VG_(atoll)(&argv[i][17]);
1111
1112 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=yes"))
1113 VG_(clo_lowlat_signals) = True;
1114 else if (VG_CLO_STREQ(argv[i], "--lowlat-signals=no"))
1115 VG_(clo_lowlat_signals) = False;
1116
1117 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=yes"))
1118 VG_(clo_lowlat_syscalls) = True;
1119 else if (VG_CLO_STREQ(argv[i], "--lowlat-syscalls=no"))
1120 VG_(clo_lowlat_syscalls) = False;
1121
njn43c799e2003-04-08 00:08:52 +00001122 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001123 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1124
njn43c799e2003-04-08 00:08:52 +00001125 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001126 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1127
jsgf855d93d2003-10-13 22:26:55 +00001128 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=yes"))
1129 VG_(clo_wait_for_gdb) = True;
1130 else if (VG_CLO_STREQ(argv[i], "--wait-for-gdb=no"))
1131 VG_(clo_wait_for_gdb) = False;
1132
njn43c799e2003-04-08 00:08:52 +00001133 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001134 /* Make sure it's sane. */
1135 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
njn6c846552003-09-16 07:41:43 +00001136 if (VG_(clo_backtrace_size) < 1)
1137 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001138 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1139 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1140 }
1141
njn25e49d8e72002-09-23 09:36:25 +00001142 else if (VG_(needs).command_line_options) {
1143 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1144 if (!ok)
1145 usage();
1146 }
sewardjde4a1d02002-03-22 01:27:54 +00001147 else
njn25e49d8e72002-09-23 09:36:25 +00001148 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001149 }
1150
1151# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001152
njnf9ebf672003-05-12 21:41:30 +00001153 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001154 VG_(clo_verbosity) = 0;
1155
1156 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1157 VG_(message)(Vg_UserMsg, "");
1158 VG_(message)(Vg_UserMsg,
1159 "--gdb-attach=yes conflicts with --trace-children=yes");
1160 VG_(message)(Vg_UserMsg,
1161 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001162 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001163 }
1164
sewardj4cf05692002-10-27 20:28:29 +00001165 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1166 should be connected to whatever sink has been selected, and we
1167 indiscriminately chuck stuff into it without worrying what the
1168 nature of it is. Oh the wonder of Unix streams. */
1169
nethercotee1730692003-11-20 10:38:07 +00001170 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001171 the terminal any problems to do with processing command line
1172 opts. */
nethercotee1730692003-11-20 10:38:07 +00001173 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001174 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001175
1176 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001177
sewardj4cf05692002-10-27 20:28:29 +00001178 case VgLogTo_Fd:
1179 vg_assert(VG_(clo_logfile_name) == NULL);
1180 VG_(clo_logfile_fd) = eventually_logfile_fd;
1181 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001182
sewardj4cf05692002-10-27 20:28:29 +00001183 case VgLogTo_File: {
1184 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001185 Int seq = 0;
1186 Int pid = VG_(getpid)();
1187
sewardj4cf05692002-10-27 20:28:29 +00001188 vg_assert(VG_(clo_logfile_name) != NULL);
1189 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001190
1191 for(;;) {
1192 if (seq == 0)
1193 VG_(sprintf)(logfilename, "%s.pid%d",
1194 VG_(clo_logfile_name), pid );
1195 else
1196 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1197 VG_(clo_logfile_name), pid, seq );
1198 seq++;
1199
1200 eventually_logfile_fd
1201 = VG_(open)(logfilename,
1202 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1203 VKI_S_IRUSR|VKI_S_IWUSR);
1204 if (eventually_logfile_fd >= 0) {
1205 VG_(clo_logfile_fd) = eventually_logfile_fd;
1206 break;
1207 } else {
1208 if (eventually_logfile_fd != -VKI_EEXIST) {
1209 VG_(message)(Vg_UserMsg,
1210 "Can't create/open log file `%s.pid%d'; giving up!",
1211 VG_(clo_logfile_name), pid);
1212 VG_(bad_option)(
1213 "--logfile=<file> didn't work out for some reason.");
1214 break;
1215 }
1216 }
1217 }
sewardj4cf05692002-10-27 20:28:29 +00001218 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001219 }
1220
1221 case VgLogTo_Socket: {
1222 vg_assert(VG_(clo_logfile_name) != NULL);
1223 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1224 eventually_logfile_fd
1225 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1226 if (eventually_logfile_fd == -1) {
1227 VG_(message)(Vg_UserMsg,
1228 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1229 VG_(message)(Vg_UserMsg,
1230 "of `%s'; giving up!", VG_(clo_logfile_name) );
1231 VG_(bad_option)(
1232 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001233 }
sewardj73cf3bc2002-11-03 03:20:15 +00001234 if (eventually_logfile_fd == -2) {
1235 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001236 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001237 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001238 VG_(message)(Vg_UserMsg,
1239 "Log messages will sent to stderr instead." );
1240 VG_(message)(Vg_UserMsg,
1241 "" );
1242 /* We don't change anything here. */
1243 } else {
1244 vg_assert(eventually_logfile_fd > 0);
1245 VG_(clo_logfile_fd) = eventually_logfile_fd;
1246 VG_(logging_to_filedes) = False;
1247 }
sewardj73cf3bc2002-11-03 03:20:15 +00001248 break;
1249 }
1250
sewardj4cf05692002-10-27 20:28:29 +00001251 }
1252
jsgf855d93d2003-10-13 22:26:55 +00001253 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
1254 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_MAX_FD+1);
1255 if (eventually_logfile_fd < 0)
1256 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1257 else {
1258 VG_(clo_logfile_fd) = eventually_logfile_fd;
1259 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1260 }
1261
sewardj4cf05692002-10-27 20:28:29 +00001262 /* Ok, the logging sink is running now. Print a suitable preamble.
1263 If logging to file or a socket, write details of parent PID and
1264 command line args, to help people trying to interpret the
1265 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001266
sewardj83adf412002-05-01 01:25:45 +00001267 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001268 /* Skin details */
1269 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1270 VG_(details).name,
1271 NULL == VG_(details).version ? "" : "-",
1272 NULL == VG_(details).version
1273 ? (Char*)"" : VG_(details).version,
1274 VG_(details).description);
1275 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001276
njnd04b7c62002-10-03 14:05:52 +00001277 /* Core details */
1278 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001279 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001280 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001281 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001282 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001283 }
1284
nethercotec1e395d2003-11-10 13:26:49 +00001285 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001286 VG_(message)(Vg_UserMsg, "");
1287 VG_(message)(Vg_UserMsg,
1288 "My PID = %d, parent PID = %d. Prog and args are:",
1289 VG_(getpid)(), VG_(getppid)() );
1290 for (i = 0; i < VG_(client_argc); i++)
1291 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1292 }
1293
sewardjde4a1d02002-03-22 01:27:54 +00001294 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001295 if (VG_(clo_log_to) != VgLogTo_Fd)
1296 VG_(message)(Vg_UserMsg, "");
njn86dc2bc2003-09-09 07:26:21 +00001297 VG_(message)(Vg_UserMsg, "Command line");
1298 for (i = 0; i < VG_(client_argc); i++)
1299 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1300
sewardjde4a1d02002-03-22 01:27:54 +00001301 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1302 for (i = 0; i < argc; i++) {
1303 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1304 }
1305 }
1306
njn25e49d8e72002-09-23 09:36:25 +00001307 if (VG_(clo_n_suppressions) == 0 &&
1308 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001309 config_error("No error-suppression files were specified.");
1310 }
sewardj4cf05692002-10-27 20:28:29 +00001311
njn6a230532003-07-21 10:38:23 +00001312 if (VG_(clo_gen_suppressions) &&
1313 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1314 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1315 " as it doesn't generate errors.");
1316 }
1317
sewardjde4a1d02002-03-22 01:27:54 +00001318}
1319
sewardjde4a1d02002-03-22 01:27:54 +00001320/* ---------------------------------------------------------------------
1321 Copying to/from m_state_static.
1322 ------------------------------------------------------------------ */
1323
sewardjb91ae7f2003-04-29 23:50:00 +00001324/* See comment about this in vg_include.h. Change only with
1325 great care.
1326*/
1327__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001328UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1329 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001330 + 1 /* %eflags */
1331 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001332 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001333 ];
1334
sewardjfa492d42002-12-08 18:20:01 +00001335UInt VG_(insertDflag)(UInt eflags, Int d)
1336{
1337 vg_assert(d == 1 || d == -1);
1338 eflags &= ~EFlagD;
1339
1340 if (d < 0)
1341 eflags |= EFlagD;
1342
1343 return eflags;
1344}
1345
1346Int VG_(extractDflag)(UInt eflags)
1347{
1348 Int ret;
1349
1350 if (eflags & EFlagD)
1351 ret = -1;
1352 else
1353 ret = 1;
1354
1355 return ret;
1356}
1357
sewardjde4a1d02002-03-22 01:27:54 +00001358void VG_(copy_baseBlock_to_m_state_static) ( void )
1359{
1360 Int i;
sewardj92a59562002-09-30 00:53:10 +00001361 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1362 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1363 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1364 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1365 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1366 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001367
sewardj92a59562002-09-30 00:53:10 +00001368 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1369 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1370 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1371 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1372 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1373 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1374 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1375 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1376
sewardjb91ae7f2003-04-29 23:50:00 +00001377 VG_(m_state_static)[56/4]
1378 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1379 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001380 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001381
sewardjb91ae7f2003-04-29 23:50:00 +00001382 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001383 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001384 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001385}
1386
1387
1388void VG_(copy_m_state_static_to_baseBlock) ( void )
1389{
1390 Int i;
sewardj92a59562002-09-30 00:53:10 +00001391 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1392 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1393 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1394 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1395 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1396 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001397
sewardj92a59562002-09-30 00:53:10 +00001398 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1399 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1400 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1401 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1402 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1403 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1404 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1405 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1406
sewardjb91ae7f2003-04-29 23:50:00 +00001407 VG_(baseBlock)[VGOFF_(m_eflags)]
1408 = VG_(m_state_static)[56/4] & ~EFlagD;
1409 VG_(baseBlock)[VGOFF_(m_dflag)]
1410 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001411
sewardj92a59562002-09-30 00:53:10 +00001412 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001413
sewardjb91ae7f2003-04-29 23:50:00 +00001414 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1415 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001416 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001417}
1418
njn25e49d8e72002-09-23 09:36:25 +00001419Addr VG_(get_stack_pointer) ( void )
1420{
1421 return VG_(baseBlock)[VGOFF_(m_esp)];
1422}
1423
1424/* Some random tests needed for leak checking */
1425
1426Bool VG_(within_stack)(Addr a)
1427{
1428 if (a >= ((Addr)(&VG_(stack)))
1429 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1430 return True;
1431 else
1432 return False;
1433}
1434
sewardjecf8e102003-07-12 12:11:39 +00001435Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001436{
1437 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001438 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001439 return True;
sewardjecf8e102003-07-12 12:11:39 +00001440
1441 if (a >= ((Addr)(&VG_(threads)[0]))
1442 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1443 return True;
1444
1445 return False;
njn25e49d8e72002-09-23 09:36:25 +00001446}
sewardjde4a1d02002-03-22 01:27:54 +00001447
1448/* ---------------------------------------------------------------------
1449 Show accumulated counts.
1450 ------------------------------------------------------------------ */
1451
njn25e49d8e72002-09-23 09:36:25 +00001452static __inline__ Int safe_idiv(Int a, Int b)
1453{
1454 return (b == 0 ? 0 : a / b);
1455}
1456
sewardjde4a1d02002-03-22 01:27:54 +00001457static void vg_show_counts ( void )
1458{
1459 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001460 " TT/TC: %d tc sectors discarded.",
1461 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001462 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001463 " %d chainings, %d unchainings.",
1464 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1465 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001466 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001467 VG_(overall_in_count),
1468 VG_(overall_in_osize),
1469 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001470 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1471 VG_(message)(Vg_DebugMsg,
1472 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001473 VG_(overall_out_count),
1474 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001475 VG_(overall_out_tsize),
1476 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001477 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001478 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001479 VG_(bbs_done),
1480 VG_(unchained_jumps_done),
1481 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1482 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1483 );
1484
1485 VG_(message)(Vg_DebugMsg,
1486 " %d/%d major/minor sched events. %d tt_fast misses.",
1487 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001488 VG_(num_scheduling_events_MINOR),
1489 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001490
sewardjde4a1d02002-03-22 01:27:54 +00001491 VG_(message)(Vg_DebugMsg,
1492 "reg-alloc: %d t-req-spill, "
1493 "%d+%d orig+spill uis, %d total-reg-r.",
1494 VG_(translations_needing_spill),
1495 VG_(uinstrs_prealloc),
1496 VG_(uinstrs_spill),
1497 VG_(total_reg_rank) );
1498 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001499 " sanity: %d cheap, %d expensive checks.",
1500 VG_(sanity_fast_count),
1501 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001502 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001503}
1504
1505
1506/* ---------------------------------------------------------------------
1507 Main!
1508 ------------------------------------------------------------------ */
1509
jsgf855d93d2003-10-13 22:26:55 +00001510/* Initialize the PID and PGRP of scheduler LWP; this is also called
1511 in any new children after fork. */
1512static void newpid(ThreadId unused)
1513{
1514 /* PID of scheduler LWP */
1515 VG_(main_pid) = VG_(getpid)();
1516 VG_(main_pgrp) = VG_(getpgrp)();
1517}
1518
sewardjde4a1d02002-03-22 01:27:54 +00001519/* Where we jump to once Valgrind has got control, and the real
1520 machine's state has been copied to the m_state_static. */
1521
1522void VG_(main) ( void )
1523{
sewardj2e93c502002-04-12 11:12:52 +00001524 Int i;
1525 VgSchedReturnCode src;
sewardjde4a1d02002-03-22 01:27:54 +00001526
njn0c7a5b52003-04-30 09:00:33 +00001527 if (0) {
1528 if (VG_(have_ssestate))
1529 VG_(printf)("Looks like a SSE-capable CPU\n");
1530 else
1531 VG_(printf)("Looks like a MMX-only CPU\n");
1532 }
sewardjb91ae7f2003-04-29 23:50:00 +00001533
njn27f1a382002-11-08 15:48:16 +00001534 /* Check skin and core versions are compatible */
1535 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1536 VG_(printf)("Error:\n"
nethercote137bc552003-11-14 17:47:54 +00001537 " Tool and core interface versions do not match.\n"
njn27f1a382002-11-08 15:48:16 +00001538 " Interface version used by core is: %d.%d\n"
nethercote137bc552003-11-14 17:47:54 +00001539 " Interface version used by tool is: %d.%d\n"
njn27f1a382002-11-08 15:48:16 +00001540 " The major version numbers must match.\n",
1541 VG_CORE_INTERFACE_MAJOR_VERSION,
1542 VG_CORE_INTERFACE_MINOR_VERSION,
1543 VG_(skin_interface_major_version),
1544 VG_(skin_interface_minor_version));
1545 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1546 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1547 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1548 else
1549 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1550 VG_(printf)(" Aborting, sorry.\n");
1551 VG_(exit)(1);
1552 }
1553
jsgf855d93d2003-10-13 22:26:55 +00001554 VG_(atfork)(NULL, NULL, newpid);
1555 newpid(VG_INVALID_THREADID);
1556
sewardjde4a1d02002-03-22 01:27:54 +00001557 /* Set up our stack sanity-check words. */
1558 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001559 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1560 VG_(stack)[VG_STACK_SIZE_W-1-i]
1561 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001562 }
1563
njn3e884182003-04-15 13:03:23 +00001564 /* Read /proc/self/maps into a buffer. Must be before:
1565 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1566 superblocks are not erroneously identified as being owned by the
1567 client, which would be bad.
1568 - init_memory(): that's where the buffer is parsed
1569 - init_tt_tc(): so the anonymous mmaps for the translation table and
1570 translation cache aren't identified as part of the client, which would
1571 waste > 20M of virtual address space, and be bad.
1572 */
njnfa1016e2003-09-25 17:54:11 +00001573 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001574
njn25e49d8e72002-09-23 09:36:25 +00001575 /* Setup stuff that depends on the skin. Must be before:
1576 - vg_init_baseBlock(): to register helpers
1577 - process_cmd_line_options(): to register skin name and description,
1578 and turn on/off 'command_line_options' need
1579 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001580 */
njn810086f2002-11-14 12:42:47 +00001581 SK_(pre_clo_init)();
1582 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001583
njncc7bb472002-10-14 09:25:19 +00001584 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001585 process_cmd_line_options();
1586
jsgf855d93d2003-10-13 22:26:55 +00001587 /* Hook to delay things long enough so we can get the pid and
1588 attach GDB in another shell. */
1589 if (VG_(clo_wait_for_gdb)) {
1590 VG_(printf)("pid=%d\n", VG_(getpid)());
1591 /* do "jump *$eip" to skip this in gdb */
1592 VG_(do_syscall)(__NR_pause);
1593 }
1594
njn3e884182003-04-15 13:03:23 +00001595 /* Do post command-line processing initialisation. Must be before:
1596 - vg_init_baseBlock(): to register any more helpers
1597 */
njncc7bb472002-10-14 09:25:19 +00001598 SK_(post_clo_init)();
1599
njn3e884182003-04-15 13:03:23 +00001600 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001601 vg_init_baseBlock();
1602
rjwalshf5f536f2003-11-17 17:45:00 +00001603 /* Search for file descriptors that are inherited from our parent. */
1604 if (VG_(clo_track_fds))
1605 VG_(init_preopened_fds)();
1606
sewardj018f7622002-05-15 21:13:39 +00001607 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001608 baseBlock into VG_(threads)[1]. Must be before:
1609 - VG_(sigstartup_actions)()
1610 */
sewardj018f7622002-05-15 21:13:39 +00001611 VG_(scheduler_init)();
1612
jsgf855d93d2003-10-13 22:26:55 +00001613 /* Set up the ProxyLWP machinery */
1614 VG_(proxy_init)();
1615
sewardj018f7622002-05-15 21:13:39 +00001616 /* Initialise the signal handling subsystem, temporarily parking
1617 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001618 VG_(sigstartup_actions)();
1619
sewardj018f7622002-05-15 21:13:39 +00001620 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001621 if (VG_(clo_profile))
1622 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001623
sewardj5f07b662002-04-23 16:52:51 +00001624 /* Start calibration of our RDTSC-based clock. */
1625 VG_(start_rdtsc_calibration)();
1626
njn3e884182003-04-15 13:03:23 +00001627 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001628 VGP_PUSHCC(VgpInitMem);
1629 VG_(init_memory)();
1630 VGP_POPCC(VgpInitMem);
1631
1632 /* Read the list of errors to suppress. This should be found in
1633 the file specified by vg_clo_suppressions. */
1634 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1635 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001636
sewardj5f07b662002-04-23 16:52:51 +00001637 /* End calibration of our RDTSC-based clock, leaving it as long as
1638 we can. */
1639 VG_(end_rdtsc_calibration)();
1640
njn3e884182003-04-15 13:03:23 +00001641 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001642 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001643
1644 if (VG_(clo_verbosity) == 1) {
1645 VG_(message)(Vg_UserMsg,
1646 "For more details, rerun with: -v");
1647 }
1648
sewardj25c7c3a2003-07-10 00:17:58 +00001649 /* Force a read of the debug info so that we can look for
1650 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001651 VG_(setup_code_redirect_table)();
1652
sewardjde4a1d02002-03-22 01:27:54 +00001653 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1654 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001655 if (VG_(clo_verbosity) > 0)
1656 VG_(message)(Vg_UserMsg, "");
1657
1658 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001659
sewardj018f7622002-05-15 21:13:39 +00001660 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001661 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001662 VGP_PUSHCC(VgpSched);
jsgf855d93d2003-10-13 22:26:55 +00001663
1664 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
1665 VG_(fatal_signal_set) = True;
1666 src = VG_(scheduler)();
1667 } else
1668 src = VgSrc_FatalSig;
1669
njn25e49d8e72002-09-23 09:36:25 +00001670 VGP_POPCC(VgpSched);
1671 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001672
1673 if (VG_(clo_verbosity) > 0)
1674 VG_(message)(Vg_UserMsg, "");
1675
sewardj2e93c502002-04-12 11:12:52 +00001676 if (src == VgSrc_Deadlock) {
1677 VG_(message)(Vg_UserMsg,
1678 "Warning: pthread scheduler exited due to deadlock");
1679 }
1680
rjwalshf5f536f2003-11-17 17:45:00 +00001681 /* Print out file descriptor summary and stats. */
1682 if(VG_(clo_track_fds))
1683 VG_(fd_stats)();
1684
njn25e49d8e72002-09-23 09:36:25 +00001685 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001686 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001687
njn7d9f94d2003-04-22 21:41:40 +00001688 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001689
sewardj0c3b53f2002-05-01 01:58:35 +00001690 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001691
1692 if (VG_(clo_verbosity) > 1)
1693 vg_show_counts();
1694
sewardjc0d8f682002-11-30 00:49:43 +00001695 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001696 VG_(print_UInstr_histogram)();
1697
sewardjde4a1d02002-03-22 01:27:54 +00001698 if (0) {
1699 VG_(message)(Vg_DebugMsg, "");
1700 VG_(message)(Vg_DebugMsg,
1701 "------ Valgrind's internal memory use stats follow ------" );
1702 VG_(mallocSanityCheckAll)();
1703 VG_(show_all_arena_stats)();
1704 VG_(message)(Vg_DebugMsg,
1705 "------ Valgrind's ExeContext management stats follow ------" );
1706 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001707 }
1708
njn25e49d8e72002-09-23 09:36:25 +00001709 if (VG_(clo_profile))
1710 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001711
1712 VG_(shutdown_logging)();
1713
sewardj3e1eb1f2002-05-18 13:14:17 +00001714 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1715 processes don't get traced into. Also mess up $libdir/valgrind
1716 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001717 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1718 pointless when we are just about to VgSrc_ExitSyscall. So don't
1719 bother in that case. */
1720 if ((!VG_(clo_trace_children))
1721 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001722 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1723 VG_(getenv)("LD_PRELOAD"),
1724 VG_(getenv)("LD_LIBRARY_PATH")
1725 );
sewardjde4a1d02002-03-22 01:27:54 +00001726 }
1727
jsgf855d93d2003-10-13 22:26:55 +00001728 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
1729 vg_assert(src == VgSrc_FatalSig ||
1730 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
1731 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
1732 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
1733
sewardj7e87e382002-05-03 19:09:05 +00001734 /* Decide how to exit. This depends on what the scheduler
1735 returned. */
jsgf855d93d2003-10-13 22:26:55 +00001736
sewardj7e87e382002-05-03 19:09:05 +00001737 switch (src) {
1738 case VgSrc_ExitSyscall: /* the normal way out */
1739 vg_assert(VG_(last_run_tid) > 0
1740 && VG_(last_run_tid) < VG_N_THREADS);
jsgf855d93d2003-10-13 22:26:55 +00001741 VG_(proxy_shutdown)();
1742
njn25e49d8e72002-09-23 09:36:25 +00001743 /* The thread's %EBX at the time it did __NR_exit() will hold
1744 the arg to __NR_exit(), so we just do __NR_exit() with
1745 that arg. */
1746 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001747 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001748 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001749 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001750
sewardj7e87e382002-05-03 19:09:05 +00001751 case VgSrc_Deadlock:
1752 /* Just exit now. No point in continuing. */
jsgf855d93d2003-10-13 22:26:55 +00001753 VG_(proxy_shutdown)();
sewardj7e87e382002-05-03 19:09:05 +00001754 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001755 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001756 break;
1757
1758 case VgSrc_BbsDone:
1759 /* Tricky; we have to try and switch back to the real CPU.
1760 This is all very dodgy and won't work at all in the
1761 presence of threads, or if the client happened to be
1762 running a signal handler. */
1763 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001764 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001765 VG_(load_thread_state)(1 /* root thread */ );
1766 VG_(copy_baseBlock_to_m_state_static)();
1767
jsgf855d93d2003-10-13 22:26:55 +00001768 VG_(proxy_shutdown)();
1769
sewardj7e87e382002-05-03 19:09:05 +00001770 /* This pushes a return address on the simulator's stack,
1771 which is abandoned. We call vg_sigshutdown_actions() at
1772 the end of vg_switch_to_real_CPU(), so as to ensure that
1773 the original stack and machine state is restored before
1774 the real signal mechanism is restored. */
1775 VG_(switch_to_real_CPU)();
1776
jsgf855d93d2003-10-13 22:26:55 +00001777 case VgSrc_FatalSig:
1778 /* We were killed by a fatal signal, so replicate the effect */
1779 vg_assert(VG_(fatal_sigNo) != -1);
1780 VG_(kill_self)(VG_(fatal_sigNo));
1781 VG_(core_panic)("vg_main(): signal was supposed to be fatal");
1782 break;
1783
sewardj7e87e382002-05-03 19:09:05 +00001784 default:
njne427a662002-10-02 11:08:25 +00001785 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001786 }
sewardjde4a1d02002-03-22 01:27:54 +00001787}
1788
1789
1790/* Debugging thing .. can be called from assembly with OYNK macro. */
1791void VG_(oynk) ( Int n )
1792{
1793 OINK(n);
1794}
1795
1796
1797/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1798 "valgrinq.so", which doesn't do anything. This is used to avoid
1799 tracing into child processes. To make this work the build system
1800 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001801
njn25e49d8e72002-09-23 09:36:25 +00001802 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1803 without it, child processes try to find valgrind.so symbols in the
1804 skin .so.
1805
sewardj78e25c92002-05-20 23:38:33 +00001806 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1807 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1808 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001809*/
sewardj45b672d2003-07-25 19:58:11 +00001810static void slideleft ( Char* s )
1811{
1812 vg_assert(s && (*s == ' ' || *s == ':'));
1813 while (True) {
1814 s[0] = s[1];
1815 if (s[0] == '\0') break;
1816 s++;
1817 }
1818}
1819
1820
sewardj3e1eb1f2002-05-18 13:14:17 +00001821void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1822 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001823{
njn42e23f22003-05-05 12:47:25 +00001824 Char* vg_prel = NULL;
1825 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001826 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001827 Char* p;
1828 Char* coredir_first;
1829 Char* coredir_last;
1830 Int coredir_len;
1831 Int i;
1832 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001833
njn42e23f22003-05-05 12:47:25 +00001834#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001835
njn42e23f22003-05-05 12:47:25 +00001836 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001837
njn42e23f22003-05-05 12:47:25 +00001838 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1839
njnc2f5bb02003-07-23 09:40:50 +00001840 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1841 LD_LIBRARY_PATH = "<coredir>:Y" */
1842
njn42e23f22003-05-05 12:47:25 +00001843 /* Setting up, finding things */
1844
1845 /* LD_PRELOAD: Search for "valgrind.so" */
1846 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1847
1848 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001849 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001850 if (NULL == vg_prel) {
1851 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001852 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001853 }
1854
njnc2f5bb02003-07-23 09:40:50 +00001855 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001856 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001857
njn42e23f22003-05-05 12:47:25 +00001858 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1859 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1860 coredir_first = p+1;
1861 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001862 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001863
1864 /* LD_PRELOAD: find "vgskin_foo.so" */
1865 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1866 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001867
njnc2f5bb02003-07-23 09:40:50 +00001868 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001869 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001870 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1871 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001872 *coredir_last = '/'; /* Undo zero-termination */
1873
1874 /* Changing things */
1875
1876 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1877 if (vg_prel[7] != 'd') MUTANCY(6);
1878 vg_prel[7] = 'q';
1879
njnc2f5bb02003-07-23 09:40:50 +00001880 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1881 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1882 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001883 while (*p != ':' && p >= ld_preload_str) {
1884 *p = ' ';
1885 p--;
njn25e49d8e72002-09-23 09:36:25 +00001886 }
njnc2f5bb02003-07-23 09:40:50 +00001887 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1888 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001889 p = sk_prel;
1890 while (*p != ':' && *p != '\0') {
1891 *p = ' ';
1892 p++;
1893 }
1894 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001895
njnc2f5bb02003-07-23 09:40:50 +00001896 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001897 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001898 coredir2[i] = ' ';
sewardj45b672d2003-07-25 19:58:11 +00001899
1900 /* Zap the leading spaces and : in both strings. */
1901 while (ld_preload_str[0] == ' ') slideleft(ld_preload_str);
1902 if (ld_preload_str[0] == ':') slideleft(ld_preload_str);
1903
1904 while (ld_library_path_str[0] == ' ') slideleft(ld_library_path_str);
1905 if (ld_library_path_str[0] == ':') slideleft(ld_library_path_str);
1906
njn42e23f22003-05-05 12:47:25 +00001907 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001908
sewardj78e25c92002-05-20 23:38:33 +00001909 return;
1910
njn42e23f22003-05-05 12:47:25 +00001911
1912mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001913 VG_(printf)(
1914 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1915 " what = %d\n"
1916 " ld_preload_str = `%s'\n"
1917 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001918 " vg_prel = `%s'\n"
1919 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001920 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001921 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001922 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001923 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001924 );
sewardjc26b4482002-07-13 12:20:35 +00001925 VG_(printf)(
1926 "\n"
1927 "Note that this is often caused by mis-installation of valgrind.\n"
1928 "Correct installation procedure is:\n"
1929 " ./configure --prefix=/install/dir\n"
1930 " make install\n"
1931 "And then use /install/dir/bin/valgrind\n"
1932 "Moving the installation directory elsewhere after 'make install'\n"
1933 "will cause the above error. Hand-editing the paths in the shell\n"
1934 "scripts is also likely to cause problems.\n"
1935 "\n"
1936 );
njne427a662002-10-02 11:08:25 +00001937 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001938}
1939
sewardj3e1eb1f2002-05-18 13:14:17 +00001940
sewardjde4a1d02002-03-22 01:27:54 +00001941/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1942 it to attach to this process. Called if the user requests this
1943 service after an error has been shown, so she can poke around and
1944 look at parameters, memory, etc. You can't meaningfully get GDB to
1945 continue the program, though; to continue, quit GDB. */
1946extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1947{
sewardje6a25242002-04-21 22:03:07 +00001948 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001949 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001950
njn9315df32003-04-16 20:50:50 +00001951 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001952 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001953 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1954 res = VG_(system)(buf);
1955 if (res == 0) {
1956 VG_(message)(Vg_UserMsg, "");
1957 VG_(message)(Vg_UserMsg,
1958 "GDB has detached. Valgrind regains control. We continue.");
1959 } else {
1960 VG_(message)(Vg_UserMsg, "Apparently failed!");
1961 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001962 }
sewardjde4a1d02002-03-22 01:27:54 +00001963}
1964
1965
1966/* Print some helpful-ish text about unimplemented things, and give
1967 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001968void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001969{
1970 VG_(message)(Vg_UserMsg, "");
1971 VG_(message)(Vg_UserMsg,
1972 "Valgrind detected that your program requires");
1973 VG_(message)(Vg_UserMsg,
1974 "the following unimplemented functionality:");
1975 VG_(message)(Vg_UserMsg, " %s", msg);
1976 VG_(message)(Vg_UserMsg,
1977 "This may be because the functionality is hard to implement,");
1978 VG_(message)(Vg_UserMsg,
1979 "or because no reasonable program would behave this way,");
1980 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001981 "or because nobody has yet needed it. In any case, let us know at");
sewardjde4a1d02002-03-22 01:27:54 +00001982 VG_(message)(Vg_UserMsg,
nethercote421281e2003-11-20 16:20:55 +00001983 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
sewardjde4a1d02002-03-22 01:27:54 +00001984 VG_(message)(Vg_UserMsg,
1985 "");
1986 VG_(message)(Vg_UserMsg,
1987 "Valgrind has to exit now. Sorry. Bye!");
1988 VG_(message)(Vg_UserMsg,
1989 "");
sewardj15a43e12002-04-17 19:35:12 +00001990 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001991 VG_(exit)(1);
1992}
1993
1994
njn25e49d8e72002-09-23 09:36:25 +00001995/* ---------------------------------------------------------------------
1996 Sanity check machinery (permanently engaged).
1997 ------------------------------------------------------------------ */
1998
1999/* A fast sanity check -- suitable for calling circa once per
2000 millisecond. */
2001
2002void VG_(do_sanity_checks) ( Bool force_expensive )
2003{
2004 Int i;
2005
njn37cea302002-09-30 11:24:00 +00002006 VGP_PUSHCC(VgpCoreCheapSanity);
2007
njn25e49d8e72002-09-23 09:36:25 +00002008 if (VG_(sanity_level) < 1) return;
2009
2010 /* --- First do all the tests that we can do quickly. ---*/
2011
2012 VG_(sanity_fast_count)++;
2013
2014 /* Check that we haven't overrun our private stack. */
2015 for (i = 0; i < 10; i++) {
2016 vg_assert(VG_(stack)[i]
2017 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00002018 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
2019 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00002020 }
2021
2022 /* Check stuff pertaining to the memory check system. */
2023
2024 /* Check that nobody has spuriously claimed that the first or
2025 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002026 if (VG_(needs).sanity_checks) {
2027 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002028 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002029 VGP_POPCC(VgpSkinCheapSanity);
2030 }
njn25e49d8e72002-09-23 09:36:25 +00002031
2032 /* --- Now some more expensive checks. ---*/
2033
2034 /* Once every 25 times, check some more expensive stuff. */
2035 if ( force_expensive
2036 || VG_(sanity_level) > 1
2037 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2038
njn37cea302002-09-30 11:24:00 +00002039 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002040 VG_(sanity_slow_count)++;
2041
jsgf855d93d2003-10-13 22:26:55 +00002042 VG_(proxy_sanity)();
2043
njn25e49d8e72002-09-23 09:36:25 +00002044# if 0
2045 { void zzzmemscan(void); zzzmemscan(); }
2046# endif
2047
2048 if ((VG_(sanity_fast_count) % 250) == 0)
2049 VG_(sanity_check_tc_tt)();
2050
2051 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002052 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002053 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002054 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002055 }
2056 /*
2057 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2058 */
njn37cea302002-09-30 11:24:00 +00002059 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002060 }
2061
2062 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002063 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002064 /* Check sanity of the low-level memory manager. Note that bugs
2065 in the client's code can cause this to fail, so we don't do
2066 this check unless specially asked for. And because it's
2067 potentially very expensive. */
2068 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002069 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002070 }
njn37cea302002-09-30 11:24:00 +00002071 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002072}
sewardjde4a1d02002-03-22 01:27:54 +00002073/*--------------------------------------------------------------------*/
2074/*--- end vg_main.c ---*/
2075/*--------------------------------------------------------------------*/