blob: 2331ec25ec4dc5b783728df8749ad67d7cea20f2 [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 */
180static void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
181{
182 Int i;
183 for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
184}
sewardjde4a1d02002-03-22 01:27:54 +0000185
njnf4ce3d32003-02-10 10:17:26 +0000186Bool VG_(need_to_handle_esp_assignment)(void)
187{
njn9b007f62003-04-07 14:40:25 +0000188 return ( VG_(track_events).new_mem_stack_4 ||
189 VG_(track_events).die_mem_stack_4 ||
190 VG_(track_events).new_mem_stack_8 ||
191 VG_(track_events).die_mem_stack_8 ||
192 VG_(track_events).new_mem_stack_12 ||
193 VG_(track_events).die_mem_stack_12 ||
194 VG_(track_events).new_mem_stack_16 ||
195 VG_(track_events).die_mem_stack_16 ||
196 VG_(track_events).new_mem_stack_32 ||
197 VG_(track_events).die_mem_stack_32 ||
198 VG_(track_events).new_mem_stack ||
199 VG_(track_events).die_mem_stack
200 );
njnf4ce3d32003-02-10 10:17:26 +0000201}
202
sewardjde4a1d02002-03-22 01:27:54 +0000203/* Here we assign actual offsets. It's important to get the most
204 popular referents within 128 bytes of the start, so we can take
205 advantage of short addressing modes relative to %ebp. Popularity
206 of offsets was measured on 22 Feb 02 running a KDE application, and
207 the slots rearranged accordingly, with a 1.5% reduction in total
208 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000209static void vg_init_baseBlock ( void )
210{
sewardjde4a1d02002-03-22 01:27:54 +0000211 /* Those with offsets under 128 are carefully chosen. */
212
213 /* WORD offsets in this column */
214 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
215 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
216 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
217 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
218 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
219 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
220 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
221 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
222 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
223
njn25e49d8e72002-09-23 09:36:25 +0000224 if (VG_(needs).shadow_regs) {
225 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
226 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
227 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
228 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
229 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
230 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
231 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
232 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
233 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
234 }
sewardjde4a1d02002-03-22 01:27:54 +0000235
njn25e49d8e72002-09-23 09:36:25 +0000236 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
237 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000238
njn9b007f62003-04-07 14:40:25 +0000239 /* Make these most-frequently-called specialised ones compact, if they
240 are used. */
241 if (VG_(track_events).new_mem_stack_4)
242 VG_(register_compact_helper)( (Addr) VG_(track_events).new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000243
njn9b007f62003-04-07 14:40:25 +0000244 if (VG_(track_events).die_mem_stack_4)
245 VG_(register_compact_helper)( (Addr) VG_(track_events).die_mem_stack_4);
246
247 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000248 /* Allocate slots for compact helpers */
249 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
250 VG_(compact_helper_offsets),
251 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000252
njn25e49d8e72002-09-23 09:36:25 +0000253 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000254 VGOFF_(m_eip) = alloc_BaB(1);
255
256 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000257 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
258 * boundary at >= 32 words, but most spills are to low numbered spill
259 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000260 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
261
njn25e49d8e72002-09-23 09:36:25 +0000262 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000263 short-amode-boundary, there's no point. */
264
sewardjfa492d42002-12-08 18:20:01 +0000265 VGOFF_(m_dflag) = alloc_BaB(1);
266
sewardjb91ae7f2003-04-29 23:50:00 +0000267 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000268 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000269 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
270 vg_assert(
271 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
272 % 16 )
273 == 0
274 );
sewardjde4a1d02002-03-22 01:27:54 +0000275
sewardj92a59562002-09-30 00:53:10 +0000276 /* This thread's LDT pointer, and segment registers. */
277 VGOFF_(ldt) = alloc_BaB(1);
278 VGOFF_(m_cs) = alloc_BaB(1);
279 VGOFF_(m_ss) = alloc_BaB(1);
280 VGOFF_(m_ds) = alloc_BaB(1);
281 VGOFF_(m_es) = alloc_BaB(1);
282 VGOFF_(m_fs) = alloc_BaB(1);
283 VGOFF_(m_gs) = alloc_BaB(1);
284
sewardje1042472002-09-30 12:33:11 +0000285 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
286
njn9b007f62003-04-07 14:40:25 +0000287#define REG(kind, size) \
288 if (VG_(track_events).kind##_mem_stack##size) \
289 VG_(register_noncompact_helper)( \
290 (Addr) VG_(track_events).kind##_mem_stack##size );
291
292 REG(new, _8);
293 REG(new, _12);
294 REG(new, _16);
295 REG(new, _32);
296 REG(new, );
297 REG(die, _8);
298 REG(die, _12);
299 REG(die, _16);
300 REG(die, _32);
301 REG(die, );
302#undef REG
303
304 if (VG_(need_to_handle_esp_assignment)())
305 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
306
sewardj92a59562002-09-30 00:53:10 +0000307 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000308 VGOFF_(helper_idiv_64_32)
309 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
310 VGOFF_(helper_div_64_32)
311 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
312 VGOFF_(helper_idiv_32_16)
313 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
314 VGOFF_(helper_div_32_16)
315 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
316 VGOFF_(helper_idiv_16_8)
317 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
318 VGOFF_(helper_div_16_8)
319 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
320
321 VGOFF_(helper_imul_32_64)
322 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
323 VGOFF_(helper_mul_32_64)
324 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
325 VGOFF_(helper_imul_16_32)
326 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
327 VGOFF_(helper_mul_16_32)
328 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
329 VGOFF_(helper_imul_8_16)
330 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
331 VGOFF_(helper_mul_8_16)
332 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
333
334 VGOFF_(helper_CLD)
335 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
336 VGOFF_(helper_STD)
337 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
338 VGOFF_(helper_get_dirflag)
339 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
340
sewardj7d78e782002-06-02 00:04:00 +0000341 VGOFF_(helper_CLC)
342 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000343 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000344 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
345
sewardjde4a1d02002-03-22 01:27:54 +0000346 VGOFF_(helper_shldl)
347 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
348 VGOFF_(helper_shldw)
349 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
350 VGOFF_(helper_shrdl)
351 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
352 VGOFF_(helper_shrdw)
353 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
354
355 VGOFF_(helper_RDTSC)
356 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
357 VGOFF_(helper_CPUID)
358 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
359
sewardjde4a1d02002-03-22 01:27:54 +0000360 VGOFF_(helper_bsf)
361 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
362 VGOFF_(helper_bsr)
363 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
364
365 VGOFF_(helper_fstsw_AX)
366 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
367 VGOFF_(helper_SAHF)
368 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000369 VGOFF_(helper_DAS)
370 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000371 VGOFF_(helper_DAA)
372 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000373
sewardj51096432002-12-14 23:59:09 +0000374 VGOFF_(helper_undefined_instruction)
375 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
376
sewardj92a59562002-09-30 00:53:10 +0000377 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000378 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
379 VG_(noncompact_helper_offsets),
380 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000381
njncc7bb472002-10-14 09:25:19 +0000382
383 /* Initialise slots that require it */
384 VG_(copy_m_state_static_to_baseBlock)();
385
386 /* Pretend the root thread has a completely empty LDT to start with. */
387 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
388
389 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000390 if (VG_(needs).shadow_regs) {
391 UInt eflags;
392
393 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
394 VG_(baseBlock)[VGOFF_(sh_esp)] =
395 VG_(baseBlock)[VGOFF_(sh_ebp)] =
396 VG_(baseBlock)[VGOFF_(sh_eax)] =
397 VG_(baseBlock)[VGOFF_(sh_ecx)] =
398 VG_(baseBlock)[VGOFF_(sh_edx)] =
399 VG_(baseBlock)[VGOFF_(sh_ebx)] =
400 VG_(baseBlock)[VGOFF_(sh_esi)] =
401 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
402 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
403
njncc7bb472002-10-14 09:25:19 +0000404 } else {
njn25e49d8e72002-09-23 09:36:25 +0000405 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000406 }
sewardjde4a1d02002-03-22 01:27:54 +0000407}
408
409
410/* ---------------------------------------------------------------------
411 Global entities which are not referenced from generated code.
412 ------------------------------------------------------------------ */
413
414/* The stack on which Valgrind runs. We can't use the same stack as
415 the simulatee -- that's an important design decision. */
njn6eba4ef2003-05-01 08:06:41 +0000416UInt VG_(stack)[VG_STACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000417
418/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000419UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000420
421/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000422__attribute__ ((aligned (16)))
423UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000424Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000425
426/* Counts downwards in vg_run_innerloop. */
427UInt VG_(dispatch_ctr);
428
sewardjde4a1d02002-03-22 01:27:54 +0000429
430/* 64-bit counter for the number of basic blocks done. */
431ULong VG_(bbs_done);
432/* 64-bit counter for the number of bbs to go before a debug exit. */
433ULong VG_(bbs_to_go);
434
sewardj7e87e382002-05-03 19:09:05 +0000435/* This is the ThreadId of the last thread the scheduler ran. */
436ThreadId VG_(last_run_tid) = 0;
437
njn25e49d8e72002-09-23 09:36:25 +0000438/* This is the argument to __NR_exit() supplied by the first thread to
439 call that syscall. We eventually pass that to __NR_exit() for
440 real. */
njn633de322003-05-12 20:40:13 +0000441Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000442
sewardj73cf3bc2002-11-03 03:20:15 +0000443/* Tell the logging mechanism whether we are logging to a file
444 descriptor or a socket descriptor. */
445Bool VG_(logging_to_filedes) = True;
446
sewardjb91ae7f2003-04-29 23:50:00 +0000447/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
448 the SSE state all over the place. This is set up very early, in
449 vg_startup.S. We have to determine it early since we can't even
450 correctly snapshot the startup machine state without it. */
451/* Initially True. Safer to err on the side of SSEness and get SIGILL
452 than to not notice for some reason that we have SSE and get wierd
453 errors later on. */
454Bool VG_(have_ssestate) = True;
455
sewardjde4a1d02002-03-22 01:27:54 +0000456
457/* ---------------------------------------------------------------------
458 Counters, for informational purposes only.
459 ------------------------------------------------------------------ */
460
461/* Number of lookups which miss the fast tt helper. */
462UInt VG_(tt_fast_misses) = 0;
463
464
sewardjc0d8f682002-11-30 00:49:43 +0000465/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000466
sewardjde4a1d02002-03-22 01:27:54 +0000467/* Number and total o/t size of translations overall. */
468UInt VG_(overall_in_count) = 0;
469UInt VG_(overall_in_osize) = 0;
470UInt VG_(overall_in_tsize) = 0;
471/* Number and total o/t size of discards overall. */
472UInt VG_(overall_out_count) = 0;
473UInt VG_(overall_out_osize) = 0;
474UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000475/* The number of discards of TT/TC. */
476UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000477/* Counts of chain and unchain operations done. */
478UInt VG_(bb_enchain_count) = 0;
479UInt VG_(bb_dechain_count) = 0;
480/* Number of unchained jumps performed. */
481UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000482
483
484/* Counts pertaining to the register allocator. */
485
486/* total number of uinstrs input to reg-alloc */
487UInt VG_(uinstrs_prealloc) = 0;
488
489/* total number of uinstrs added due to spill code */
490UInt VG_(uinstrs_spill) = 0;
491
492/* number of bbs requiring spill code */
493UInt VG_(translations_needing_spill) = 0;
494
495/* total of register ranks over all translations */
496UInt VG_(total_reg_rank) = 0;
497
498
sewardjde4a1d02002-03-22 01:27:54 +0000499/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000500UInt VG_(sanity_fast_count) = 0;
501UInt VG_(sanity_slow_count) = 0;
502
sewardj2e93c502002-04-12 11:12:52 +0000503/* Counts pertaining to the scheduler. */
504UInt VG_(num_scheduling_events_MINOR) = 0;
505UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000506
507
508/* ---------------------------------------------------------------------
509 Values derived from command-line options.
510 ------------------------------------------------------------------ */
511
njn25e49d8e72002-09-23 09:36:25 +0000512/* Define, and set defaults. */
513Bool VG_(clo_error_limit) = True;
514Bool VG_(clo_GDB_attach) = False;
njn43c799e2003-04-08 00:08:52 +0000515Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000516Int VG_(sanity_level) = 1;
517Int VG_(clo_verbosity) = 1;
518Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000519Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000520
521/* See big comment in vg_include.h for meaning of these three. */
522VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
523Int VG_(clo_logfile_fd) = 2;
524Char* VG_(clo_logfile_name) = NULL;
525
njn25e49d8e72002-09-23 09:36:25 +0000526Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000527Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000528Bool VG_(clo_profile) = False;
529Bool VG_(clo_single_step) = False;
530Bool VG_(clo_optimise) = True;
531UChar VG_(clo_trace_codegen) = 0; // 00000000b
532Bool VG_(clo_trace_syscalls) = False;
533Bool VG_(clo_trace_signals) = False;
534Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000535Bool VG_(clo_trace_sched) = False;
536Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000537ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000538Int VG_(clo_dump_error) = 0;
539Int VG_(clo_backtrace_size) = 4;
540Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000541Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000542Bool VG_(clo_chain_bb) = True;
sewardj2370f3b2002-11-30 15:01:01 +0000543
sewardjde4a1d02002-03-22 01:27:54 +0000544/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
545 to behave. Initially we say False. */
546Bool VG_(running_on_simd_CPU) = False;
547
548/* Holds client's %esp at the point we gained control. */
549Addr VG_(esp_at_startup);
550
sewardjd5815ec2003-04-06 12:23:27 +0000551/* Indicates presence, and holds address of client's sysinfo page, a
552 feature of some modern kernels used to provide vsyscalls, etc. */
553Bool VG_(sysinfo_page_exists) = False;
554Addr VG_(sysinfo_page_addr) = 0;
555
sewardjde4a1d02002-03-22 01:27:54 +0000556/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
557 envp[] as extracted from the client's stack at startup-time. */
558Int VG_(client_argc);
559Char** VG_(client_argv);
560Char** VG_(client_envp);
561
562/* A place into which to copy the value of env var VG_ARGS, so we
563 don't have to modify the original. */
564static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
565
sewardjde4a1d02002-03-22 01:27:54 +0000566/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000567 Processing of command-line options.
568 ------------------------------------------------------------------ */
569
njn25e49d8e72002-09-23 09:36:25 +0000570void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000571{
572 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000573 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000574 VG_(clo_logfile_fd) = 2; /* stderr */
575 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
576 VG_(exit)(1);
577}
578
579static void config_error ( Char* msg )
580{
581 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000582 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000583 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000584 VG_(printf)(
585 "valgrind.so: Startup or configuration error:\n %s\n", msg);
586 VG_(printf)(
587 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000588 VG_(exit)(1);
589}
590
sewardja1679dd2002-05-10 22:31:40 +0000591static void args_grok_error ( Char* msg )
592{
593 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000594 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000595 VG_(clo_logfile_fd) = 2; /* stderr */
596 VG_(printf)("valgrind.so: When searching for "
597 "client's argc/argc/envp:\n\t%s\n", msg);
598 config_error("couldn't find client's argc/argc/envp");
599}
600
njn25e49d8e72002-09-23 09:36:25 +0000601static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000602{
njn25e49d8e72002-09-23 09:36:25 +0000603 Char* usage1 =
604"usage: valgrind [options] prog-and-args\n"
605"\n"
606" core user options, with defaults in [ ], are:\n"
607" --help show this message\n"
608" --version show version\n"
609" --skin=<name> main task (skin to use) [Valgrind]\n"
610" -q --quiet run silently; only print error msgs\n"
611" -v --verbose be more verbose, incl counts of errors\n"
612" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
njn43c799e2003-04-08 00:08:52 +0000613" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000614" --demangle=no|yes automatically demangle C++ names? [yes]\n"
615" --num-callers=<number> show <num> callers in stack traces [4]\n"
616" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000617" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000618" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000619" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000620" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000621" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000622" --suppressions=<filename> suppress errors described in\n"
623" suppressions file <filename>\n"
624" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000625" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000626"\n"
627" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000628
njn7cf0bd32002-06-08 13:36:03 +0000629
njn25e49d8e72002-09-23 09:36:25 +0000630 Char* usage2 =
631"\n"
632" core options for debugging Valgrind itself are:\n"
633" --sanity-level=<number> level of sanity checking to do [1]\n"
634" --single-step=no|yes translate each instr separately? [no]\n"
635" --optimise=no|yes improve intermediate code? [yes]\n"
636" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000637" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000638" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
639" --trace-syscalls=no|yes show all system calls? [no]\n"
640" --trace-signals=no|yes show signal handling details? [no]\n"
641" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000642" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000643" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000644" --stop-after=<number> switch to real CPU after executing\n"
645" <number> basic blocks [infinity]\n"
646" --dump-error=<number> show translation for basic block\n"
647" associated with <number>'th\n"
648" error context [0=don't show any]\n"
649"\n"
njn3e884182003-04-15 13:03:23 +0000650" %s skin debugging options:\n";
651
652 Char* usage3 =
653"\n"
njn25e49d8e72002-09-23 09:36:25 +0000654" Extra options are read from env variable $VALGRIND_OPTS\n"
655"\n"
njn0e1b5142003-04-15 14:58:06 +0000656" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000657" and licensed under the GNU General Public License, version 2.\n"
658" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000659"\n"
660" Skins are copyright and licensed by their authors. See each\n"
661" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000662"\n";
njn7cf0bd32002-06-08 13:36:03 +0000663
njnd04b7c62002-10-03 14:05:52 +0000664 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000665 /* Don't print skin string directly for security, ha! */
666 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000667 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000668 else
669 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000670 VG_(printf)(usage2, VG_(details).name);
671 if (VG_(needs).command_line_options)
672 SK_(print_debug_usage)();
673 else
674 VG_(printf)(" (none)\n");
675 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000676
njn25e49d8e72002-09-23 09:36:25 +0000677 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000678 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000679 VG_(clo_logfile_fd) = 2; /* stderr */
680 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000681}
sewardjde4a1d02002-03-22 01:27:54 +0000682
sewardj1c1b1162003-02-23 01:25:51 +0000683
sewardj49e630d2003-04-23 21:18:52 +0000684/* Callback for looking for the stack segment. */
685Addr VG_(foundstack_start) = (Addr)NULL;
686UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000687
688static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000689 Char r, Char w, Char x,
690 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000691{
692 Addr lastword;
693 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000694 if (r != 'r' || w != 'w'
695 /* || x != 'x' --not necessarily so on x86-64*/
696 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000697 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000698 if (start <= VG_(esp_at_startup)
699 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000700 VG_(foundstack_start) = start;
701 VG_(foundstack_size) = size;
702 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000703 }
704}
705
706
707
sewardjde4a1d02002-03-22 01:27:54 +0000708static void process_cmd_line_options ( void )
709{
njn25e49d8e72002-09-23 09:36:25 +0000710 Char* argv[M_VG_CMDLINE_OPTS];
711 UInt argc;
712 Char* p;
713 Char* str;
714 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000715
716# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000717
sewardjde4a1d02002-03-22 01:27:54 +0000718 eventually_logfile_fd = VG_(clo_logfile_fd);
719
720 /* Once logging is started, we can safely send messages pertaining
721 to failures in initialisation. */
722 VG_(startup_logging)();
723
sewardj19d81412002-06-03 01:10:40 +0000724 /* Check for sane path in ./configure --prefix=... */
725 if (VG_(strlen)(VG_LIBDIR) < 1
726 || VG_LIBDIR[0] != '/')
727 config_error("Please use absolute paths in "
728 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000729
sewardja1679dd2002-05-10 22:31:40 +0000730 /* (Suggested by Fabrice Bellard ... )
731 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000732 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000733 change less often than the libc ones. */
734 {
sewardj53fe4582003-02-23 01:41:17 +0000735 UInt* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000736
njn3e884182003-04-15 13:03:23 +0000737 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000738 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000739 has rwx permissions and no associated file. Note that this uses
740 the /proc/self/maps contents read at the start of VG_(main)(),
741 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000742
njn3e884182003-04-15 13:03:23 +0000743 VG_(read_procselfmaps)( vg_findstack_callback, /*read_from_file*/False );
sewardj53fe4582003-02-23 01:41:17 +0000744
sewardj49e630d2003-04-23 21:18:52 +0000745 /* Now foundstack_start and foundstack_size should delimit the stack. */
746 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000747 args_grok_error("Cannot determine stack segment "
748 "from /proc/self/maps");
749 }
sewardj1c1b1162003-02-23 01:25:51 +0000750
751 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000752 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000753 VG_(foundstack_start),
754 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000755
sewardj49e630d2003-04-23 21:18:52 +0000756 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000757 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
758 args_grok_error("Stack segment is not page aligned?!");
759 }
sewardj1c1b1162003-02-23 01:25:51 +0000760
sewardj53fe4582003-02-23 01:41:17 +0000761 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
762 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000763
sewardj38170912002-05-10 21:07:22 +0000764 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000765 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000766 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000767 sp--;
768 }
sewardj38170912002-05-10 21:07:22 +0000769
770 if (sp[2] == VKI_AT_BASE
771 && sp[0] == VKI_AT_PAGESZ
772 && sp[-2] == VKI_AT_PHNUM
773 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000774 && sp[-6] == VKI_AT_PHDR
775 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000776 if (0)
777 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000778 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000779 } else
780 if (sp[2] == VKI_AT_CLKTCK
781 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000782 && sp[-2] == VKI_AT_HWCAP
783 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000784 if (0)
785 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
786 sp -= 2;
787 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000788 if (sp[2] == VKI_AT_CLKTCK
789 && sp[0] == VKI_AT_PAGESZ
790 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000791 && sp[-4] == VKI_AT_SYSINFO
792 && sp[-4-1] == 0) {
793 if (0)
794 VG_(printf)("Looks like you've got a 2.4.X kernel with "
795 "a sysinfo page at %x here.\n", sp[-3]);
796 VG_(sysinfo_page_exists) = True;
797 VG_(sysinfo_page_addr) = sp[-3];
798 sp -= 4;
799 } else
800 if (sp[2] == VKI_AT_CLKTCK
801 && sp[0] == VKI_AT_PAGESZ
802 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000803 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
804 && sp[-4-1] == 0) {
805 if (0)
806 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
807 "kernel here.\n");
808 sp -= 4;
809 } else
810 if (sp[2] == VKI_AT_CLKTCK
811 && sp[0] == VKI_AT_PAGESZ
812 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000813 && sp[-2-20-1] == 0) {
814 if (0)
815 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
816 sp -= 22;
817 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000818 if (sp[2] == VKI_AT_CLKTCK
819 && sp[0] == VKI_AT_PAGESZ
820 && sp[-2] == VKI_AT_HWCAP
821 && sp[-4-1] == 0) {
822 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000823 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000824 sp -= 4;
825 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000826 if (sp[2] == VKI_AT_CLKTCK
827 && sp[0] == VKI_AT_PAGESZ
828 && sp[-2] == VKI_AT_HWCAP
829 && sp[-6] == VKI_AT_SYSINFO
830 && sp[-6-1] == 0) {
831 if (0)
832 VG_(printf)("Looks like a >= 2.5.68 kernel with "
833 "a sysinfo page at %x here.\n", sp[-5]);
834 VG_(sysinfo_page_exists) = True;
835 VG_(sysinfo_page_addr) = sp[-5];
836 sp -= 6;
837 } else
sewardja1679dd2002-05-10 22:31:40 +0000838 args_grok_error(
839 "ELF frame does not look like 2.2.X or 2.4.X.\n "
840 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
841 );
sewardj38170912002-05-10 21:07:22 +0000842
843 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000844 if (*sp != 0)
845 args_grok_error("can't find NULL at end of env[]");
846
sewardj38170912002-05-10 21:07:22 +0000847 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000848 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000849 while (True) {
850 sp --;
851 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000852 if (++ctr >= 1000)
853 args_grok_error(
854 "suspiciously many (1000) env[] entries; giving up");
855
sewardj38170912002-05-10 21:07:22 +0000856 }
857 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000858 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000859
sewardja1679dd2002-05-10 22:31:40 +0000860 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000861 VG_(client_argc) = 0;
862 while (True) {
863 sp--;
864 if (*sp == VG_(client_argc))
865 break;
866 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000867 if (++ctr >= 1000)
868 args_grok_error(
869 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000870 }
871
sewardja1679dd2002-05-10 22:31:40 +0000872 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000873 }
874
sewardjde4a1d02002-03-22 01:27:54 +0000875 /* Now that VG_(client_envp) has been set, we can extract the args
876 for Valgrind itself. Copy into global var so that we don't have to
877 write zeroes to the getenv'd value itself. */
878 str = VG_(getenv)("VG_ARGS");
879 argc = 0;
880
881 if (!str) {
882 config_error("Can't read options from env var VG_ARGS.");
883 }
884
885 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
886 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
887 }
888 VG_(strcpy)(vg_cmdline_copy, str);
889 str = NULL;
890
891 p = &vg_cmdline_copy[0];
892 while (True) {
893 while (ISSPACE(*p)) { *p = 0; p++; }
894 if (*p == 0) break;
895 if (argc < M_VG_CMDLINE_OPTS-1) {
896 argv[argc] = p; argc++;
897 } else {
898 config_error(
899 "Found more than M_CMDLINE_OPTS command-line opts.");
900 }
901 while (*p != 0 && !ISSPACE(*p)) p++;
902 }
903
904 for (i = 0; i < argc; i++) {
905
njn43c799e2003-04-08 00:08:52 +0000906 if (VG_CLO_STREQ(argv[i], "-v") ||
907 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000908 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000909 else if (VG_CLO_STREQ(argv[i], "-q") ||
910 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000911 VG_(clo_verbosity)--;
912
njn43c799e2003-04-08 00:08:52 +0000913 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000914 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000915 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000916 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000917
njn43c799e2003-04-08 00:08:52 +0000918 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000919 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000920 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000921 VG_(clo_GDB_attach) = False;
922
njn43c799e2003-04-08 00:08:52 +0000923 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
924 VG_(clo_gen_suppressions) = True;
925 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
926 VG_(clo_gen_suppressions) = False;
927
928 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000929 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000930 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000931 VG_(clo_demangle) = False;
932
njn43c799e2003-04-08 00:08:52 +0000933 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000934 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000935 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000936 VG_(clo_trace_children) = False;
937
njn43c799e2003-04-08 00:08:52 +0000938 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000939 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000940 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000941 VG_(clo_run_libc_freeres) = False;
942
njn43c799e2003-04-08 00:08:52 +0000943 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000944 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
945
njn43c799e2003-04-08 00:08:52 +0000946 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000947 VG_(clo_log_to) = VgLogTo_Fd;
948 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000949 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000950 }
951
njn43c799e2003-04-08 00:08:52 +0000952 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000953 VG_(clo_log_to) = VgLogTo_File;
954 VG_(clo_logfile_name) = &argv[i][10];
955 }
sewardjde4a1d02002-03-22 01:27:54 +0000956
njn43c799e2003-04-08 00:08:52 +0000957 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000958 VG_(clo_log_to) = VgLogTo_Socket;
959 VG_(clo_logfile_name) = &argv[i][12];
960 }
961
njn43c799e2003-04-08 00:08:52 +0000962 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000963 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000964 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000965 VG_(message)(Vg_UserMsg,
966 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000967 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000968 }
969 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
970 VG_(clo_n_suppressions)++;
971 }
njn43c799e2003-04-08 00:08:52 +0000972 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000973 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000974 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000975 VG_(clo_profile) = False;
976
njn43c799e2003-04-08 00:08:52 +0000977 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000978 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000979 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000980 VG_(clo_chain_bb) = False;
981
njn43c799e2003-04-08 00:08:52 +0000982 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000983 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000984 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000985 VG_(clo_single_step) = False;
986
njn43c799e2003-04-08 00:08:52 +0000987 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000988 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000989 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000990 VG_(clo_optimise) = False;
991
njn25e49d8e72002-09-23 09:36:25 +0000992 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +0000993 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +0000994 Int j;
995 char* opt = & argv[i][16];
996
997 if (5 != VG_(strlen)(opt)) {
998 VG_(message)(Vg_UserMsg,
999 "--trace-codegen argument must have 5 digits");
1000 VG_(bad_option)(argv[i]);
1001 }
1002 for (j = 0; j < 5; j++) {
1003 if ('0' == opt[j]) { /* do nothing */ }
1004 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1005 else {
1006 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1007 "contain 0s and 1s");
1008 VG_(bad_option)(argv[i]);
1009 }
1010 }
1011 }
sewardjde4a1d02002-03-22 01:27:54 +00001012
njn43c799e2003-04-08 00:08:52 +00001013 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001014 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001015 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001016 VG_(clo_trace_syscalls) = False;
1017
njn43c799e2003-04-08 00:08:52 +00001018 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001019 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001020 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001021 VG_(clo_trace_signals) = False;
1022
njn43c799e2003-04-08 00:08:52 +00001023 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001024 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001025 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001026 VG_(clo_trace_symtab) = False;
1027
njn43c799e2003-04-08 00:08:52 +00001028 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001029 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001030 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001031 VG_(clo_trace_sched) = False;
1032
njn43c799e2003-04-08 00:08:52 +00001033 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001034 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001035 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001036 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001037 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001038 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001039
njn43c799e2003-04-08 00:08:52 +00001040 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001041 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001042
njn43c799e2003-04-08 00:08:52 +00001043 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001044 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1045
njn43c799e2003-04-08 00:08:52 +00001046 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001047 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1048
njn43c799e2003-04-08 00:08:52 +00001049 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001050 /* Make sure it's sane. */
1051 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1052 if (VG_(clo_backtrace_size) < 2)
1053 VG_(clo_backtrace_size) = 2;
1054 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1055 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1056 }
1057
njn25e49d8e72002-09-23 09:36:25 +00001058 else if (VG_(needs).command_line_options) {
1059 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1060 if (!ok)
1061 usage();
1062 }
sewardjde4a1d02002-03-22 01:27:54 +00001063 else
njn25e49d8e72002-09-23 09:36:25 +00001064 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001065 }
1066
1067# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001068
njnf9ebf672003-05-12 21:41:30 +00001069 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001070 VG_(clo_verbosity) = 0;
1071
1072 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1073 VG_(message)(Vg_UserMsg, "");
1074 VG_(message)(Vg_UserMsg,
1075 "--gdb-attach=yes conflicts with --trace-children=yes");
1076 VG_(message)(Vg_UserMsg,
1077 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001078 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001079 }
1080
sewardj4cf05692002-10-27 20:28:29 +00001081 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1082 should be connected to whatever sink has been selected, and we
1083 indiscriminately chuck stuff into it without worrying what the
1084 nature of it is. Oh the wonder of Unix streams. */
1085
1086 /* So far we should be still attached to stderr, so we can show on
1087 the terminal any problems to do with processing command line
1088 opts. */
1089 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001090 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001091
1092 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001093
sewardj4cf05692002-10-27 20:28:29 +00001094 case VgLogTo_Fd:
1095 vg_assert(VG_(clo_logfile_name) == NULL);
1096 VG_(clo_logfile_fd) = eventually_logfile_fd;
1097 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001098
sewardj4cf05692002-10-27 20:28:29 +00001099 case VgLogTo_File: {
1100 Char logfilename[1000];
1101 vg_assert(VG_(clo_logfile_name) != NULL);
1102 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1103 VG_(sprintf)(logfilename, "%s.pid%d",
1104 VG_(clo_logfile_name), VG_(getpid)() );
1105 eventually_logfile_fd
1106 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1107 VKI_S_IRUSR|VKI_S_IWUSR);
1108 if (eventually_logfile_fd != -1) {
1109 VG_(clo_logfile_fd) = eventually_logfile_fd;
1110 } else {
1111 VG_(message)(Vg_UserMsg,
1112 "Can't create/open log file `%s.pid%d'; giving up!",
1113 VG_(clo_logfile_name), VG_(getpid)());
1114 VG_(bad_option)(
1115 "--logfile=<file> didn't work out for some reason.");
1116 }
1117 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001118 }
1119
1120 case VgLogTo_Socket: {
1121 vg_assert(VG_(clo_logfile_name) != NULL);
1122 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1123 eventually_logfile_fd
1124 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1125 if (eventually_logfile_fd == -1) {
1126 VG_(message)(Vg_UserMsg,
1127 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1128 VG_(message)(Vg_UserMsg,
1129 "of `%s'; giving up!", VG_(clo_logfile_name) );
1130 VG_(bad_option)(
1131 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001132 }
sewardj73cf3bc2002-11-03 03:20:15 +00001133 if (eventually_logfile_fd == -2) {
1134 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001135 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001136 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001137 VG_(message)(Vg_UserMsg,
1138 "Log messages will sent to stderr instead." );
1139 VG_(message)(Vg_UserMsg,
1140 "" );
1141 /* We don't change anything here. */
1142 } else {
1143 vg_assert(eventually_logfile_fd > 0);
1144 VG_(clo_logfile_fd) = eventually_logfile_fd;
1145 VG_(logging_to_filedes) = False;
1146 }
sewardj73cf3bc2002-11-03 03:20:15 +00001147 break;
1148 }
1149
sewardj4cf05692002-10-27 20:28:29 +00001150 }
1151
1152 /* Ok, the logging sink is running now. Print a suitable preamble.
1153 If logging to file or a socket, write details of parent PID and
1154 command line args, to help people trying to interpret the
1155 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001156
sewardj83adf412002-05-01 01:25:45 +00001157 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001158 /* Skin details */
1159 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1160 VG_(details).name,
1161 NULL == VG_(details).version ? "" : "-",
1162 NULL == VG_(details).version
1163 ? (Char*)"" : VG_(details).version,
1164 VG_(details).description);
1165 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001166
njnd04b7c62002-10-03 14:05:52 +00001167 /* Core details */
1168 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001169 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001170 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001171 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001172 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001173 }
1174
sewardj4cf05692002-10-27 20:28:29 +00001175 if (VG_(clo_log_to) != VgLogTo_Fd) {
1176 VG_(message)(Vg_UserMsg, "");
1177 VG_(message)(Vg_UserMsg,
1178 "My PID = %d, parent PID = %d. Prog and args are:",
1179 VG_(getpid)(), VG_(getppid)() );
1180 for (i = 0; i < VG_(client_argc); i++)
1181 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1182 }
1183
sewardjde4a1d02002-03-22 01:27:54 +00001184 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001185 if (VG_(clo_log_to) != VgLogTo_Fd)
1186 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001187 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1188 for (i = 0; i < argc; i++) {
1189 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1190 }
1191 }
1192
njn25e49d8e72002-09-23 09:36:25 +00001193 if (VG_(clo_n_suppressions) == 0 &&
1194 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001195 config_error("No error-suppression files were specified.");
1196 }
sewardj4cf05692002-10-27 20:28:29 +00001197
sewardjde4a1d02002-03-22 01:27:54 +00001198}
1199
sewardjde4a1d02002-03-22 01:27:54 +00001200/* ---------------------------------------------------------------------
1201 Copying to/from m_state_static.
1202 ------------------------------------------------------------------ */
1203
sewardjb91ae7f2003-04-29 23:50:00 +00001204/* See comment about this in vg_include.h. Change only with
1205 great care.
1206*/
1207__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001208UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1209 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001210 + 1 /* %eflags */
1211 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001212 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001213 ];
1214
sewardjfa492d42002-12-08 18:20:01 +00001215UInt VG_(insertDflag)(UInt eflags, Int d)
1216{
1217 vg_assert(d == 1 || d == -1);
1218 eflags &= ~EFlagD;
1219
1220 if (d < 0)
1221 eflags |= EFlagD;
1222
1223 return eflags;
1224}
1225
1226Int VG_(extractDflag)(UInt eflags)
1227{
1228 Int ret;
1229
1230 if (eflags & EFlagD)
1231 ret = -1;
1232 else
1233 ret = 1;
1234
1235 return ret;
1236}
1237
sewardjde4a1d02002-03-22 01:27:54 +00001238void VG_(copy_baseBlock_to_m_state_static) ( void )
1239{
1240 Int i;
sewardj92a59562002-09-30 00:53:10 +00001241 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1242 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1243 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1244 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1245 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1246 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001247
sewardj92a59562002-09-30 00:53:10 +00001248 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1249 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1250 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1251 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1252 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1253 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1254 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1255 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1256
sewardjb91ae7f2003-04-29 23:50:00 +00001257 VG_(m_state_static)[56/4]
1258 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1259 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001260 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001261
sewardjb91ae7f2003-04-29 23:50:00 +00001262 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001263 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001264 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001265}
1266
1267
1268void VG_(copy_m_state_static_to_baseBlock) ( void )
1269{
1270 Int i;
sewardj92a59562002-09-30 00:53:10 +00001271 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1272 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1273 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1274 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1275 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1276 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001277
sewardj92a59562002-09-30 00:53:10 +00001278 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1279 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1280 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1281 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1282 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1283 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1284 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1285 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1286
sewardjb91ae7f2003-04-29 23:50:00 +00001287 VG_(baseBlock)[VGOFF_(m_eflags)]
1288 = VG_(m_state_static)[56/4] & ~EFlagD;
1289 VG_(baseBlock)[VGOFF_(m_dflag)]
1290 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001291
sewardj92a59562002-09-30 00:53:10 +00001292 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001293
sewardjb91ae7f2003-04-29 23:50:00 +00001294 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1295 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001296 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001297}
1298
njn25e49d8e72002-09-23 09:36:25 +00001299Addr VG_(get_stack_pointer) ( void )
1300{
1301 return VG_(baseBlock)[VGOFF_(m_esp)];
1302}
1303
1304/* Some random tests needed for leak checking */
1305
1306Bool VG_(within_stack)(Addr a)
1307{
1308 if (a >= ((Addr)(&VG_(stack)))
1309 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1310 return True;
1311 else
1312 return False;
1313}
1314
1315Bool VG_(within_m_state_static)(Addr a)
1316{
1317 if (a >= ((Addr)(&VG_(m_state_static)))
1318 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1319 return True;
1320 else
1321 return False;
1322}
sewardjde4a1d02002-03-22 01:27:54 +00001323
1324/* ---------------------------------------------------------------------
1325 Show accumulated counts.
1326 ------------------------------------------------------------------ */
1327
njn25e49d8e72002-09-23 09:36:25 +00001328static __inline__ Int safe_idiv(Int a, Int b)
1329{
1330 return (b == 0 ? 0 : a / b);
1331}
1332
sewardjde4a1d02002-03-22 01:27:54 +00001333static void vg_show_counts ( void )
1334{
1335 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001336 " TT/TC: %d tc sectors discarded.",
1337 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001338 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001339 " %d chainings, %d unchainings.",
1340 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1341 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001342 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001343 VG_(overall_in_count),
1344 VG_(overall_in_osize),
1345 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001346 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1347 VG_(message)(Vg_DebugMsg,
1348 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001349 VG_(overall_out_count),
1350 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001351 VG_(overall_out_tsize),
1352 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001353 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001354 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001355 VG_(bbs_done),
1356 VG_(unchained_jumps_done),
1357 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1358 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1359 );
1360
1361 VG_(message)(Vg_DebugMsg,
1362 " %d/%d major/minor sched events. %d tt_fast misses.",
1363 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001364 VG_(num_scheduling_events_MINOR),
1365 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001366
sewardjde4a1d02002-03-22 01:27:54 +00001367 VG_(message)(Vg_DebugMsg,
1368 "reg-alloc: %d t-req-spill, "
1369 "%d+%d orig+spill uis, %d total-reg-r.",
1370 VG_(translations_needing_spill),
1371 VG_(uinstrs_prealloc),
1372 VG_(uinstrs_spill),
1373 VG_(total_reg_rank) );
1374 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001375 " sanity: %d cheap, %d expensive checks.",
1376 VG_(sanity_fast_count),
1377 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001378 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001379}
1380
1381
1382/* ---------------------------------------------------------------------
1383 Main!
1384 ------------------------------------------------------------------ */
1385
1386/* Where we jump to once Valgrind has got control, and the real
1387 machine's state has been copied to the m_state_static. */
1388
1389void VG_(main) ( void )
1390{
sewardj2e93c502002-04-12 11:12:52 +00001391 Int i;
1392 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001393 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001394
njn0c7a5b52003-04-30 09:00:33 +00001395 if (0) {
1396 if (VG_(have_ssestate))
1397 VG_(printf)("Looks like a SSE-capable CPU\n");
1398 else
1399 VG_(printf)("Looks like a MMX-only CPU\n");
1400 }
sewardjb91ae7f2003-04-29 23:50:00 +00001401
njn27f1a382002-11-08 15:48:16 +00001402 /* Check skin and core versions are compatible */
1403 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1404 VG_(printf)("Error:\n"
1405 " Skin and core interface versions do not match.\n"
1406 " Interface version used by core is: %d.%d\n"
1407 " Interface version used by skin is: %d.%d\n"
1408 " The major version numbers must match.\n",
1409 VG_CORE_INTERFACE_MAJOR_VERSION,
1410 VG_CORE_INTERFACE_MINOR_VERSION,
1411 VG_(skin_interface_major_version),
1412 VG_(skin_interface_minor_version));
1413 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1414 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1415 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1416 else
1417 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1418 VG_(printf)(" Aborting, sorry.\n");
1419 VG_(exit)(1);
1420 }
1421
sewardjde4a1d02002-03-22 01:27:54 +00001422 /* Set up our stack sanity-check words. */
1423 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001424 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1425 VG_(stack)[VG_STACK_SIZE_W-1-i]
1426 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001427 }
1428
njn3e884182003-04-15 13:03:23 +00001429 /* Read /proc/self/maps into a buffer. Must be before:
1430 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1431 superblocks are not erroneously identified as being owned by the
1432 client, which would be bad.
1433 - init_memory(): that's where the buffer is parsed
1434 - init_tt_tc(): so the anonymous mmaps for the translation table and
1435 translation cache aren't identified as part of the client, which would
1436 waste > 20M of virtual address space, and be bad.
1437 */
1438 VG_(read_procselfmaps_contents)();
1439
sewardj1c1b1162003-02-23 01:25:51 +00001440 /* Hook to delay things long enough so we can get the pid and
1441 attach GDB in another shell. */
1442 if (0) {
1443 Int p, q;
1444 VG_(printf)("pid=%d\n", VG_(getpid)());
1445 for (p = 0; p < 50000; p++)
1446 for (q = 0; q < 50000; q++) ;
1447 }
1448
njn25e49d8e72002-09-23 09:36:25 +00001449 /* Setup stuff that depends on the skin. Must be before:
1450 - vg_init_baseBlock(): to register helpers
1451 - process_cmd_line_options(): to register skin name and description,
1452 and turn on/off 'command_line_options' need
1453 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001454 */
njn810086f2002-11-14 12:42:47 +00001455 SK_(pre_clo_init)();
1456 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001457
njncc7bb472002-10-14 09:25:19 +00001458 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001459 process_cmd_line_options();
1460
njn3e884182003-04-15 13:03:23 +00001461 /* Do post command-line processing initialisation. Must be before:
1462 - vg_init_baseBlock(): to register any more helpers
1463 */
njncc7bb472002-10-14 09:25:19 +00001464 SK_(post_clo_init)();
1465
njn3e884182003-04-15 13:03:23 +00001466 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001467 vg_init_baseBlock();
1468
sewardj018f7622002-05-15 21:13:39 +00001469 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001470 baseBlock into VG_(threads)[1]. Must be before:
1471 - VG_(sigstartup_actions)()
1472 */
sewardj018f7622002-05-15 21:13:39 +00001473 VG_(scheduler_init)();
1474
1475 /* Initialise the signal handling subsystem, temporarily parking
1476 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001477 VG_(sigstartup_actions)();
1478
sewardj018f7622002-05-15 21:13:39 +00001479 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001480 if (VG_(clo_profile))
1481 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001482
sewardj5f07b662002-04-23 16:52:51 +00001483 /* Start calibration of our RDTSC-based clock. */
1484 VG_(start_rdtsc_calibration)();
1485
njn3e884182003-04-15 13:03:23 +00001486 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001487 VGP_PUSHCC(VgpInitMem);
1488 VG_(init_memory)();
1489 VGP_POPCC(VgpInitMem);
1490
1491 /* Read the list of errors to suppress. This should be found in
1492 the file specified by vg_clo_suppressions. */
1493 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1494 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001495
sewardj5f07b662002-04-23 16:52:51 +00001496 /* End calibration of our RDTSC-based clock, leaving it as long as
1497 we can. */
1498 VG_(end_rdtsc_calibration)();
1499
njn3e884182003-04-15 13:03:23 +00001500 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001501 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001502
1503 if (VG_(clo_verbosity) == 1) {
1504 VG_(message)(Vg_UserMsg,
1505 "For more details, rerun with: -v");
1506 }
1507
1508 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1509 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001510 if (VG_(clo_verbosity) > 0)
1511 VG_(message)(Vg_UserMsg, "");
1512
1513 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001514
sewardj018f7622002-05-15 21:13:39 +00001515 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001516 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001517 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001518 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001519 VGP_POPCC(VgpSched);
1520 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001521
1522 if (VG_(clo_verbosity) > 0)
1523 VG_(message)(Vg_UserMsg, "");
1524
sewardj2e93c502002-04-12 11:12:52 +00001525 if (src == VgSrc_Deadlock) {
1526 VG_(message)(Vg_UserMsg,
1527 "Warning: pthread scheduler exited due to deadlock");
1528 }
1529
njn25e49d8e72002-09-23 09:36:25 +00001530 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001531 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001532
njn7d9f94d2003-04-22 21:41:40 +00001533 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001534
sewardj0c3b53f2002-05-01 01:58:35 +00001535 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001536
1537 if (VG_(clo_verbosity) > 1)
1538 vg_show_counts();
1539
sewardjc0d8f682002-11-30 00:49:43 +00001540 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001541 VG_(print_UInstr_histogram)();
1542
sewardjde4a1d02002-03-22 01:27:54 +00001543 if (0) {
1544 VG_(message)(Vg_DebugMsg, "");
1545 VG_(message)(Vg_DebugMsg,
1546 "------ Valgrind's internal memory use stats follow ------" );
1547 VG_(mallocSanityCheckAll)();
1548 VG_(show_all_arena_stats)();
1549 VG_(message)(Vg_DebugMsg,
1550 "------ Valgrind's ExeContext management stats follow ------" );
1551 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001552 }
1553
njn25e49d8e72002-09-23 09:36:25 +00001554 if (VG_(clo_profile))
1555 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001556
1557 VG_(shutdown_logging)();
1558
sewardj3e1eb1f2002-05-18 13:14:17 +00001559 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1560 processes don't get traced into. Also mess up $libdir/valgrind
1561 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001562 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1563 pointless when we are just about to VgSrc_ExitSyscall. So don't
1564 bother in that case. */
1565 if ((!VG_(clo_trace_children))
1566 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001567 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1568 VG_(getenv)("LD_PRELOAD"),
1569 VG_(getenv)("LD_LIBRARY_PATH")
1570 );
sewardjde4a1d02002-03-22 01:27:54 +00001571 }
1572
sewardj7e87e382002-05-03 19:09:05 +00001573 /* Decide how to exit. This depends on what the scheduler
1574 returned. */
1575 switch (src) {
1576 case VgSrc_ExitSyscall: /* the normal way out */
1577 vg_assert(VG_(last_run_tid) > 0
1578 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001579 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001580 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001581 /* The thread's %EBX at the time it did __NR_exit() will hold
1582 the arg to __NR_exit(), so we just do __NR_exit() with
1583 that arg. */
1584 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001585 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001586 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001587 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001588
sewardj7e87e382002-05-03 19:09:05 +00001589 case VgSrc_Deadlock:
1590 /* Just exit now. No point in continuing. */
1591 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001592 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001593 break;
1594
1595 case VgSrc_BbsDone:
1596 /* Tricky; we have to try and switch back to the real CPU.
1597 This is all very dodgy and won't work at all in the
1598 presence of threads, or if the client happened to be
1599 running a signal handler. */
1600 /* Prepare to restore state to the real CPU. */
1601 VG_(load_thread_state)(1 /* root thread */ );
1602 VG_(copy_baseBlock_to_m_state_static)();
1603
1604 /* This pushes a return address on the simulator's stack,
1605 which is abandoned. We call vg_sigshutdown_actions() at
1606 the end of vg_switch_to_real_CPU(), so as to ensure that
1607 the original stack and machine state is restored before
1608 the real signal mechanism is restored. */
1609 VG_(switch_to_real_CPU)();
1610
1611 default:
njne427a662002-10-02 11:08:25 +00001612 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001613 }
sewardjde4a1d02002-03-22 01:27:54 +00001614}
1615
1616
1617/* Debugging thing .. can be called from assembly with OYNK macro. */
1618void VG_(oynk) ( Int n )
1619{
1620 OINK(n);
1621}
1622
1623
1624/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1625 "valgrinq.so", which doesn't do anything. This is used to avoid
1626 tracing into child processes. To make this work the build system
1627 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001628
njn25e49d8e72002-09-23 09:36:25 +00001629 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1630 without it, child processes try to find valgrind.so symbols in the
1631 skin .so.
1632
sewardj78e25c92002-05-20 23:38:33 +00001633 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1634 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1635 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001636*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001637void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1638 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001639{
njn42e23f22003-05-05 12:47:25 +00001640 Char* vg_prel = NULL;
1641 Char* sk_prel = NULL;
1642 Char* pth_path = NULL;
1643 Char* p;
1644 Char* coredir_first;
1645 Char* coredir_last;
1646 Int coredir_len;
1647 Int i;
1648 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001649
njn42e23f22003-05-05 12:47:25 +00001650#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001651
njn42e23f22003-05-05 12:47:25 +00001652 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001653
njn42e23f22003-05-05 12:47:25 +00001654 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1655
1656 /* Setting up, finding things */
1657
1658 /* LD_PRELOAD: Search for "valgrind.so" */
1659 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1660
1661 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
1662 "valgrindq.so" should be there instead. Then stop. */
1663 if (NULL == vg_prel) {
1664 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001665 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001666 }
1667
njn42e23f22003-05-05 12:47:25 +00001668 /* LD_PRELOAD: coredir == directory containing "valgrind.so" */
1669 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001670
njn42e23f22003-05-05 12:47:25 +00001671 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1672 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1673 coredir_first = p+1;
1674 coredir_last = vg_prel - 1;
1675 coredir_len = coredir_last - coredir_first + 1;
1676
1677 /* LD_PRELOAD: find "vgskin_foo.so" */
1678 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1679 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001680
njn42e23f22003-05-05 12:47:25 +00001681 /* LD_LIBRARY_PATH: find coredir */
1682 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
1683 pth_path = VG_(strstr)(ld_library_path_str, coredir_first);
1684 if (pth_path == NULL) MUTANCY(5);
1685 *coredir_last = '/'; /* Undo zero-termination */
1686
1687 /* Changing things */
1688
1689 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1690 if (vg_prel[7] != 'd') MUTANCY(6);
1691 vg_prel[7] = 'q';
1692
1693 /* LD_PRELOAD: "/.../vgskin_foo.so" --> blank */
1694 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1695 p = sk_prel;
1696 while (*p != ':' && p >= ld_preload_str) {
1697 *p = ' ';
1698 p--;
njn25e49d8e72002-09-23 09:36:25 +00001699 }
njn42e23f22003-05-05 12:47:25 +00001700 /* Blank from "vgskin_" to next LD_PRELOAD entry (must be one, since
1701 the valgrind.so entry must follow) */
1702 p = sk_prel;
1703 while (*p != ':' && *p != '\0') {
1704 *p = ' ';
1705 p++;
1706 }
1707 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
1708 *p = ' '; /* blank ending ':' */
njn25e49d8e72002-09-23 09:36:25 +00001709
njn42e23f22003-05-05 12:47:25 +00001710 /* LD_LIBRARY_PATH: coredir --> blank */
1711 for (i = 0; i < coredir_len; i++)
1712 pth_path[i] = ' ';
1713
1714 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001715
sewardj78e25c92002-05-20 23:38:33 +00001716 return;
1717
njn42e23f22003-05-05 12:47:25 +00001718
1719mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001720 VG_(printf)(
1721 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1722 " what = %d\n"
1723 " ld_preload_str = `%s'\n"
1724 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001725 " vg_prel = `%s'\n"
1726 " sk_prel = `%s'\n"
1727 " pth_path = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001728 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001729 what, ld_preload_str, ld_library_path_str,
njn42e23f22003-05-05 12:47:25 +00001730 vg_prel, sk_prel, pth_path, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001731 );
sewardjc26b4482002-07-13 12:20:35 +00001732 VG_(printf)(
1733 "\n"
1734 "Note that this is often caused by mis-installation of valgrind.\n"
1735 "Correct installation procedure is:\n"
1736 " ./configure --prefix=/install/dir\n"
1737 " make install\n"
1738 "And then use /install/dir/bin/valgrind\n"
1739 "Moving the installation directory elsewhere after 'make install'\n"
1740 "will cause the above error. Hand-editing the paths in the shell\n"
1741 "scripts is also likely to cause problems.\n"
1742 "\n"
1743 );
njne427a662002-10-02 11:08:25 +00001744 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001745}
1746
sewardj3e1eb1f2002-05-18 13:14:17 +00001747
sewardjde4a1d02002-03-22 01:27:54 +00001748/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1749 it to attach to this process. Called if the user requests this
1750 service after an error has been shown, so she can poke around and
1751 look at parameters, memory, etc. You can't meaningfully get GDB to
1752 continue the program, though; to continue, quit GDB. */
1753extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1754{
sewardje6a25242002-04-21 22:03:07 +00001755 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001756 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001757
1758#define TO_STRING(x) TO_STRING2(x)
1759#define TO_STRING2(x) #x
1760
1761 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
njn17b85352003-04-18 12:54:24 +00001762 TO_STRING(GDB_PATH), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001763 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1764 res = VG_(system)(buf);
1765 if (res == 0) {
1766 VG_(message)(Vg_UserMsg, "");
1767 VG_(message)(Vg_UserMsg,
1768 "GDB has detached. Valgrind regains control. We continue.");
1769 } else {
1770 VG_(message)(Vg_UserMsg, "Apparently failed!");
1771 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001772 }
njn9315df32003-04-16 20:50:50 +00001773#undef TO_STRING
1774#undef TO_STRING2
sewardjde4a1d02002-03-22 01:27:54 +00001775}
1776
1777
1778/* Print some helpful-ish text about unimplemented things, and give
1779 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001780void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001781{
1782 VG_(message)(Vg_UserMsg, "");
1783 VG_(message)(Vg_UserMsg,
1784 "Valgrind detected that your program requires");
1785 VG_(message)(Vg_UserMsg,
1786 "the following unimplemented functionality:");
1787 VG_(message)(Vg_UserMsg, " %s", msg);
1788 VG_(message)(Vg_UserMsg,
1789 "This may be because the functionality is hard to implement,");
1790 VG_(message)(Vg_UserMsg,
1791 "or because no reasonable program would behave this way,");
1792 VG_(message)(Vg_UserMsg,
1793 "or because nobody has yet needed it. In any case, let me know");
1794 VG_(message)(Vg_UserMsg,
1795 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1796 VG_(message)(Vg_UserMsg,
1797 "");
1798 VG_(message)(Vg_UserMsg,
1799 "Valgrind has to exit now. Sorry. Bye!");
1800 VG_(message)(Vg_UserMsg,
1801 "");
sewardj15a43e12002-04-17 19:35:12 +00001802 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001803 VG_(exit)(1);
1804}
1805
1806
njn25e49d8e72002-09-23 09:36:25 +00001807/* ---------------------------------------------------------------------
1808 Sanity check machinery (permanently engaged).
1809 ------------------------------------------------------------------ */
1810
1811/* A fast sanity check -- suitable for calling circa once per
1812 millisecond. */
1813
1814void VG_(do_sanity_checks) ( Bool force_expensive )
1815{
1816 Int i;
1817
njn37cea302002-09-30 11:24:00 +00001818 VGP_PUSHCC(VgpCoreCheapSanity);
1819
njn25e49d8e72002-09-23 09:36:25 +00001820 if (VG_(sanity_level) < 1) return;
1821
1822 /* --- First do all the tests that we can do quickly. ---*/
1823
1824 VG_(sanity_fast_count)++;
1825
1826 /* Check that we haven't overrun our private stack. */
1827 for (i = 0; i < 10; i++) {
1828 vg_assert(VG_(stack)[i]
1829 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00001830 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
1831 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00001832 }
1833
1834 /* Check stuff pertaining to the memory check system. */
1835
1836 /* Check that nobody has spuriously claimed that the first or
1837 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001838 if (VG_(needs).sanity_checks) {
1839 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001840 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001841 VGP_POPCC(VgpSkinCheapSanity);
1842 }
njn25e49d8e72002-09-23 09:36:25 +00001843
1844 /* --- Now some more expensive checks. ---*/
1845
1846 /* Once every 25 times, check some more expensive stuff. */
1847 if ( force_expensive
1848 || VG_(sanity_level) > 1
1849 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1850
njn37cea302002-09-30 11:24:00 +00001851 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001852 VG_(sanity_slow_count)++;
1853
1854# if 0
1855 { void zzzmemscan(void); zzzmemscan(); }
1856# endif
1857
1858 if ((VG_(sanity_fast_count) % 250) == 0)
1859 VG_(sanity_check_tc_tt)();
1860
1861 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001862 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001863 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001864 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001865 }
1866 /*
1867 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1868 */
njn37cea302002-09-30 11:24:00 +00001869 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001870 }
1871
1872 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001873 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001874 /* Check sanity of the low-level memory manager. Note that bugs
1875 in the client's code can cause this to fail, so we don't do
1876 this check unless specially asked for. And because it's
1877 potentially very expensive. */
1878 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001879 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001880 }
njn37cea302002-09-30 11:24:00 +00001881 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001882}
sewardjde4a1d02002-03-22 01:27:54 +00001883/*--------------------------------------------------------------------*/
1884/*--- end vg_main.c ---*/
1885/*--------------------------------------------------------------------*/