blob: 960fa757304f046cdf9e0707fa046201fbd63a9f [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;
93Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
94Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
95Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000096Int VGOFF_(helper_bsf) = INVALID_OFFSET;
97Int VGOFF_(helper_bsr) = INVALID_OFFSET;
98Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
99Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +0000100Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +0000101Int VGOFF_(helper_DAA) = INVALID_OFFSET;
sewardj51096432002-12-14 23:59:09 +0000102Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +0000103
104/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
105 * increased too much, they won't really be compact any more... */
106#define MAX_COMPACT_HELPERS 8
njnfedb7362003-02-24 10:21:45 +0000107#define MAX_NONCOMPACT_HELPERS 50
njn25e49d8e72002-09-23 09:36:25 +0000108
109UInt VG_(n_compact_helpers) = 0;
110UInt VG_(n_noncompact_helpers) = 0;
111
112Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
113Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
114Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
115Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
sewardjde4a1d02002-03-22 01:27:54 +0000116
117/* This is the actual defn of baseblock. */
118UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
119
njn25e49d8e72002-09-23 09:36:25 +0000120
sewardjde4a1d02002-03-22 01:27:54 +0000121/* Words. */
122static Int baB_off = 0;
123
124/* Returns the offset, in words. */
125static Int alloc_BaB ( Int words )
126{
127 Int off = baB_off;
128 baB_off += words;
129 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000130 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000131
132 return off;
133}
134
njn0c7a5b52003-04-30 09:00:33 +0000135/* Align offset, in *bytes* */
136static void align_BaB ( UInt align )
137{
138 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
139 baB_off += (align-1);
140 baB_off &= ~(align-1);
141}
142
sewardjde4a1d02002-03-22 01:27:54 +0000143/* Allocate 1 word in baseBlock and set it to the given value. */
144static Int alloc_BaB_1_set ( Addr a )
145{
146 Int off = alloc_BaB(1);
147 VG_(baseBlock)[off] = (UInt)a;
148 return off;
149}
150
njn25e49d8e72002-09-23 09:36:25 +0000151/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000152 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000153void VG_(register_compact_helper)(Addr a)
154{
155 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
156 VG_(printf)("Can only register %d compact helpers\n",
157 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000158 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000159 }
160 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
161 VG_(n_compact_helpers)++;
162}
163
164/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
165 * is filled in later.
166 */
167void VG_(register_noncompact_helper)(Addr a)
168{
169 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
170 VG_(printf)("Can only register %d non-compact helpers\n",
171 MAX_NONCOMPACT_HELPERS);
172 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000173 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000174 }
175 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
176 VG_(n_noncompact_helpers)++;
177}
178
179/* Allocate offsets in baseBlock for the skin helpers */
sewardj05bcdcb2003-05-18 10:05:38 +0000180static
181void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
njn25e49d8e72002-09-23 09:36:25 +0000182{
sewardj05bcdcb2003-05-18 10:05:38 +0000183 UInt i;
184 for (i = 0; i < n; i++)
185 offsets[i] = alloc_BaB_1_set( addrs[i] );
njn25e49d8e72002-09-23 09:36:25 +0000186}
sewardjde4a1d02002-03-22 01:27:54 +0000187
njnf4ce3d32003-02-10 10:17:26 +0000188Bool VG_(need_to_handle_esp_assignment)(void)
189{
njn9b007f62003-04-07 14:40:25 +0000190 return ( VG_(track_events).new_mem_stack_4 ||
191 VG_(track_events).die_mem_stack_4 ||
192 VG_(track_events).new_mem_stack_8 ||
193 VG_(track_events).die_mem_stack_8 ||
194 VG_(track_events).new_mem_stack_12 ||
195 VG_(track_events).die_mem_stack_12 ||
196 VG_(track_events).new_mem_stack_16 ||
197 VG_(track_events).die_mem_stack_16 ||
198 VG_(track_events).new_mem_stack_32 ||
199 VG_(track_events).die_mem_stack_32 ||
200 VG_(track_events).new_mem_stack ||
201 VG_(track_events).die_mem_stack
202 );
njnf4ce3d32003-02-10 10:17:26 +0000203}
204
sewardjde4a1d02002-03-22 01:27:54 +0000205/* Here we assign actual offsets. It's important to get the most
206 popular referents within 128 bytes of the start, so we can take
207 advantage of short addressing modes relative to %ebp. Popularity
208 of offsets was measured on 22 Feb 02 running a KDE application, and
209 the slots rearranged accordingly, with a 1.5% reduction in total
210 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000211static void vg_init_baseBlock ( void )
212{
sewardjde4a1d02002-03-22 01:27:54 +0000213 /* Those with offsets under 128 are carefully chosen. */
214
215 /* WORD offsets in this column */
216 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
217 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
218 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
219 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
220 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
221 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
222 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
223 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
224 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
225
njn25e49d8e72002-09-23 09:36:25 +0000226 if (VG_(needs).shadow_regs) {
227 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
228 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
229 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
230 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
231 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
232 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
233 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
234 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
235 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
236 }
sewardjde4a1d02002-03-22 01:27:54 +0000237
njn25e49d8e72002-09-23 09:36:25 +0000238 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
239 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000240
njn9b007f62003-04-07 14:40:25 +0000241 /* Make these most-frequently-called specialised ones compact, if they
242 are used. */
243 if (VG_(track_events).new_mem_stack_4)
244 VG_(register_compact_helper)( (Addr) VG_(track_events).new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000245
njn9b007f62003-04-07 14:40:25 +0000246 if (VG_(track_events).die_mem_stack_4)
247 VG_(register_compact_helper)( (Addr) VG_(track_events).die_mem_stack_4);
248
249 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000250 /* Allocate slots for compact helpers */
251 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
252 VG_(compact_helper_offsets),
253 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000254
njn25e49d8e72002-09-23 09:36:25 +0000255 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000256 VGOFF_(m_eip) = alloc_BaB(1);
257
258 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000259 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
260 * boundary at >= 32 words, but most spills are to low numbered spill
261 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000262 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
263
njn25e49d8e72002-09-23 09:36:25 +0000264 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000265 short-amode-boundary, there's no point. */
266
sewardjfa492d42002-12-08 18:20:01 +0000267 VGOFF_(m_dflag) = alloc_BaB(1);
268
sewardjb91ae7f2003-04-29 23:50:00 +0000269 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000270 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000271 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
272 vg_assert(
273 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
274 % 16 )
275 == 0
276 );
sewardjde4a1d02002-03-22 01:27:54 +0000277
sewardj92a59562002-09-30 00:53:10 +0000278 /* This thread's LDT pointer, and segment registers. */
279 VGOFF_(ldt) = alloc_BaB(1);
280 VGOFF_(m_cs) = alloc_BaB(1);
281 VGOFF_(m_ss) = alloc_BaB(1);
282 VGOFF_(m_ds) = alloc_BaB(1);
283 VGOFF_(m_es) = alloc_BaB(1);
284 VGOFF_(m_fs) = alloc_BaB(1);
285 VGOFF_(m_gs) = alloc_BaB(1);
286
sewardje1042472002-09-30 12:33:11 +0000287 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
288
njn9b007f62003-04-07 14:40:25 +0000289#define REG(kind, size) \
290 if (VG_(track_events).kind##_mem_stack##size) \
291 VG_(register_noncompact_helper)( \
292 (Addr) VG_(track_events).kind##_mem_stack##size );
293
294 REG(new, _8);
295 REG(new, _12);
296 REG(new, _16);
297 REG(new, _32);
298 REG(new, );
299 REG(die, _8);
300 REG(die, _12);
301 REG(die, _16);
302 REG(die, _32);
303 REG(die, );
304#undef REG
305
306 if (VG_(need_to_handle_esp_assignment)())
307 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
308
sewardj92a59562002-09-30 00:53:10 +0000309 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000310 VGOFF_(helper_idiv_64_32)
311 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
312 VGOFF_(helper_div_64_32)
313 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
314 VGOFF_(helper_idiv_32_16)
315 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
316 VGOFF_(helper_div_32_16)
317 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
318 VGOFF_(helper_idiv_16_8)
319 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
320 VGOFF_(helper_div_16_8)
321 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
322
323 VGOFF_(helper_imul_32_64)
324 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
325 VGOFF_(helper_mul_32_64)
326 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
327 VGOFF_(helper_imul_16_32)
328 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
329 VGOFF_(helper_mul_16_32)
330 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
331 VGOFF_(helper_imul_8_16)
332 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
333 VGOFF_(helper_mul_8_16)
334 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
335
336 VGOFF_(helper_CLD)
337 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
338 VGOFF_(helper_STD)
339 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
340 VGOFF_(helper_get_dirflag)
341 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
342
sewardj7d78e782002-06-02 00:04:00 +0000343 VGOFF_(helper_CLC)
344 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000345 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000346 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
347
sewardjde4a1d02002-03-22 01:27:54 +0000348 VGOFF_(helper_shldl)
349 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
350 VGOFF_(helper_shldw)
351 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
352 VGOFF_(helper_shrdl)
353 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
354 VGOFF_(helper_shrdw)
355 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
356
357 VGOFF_(helper_RDTSC)
358 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
359 VGOFF_(helper_CPUID)
360 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
361
sewardjde4a1d02002-03-22 01:27:54 +0000362 VGOFF_(helper_bsf)
363 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
364 VGOFF_(helper_bsr)
365 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
366
367 VGOFF_(helper_fstsw_AX)
368 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
369 VGOFF_(helper_SAHF)
370 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000371 VGOFF_(helper_DAS)
372 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000373 VGOFF_(helper_DAA)
374 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000375
sewardj51096432002-12-14 23:59:09 +0000376 VGOFF_(helper_undefined_instruction)
377 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
378
sewardj92a59562002-09-30 00:53:10 +0000379 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000380 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
381 VG_(noncompact_helper_offsets),
382 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000383
njncc7bb472002-10-14 09:25:19 +0000384
385 /* Initialise slots that require it */
386 VG_(copy_m_state_static_to_baseBlock)();
387
388 /* Pretend the root thread has a completely empty LDT to start with. */
389 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
390
391 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000392 if (VG_(needs).shadow_regs) {
393 UInt eflags;
394
395 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
396 VG_(baseBlock)[VGOFF_(sh_esp)] =
397 VG_(baseBlock)[VGOFF_(sh_ebp)] =
398 VG_(baseBlock)[VGOFF_(sh_eax)] =
399 VG_(baseBlock)[VGOFF_(sh_ecx)] =
400 VG_(baseBlock)[VGOFF_(sh_edx)] =
401 VG_(baseBlock)[VGOFF_(sh_ebx)] =
402 VG_(baseBlock)[VGOFF_(sh_esi)] =
403 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
404 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
405
njncc7bb472002-10-14 09:25:19 +0000406 } else {
njn25e49d8e72002-09-23 09:36:25 +0000407 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000408 }
sewardjde4a1d02002-03-22 01:27:54 +0000409}
410
411
412/* ---------------------------------------------------------------------
413 Global entities which are not referenced from generated code.
414 ------------------------------------------------------------------ */
415
416/* The stack on which Valgrind runs. We can't use the same stack as
417 the simulatee -- that's an important design decision. */
njn6eba4ef2003-05-01 08:06:41 +0000418UInt VG_(stack)[VG_STACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000419
420/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000421UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000422
423/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000424__attribute__ ((aligned (16)))
425UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000426Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000427
428/* Counts downwards in vg_run_innerloop. */
429UInt VG_(dispatch_ctr);
430
sewardjde4a1d02002-03-22 01:27:54 +0000431
432/* 64-bit counter for the number of basic blocks done. */
433ULong VG_(bbs_done);
434/* 64-bit counter for the number of bbs to go before a debug exit. */
435ULong VG_(bbs_to_go);
436
sewardj7e87e382002-05-03 19:09:05 +0000437/* This is the ThreadId of the last thread the scheduler ran. */
438ThreadId VG_(last_run_tid) = 0;
439
njn25e49d8e72002-09-23 09:36:25 +0000440/* This is the argument to __NR_exit() supplied by the first thread to
441 call that syscall. We eventually pass that to __NR_exit() for
442 real. */
njn633de322003-05-12 20:40:13 +0000443Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000444
sewardj73cf3bc2002-11-03 03:20:15 +0000445/* Tell the logging mechanism whether we are logging to a file
446 descriptor or a socket descriptor. */
447Bool VG_(logging_to_filedes) = True;
448
sewardjb91ae7f2003-04-29 23:50:00 +0000449/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
450 the SSE state all over the place. This is set up very early, in
451 vg_startup.S. We have to determine it early since we can't even
452 correctly snapshot the startup machine state without it. */
453/* Initially True. Safer to err on the side of SSEness and get SIGILL
454 than to not notice for some reason that we have SSE and get wierd
455 errors later on. */
456Bool VG_(have_ssestate) = True;
457
sewardjde4a1d02002-03-22 01:27:54 +0000458
459/* ---------------------------------------------------------------------
460 Counters, for informational purposes only.
461 ------------------------------------------------------------------ */
462
463/* Number of lookups which miss the fast tt helper. */
464UInt VG_(tt_fast_misses) = 0;
465
466
sewardjc0d8f682002-11-30 00:49:43 +0000467/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000468
sewardjde4a1d02002-03-22 01:27:54 +0000469/* Number and total o/t size of translations overall. */
470UInt VG_(overall_in_count) = 0;
471UInt VG_(overall_in_osize) = 0;
472UInt VG_(overall_in_tsize) = 0;
473/* Number and total o/t size of discards overall. */
474UInt VG_(overall_out_count) = 0;
475UInt VG_(overall_out_osize) = 0;
476UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000477/* The number of discards of TT/TC. */
478UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000479/* Counts of chain and unchain operations done. */
480UInt VG_(bb_enchain_count) = 0;
481UInt VG_(bb_dechain_count) = 0;
482/* Number of unchained jumps performed. */
483UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000484
485
486/* Counts pertaining to the register allocator. */
487
488/* total number of uinstrs input to reg-alloc */
489UInt VG_(uinstrs_prealloc) = 0;
490
491/* total number of uinstrs added due to spill code */
492UInt VG_(uinstrs_spill) = 0;
493
494/* number of bbs requiring spill code */
495UInt VG_(translations_needing_spill) = 0;
496
497/* total of register ranks over all translations */
498UInt VG_(total_reg_rank) = 0;
499
500
sewardjde4a1d02002-03-22 01:27:54 +0000501/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000502UInt VG_(sanity_fast_count) = 0;
503UInt VG_(sanity_slow_count) = 0;
504
sewardj2e93c502002-04-12 11:12:52 +0000505/* Counts pertaining to the scheduler. */
506UInt VG_(num_scheduling_events_MINOR) = 0;
507UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000508
509
510/* ---------------------------------------------------------------------
511 Values derived from command-line options.
512 ------------------------------------------------------------------ */
513
njn25e49d8e72002-09-23 09:36:25 +0000514/* Define, and set defaults. */
515Bool VG_(clo_error_limit) = True;
516Bool VG_(clo_GDB_attach) = False;
njn43c799e2003-04-08 00:08:52 +0000517Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000518Int VG_(sanity_level) = 1;
519Int VG_(clo_verbosity) = 1;
520Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000521Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000522
523/* See big comment in vg_include.h for meaning of these three. */
524VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
525Int VG_(clo_logfile_fd) = 2;
526Char* VG_(clo_logfile_name) = NULL;
527
njn25e49d8e72002-09-23 09:36:25 +0000528Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000529Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000530Bool VG_(clo_profile) = False;
531Bool VG_(clo_single_step) = False;
532Bool VG_(clo_optimise) = True;
533UChar VG_(clo_trace_codegen) = 0; // 00000000b
534Bool VG_(clo_trace_syscalls) = False;
535Bool VG_(clo_trace_signals) = False;
536Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000537Bool VG_(clo_trace_sched) = False;
538Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000539ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000540Int VG_(clo_dump_error) = 0;
541Int VG_(clo_backtrace_size) = 4;
542Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000543Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000544Bool VG_(clo_chain_bb) = True;
sewardj2370f3b2002-11-30 15:01:01 +0000545
sewardjde4a1d02002-03-22 01:27:54 +0000546/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
547 to behave. Initially we say False. */
548Bool VG_(running_on_simd_CPU) = False;
549
550/* Holds client's %esp at the point we gained control. */
551Addr VG_(esp_at_startup);
552
sewardjd5815ec2003-04-06 12:23:27 +0000553/* Indicates presence, and holds address of client's sysinfo page, a
554 feature of some modern kernels used to provide vsyscalls, etc. */
555Bool VG_(sysinfo_page_exists) = False;
556Addr VG_(sysinfo_page_addr) = 0;
557
sewardjde4a1d02002-03-22 01:27:54 +0000558/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
559 envp[] as extracted from the client's stack at startup-time. */
560Int VG_(client_argc);
561Char** VG_(client_argv);
562Char** VG_(client_envp);
563
564/* A place into which to copy the value of env var VG_ARGS, so we
565 don't have to modify the original. */
566static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
567
sewardjde4a1d02002-03-22 01:27:54 +0000568/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000569 Processing of command-line options.
570 ------------------------------------------------------------------ */
571
njn25e49d8e72002-09-23 09:36:25 +0000572void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000573{
574 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000575 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000576 VG_(clo_logfile_fd) = 2; /* stderr */
577 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
578 VG_(exit)(1);
579}
580
581static void config_error ( Char* msg )
582{
583 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000584 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000585 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000586 VG_(printf)(
587 "valgrind.so: Startup or configuration error:\n %s\n", msg);
588 VG_(printf)(
589 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000590 VG_(exit)(1);
591}
592
sewardja1679dd2002-05-10 22:31:40 +0000593static void args_grok_error ( Char* msg )
594{
595 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000596 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000597 VG_(clo_logfile_fd) = 2; /* stderr */
598 VG_(printf)("valgrind.so: When searching for "
599 "client's argc/argc/envp:\n\t%s\n", msg);
600 config_error("couldn't find client's argc/argc/envp");
601}
602
njn25e49d8e72002-09-23 09:36:25 +0000603static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000604{
njn25e49d8e72002-09-23 09:36:25 +0000605 Char* usage1 =
606"usage: valgrind [options] prog-and-args\n"
607"\n"
608" core user options, with defaults in [ ], are:\n"
609" --help show this message\n"
610" --version show version\n"
611" --skin=<name> main task (skin to use) [Valgrind]\n"
612" -q --quiet run silently; only print error msgs\n"
613" -v --verbose be more verbose, incl counts of errors\n"
614" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
njn43c799e2003-04-08 00:08:52 +0000615" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000616" --demangle=no|yes automatically demangle C++ names? [yes]\n"
617" --num-callers=<number> show <num> callers in stack traces [4]\n"
618" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000619" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000620" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000621" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000622" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000623" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000624" --suppressions=<filename> suppress errors described in\n"
625" suppressions file <filename>\n"
626" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000627" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000628"\n"
629" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000630
njn7cf0bd32002-06-08 13:36:03 +0000631
njn25e49d8e72002-09-23 09:36:25 +0000632 Char* usage2 =
633"\n"
634" core options for debugging Valgrind itself are:\n"
635" --sanity-level=<number> level of sanity checking to do [1]\n"
636" --single-step=no|yes translate each instr separately? [no]\n"
637" --optimise=no|yes improve intermediate code? [yes]\n"
638" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000639" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000640" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
641" --trace-syscalls=no|yes show all system calls? [no]\n"
642" --trace-signals=no|yes show signal handling details? [no]\n"
643" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000644" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000645" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000646" --stop-after=<number> switch to real CPU after executing\n"
647" <number> basic blocks [infinity]\n"
648" --dump-error=<number> show translation for basic block\n"
649" associated with <number>'th\n"
650" error context [0=don't show any]\n"
651"\n"
njn3e884182003-04-15 13:03:23 +0000652" %s skin debugging options:\n";
653
654 Char* usage3 =
655"\n"
njn25e49d8e72002-09-23 09:36:25 +0000656" Extra options are read from env variable $VALGRIND_OPTS\n"
657"\n"
njn0e1b5142003-04-15 14:58:06 +0000658" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000659" and licensed under the GNU General Public License, version 2.\n"
660" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000661"\n"
662" Skins are copyright and licensed by their authors. See each\n"
663" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000664"\n";
njn7cf0bd32002-06-08 13:36:03 +0000665
njnd04b7c62002-10-03 14:05:52 +0000666 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000667 /* Don't print skin string directly for security, ha! */
668 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000669 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000670 else
671 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000672 VG_(printf)(usage2, VG_(details).name);
673 if (VG_(needs).command_line_options)
674 SK_(print_debug_usage)();
675 else
676 VG_(printf)(" (none)\n");
677 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000678
njn25e49d8e72002-09-23 09:36:25 +0000679 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000680 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000681 VG_(clo_logfile_fd) = 2; /* stderr */
682 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000683}
sewardjde4a1d02002-03-22 01:27:54 +0000684
sewardj1c1b1162003-02-23 01:25:51 +0000685
sewardj49e630d2003-04-23 21:18:52 +0000686/* Callback for looking for the stack segment. */
687Addr VG_(foundstack_start) = (Addr)NULL;
688UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000689
690static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000691 Char r, Char w, Char x,
692 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000693{
694 Addr lastword;
695 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000696 if (r != 'r' || w != 'w'
697 /* || x != 'x' --not necessarily so on x86-64*/
698 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000699 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000700 if (start <= VG_(esp_at_startup)
701 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000702 VG_(foundstack_start) = start;
703 VG_(foundstack_size) = size;
704 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000705 }
706}
707
708
709
sewardjde4a1d02002-03-22 01:27:54 +0000710static void process_cmd_line_options ( void )
711{
njn25e49d8e72002-09-23 09:36:25 +0000712 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000713 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000714 Char* p;
715 Char* str;
716 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000717
718# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000719
sewardjde4a1d02002-03-22 01:27:54 +0000720 eventually_logfile_fd = VG_(clo_logfile_fd);
721
722 /* Once logging is started, we can safely send messages pertaining
723 to failures in initialisation. */
724 VG_(startup_logging)();
725
sewardj19d81412002-06-03 01:10:40 +0000726 /* Check for sane path in ./configure --prefix=... */
727 if (VG_(strlen)(VG_LIBDIR) < 1
728 || VG_LIBDIR[0] != '/')
729 config_error("Please use absolute paths in "
730 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000731
sewardja1679dd2002-05-10 22:31:40 +0000732 /* (Suggested by Fabrice Bellard ... )
733 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000734 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000735 change less often than the libc ones. */
736 {
sewardj05bcdcb2003-05-18 10:05:38 +0000737 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000738
njn3e884182003-04-15 13:03:23 +0000739 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000740 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000741 has rwx permissions and no associated file. Note that this uses
742 the /proc/self/maps contents read at the start of VG_(main)(),
743 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000744
njn3e884182003-04-15 13:03:23 +0000745 VG_(read_procselfmaps)( vg_findstack_callback, /*read_from_file*/False );
sewardj53fe4582003-02-23 01:41:17 +0000746
sewardj49e630d2003-04-23 21:18:52 +0000747 /* Now foundstack_start and foundstack_size should delimit the stack. */
748 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000749 args_grok_error("Cannot determine stack segment "
750 "from /proc/self/maps");
751 }
sewardj1c1b1162003-02-23 01:25:51 +0000752
753 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000754 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000755 VG_(foundstack_start),
756 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000757
sewardj49e630d2003-04-23 21:18:52 +0000758 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000759 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
760 args_grok_error("Stack segment is not page aligned?!");
761 }
sewardj1c1b1162003-02-23 01:25:51 +0000762
sewardj53fe4582003-02-23 01:41:17 +0000763 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
764 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000765
sewardj38170912002-05-10 21:07:22 +0000766 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000767 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000768 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000769 sp--;
770 }
sewardj38170912002-05-10 21:07:22 +0000771
772 if (sp[2] == VKI_AT_BASE
773 && sp[0] == VKI_AT_PAGESZ
774 && sp[-2] == VKI_AT_PHNUM
775 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000776 && sp[-6] == VKI_AT_PHDR
777 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000778 if (0)
779 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000780 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000781 } else
782 if (sp[2] == VKI_AT_CLKTCK
783 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000784 && sp[-2] == VKI_AT_HWCAP
785 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000786 if (0)
787 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
788 sp -= 2;
789 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000790 if (sp[2] == VKI_AT_CLKTCK
791 && sp[0] == VKI_AT_PAGESZ
792 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000793 && sp[-4] == VKI_AT_SYSINFO
794 && sp[-4-1] == 0) {
795 if (0)
796 VG_(printf)("Looks like you've got a 2.4.X kernel with "
797 "a sysinfo page at %x here.\n", sp[-3]);
798 VG_(sysinfo_page_exists) = True;
799 VG_(sysinfo_page_addr) = sp[-3];
800 sp -= 4;
801 } else
802 if (sp[2] == VKI_AT_CLKTCK
803 && sp[0] == VKI_AT_PAGESZ
804 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000805 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
806 && sp[-4-1] == 0) {
807 if (0)
808 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
809 "kernel here.\n");
810 sp -= 4;
811 } else
812 if (sp[2] == VKI_AT_CLKTCK
813 && sp[0] == VKI_AT_PAGESZ
814 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000815 && sp[-2-20-1] == 0) {
816 if (0)
817 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
818 sp -= 22;
819 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000820 if (sp[2] == VKI_AT_CLKTCK
821 && sp[0] == VKI_AT_PAGESZ
822 && sp[-2] == VKI_AT_HWCAP
823 && sp[-4-1] == 0) {
824 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000825 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000826 sp -= 4;
827 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000828 if (sp[2] == VKI_AT_CLKTCK
829 && sp[0] == VKI_AT_PAGESZ
830 && sp[-2] == VKI_AT_HWCAP
831 && sp[-6] == VKI_AT_SYSINFO
832 && sp[-6-1] == 0) {
833 if (0)
834 VG_(printf)("Looks like a >= 2.5.68 kernel with "
835 "a sysinfo page at %x here.\n", sp[-5]);
836 VG_(sysinfo_page_exists) = True;
837 VG_(sysinfo_page_addr) = sp[-5];
838 sp -= 6;
839 } else
sewardja1679dd2002-05-10 22:31:40 +0000840 args_grok_error(
841 "ELF frame does not look like 2.2.X or 2.4.X.\n "
842 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
843 );
sewardj38170912002-05-10 21:07:22 +0000844
845 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000846 if (*sp != 0)
847 args_grok_error("can't find NULL at end of env[]");
848
sewardj38170912002-05-10 21:07:22 +0000849 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000850 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000851 while (True) {
852 sp --;
853 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000854 if (++ctr >= 1000)
855 args_grok_error(
856 "suspiciously many (1000) env[] entries; giving up");
857
sewardj38170912002-05-10 21:07:22 +0000858 }
859 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000860 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000861
sewardja1679dd2002-05-10 22:31:40 +0000862 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000863 VG_(client_argc) = 0;
864 while (True) {
865 sp--;
866 if (*sp == VG_(client_argc))
867 break;
868 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000869 if (++ctr >= 1000)
870 args_grok_error(
871 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000872 }
873
sewardja1679dd2002-05-10 22:31:40 +0000874 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000875 }
876
sewardjde4a1d02002-03-22 01:27:54 +0000877 /* Now that VG_(client_envp) has been set, we can extract the args
878 for Valgrind itself. Copy into global var so that we don't have to
879 write zeroes to the getenv'd value itself. */
880 str = VG_(getenv)("VG_ARGS");
881 argc = 0;
882
883 if (!str) {
884 config_error("Can't read options from env var VG_ARGS.");
885 }
886
887 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
888 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
889 }
890 VG_(strcpy)(vg_cmdline_copy, str);
891 str = NULL;
892
893 p = &vg_cmdline_copy[0];
894 while (True) {
895 while (ISSPACE(*p)) { *p = 0; p++; }
896 if (*p == 0) break;
897 if (argc < M_VG_CMDLINE_OPTS-1) {
898 argv[argc] = p; argc++;
899 } else {
900 config_error(
901 "Found more than M_CMDLINE_OPTS command-line opts.");
902 }
903 while (*p != 0 && !ISSPACE(*p)) p++;
904 }
905
906 for (i = 0; i < argc; i++) {
907
njn43c799e2003-04-08 00:08:52 +0000908 if (VG_CLO_STREQ(argv[i], "-v") ||
909 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000910 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000911 else if (VG_CLO_STREQ(argv[i], "-q") ||
912 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000913 VG_(clo_verbosity)--;
914
njn43c799e2003-04-08 00:08:52 +0000915 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000916 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000917 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000918 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000919
njn43c799e2003-04-08 00:08:52 +0000920 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000921 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000922 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000923 VG_(clo_GDB_attach) = False;
924
njn43c799e2003-04-08 00:08:52 +0000925 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
926 VG_(clo_gen_suppressions) = True;
927 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
928 VG_(clo_gen_suppressions) = False;
929
930 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000931 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000932 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000933 VG_(clo_demangle) = False;
934
njn43c799e2003-04-08 00:08:52 +0000935 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000936 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000937 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000938 VG_(clo_trace_children) = False;
939
njn43c799e2003-04-08 00:08:52 +0000940 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000941 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000942 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000943 VG_(clo_run_libc_freeres) = False;
944
njn43c799e2003-04-08 00:08:52 +0000945 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000946 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
947
njn43c799e2003-04-08 00:08:52 +0000948 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000949 VG_(clo_log_to) = VgLogTo_Fd;
950 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000951 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000952 }
953
njn43c799e2003-04-08 00:08:52 +0000954 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000955 VG_(clo_log_to) = VgLogTo_File;
956 VG_(clo_logfile_name) = &argv[i][10];
957 }
sewardjde4a1d02002-03-22 01:27:54 +0000958
njn43c799e2003-04-08 00:08:52 +0000959 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000960 VG_(clo_log_to) = VgLogTo_Socket;
961 VG_(clo_logfile_name) = &argv[i][12];
962 }
963
njn43c799e2003-04-08 00:08:52 +0000964 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000965 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000966 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000967 VG_(message)(Vg_UserMsg,
968 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000969 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000970 }
971 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
972 VG_(clo_n_suppressions)++;
973 }
njn43c799e2003-04-08 00:08:52 +0000974 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000975 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000976 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000977 VG_(clo_profile) = False;
978
njn43c799e2003-04-08 00:08:52 +0000979 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000980 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000981 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000982 VG_(clo_chain_bb) = False;
983
njn43c799e2003-04-08 00:08:52 +0000984 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000985 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000986 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000987 VG_(clo_single_step) = False;
988
njn43c799e2003-04-08 00:08:52 +0000989 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000990 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000991 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000992 VG_(clo_optimise) = False;
993
njn25e49d8e72002-09-23 09:36:25 +0000994 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +0000995 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +0000996 Int j;
997 char* opt = & argv[i][16];
998
999 if (5 != VG_(strlen)(opt)) {
1000 VG_(message)(Vg_UserMsg,
1001 "--trace-codegen argument must have 5 digits");
1002 VG_(bad_option)(argv[i]);
1003 }
1004 for (j = 0; j < 5; j++) {
1005 if ('0' == opt[j]) { /* do nothing */ }
1006 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1007 else {
1008 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1009 "contain 0s and 1s");
1010 VG_(bad_option)(argv[i]);
1011 }
1012 }
1013 }
sewardjde4a1d02002-03-22 01:27:54 +00001014
njn43c799e2003-04-08 00:08:52 +00001015 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001016 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001017 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001018 VG_(clo_trace_syscalls) = False;
1019
njn43c799e2003-04-08 00:08:52 +00001020 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001021 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001022 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001023 VG_(clo_trace_signals) = False;
1024
njn43c799e2003-04-08 00:08:52 +00001025 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001026 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001027 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001028 VG_(clo_trace_symtab) = False;
1029
njn43c799e2003-04-08 00:08:52 +00001030 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001031 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001032 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001033 VG_(clo_trace_sched) = False;
1034
njn43c799e2003-04-08 00:08:52 +00001035 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001036 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001037 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001038 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001039 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001040 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001041
njn43c799e2003-04-08 00:08:52 +00001042 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001043 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001044
njn43c799e2003-04-08 00:08:52 +00001045 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001046 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1047
njn43c799e2003-04-08 00:08:52 +00001048 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001049 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1050
njn43c799e2003-04-08 00:08:52 +00001051 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001052 /* Make sure it's sane. */
1053 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1054 if (VG_(clo_backtrace_size) < 2)
1055 VG_(clo_backtrace_size) = 2;
1056 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1057 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1058 }
1059
njn25e49d8e72002-09-23 09:36:25 +00001060 else if (VG_(needs).command_line_options) {
1061 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1062 if (!ok)
1063 usage();
1064 }
sewardjde4a1d02002-03-22 01:27:54 +00001065 else
njn25e49d8e72002-09-23 09:36:25 +00001066 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001067 }
1068
1069# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001070
njnf9ebf672003-05-12 21:41:30 +00001071 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001072 VG_(clo_verbosity) = 0;
1073
1074 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1075 VG_(message)(Vg_UserMsg, "");
1076 VG_(message)(Vg_UserMsg,
1077 "--gdb-attach=yes conflicts with --trace-children=yes");
1078 VG_(message)(Vg_UserMsg,
1079 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001080 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001081 }
1082
sewardj4cf05692002-10-27 20:28:29 +00001083 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1084 should be connected to whatever sink has been selected, and we
1085 indiscriminately chuck stuff into it without worrying what the
1086 nature of it is. Oh the wonder of Unix streams. */
1087
1088 /* So far we should be still attached to stderr, so we can show on
1089 the terminal any problems to do with processing command line
1090 opts. */
1091 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001092 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001093
1094 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001095
sewardj4cf05692002-10-27 20:28:29 +00001096 case VgLogTo_Fd:
1097 vg_assert(VG_(clo_logfile_name) == NULL);
1098 VG_(clo_logfile_fd) = eventually_logfile_fd;
1099 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001100
sewardj4cf05692002-10-27 20:28:29 +00001101 case VgLogTo_File: {
1102 Char logfilename[1000];
1103 vg_assert(VG_(clo_logfile_name) != NULL);
1104 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1105 VG_(sprintf)(logfilename, "%s.pid%d",
1106 VG_(clo_logfile_name), VG_(getpid)() );
1107 eventually_logfile_fd
1108 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1109 VKI_S_IRUSR|VKI_S_IWUSR);
1110 if (eventually_logfile_fd != -1) {
1111 VG_(clo_logfile_fd) = eventually_logfile_fd;
1112 } else {
1113 VG_(message)(Vg_UserMsg,
1114 "Can't create/open log file `%s.pid%d'; giving up!",
1115 VG_(clo_logfile_name), VG_(getpid)());
1116 VG_(bad_option)(
1117 "--logfile=<file> didn't work out for some reason.");
1118 }
1119 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001120 }
1121
1122 case VgLogTo_Socket: {
1123 vg_assert(VG_(clo_logfile_name) != NULL);
1124 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1125 eventually_logfile_fd
1126 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1127 if (eventually_logfile_fd == -1) {
1128 VG_(message)(Vg_UserMsg,
1129 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1130 VG_(message)(Vg_UserMsg,
1131 "of `%s'; giving up!", VG_(clo_logfile_name) );
1132 VG_(bad_option)(
1133 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001134 }
sewardj73cf3bc2002-11-03 03:20:15 +00001135 if (eventually_logfile_fd == -2) {
1136 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001137 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001138 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001139 VG_(message)(Vg_UserMsg,
1140 "Log messages will sent to stderr instead." );
1141 VG_(message)(Vg_UserMsg,
1142 "" );
1143 /* We don't change anything here. */
1144 } else {
1145 vg_assert(eventually_logfile_fd > 0);
1146 VG_(clo_logfile_fd) = eventually_logfile_fd;
1147 VG_(logging_to_filedes) = False;
1148 }
sewardj73cf3bc2002-11-03 03:20:15 +00001149 break;
1150 }
1151
sewardj4cf05692002-10-27 20:28:29 +00001152 }
1153
1154 /* Ok, the logging sink is running now. Print a suitable preamble.
1155 If logging to file or a socket, write details of parent PID and
1156 command line args, to help people trying to interpret the
1157 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001158
sewardj83adf412002-05-01 01:25:45 +00001159 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001160 /* Skin details */
1161 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1162 VG_(details).name,
1163 NULL == VG_(details).version ? "" : "-",
1164 NULL == VG_(details).version
1165 ? (Char*)"" : VG_(details).version,
1166 VG_(details).description);
1167 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001168
njnd04b7c62002-10-03 14:05:52 +00001169 /* Core details */
1170 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001171 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001172 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001173 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001174 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001175 }
1176
sewardj4cf05692002-10-27 20:28:29 +00001177 if (VG_(clo_log_to) != VgLogTo_Fd) {
1178 VG_(message)(Vg_UserMsg, "");
1179 VG_(message)(Vg_UserMsg,
1180 "My PID = %d, parent PID = %d. Prog and args are:",
1181 VG_(getpid)(), VG_(getppid)() );
1182 for (i = 0; i < VG_(client_argc); i++)
1183 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1184 }
1185
sewardjde4a1d02002-03-22 01:27:54 +00001186 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001187 if (VG_(clo_log_to) != VgLogTo_Fd)
1188 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001189 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1190 for (i = 0; i < argc; i++) {
1191 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1192 }
1193 }
1194
njn25e49d8e72002-09-23 09:36:25 +00001195 if (VG_(clo_n_suppressions) == 0 &&
1196 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001197 config_error("No error-suppression files were specified.");
1198 }
sewardj4cf05692002-10-27 20:28:29 +00001199
sewardjde4a1d02002-03-22 01:27:54 +00001200}
1201
sewardjde4a1d02002-03-22 01:27:54 +00001202/* ---------------------------------------------------------------------
1203 Copying to/from m_state_static.
1204 ------------------------------------------------------------------ */
1205
sewardjb91ae7f2003-04-29 23:50:00 +00001206/* See comment about this in vg_include.h. Change only with
1207 great care.
1208*/
1209__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001210UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1211 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001212 + 1 /* %eflags */
1213 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001214 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001215 ];
1216
sewardjfa492d42002-12-08 18:20:01 +00001217UInt VG_(insertDflag)(UInt eflags, Int d)
1218{
1219 vg_assert(d == 1 || d == -1);
1220 eflags &= ~EFlagD;
1221
1222 if (d < 0)
1223 eflags |= EFlagD;
1224
1225 return eflags;
1226}
1227
1228Int VG_(extractDflag)(UInt eflags)
1229{
1230 Int ret;
1231
1232 if (eflags & EFlagD)
1233 ret = -1;
1234 else
1235 ret = 1;
1236
1237 return ret;
1238}
1239
sewardjde4a1d02002-03-22 01:27:54 +00001240void VG_(copy_baseBlock_to_m_state_static) ( void )
1241{
1242 Int i;
sewardj92a59562002-09-30 00:53:10 +00001243 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1244 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1245 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1246 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1247 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1248 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001249
sewardj92a59562002-09-30 00:53:10 +00001250 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1251 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1252 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1253 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1254 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1255 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1256 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1257 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1258
sewardjb91ae7f2003-04-29 23:50:00 +00001259 VG_(m_state_static)[56/4]
1260 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1261 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001262 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001263
sewardjb91ae7f2003-04-29 23:50:00 +00001264 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001265 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001266 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001267}
1268
1269
1270void VG_(copy_m_state_static_to_baseBlock) ( void )
1271{
1272 Int i;
sewardj92a59562002-09-30 00:53:10 +00001273 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1274 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1275 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1276 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1277 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1278 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001279
sewardj92a59562002-09-30 00:53:10 +00001280 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1281 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1282 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1283 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1284 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1285 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1286 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1287 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1288
sewardjb91ae7f2003-04-29 23:50:00 +00001289 VG_(baseBlock)[VGOFF_(m_eflags)]
1290 = VG_(m_state_static)[56/4] & ~EFlagD;
1291 VG_(baseBlock)[VGOFF_(m_dflag)]
1292 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001293
sewardj92a59562002-09-30 00:53:10 +00001294 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001295
sewardjb91ae7f2003-04-29 23:50:00 +00001296 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1297 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001298 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001299}
1300
njn25e49d8e72002-09-23 09:36:25 +00001301Addr VG_(get_stack_pointer) ( void )
1302{
1303 return VG_(baseBlock)[VGOFF_(m_esp)];
1304}
1305
1306/* Some random tests needed for leak checking */
1307
1308Bool VG_(within_stack)(Addr a)
1309{
1310 if (a >= ((Addr)(&VG_(stack)))
1311 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1312 return True;
1313 else
1314 return False;
1315}
1316
1317Bool VG_(within_m_state_static)(Addr a)
1318{
1319 if (a >= ((Addr)(&VG_(m_state_static)))
1320 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1321 return True;
1322 else
1323 return False;
1324}
sewardjde4a1d02002-03-22 01:27:54 +00001325
1326/* ---------------------------------------------------------------------
1327 Show accumulated counts.
1328 ------------------------------------------------------------------ */
1329
njn25e49d8e72002-09-23 09:36:25 +00001330static __inline__ Int safe_idiv(Int a, Int b)
1331{
1332 return (b == 0 ? 0 : a / b);
1333}
1334
sewardjde4a1d02002-03-22 01:27:54 +00001335static void vg_show_counts ( void )
1336{
1337 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001338 " TT/TC: %d tc sectors discarded.",
1339 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001340 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001341 " %d chainings, %d unchainings.",
1342 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1343 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001344 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001345 VG_(overall_in_count),
1346 VG_(overall_in_osize),
1347 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001348 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1349 VG_(message)(Vg_DebugMsg,
1350 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001351 VG_(overall_out_count),
1352 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001353 VG_(overall_out_tsize),
1354 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001355 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001356 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001357 VG_(bbs_done),
1358 VG_(unchained_jumps_done),
1359 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1360 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1361 );
1362
1363 VG_(message)(Vg_DebugMsg,
1364 " %d/%d major/minor sched events. %d tt_fast misses.",
1365 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001366 VG_(num_scheduling_events_MINOR),
1367 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001368
sewardjde4a1d02002-03-22 01:27:54 +00001369 VG_(message)(Vg_DebugMsg,
1370 "reg-alloc: %d t-req-spill, "
1371 "%d+%d orig+spill uis, %d total-reg-r.",
1372 VG_(translations_needing_spill),
1373 VG_(uinstrs_prealloc),
1374 VG_(uinstrs_spill),
1375 VG_(total_reg_rank) );
1376 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001377 " sanity: %d cheap, %d expensive checks.",
1378 VG_(sanity_fast_count),
1379 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001380 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001381}
1382
1383
1384/* ---------------------------------------------------------------------
1385 Main!
1386 ------------------------------------------------------------------ */
1387
1388/* Where we jump to once Valgrind has got control, and the real
1389 machine's state has been copied to the m_state_static. */
1390
1391void VG_(main) ( void )
1392{
sewardj2e93c502002-04-12 11:12:52 +00001393 Int i;
1394 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001395 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001396
njn0c7a5b52003-04-30 09:00:33 +00001397 if (0) {
1398 if (VG_(have_ssestate))
1399 VG_(printf)("Looks like a SSE-capable CPU\n");
1400 else
1401 VG_(printf)("Looks like a MMX-only CPU\n");
1402 }
sewardjb91ae7f2003-04-29 23:50:00 +00001403
njn27f1a382002-11-08 15:48:16 +00001404 /* Check skin and core versions are compatible */
1405 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1406 VG_(printf)("Error:\n"
1407 " Skin and core interface versions do not match.\n"
1408 " Interface version used by core is: %d.%d\n"
1409 " Interface version used by skin is: %d.%d\n"
1410 " The major version numbers must match.\n",
1411 VG_CORE_INTERFACE_MAJOR_VERSION,
1412 VG_CORE_INTERFACE_MINOR_VERSION,
1413 VG_(skin_interface_major_version),
1414 VG_(skin_interface_minor_version));
1415 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1416 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1417 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1418 else
1419 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1420 VG_(printf)(" Aborting, sorry.\n");
1421 VG_(exit)(1);
1422 }
1423
sewardjde4a1d02002-03-22 01:27:54 +00001424 /* Set up our stack sanity-check words. */
1425 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001426 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1427 VG_(stack)[VG_STACK_SIZE_W-1-i]
1428 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001429 }
1430
njn3e884182003-04-15 13:03:23 +00001431 /* Read /proc/self/maps into a buffer. Must be before:
1432 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1433 superblocks are not erroneously identified as being owned by the
1434 client, which would be bad.
1435 - init_memory(): that's where the buffer is parsed
1436 - init_tt_tc(): so the anonymous mmaps for the translation table and
1437 translation cache aren't identified as part of the client, which would
1438 waste > 20M of virtual address space, and be bad.
1439 */
1440 VG_(read_procselfmaps_contents)();
1441
sewardj1c1b1162003-02-23 01:25:51 +00001442 /* Hook to delay things long enough so we can get the pid and
1443 attach GDB in another shell. */
1444 if (0) {
1445 Int p, q;
1446 VG_(printf)("pid=%d\n", VG_(getpid)());
1447 for (p = 0; p < 50000; p++)
1448 for (q = 0; q < 50000; q++) ;
1449 }
1450
njn25e49d8e72002-09-23 09:36:25 +00001451 /* Setup stuff that depends on the skin. Must be before:
1452 - vg_init_baseBlock(): to register helpers
1453 - process_cmd_line_options(): to register skin name and description,
1454 and turn on/off 'command_line_options' need
1455 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001456 */
njn810086f2002-11-14 12:42:47 +00001457 SK_(pre_clo_init)();
1458 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001459
njncc7bb472002-10-14 09:25:19 +00001460 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001461 process_cmd_line_options();
1462
njn3e884182003-04-15 13:03:23 +00001463 /* Do post command-line processing initialisation. Must be before:
1464 - vg_init_baseBlock(): to register any more helpers
1465 */
njncc7bb472002-10-14 09:25:19 +00001466 SK_(post_clo_init)();
1467
njn3e884182003-04-15 13:03:23 +00001468 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001469 vg_init_baseBlock();
1470
sewardj018f7622002-05-15 21:13:39 +00001471 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001472 baseBlock into VG_(threads)[1]. Must be before:
1473 - VG_(sigstartup_actions)()
1474 */
sewardj018f7622002-05-15 21:13:39 +00001475 VG_(scheduler_init)();
1476
1477 /* Initialise the signal handling subsystem, temporarily parking
1478 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001479 VG_(sigstartup_actions)();
1480
sewardj018f7622002-05-15 21:13:39 +00001481 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001482 if (VG_(clo_profile))
1483 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001484
sewardj5f07b662002-04-23 16:52:51 +00001485 /* Start calibration of our RDTSC-based clock. */
1486 VG_(start_rdtsc_calibration)();
1487
njn3e884182003-04-15 13:03:23 +00001488 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001489 VGP_PUSHCC(VgpInitMem);
1490 VG_(init_memory)();
1491 VGP_POPCC(VgpInitMem);
1492
1493 /* Read the list of errors to suppress. This should be found in
1494 the file specified by vg_clo_suppressions. */
1495 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1496 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001497
sewardj5f07b662002-04-23 16:52:51 +00001498 /* End calibration of our RDTSC-based clock, leaving it as long as
1499 we can. */
1500 VG_(end_rdtsc_calibration)();
1501
njn3e884182003-04-15 13:03:23 +00001502 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001503 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001504
1505 if (VG_(clo_verbosity) == 1) {
1506 VG_(message)(Vg_UserMsg,
1507 "For more details, rerun with: -v");
1508 }
1509
1510 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1511 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001512 if (VG_(clo_verbosity) > 0)
1513 VG_(message)(Vg_UserMsg, "");
1514
1515 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001516
sewardj018f7622002-05-15 21:13:39 +00001517 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001518 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001519 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001520 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001521 VGP_POPCC(VgpSched);
1522 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001523
1524 if (VG_(clo_verbosity) > 0)
1525 VG_(message)(Vg_UserMsg, "");
1526
sewardj2e93c502002-04-12 11:12:52 +00001527 if (src == VgSrc_Deadlock) {
1528 VG_(message)(Vg_UserMsg,
1529 "Warning: pthread scheduler exited due to deadlock");
1530 }
1531
njn25e49d8e72002-09-23 09:36:25 +00001532 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001533 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001534
njn7d9f94d2003-04-22 21:41:40 +00001535 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001536
sewardj0c3b53f2002-05-01 01:58:35 +00001537 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001538
1539 if (VG_(clo_verbosity) > 1)
1540 vg_show_counts();
1541
sewardjc0d8f682002-11-30 00:49:43 +00001542 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001543 VG_(print_UInstr_histogram)();
1544
sewardjde4a1d02002-03-22 01:27:54 +00001545 if (0) {
1546 VG_(message)(Vg_DebugMsg, "");
1547 VG_(message)(Vg_DebugMsg,
1548 "------ Valgrind's internal memory use stats follow ------" );
1549 VG_(mallocSanityCheckAll)();
1550 VG_(show_all_arena_stats)();
1551 VG_(message)(Vg_DebugMsg,
1552 "------ Valgrind's ExeContext management stats follow ------" );
1553 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001554 }
1555
njn25e49d8e72002-09-23 09:36:25 +00001556 if (VG_(clo_profile))
1557 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001558
1559 VG_(shutdown_logging)();
1560
sewardj3e1eb1f2002-05-18 13:14:17 +00001561 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1562 processes don't get traced into. Also mess up $libdir/valgrind
1563 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001564 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1565 pointless when we are just about to VgSrc_ExitSyscall. So don't
1566 bother in that case. */
1567 if ((!VG_(clo_trace_children))
1568 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001569 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1570 VG_(getenv)("LD_PRELOAD"),
1571 VG_(getenv)("LD_LIBRARY_PATH")
1572 );
sewardjde4a1d02002-03-22 01:27:54 +00001573 }
1574
sewardj7e87e382002-05-03 19:09:05 +00001575 /* Decide how to exit. This depends on what the scheduler
1576 returned. */
1577 switch (src) {
1578 case VgSrc_ExitSyscall: /* the normal way out */
1579 vg_assert(VG_(last_run_tid) > 0
1580 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001581 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001582 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001583 /* The thread's %EBX at the time it did __NR_exit() will hold
1584 the arg to __NR_exit(), so we just do __NR_exit() with
1585 that arg. */
1586 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001587 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001588 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001589 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001590
sewardj7e87e382002-05-03 19:09:05 +00001591 case VgSrc_Deadlock:
1592 /* Just exit now. No point in continuing. */
1593 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001594 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001595 break;
1596
1597 case VgSrc_BbsDone:
1598 /* Tricky; we have to try and switch back to the real CPU.
1599 This is all very dodgy and won't work at all in the
1600 presence of threads, or if the client happened to be
1601 running a signal handler. */
1602 /* Prepare to restore state to the real CPU. */
1603 VG_(load_thread_state)(1 /* root thread */ );
1604 VG_(copy_baseBlock_to_m_state_static)();
1605
1606 /* This pushes a return address on the simulator's stack,
1607 which is abandoned. We call vg_sigshutdown_actions() at
1608 the end of vg_switch_to_real_CPU(), so as to ensure that
1609 the original stack and machine state is restored before
1610 the real signal mechanism is restored. */
1611 VG_(switch_to_real_CPU)();
1612
1613 default:
njne427a662002-10-02 11:08:25 +00001614 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001615 }
sewardjde4a1d02002-03-22 01:27:54 +00001616}
1617
1618
1619/* Debugging thing .. can be called from assembly with OYNK macro. */
1620void VG_(oynk) ( Int n )
1621{
1622 OINK(n);
1623}
1624
1625
1626/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1627 "valgrinq.so", which doesn't do anything. This is used to avoid
1628 tracing into child processes. To make this work the build system
1629 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001630
njn25e49d8e72002-09-23 09:36:25 +00001631 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1632 without it, child processes try to find valgrind.so symbols in the
1633 skin .so.
1634
sewardj78e25c92002-05-20 23:38:33 +00001635 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1636 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1637 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001638*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001639void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1640 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001641{
njn42e23f22003-05-05 12:47:25 +00001642 Char* vg_prel = NULL;
1643 Char* sk_prel = NULL;
1644 Char* pth_path = NULL;
1645 Char* p;
1646 Char* coredir_first;
1647 Char* coredir_last;
1648 Int coredir_len;
1649 Int i;
1650 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001651
njn42e23f22003-05-05 12:47:25 +00001652#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001653
njn42e23f22003-05-05 12:47:25 +00001654 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001655
njn42e23f22003-05-05 12:47:25 +00001656 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1657
1658 /* Setting up, finding things */
1659
1660 /* LD_PRELOAD: Search for "valgrind.so" */
1661 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1662
1663 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
1664 "valgrindq.so" should be there instead. Then stop. */
1665 if (NULL == vg_prel) {
1666 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001667 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001668 }
1669
njn42e23f22003-05-05 12:47:25 +00001670 /* LD_PRELOAD: coredir == directory containing "valgrind.so" */
1671 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001672
njn42e23f22003-05-05 12:47:25 +00001673 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1674 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1675 coredir_first = p+1;
1676 coredir_last = vg_prel - 1;
1677 coredir_len = coredir_last - coredir_first + 1;
1678
1679 /* LD_PRELOAD: find "vgskin_foo.so" */
1680 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1681 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001682
njn42e23f22003-05-05 12:47:25 +00001683 /* LD_LIBRARY_PATH: find coredir */
1684 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
1685 pth_path = VG_(strstr)(ld_library_path_str, coredir_first);
1686 if (pth_path == NULL) MUTANCY(5);
1687 *coredir_last = '/'; /* Undo zero-termination */
1688
1689 /* Changing things */
1690
1691 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1692 if (vg_prel[7] != 'd') MUTANCY(6);
1693 vg_prel[7] = 'q';
1694
1695 /* LD_PRELOAD: "/.../vgskin_foo.so" --> blank */
1696 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1697 p = sk_prel;
1698 while (*p != ':' && p >= ld_preload_str) {
1699 *p = ' ';
1700 p--;
njn25e49d8e72002-09-23 09:36:25 +00001701 }
njn42e23f22003-05-05 12:47:25 +00001702 /* Blank from "vgskin_" to next LD_PRELOAD entry (must be one, since
1703 the valgrind.so entry must follow) */
1704 p = sk_prel;
1705 while (*p != ':' && *p != '\0') {
1706 *p = ' ';
1707 p++;
1708 }
1709 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
1710 *p = ' '; /* blank ending ':' */
njn25e49d8e72002-09-23 09:36:25 +00001711
njn42e23f22003-05-05 12:47:25 +00001712 /* LD_LIBRARY_PATH: coredir --> blank */
1713 for (i = 0; i < coredir_len; i++)
1714 pth_path[i] = ' ';
1715
1716 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001717
sewardj78e25c92002-05-20 23:38:33 +00001718 return;
1719
njn42e23f22003-05-05 12:47:25 +00001720
1721mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001722 VG_(printf)(
1723 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1724 " what = %d\n"
1725 " ld_preload_str = `%s'\n"
1726 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001727 " vg_prel = `%s'\n"
1728 " sk_prel = `%s'\n"
1729 " pth_path = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001730 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001731 what, ld_preload_str, ld_library_path_str,
njn42e23f22003-05-05 12:47:25 +00001732 vg_prel, sk_prel, pth_path, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001733 );
sewardjc26b4482002-07-13 12:20:35 +00001734 VG_(printf)(
1735 "\n"
1736 "Note that this is often caused by mis-installation of valgrind.\n"
1737 "Correct installation procedure is:\n"
1738 " ./configure --prefix=/install/dir\n"
1739 " make install\n"
1740 "And then use /install/dir/bin/valgrind\n"
1741 "Moving the installation directory elsewhere after 'make install'\n"
1742 "will cause the above error. Hand-editing the paths in the shell\n"
1743 "scripts is also likely to cause problems.\n"
1744 "\n"
1745 );
njne427a662002-10-02 11:08:25 +00001746 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001747}
1748
sewardj3e1eb1f2002-05-18 13:14:17 +00001749
sewardjde4a1d02002-03-22 01:27:54 +00001750/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1751 it to attach to this process. Called if the user requests this
1752 service after an error has been shown, so she can poke around and
1753 look at parameters, memory, etc. You can't meaningfully get GDB to
1754 continue the program, though; to continue, quit GDB. */
1755extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1756{
sewardje6a25242002-04-21 22:03:07 +00001757 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001758 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001759
1760#define TO_STRING(x) TO_STRING2(x)
1761#define TO_STRING2(x) #x
1762
1763 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
njn17b85352003-04-18 12:54:24 +00001764 TO_STRING(GDB_PATH), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001765 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1766 res = VG_(system)(buf);
1767 if (res == 0) {
1768 VG_(message)(Vg_UserMsg, "");
1769 VG_(message)(Vg_UserMsg,
1770 "GDB has detached. Valgrind regains control. We continue.");
1771 } else {
1772 VG_(message)(Vg_UserMsg, "Apparently failed!");
1773 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001774 }
njn9315df32003-04-16 20:50:50 +00001775#undef TO_STRING
1776#undef TO_STRING2
sewardjde4a1d02002-03-22 01:27:54 +00001777}
1778
1779
1780/* Print some helpful-ish text about unimplemented things, and give
1781 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001782void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001783{
1784 VG_(message)(Vg_UserMsg, "");
1785 VG_(message)(Vg_UserMsg,
1786 "Valgrind detected that your program requires");
1787 VG_(message)(Vg_UserMsg,
1788 "the following unimplemented functionality:");
1789 VG_(message)(Vg_UserMsg, " %s", msg);
1790 VG_(message)(Vg_UserMsg,
1791 "This may be because the functionality is hard to implement,");
1792 VG_(message)(Vg_UserMsg,
1793 "or because no reasonable program would behave this way,");
1794 VG_(message)(Vg_UserMsg,
1795 "or because nobody has yet needed it. In any case, let me know");
1796 VG_(message)(Vg_UserMsg,
1797 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1798 VG_(message)(Vg_UserMsg,
1799 "");
1800 VG_(message)(Vg_UserMsg,
1801 "Valgrind has to exit now. Sorry. Bye!");
1802 VG_(message)(Vg_UserMsg,
1803 "");
sewardj15a43e12002-04-17 19:35:12 +00001804 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001805 VG_(exit)(1);
1806}
1807
1808
njn25e49d8e72002-09-23 09:36:25 +00001809/* ---------------------------------------------------------------------
1810 Sanity check machinery (permanently engaged).
1811 ------------------------------------------------------------------ */
1812
1813/* A fast sanity check -- suitable for calling circa once per
1814 millisecond. */
1815
1816void VG_(do_sanity_checks) ( Bool force_expensive )
1817{
1818 Int i;
1819
njn37cea302002-09-30 11:24:00 +00001820 VGP_PUSHCC(VgpCoreCheapSanity);
1821
njn25e49d8e72002-09-23 09:36:25 +00001822 if (VG_(sanity_level) < 1) return;
1823
1824 /* --- First do all the tests that we can do quickly. ---*/
1825
1826 VG_(sanity_fast_count)++;
1827
1828 /* Check that we haven't overrun our private stack. */
1829 for (i = 0; i < 10; i++) {
1830 vg_assert(VG_(stack)[i]
1831 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00001832 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
1833 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00001834 }
1835
1836 /* Check stuff pertaining to the memory check system. */
1837
1838 /* Check that nobody has spuriously claimed that the first or
1839 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001840 if (VG_(needs).sanity_checks) {
1841 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001842 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001843 VGP_POPCC(VgpSkinCheapSanity);
1844 }
njn25e49d8e72002-09-23 09:36:25 +00001845
1846 /* --- Now some more expensive checks. ---*/
1847
1848 /* Once every 25 times, check some more expensive stuff. */
1849 if ( force_expensive
1850 || VG_(sanity_level) > 1
1851 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1852
njn37cea302002-09-30 11:24:00 +00001853 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001854 VG_(sanity_slow_count)++;
1855
1856# if 0
1857 { void zzzmemscan(void); zzzmemscan(); }
1858# endif
1859
1860 if ((VG_(sanity_fast_count) % 250) == 0)
1861 VG_(sanity_check_tc_tt)();
1862
1863 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001864 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001865 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001866 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001867 }
1868 /*
1869 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1870 */
njn37cea302002-09-30 11:24:00 +00001871 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001872 }
1873
1874 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001875 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001876 /* Check sanity of the low-level memory manager. Note that bugs
1877 in the client's code can cause this to fail, so we don't do
1878 this check unless specially asked for. And because it's
1879 potentially very expensive. */
1880 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001881 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001882 }
njn37cea302002-09-30 11:24:00 +00001883 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001884}
sewardjde4a1d02002-03-22 01:27:54 +00001885/*--------------------------------------------------------------------*/
1886/*--- end vg_main.c ---*/
1887/*--------------------------------------------------------------------*/