blob: 3ac5c331fde822121cb287f3183c5c8e8d3ff0e3 [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;
sewardjde4a1d02002-03-22 01:27:54 +000052Int VGOFF_(m_fpustate) = 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
135/* Allocate 1 word in baseBlock and set it to the given value. */
136static Int alloc_BaB_1_set ( Addr a )
137{
138 Int off = alloc_BaB(1);
139 VG_(baseBlock)[off] = (UInt)a;
140 return off;
141}
142
njn25e49d8e72002-09-23 09:36:25 +0000143/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000144 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000145void VG_(register_compact_helper)(Addr a)
146{
147 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
148 VG_(printf)("Can only register %d compact helpers\n",
149 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000150 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000151 }
152 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
153 VG_(n_compact_helpers)++;
154}
155
156/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
157 * is filled in later.
158 */
159void VG_(register_noncompact_helper)(Addr a)
160{
161 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
162 VG_(printf)("Can only register %d non-compact helpers\n",
163 MAX_NONCOMPACT_HELPERS);
164 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000165 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000166 }
167 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
168 VG_(n_noncompact_helpers)++;
169}
170
171/* Allocate offsets in baseBlock for the skin helpers */
172static void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
173{
174 Int i;
175 for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
176}
sewardjde4a1d02002-03-22 01:27:54 +0000177
njnf4ce3d32003-02-10 10:17:26 +0000178Bool VG_(need_to_handle_esp_assignment)(void)
179{
njn9b007f62003-04-07 14:40:25 +0000180 return ( VG_(track_events).new_mem_stack_4 ||
181 VG_(track_events).die_mem_stack_4 ||
182 VG_(track_events).new_mem_stack_8 ||
183 VG_(track_events).die_mem_stack_8 ||
184 VG_(track_events).new_mem_stack_12 ||
185 VG_(track_events).die_mem_stack_12 ||
186 VG_(track_events).new_mem_stack_16 ||
187 VG_(track_events).die_mem_stack_16 ||
188 VG_(track_events).new_mem_stack_32 ||
189 VG_(track_events).die_mem_stack_32 ||
190 VG_(track_events).new_mem_stack ||
191 VG_(track_events).die_mem_stack
192 );
njnf4ce3d32003-02-10 10:17:26 +0000193}
194
sewardjde4a1d02002-03-22 01:27:54 +0000195/* Here we assign actual offsets. It's important to get the most
196 popular referents within 128 bytes of the start, so we can take
197 advantage of short addressing modes relative to %ebp. Popularity
198 of offsets was measured on 22 Feb 02 running a KDE application, and
199 the slots rearranged accordingly, with a 1.5% reduction in total
200 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000201static void vg_init_baseBlock ( void )
202{
sewardjde4a1d02002-03-22 01:27:54 +0000203 /* Those with offsets under 128 are carefully chosen. */
204
205 /* WORD offsets in this column */
206 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
207 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
208 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
209 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
210 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
211 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
212 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
213 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
214 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
215
njn25e49d8e72002-09-23 09:36:25 +0000216 if (VG_(needs).shadow_regs) {
217 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
218 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
219 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
220 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
221 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
222 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
223 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
224 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
225 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
226 }
sewardjde4a1d02002-03-22 01:27:54 +0000227
njn25e49d8e72002-09-23 09:36:25 +0000228 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
229 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000230
njn9b007f62003-04-07 14:40:25 +0000231 /* Make these most-frequently-called specialised ones compact, if they
232 are used. */
233 if (VG_(track_events).new_mem_stack_4)
234 VG_(register_compact_helper)( (Addr) VG_(track_events).new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000235
njn9b007f62003-04-07 14:40:25 +0000236 if (VG_(track_events).die_mem_stack_4)
237 VG_(register_compact_helper)( (Addr) VG_(track_events).die_mem_stack_4);
238
239 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000240 /* Allocate slots for compact helpers */
241 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
242 VG_(compact_helper_offsets),
243 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000244
njn25e49d8e72002-09-23 09:36:25 +0000245 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000246 VGOFF_(m_eip) = alloc_BaB(1);
247
248 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000249 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
250 * boundary at >= 32 words, but most spills are to low numbered spill
251 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000252 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
253
njn25e49d8e72002-09-23 09:36:25 +0000254 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000255 short-amode-boundary, there's no point. */
256
sewardjfa492d42002-12-08 18:20:01 +0000257 VGOFF_(m_dflag) = alloc_BaB(1);
258
sewardjde4a1d02002-03-22 01:27:54 +0000259 VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
260
sewardj92a59562002-09-30 00:53:10 +0000261 /* This thread's LDT pointer, and segment registers. */
262 VGOFF_(ldt) = alloc_BaB(1);
263 VGOFF_(m_cs) = alloc_BaB(1);
264 VGOFF_(m_ss) = alloc_BaB(1);
265 VGOFF_(m_ds) = alloc_BaB(1);
266 VGOFF_(m_es) = alloc_BaB(1);
267 VGOFF_(m_fs) = alloc_BaB(1);
268 VGOFF_(m_gs) = alloc_BaB(1);
269
sewardje1042472002-09-30 12:33:11 +0000270 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
271
njn9b007f62003-04-07 14:40:25 +0000272#define REG(kind, size) \
273 if (VG_(track_events).kind##_mem_stack##size) \
274 VG_(register_noncompact_helper)( \
275 (Addr) VG_(track_events).kind##_mem_stack##size );
276
277 REG(new, _8);
278 REG(new, _12);
279 REG(new, _16);
280 REG(new, _32);
281 REG(new, );
282 REG(die, _8);
283 REG(die, _12);
284 REG(die, _16);
285 REG(die, _32);
286 REG(die, );
287#undef REG
288
289 if (VG_(need_to_handle_esp_assignment)())
290 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
291
sewardj92a59562002-09-30 00:53:10 +0000292 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000293 VGOFF_(helper_idiv_64_32)
294 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
295 VGOFF_(helper_div_64_32)
296 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
297 VGOFF_(helper_idiv_32_16)
298 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
299 VGOFF_(helper_div_32_16)
300 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
301 VGOFF_(helper_idiv_16_8)
302 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
303 VGOFF_(helper_div_16_8)
304 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
305
306 VGOFF_(helper_imul_32_64)
307 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
308 VGOFF_(helper_mul_32_64)
309 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
310 VGOFF_(helper_imul_16_32)
311 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
312 VGOFF_(helper_mul_16_32)
313 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
314 VGOFF_(helper_imul_8_16)
315 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
316 VGOFF_(helper_mul_8_16)
317 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
318
319 VGOFF_(helper_CLD)
320 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
321 VGOFF_(helper_STD)
322 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
323 VGOFF_(helper_get_dirflag)
324 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
325
sewardj7d78e782002-06-02 00:04:00 +0000326 VGOFF_(helper_CLC)
327 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000328 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000329 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
330
sewardjde4a1d02002-03-22 01:27:54 +0000331 VGOFF_(helper_shldl)
332 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
333 VGOFF_(helper_shldw)
334 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
335 VGOFF_(helper_shrdl)
336 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
337 VGOFF_(helper_shrdw)
338 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
339
340 VGOFF_(helper_RDTSC)
341 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
342 VGOFF_(helper_CPUID)
343 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
344
sewardjde4a1d02002-03-22 01:27:54 +0000345 VGOFF_(helper_bsf)
346 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
347 VGOFF_(helper_bsr)
348 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
349
350 VGOFF_(helper_fstsw_AX)
351 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
352 VGOFF_(helper_SAHF)
353 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000354 VGOFF_(helper_DAS)
355 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000356 VGOFF_(helper_DAA)
357 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000358
sewardj51096432002-12-14 23:59:09 +0000359 VGOFF_(helper_undefined_instruction)
360 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
361
sewardj92a59562002-09-30 00:53:10 +0000362 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000363 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
364 VG_(noncompact_helper_offsets),
365 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000366
njncc7bb472002-10-14 09:25:19 +0000367
368 /* Initialise slots that require it */
369 VG_(copy_m_state_static_to_baseBlock)();
370
371 /* Pretend the root thread has a completely empty LDT to start with. */
372 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
373
374 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000375 if (VG_(needs).shadow_regs) {
376 UInt eflags;
377
378 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
379 VG_(baseBlock)[VGOFF_(sh_esp)] =
380 VG_(baseBlock)[VGOFF_(sh_ebp)] =
381 VG_(baseBlock)[VGOFF_(sh_eax)] =
382 VG_(baseBlock)[VGOFF_(sh_ecx)] =
383 VG_(baseBlock)[VGOFF_(sh_edx)] =
384 VG_(baseBlock)[VGOFF_(sh_ebx)] =
385 VG_(baseBlock)[VGOFF_(sh_esi)] =
386 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
387 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
388
njncc7bb472002-10-14 09:25:19 +0000389 } else {
njn25e49d8e72002-09-23 09:36:25 +0000390 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000391 }
sewardjde4a1d02002-03-22 01:27:54 +0000392}
393
394
395/* ---------------------------------------------------------------------
396 Global entities which are not referenced from generated code.
397 ------------------------------------------------------------------ */
398
399/* The stack on which Valgrind runs. We can't use the same stack as
400 the simulatee -- that's an important design decision. */
401UInt VG_(stack)[10000];
402
403/* Ditto our signal delivery stack. */
404UInt VG_(sigstack)[10000];
405
406/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000407UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
408Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000409
410/* Counts downwards in vg_run_innerloop. */
411UInt VG_(dispatch_ctr);
412
sewardjde4a1d02002-03-22 01:27:54 +0000413
414/* 64-bit counter for the number of basic blocks done. */
415ULong VG_(bbs_done);
416/* 64-bit counter for the number of bbs to go before a debug exit. */
417ULong VG_(bbs_to_go);
418
sewardj7e87e382002-05-03 19:09:05 +0000419/* This is the ThreadId of the last thread the scheduler ran. */
420ThreadId VG_(last_run_tid) = 0;
421
njn25e49d8e72002-09-23 09:36:25 +0000422/* This is the argument to __NR_exit() supplied by the first thread to
423 call that syscall. We eventually pass that to __NR_exit() for
424 real. */
425UInt VG_(exitcode) = 0;
426
sewardj73cf3bc2002-11-03 03:20:15 +0000427/* Tell the logging mechanism whether we are logging to a file
428 descriptor or a socket descriptor. */
429Bool VG_(logging_to_filedes) = True;
430
sewardjde4a1d02002-03-22 01:27:54 +0000431
432/* ---------------------------------------------------------------------
433 Counters, for informational purposes only.
434 ------------------------------------------------------------------ */
435
436/* Number of lookups which miss the fast tt helper. */
437UInt VG_(tt_fast_misses) = 0;
438
439
sewardjc0d8f682002-11-30 00:49:43 +0000440/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000441
sewardjde4a1d02002-03-22 01:27:54 +0000442/* Number and total o/t size of translations overall. */
443UInt VG_(overall_in_count) = 0;
444UInt VG_(overall_in_osize) = 0;
445UInt VG_(overall_in_tsize) = 0;
446/* Number and total o/t size of discards overall. */
447UInt VG_(overall_out_count) = 0;
448UInt VG_(overall_out_osize) = 0;
449UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000450/* The number of discards of TT/TC. */
451UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000452/* Counts of chain and unchain operations done. */
453UInt VG_(bb_enchain_count) = 0;
454UInt VG_(bb_dechain_count) = 0;
455/* Number of unchained jumps performed. */
456UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000457
458
459/* Counts pertaining to the register allocator. */
460
461/* total number of uinstrs input to reg-alloc */
462UInt VG_(uinstrs_prealloc) = 0;
463
464/* total number of uinstrs added due to spill code */
465UInt VG_(uinstrs_spill) = 0;
466
467/* number of bbs requiring spill code */
468UInt VG_(translations_needing_spill) = 0;
469
470/* total of register ranks over all translations */
471UInt VG_(total_reg_rank) = 0;
472
473
sewardjde4a1d02002-03-22 01:27:54 +0000474/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000475UInt VG_(sanity_fast_count) = 0;
476UInt VG_(sanity_slow_count) = 0;
477
sewardj2e93c502002-04-12 11:12:52 +0000478/* Counts pertaining to the scheduler. */
479UInt VG_(num_scheduling_events_MINOR) = 0;
480UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000481
482
483/* ---------------------------------------------------------------------
484 Values derived from command-line options.
485 ------------------------------------------------------------------ */
486
njn25e49d8e72002-09-23 09:36:25 +0000487/* Define, and set defaults. */
488Bool VG_(clo_error_limit) = True;
489Bool VG_(clo_GDB_attach) = False;
njn43c799e2003-04-08 00:08:52 +0000490Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000491Int VG_(sanity_level) = 1;
492Int VG_(clo_verbosity) = 1;
493Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000494Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000495
496/* See big comment in vg_include.h for meaning of these three. */
497VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
498Int VG_(clo_logfile_fd) = 2;
499Char* VG_(clo_logfile_name) = NULL;
500
njn25e49d8e72002-09-23 09:36:25 +0000501Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000502Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000503Bool VG_(clo_profile) = False;
504Bool VG_(clo_single_step) = False;
505Bool VG_(clo_optimise) = True;
506UChar VG_(clo_trace_codegen) = 0; // 00000000b
507Bool VG_(clo_trace_syscalls) = False;
508Bool VG_(clo_trace_signals) = False;
509Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000510Bool VG_(clo_trace_sched) = False;
511Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000512ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000513Int VG_(clo_dump_error) = 0;
514Int VG_(clo_backtrace_size) = 4;
515Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000516Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000517Bool VG_(clo_chain_bb) = True;
sewardj2370f3b2002-11-30 15:01:01 +0000518
sewardjde4a1d02002-03-22 01:27:54 +0000519
520/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
521 to behave. Initially we say False. */
522Bool VG_(running_on_simd_CPU) = False;
523
524/* Holds client's %esp at the point we gained control. */
525Addr VG_(esp_at_startup);
526
sewardjd5815ec2003-04-06 12:23:27 +0000527/* Indicates presence, and holds address of client's sysinfo page, a
528 feature of some modern kernels used to provide vsyscalls, etc. */
529Bool VG_(sysinfo_page_exists) = False;
530Addr VG_(sysinfo_page_addr) = 0;
531
sewardjde4a1d02002-03-22 01:27:54 +0000532/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
533 envp[] as extracted from the client's stack at startup-time. */
534Int VG_(client_argc);
535Char** VG_(client_argv);
536Char** VG_(client_envp);
537
538/* A place into which to copy the value of env var VG_ARGS, so we
539 don't have to modify the original. */
540static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
541
sewardjde4a1d02002-03-22 01:27:54 +0000542/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000543 Processing of command-line options.
544 ------------------------------------------------------------------ */
545
njn25e49d8e72002-09-23 09:36:25 +0000546void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000547{
548 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000549 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000550 VG_(clo_logfile_fd) = 2; /* stderr */
551 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
552 VG_(exit)(1);
553}
554
555static void config_error ( Char* msg )
556{
557 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000558 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000559 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000560 VG_(printf)(
561 "valgrind.so: Startup or configuration error:\n %s\n", msg);
562 VG_(printf)(
563 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000564 VG_(exit)(1);
565}
566
sewardja1679dd2002-05-10 22:31:40 +0000567static void args_grok_error ( Char* msg )
568{
569 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000570 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000571 VG_(clo_logfile_fd) = 2; /* stderr */
572 VG_(printf)("valgrind.so: When searching for "
573 "client's argc/argc/envp:\n\t%s\n", msg);
574 config_error("couldn't find client's argc/argc/envp");
575}
576
njn25e49d8e72002-09-23 09:36:25 +0000577static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000578{
njn25e49d8e72002-09-23 09:36:25 +0000579 Char* usage1 =
580"usage: valgrind [options] prog-and-args\n"
581"\n"
582" core user options, with defaults in [ ], are:\n"
583" --help show this message\n"
584" --version show version\n"
585" --skin=<name> main task (skin to use) [Valgrind]\n"
586" -q --quiet run silently; only print error msgs\n"
587" -v --verbose be more verbose, incl counts of errors\n"
588" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
njn43c799e2003-04-08 00:08:52 +0000589" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000590" --demangle=no|yes automatically demangle C++ names? [yes]\n"
591" --num-callers=<number> show <num> callers in stack traces [4]\n"
592" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000593" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000594" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000595" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000596" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000597" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000598" --suppressions=<filename> suppress errors described in\n"
599" suppressions file <filename>\n"
600" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000601" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000602"\n"
603" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000604
njn7cf0bd32002-06-08 13:36:03 +0000605
njn25e49d8e72002-09-23 09:36:25 +0000606 Char* usage2 =
607"\n"
608" core options for debugging Valgrind itself are:\n"
609" --sanity-level=<number> level of sanity checking to do [1]\n"
610" --single-step=no|yes translate each instr separately? [no]\n"
611" --optimise=no|yes improve intermediate code? [yes]\n"
612" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000613" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000614" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
615" --trace-syscalls=no|yes show all system calls? [no]\n"
616" --trace-signals=no|yes show signal handling details? [no]\n"
617" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000618" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000619" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000620" --stop-after=<number> switch to real CPU after executing\n"
621" <number> basic blocks [infinity]\n"
622" --dump-error=<number> show translation for basic block\n"
623" associated with <number>'th\n"
624" error context [0=don't show any]\n"
625"\n"
njn3e884182003-04-15 13:03:23 +0000626" %s skin debugging options:\n";
627
628 Char* usage3 =
629"\n"
njn25e49d8e72002-09-23 09:36:25 +0000630" Extra options are read from env variable $VALGRIND_OPTS\n"
631"\n"
njn0e1b5142003-04-15 14:58:06 +0000632" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000633" and licensed under the GNU General Public License, version 2.\n"
634" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000635"\n"
636" Skins are copyright and licensed by their authors. See each\n"
637" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000638"\n";
njn7cf0bd32002-06-08 13:36:03 +0000639
njnd04b7c62002-10-03 14:05:52 +0000640 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000641 /* Don't print skin string directly for security, ha! */
642 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000643 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000644 else
645 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000646 VG_(printf)(usage2, VG_(details).name);
647 if (VG_(needs).command_line_options)
648 SK_(print_debug_usage)();
649 else
650 VG_(printf)(" (none)\n");
651 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000652
njn25e49d8e72002-09-23 09:36:25 +0000653 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000654 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000655 VG_(clo_logfile_fd) = 2; /* stderr */
656 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000657}
sewardjde4a1d02002-03-22 01:27:54 +0000658
sewardj1c1b1162003-02-23 01:25:51 +0000659
sewardj49e630d2003-04-23 21:18:52 +0000660/* Callback for looking for the stack segment. */
661Addr VG_(foundstack_start) = (Addr)NULL;
662UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000663
664static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000665 Char r, Char w, Char x,
666 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000667{
668 Addr lastword;
669 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000670 if (r != 'r' || w != 'w'
671 /* || x != 'x' --not necessarily so on x86-64*/
672 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000673 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000674 if (start <= VG_(esp_at_startup)
675 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000676 VG_(foundstack_start) = start;
677 VG_(foundstack_size) = size;
678 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000679 }
680}
681
682
683
sewardjde4a1d02002-03-22 01:27:54 +0000684static void process_cmd_line_options ( void )
685{
njn25e49d8e72002-09-23 09:36:25 +0000686 Char* argv[M_VG_CMDLINE_OPTS];
687 UInt argc;
688 Char* p;
689 Char* str;
690 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000691
692# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000693
sewardjde4a1d02002-03-22 01:27:54 +0000694 eventually_logfile_fd = VG_(clo_logfile_fd);
695
696 /* Once logging is started, we can safely send messages pertaining
697 to failures in initialisation. */
698 VG_(startup_logging)();
699
sewardj19d81412002-06-03 01:10:40 +0000700 /* Check for sane path in ./configure --prefix=... */
701 if (VG_(strlen)(VG_LIBDIR) < 1
702 || VG_LIBDIR[0] != '/')
703 config_error("Please use absolute paths in "
704 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000705
sewardja1679dd2002-05-10 22:31:40 +0000706 /* (Suggested by Fabrice Bellard ... )
707 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000708 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000709 change less often than the libc ones. */
710 {
sewardj53fe4582003-02-23 01:41:17 +0000711 UInt* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000712
njn3e884182003-04-15 13:03:23 +0000713 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000714 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000715 has rwx permissions and no associated file. Note that this uses
716 the /proc/self/maps contents read at the start of VG_(main)(),
717 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000718
njn3e884182003-04-15 13:03:23 +0000719 VG_(read_procselfmaps)( vg_findstack_callback, /*read_from_file*/False );
sewardj53fe4582003-02-23 01:41:17 +0000720
sewardj49e630d2003-04-23 21:18:52 +0000721 /* Now foundstack_start and foundstack_size should delimit the stack. */
722 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000723 args_grok_error("Cannot determine stack segment "
724 "from /proc/self/maps");
725 }
sewardj1c1b1162003-02-23 01:25:51 +0000726
727 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000728 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000729 VG_(foundstack_start),
730 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000731
sewardj49e630d2003-04-23 21:18:52 +0000732 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000733 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
734 args_grok_error("Stack segment is not page aligned?!");
735 }
sewardj1c1b1162003-02-23 01:25:51 +0000736
sewardj53fe4582003-02-23 01:41:17 +0000737 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
738 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000739
sewardj38170912002-05-10 21:07:22 +0000740 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000741 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000742 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000743 sp--;
744 }
sewardj38170912002-05-10 21:07:22 +0000745
746 if (sp[2] == VKI_AT_BASE
747 && sp[0] == VKI_AT_PAGESZ
748 && sp[-2] == VKI_AT_PHNUM
749 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000750 && sp[-6] == VKI_AT_PHDR
751 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000752 if (0)
753 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000754 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000755 } else
756 if (sp[2] == VKI_AT_CLKTCK
757 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000758 && sp[-2] == VKI_AT_HWCAP
759 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000760 if (0)
761 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
762 sp -= 2;
763 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000764 if (sp[2] == VKI_AT_CLKTCK
765 && sp[0] == VKI_AT_PAGESZ
766 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000767 && sp[-4] == VKI_AT_SYSINFO
768 && sp[-4-1] == 0) {
769 if (0)
770 VG_(printf)("Looks like you've got a 2.4.X kernel with "
771 "a sysinfo page at %x here.\n", sp[-3]);
772 VG_(sysinfo_page_exists) = True;
773 VG_(sysinfo_page_addr) = sp[-3];
774 sp -= 4;
775 } else
776 if (sp[2] == VKI_AT_CLKTCK
777 && sp[0] == VKI_AT_PAGESZ
778 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000779 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
780 && sp[-4-1] == 0) {
781 if (0)
782 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
783 "kernel here.\n");
784 sp -= 4;
785 } else
786 if (sp[2] == VKI_AT_CLKTCK
787 && sp[0] == VKI_AT_PAGESZ
788 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000789 && sp[-2-20-1] == 0) {
790 if (0)
791 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
792 sp -= 22;
793 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000794 if (sp[2] == VKI_AT_CLKTCK
795 && sp[0] == VKI_AT_PAGESZ
796 && sp[-2] == VKI_AT_HWCAP
797 && sp[-4-1] == 0) {
798 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000799 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000800 sp -= 4;
801 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000802 if (sp[2] == VKI_AT_CLKTCK
803 && sp[0] == VKI_AT_PAGESZ
804 && sp[-2] == VKI_AT_HWCAP
805 && sp[-6] == VKI_AT_SYSINFO
806 && sp[-6-1] == 0) {
807 if (0)
808 VG_(printf)("Looks like a >= 2.5.68 kernel with "
809 "a sysinfo page at %x here.\n", sp[-5]);
810 VG_(sysinfo_page_exists) = True;
811 VG_(sysinfo_page_addr) = sp[-5];
812 sp -= 6;
813 } else
sewardja1679dd2002-05-10 22:31:40 +0000814 args_grok_error(
815 "ELF frame does not look like 2.2.X or 2.4.X.\n "
816 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
817 );
sewardj38170912002-05-10 21:07:22 +0000818
819 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000820 if (*sp != 0)
821 args_grok_error("can't find NULL at end of env[]");
822
sewardj38170912002-05-10 21:07:22 +0000823 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000824 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000825 while (True) {
826 sp --;
827 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000828 if (++ctr >= 1000)
829 args_grok_error(
830 "suspiciously many (1000) env[] entries; giving up");
831
sewardj38170912002-05-10 21:07:22 +0000832 }
833 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000834 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000835
sewardja1679dd2002-05-10 22:31:40 +0000836 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000837 VG_(client_argc) = 0;
838 while (True) {
839 sp--;
840 if (*sp == VG_(client_argc))
841 break;
842 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000843 if (++ctr >= 1000)
844 args_grok_error(
845 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000846 }
847
sewardja1679dd2002-05-10 22:31:40 +0000848 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000849 }
850
sewardjde4a1d02002-03-22 01:27:54 +0000851 /* Now that VG_(client_envp) has been set, we can extract the args
852 for Valgrind itself. Copy into global var so that we don't have to
853 write zeroes to the getenv'd value itself. */
854 str = VG_(getenv)("VG_ARGS");
855 argc = 0;
856
857 if (!str) {
858 config_error("Can't read options from env var VG_ARGS.");
859 }
860
861 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
862 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
863 }
864 VG_(strcpy)(vg_cmdline_copy, str);
865 str = NULL;
866
867 p = &vg_cmdline_copy[0];
868 while (True) {
869 while (ISSPACE(*p)) { *p = 0; p++; }
870 if (*p == 0) break;
871 if (argc < M_VG_CMDLINE_OPTS-1) {
872 argv[argc] = p; argc++;
873 } else {
874 config_error(
875 "Found more than M_CMDLINE_OPTS command-line opts.");
876 }
877 while (*p != 0 && !ISSPACE(*p)) p++;
878 }
879
880 for (i = 0; i < argc; i++) {
881
njn43c799e2003-04-08 00:08:52 +0000882 if (VG_CLO_STREQ(argv[i], "-v") ||
883 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000884 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000885 else if (VG_CLO_STREQ(argv[i], "-q") ||
886 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000887 VG_(clo_verbosity)--;
888
njn43c799e2003-04-08 00:08:52 +0000889 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000890 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000891 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000892 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000893
njn43c799e2003-04-08 00:08:52 +0000894 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000895 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000896 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000897 VG_(clo_GDB_attach) = False;
898
njn43c799e2003-04-08 00:08:52 +0000899 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
900 VG_(clo_gen_suppressions) = True;
901 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
902 VG_(clo_gen_suppressions) = False;
903
904 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000905 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000906 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000907 VG_(clo_demangle) = False;
908
njn43c799e2003-04-08 00:08:52 +0000909 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000910 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000911 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000912 VG_(clo_trace_children) = False;
913
njn43c799e2003-04-08 00:08:52 +0000914 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000915 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000916 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000917 VG_(clo_run_libc_freeres) = False;
918
njn43c799e2003-04-08 00:08:52 +0000919 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000920 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
921
njn43c799e2003-04-08 00:08:52 +0000922 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000923 VG_(clo_log_to) = VgLogTo_Fd;
924 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000925 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000926 }
927
njn43c799e2003-04-08 00:08:52 +0000928 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000929 VG_(clo_log_to) = VgLogTo_File;
930 VG_(clo_logfile_name) = &argv[i][10];
931 }
sewardjde4a1d02002-03-22 01:27:54 +0000932
njn43c799e2003-04-08 00:08:52 +0000933 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000934 VG_(clo_log_to) = VgLogTo_Socket;
935 VG_(clo_logfile_name) = &argv[i][12];
936 }
937
njn43c799e2003-04-08 00:08:52 +0000938 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000939 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000940 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000941 VG_(message)(Vg_UserMsg,
942 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000943 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000944 }
945 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
946 VG_(clo_n_suppressions)++;
947 }
njn43c799e2003-04-08 00:08:52 +0000948 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000949 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000950 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000951 VG_(clo_profile) = False;
952
njn43c799e2003-04-08 00:08:52 +0000953 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000954 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000955 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000956 VG_(clo_chain_bb) = False;
957
njn43c799e2003-04-08 00:08:52 +0000958 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000959 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000960 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000961 VG_(clo_single_step) = False;
962
njn43c799e2003-04-08 00:08:52 +0000963 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000964 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000965 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000966 VG_(clo_optimise) = False;
967
njn25e49d8e72002-09-23 09:36:25 +0000968 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +0000969 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +0000970 Int j;
971 char* opt = & argv[i][16];
972
973 if (5 != VG_(strlen)(opt)) {
974 VG_(message)(Vg_UserMsg,
975 "--trace-codegen argument must have 5 digits");
976 VG_(bad_option)(argv[i]);
977 }
978 for (j = 0; j < 5; j++) {
979 if ('0' == opt[j]) { /* do nothing */ }
980 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
981 else {
982 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
983 "contain 0s and 1s");
984 VG_(bad_option)(argv[i]);
985 }
986 }
987 }
sewardjde4a1d02002-03-22 01:27:54 +0000988
njn43c799e2003-04-08 00:08:52 +0000989 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000990 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +0000991 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000992 VG_(clo_trace_syscalls) = False;
993
njn43c799e2003-04-08 00:08:52 +0000994 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000995 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +0000996 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000997 VG_(clo_trace_signals) = False;
998
njn43c799e2003-04-08 00:08:52 +0000999 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001000 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001001 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001002 VG_(clo_trace_symtab) = False;
1003
njn43c799e2003-04-08 00:08:52 +00001004 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001005 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001006 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001007 VG_(clo_trace_sched) = False;
1008
njn43c799e2003-04-08 00:08:52 +00001009 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001010 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001011 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001012 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001013 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001014 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001015
njn43c799e2003-04-08 00:08:52 +00001016 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001017 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001018
njn43c799e2003-04-08 00:08:52 +00001019 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001020 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1021
njn43c799e2003-04-08 00:08:52 +00001022 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001023 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1024
njn43c799e2003-04-08 00:08:52 +00001025 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001026 /* Make sure it's sane. */
1027 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1028 if (VG_(clo_backtrace_size) < 2)
1029 VG_(clo_backtrace_size) = 2;
1030 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1031 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1032 }
1033
njn25e49d8e72002-09-23 09:36:25 +00001034 else if (VG_(needs).command_line_options) {
1035 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1036 if (!ok)
1037 usage();
1038 }
sewardjde4a1d02002-03-22 01:27:54 +00001039 else
njn25e49d8e72002-09-23 09:36:25 +00001040 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001041 }
1042
1043# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001044
1045 if (VG_(clo_verbosity < 0))
1046 VG_(clo_verbosity) = 0;
1047
1048 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1049 VG_(message)(Vg_UserMsg, "");
1050 VG_(message)(Vg_UserMsg,
1051 "--gdb-attach=yes conflicts with --trace-children=yes");
1052 VG_(message)(Vg_UserMsg,
1053 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001054 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001055 }
1056
sewardj4cf05692002-10-27 20:28:29 +00001057 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1058 should be connected to whatever sink has been selected, and we
1059 indiscriminately chuck stuff into it without worrying what the
1060 nature of it is. Oh the wonder of Unix streams. */
1061
1062 /* So far we should be still attached to stderr, so we can show on
1063 the terminal any problems to do with processing command line
1064 opts. */
1065 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001066 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001067
1068 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001069
sewardj4cf05692002-10-27 20:28:29 +00001070 case VgLogTo_Fd:
1071 vg_assert(VG_(clo_logfile_name) == NULL);
1072 VG_(clo_logfile_fd) = eventually_logfile_fd;
1073 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001074
sewardj4cf05692002-10-27 20:28:29 +00001075 case VgLogTo_File: {
1076 Char logfilename[1000];
1077 vg_assert(VG_(clo_logfile_name) != NULL);
1078 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1079 VG_(sprintf)(logfilename, "%s.pid%d",
1080 VG_(clo_logfile_name), VG_(getpid)() );
1081 eventually_logfile_fd
1082 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1083 VKI_S_IRUSR|VKI_S_IWUSR);
1084 if (eventually_logfile_fd != -1) {
1085 VG_(clo_logfile_fd) = eventually_logfile_fd;
1086 } else {
1087 VG_(message)(Vg_UserMsg,
1088 "Can't create/open log file `%s.pid%d'; giving up!",
1089 VG_(clo_logfile_name), VG_(getpid)());
1090 VG_(bad_option)(
1091 "--logfile=<file> didn't work out for some reason.");
1092 }
1093 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001094 }
1095
1096 case VgLogTo_Socket: {
1097 vg_assert(VG_(clo_logfile_name) != NULL);
1098 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1099 eventually_logfile_fd
1100 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1101 if (eventually_logfile_fd == -1) {
1102 VG_(message)(Vg_UserMsg,
1103 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1104 VG_(message)(Vg_UserMsg,
1105 "of `%s'; giving up!", VG_(clo_logfile_name) );
1106 VG_(bad_option)(
1107 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001108 }
sewardj73cf3bc2002-11-03 03:20:15 +00001109 if (eventually_logfile_fd == -2) {
1110 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001111 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001112 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001113 VG_(message)(Vg_UserMsg,
1114 "Log messages will sent to stderr instead." );
1115 VG_(message)(Vg_UserMsg,
1116 "" );
1117 /* We don't change anything here. */
1118 } else {
1119 vg_assert(eventually_logfile_fd > 0);
1120 VG_(clo_logfile_fd) = eventually_logfile_fd;
1121 VG_(logging_to_filedes) = False;
1122 }
sewardj73cf3bc2002-11-03 03:20:15 +00001123 break;
1124 }
1125
sewardj4cf05692002-10-27 20:28:29 +00001126 }
1127
1128 /* Ok, the logging sink is running now. Print a suitable preamble.
1129 If logging to file or a socket, write details of parent PID and
1130 command line args, to help people trying to interpret the
1131 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001132
sewardj83adf412002-05-01 01:25:45 +00001133 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001134 /* Skin details */
1135 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1136 VG_(details).name,
1137 NULL == VG_(details).version ? "" : "-",
1138 NULL == VG_(details).version
1139 ? (Char*)"" : VG_(details).version,
1140 VG_(details).description);
1141 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001142
njnd04b7c62002-10-03 14:05:52 +00001143 /* Core details */
1144 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001145 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001146 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001147 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001148 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001149 }
1150
sewardj4cf05692002-10-27 20:28:29 +00001151 if (VG_(clo_log_to) != VgLogTo_Fd) {
1152 VG_(message)(Vg_UserMsg, "");
1153 VG_(message)(Vg_UserMsg,
1154 "My PID = %d, parent PID = %d. Prog and args are:",
1155 VG_(getpid)(), VG_(getppid)() );
1156 for (i = 0; i < VG_(client_argc); i++)
1157 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1158 }
1159
sewardjde4a1d02002-03-22 01:27:54 +00001160 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001161 if (VG_(clo_log_to) != VgLogTo_Fd)
1162 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001163 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1164 for (i = 0; i < argc; i++) {
1165 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1166 }
1167 }
1168
njn25e49d8e72002-09-23 09:36:25 +00001169 if (VG_(clo_n_suppressions) == 0 &&
1170 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001171 config_error("No error-suppression files were specified.");
1172 }
sewardj4cf05692002-10-27 20:28:29 +00001173
sewardjde4a1d02002-03-22 01:27:54 +00001174}
1175
sewardjde4a1d02002-03-22 01:27:54 +00001176/* ---------------------------------------------------------------------
1177 Copying to/from m_state_static.
1178 ------------------------------------------------------------------ */
1179
sewardj92a59562002-09-30 00:53:10 +00001180UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1181 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001182 + 1 /* %eflags */
1183 + 1 /* %eip */
1184 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1185 ];
1186
sewardjfa492d42002-12-08 18:20:01 +00001187UInt VG_(insertDflag)(UInt eflags, Int d)
1188{
1189 vg_assert(d == 1 || d == -1);
1190 eflags &= ~EFlagD;
1191
1192 if (d < 0)
1193 eflags |= EFlagD;
1194
1195 return eflags;
1196}
1197
1198Int VG_(extractDflag)(UInt eflags)
1199{
1200 Int ret;
1201
1202 if (eflags & EFlagD)
1203 ret = -1;
1204 else
1205 ret = 1;
1206
1207 return ret;
1208}
1209
sewardjde4a1d02002-03-22 01:27:54 +00001210void VG_(copy_baseBlock_to_m_state_static) ( void )
1211{
1212 Int i;
sewardj92a59562002-09-30 00:53:10 +00001213 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1214 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1215 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1216 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1217 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1218 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001219
sewardj92a59562002-09-30 00:53:10 +00001220 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1221 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1222 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1223 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1224 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1225 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1226 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1227 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1228
sewardjfa492d42002-12-08 18:20:01 +00001229 VG_(m_state_static)[56/4] = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1230 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001231 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001232
1233 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001234 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001235 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1236}
1237
1238
1239void VG_(copy_m_state_static_to_baseBlock) ( void )
1240{
1241 Int i;
sewardj92a59562002-09-30 00:53:10 +00001242 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1243 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1244 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1245 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1246 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1247 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001248
sewardj92a59562002-09-30 00:53:10 +00001249 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1250 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1251 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1252 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1253 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1254 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1255 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1256 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1257
sewardjfa492d42002-12-08 18:20:01 +00001258 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4] & ~EFlagD;
1259 VG_(baseBlock)[VGOFF_(m_dflag)] = VG_(extractDflag)(VG_(m_state_static)[56/4]);
1260
sewardj92a59562002-09-30 00:53:10 +00001261 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001262
1263 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1264 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001265 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001266}
1267
njn25e49d8e72002-09-23 09:36:25 +00001268Addr VG_(get_stack_pointer) ( void )
1269{
1270 return VG_(baseBlock)[VGOFF_(m_esp)];
1271}
1272
1273/* Some random tests needed for leak checking */
1274
1275Bool VG_(within_stack)(Addr a)
1276{
1277 if (a >= ((Addr)(&VG_(stack)))
1278 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1279 return True;
1280 else
1281 return False;
1282}
1283
1284Bool VG_(within_m_state_static)(Addr a)
1285{
1286 if (a >= ((Addr)(&VG_(m_state_static)))
1287 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1288 return True;
1289 else
1290 return False;
1291}
sewardjde4a1d02002-03-22 01:27:54 +00001292
1293/* ---------------------------------------------------------------------
1294 Show accumulated counts.
1295 ------------------------------------------------------------------ */
1296
njn25e49d8e72002-09-23 09:36:25 +00001297static __inline__ Int safe_idiv(Int a, Int b)
1298{
1299 return (b == 0 ? 0 : a / b);
1300}
1301
sewardjde4a1d02002-03-22 01:27:54 +00001302static void vg_show_counts ( void )
1303{
1304 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001305 " TT/TC: %d tc sectors discarded.",
1306 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001307 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001308 " %d chainings, %d unchainings.",
1309 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1310 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001311 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001312 VG_(overall_in_count),
1313 VG_(overall_in_osize),
1314 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001315 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1316 VG_(message)(Vg_DebugMsg,
1317 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001318 VG_(overall_out_count),
1319 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001320 VG_(overall_out_tsize),
1321 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001322 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001323 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001324 VG_(bbs_done),
1325 VG_(unchained_jumps_done),
1326 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1327 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1328 );
1329
1330 VG_(message)(Vg_DebugMsg,
1331 " %d/%d major/minor sched events. %d tt_fast misses.",
1332 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001333 VG_(num_scheduling_events_MINOR),
1334 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001335
sewardjde4a1d02002-03-22 01:27:54 +00001336 VG_(message)(Vg_DebugMsg,
1337 "reg-alloc: %d t-req-spill, "
1338 "%d+%d orig+spill uis, %d total-reg-r.",
1339 VG_(translations_needing_spill),
1340 VG_(uinstrs_prealloc),
1341 VG_(uinstrs_spill),
1342 VG_(total_reg_rank) );
1343 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001344 " sanity: %d cheap, %d expensive checks.",
1345 VG_(sanity_fast_count),
1346 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001347 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001348}
1349
1350
1351/* ---------------------------------------------------------------------
1352 Main!
1353 ------------------------------------------------------------------ */
1354
1355/* Where we jump to once Valgrind has got control, and the real
1356 machine's state has been copied to the m_state_static. */
1357
1358void VG_(main) ( void )
1359{
sewardj2e93c502002-04-12 11:12:52 +00001360 Int i;
1361 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001362 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001363
njn27f1a382002-11-08 15:48:16 +00001364 /* Check skin and core versions are compatible */
1365 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1366 VG_(printf)("Error:\n"
1367 " Skin and core interface versions do not match.\n"
1368 " Interface version used by core is: %d.%d\n"
1369 " Interface version used by skin is: %d.%d\n"
1370 " The major version numbers must match.\n",
1371 VG_CORE_INTERFACE_MAJOR_VERSION,
1372 VG_CORE_INTERFACE_MINOR_VERSION,
1373 VG_(skin_interface_major_version),
1374 VG_(skin_interface_minor_version));
1375 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1376 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1377 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1378 else
1379 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1380 VG_(printf)(" Aborting, sorry.\n");
1381 VG_(exit)(1);
1382 }
1383
sewardjde4a1d02002-03-22 01:27:54 +00001384 /* Set up our stack sanity-check words. */
1385 for (i = 0; i < 10; i++) {
1386 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1387 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1388 }
1389
njn3e884182003-04-15 13:03:23 +00001390 /* Read /proc/self/maps into a buffer. Must be before:
1391 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1392 superblocks are not erroneously identified as being owned by the
1393 client, which would be bad.
1394 - init_memory(): that's where the buffer is parsed
1395 - init_tt_tc(): so the anonymous mmaps for the translation table and
1396 translation cache aren't identified as part of the client, which would
1397 waste > 20M of virtual address space, and be bad.
1398 */
1399 VG_(read_procselfmaps_contents)();
1400
sewardj1c1b1162003-02-23 01:25:51 +00001401 /* Hook to delay things long enough so we can get the pid and
1402 attach GDB in another shell. */
1403 if (0) {
1404 Int p, q;
1405 VG_(printf)("pid=%d\n", VG_(getpid)());
1406 for (p = 0; p < 50000; p++)
1407 for (q = 0; q < 50000; q++) ;
1408 }
1409
njn25e49d8e72002-09-23 09:36:25 +00001410 /* Setup stuff that depends on the skin. Must be before:
1411 - vg_init_baseBlock(): to register helpers
1412 - process_cmd_line_options(): to register skin name and description,
1413 and turn on/off 'command_line_options' need
1414 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001415 */
njn810086f2002-11-14 12:42:47 +00001416 SK_(pre_clo_init)();
1417 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001418
njncc7bb472002-10-14 09:25:19 +00001419 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001420 process_cmd_line_options();
1421
njn3e884182003-04-15 13:03:23 +00001422 /* Do post command-line processing initialisation. Must be before:
1423 - vg_init_baseBlock(): to register any more helpers
1424 */
njncc7bb472002-10-14 09:25:19 +00001425 SK_(post_clo_init)();
1426
njn3e884182003-04-15 13:03:23 +00001427 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001428 vg_init_baseBlock();
1429
sewardj018f7622002-05-15 21:13:39 +00001430 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001431 baseBlock into VG_(threads)[1]. Must be before:
1432 - VG_(sigstartup_actions)()
1433 */
sewardj018f7622002-05-15 21:13:39 +00001434 VG_(scheduler_init)();
1435
1436 /* Initialise the signal handling subsystem, temporarily parking
1437 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001438 VG_(sigstartup_actions)();
1439
sewardj018f7622002-05-15 21:13:39 +00001440 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001441 if (VG_(clo_profile))
1442 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001443
sewardj5f07b662002-04-23 16:52:51 +00001444 /* Start calibration of our RDTSC-based clock. */
1445 VG_(start_rdtsc_calibration)();
1446
njn3e884182003-04-15 13:03:23 +00001447 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001448 VGP_PUSHCC(VgpInitMem);
1449 VG_(init_memory)();
1450 VGP_POPCC(VgpInitMem);
1451
1452 /* Read the list of errors to suppress. This should be found in
1453 the file specified by vg_clo_suppressions. */
1454 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1455 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001456
sewardj5f07b662002-04-23 16:52:51 +00001457 /* End calibration of our RDTSC-based clock, leaving it as long as
1458 we can. */
1459 VG_(end_rdtsc_calibration)();
1460
njn3e884182003-04-15 13:03:23 +00001461 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001462 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001463
1464 if (VG_(clo_verbosity) == 1) {
1465 VG_(message)(Vg_UserMsg,
1466 "For more details, rerun with: -v");
1467 }
1468
1469 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1470 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001471 if (VG_(clo_verbosity) > 0)
1472 VG_(message)(Vg_UserMsg, "");
1473
1474 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001475
sewardj018f7622002-05-15 21:13:39 +00001476 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001477 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001478 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001479 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001480 VGP_POPCC(VgpSched);
1481 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001482
1483 if (VG_(clo_verbosity) > 0)
1484 VG_(message)(Vg_UserMsg, "");
1485
sewardj2e93c502002-04-12 11:12:52 +00001486 if (src == VgSrc_Deadlock) {
1487 VG_(message)(Vg_UserMsg,
1488 "Warning: pthread scheduler exited due to deadlock");
1489 }
1490
njn25e49d8e72002-09-23 09:36:25 +00001491 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001492 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001493
njn7d9f94d2003-04-22 21:41:40 +00001494 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001495
sewardj0c3b53f2002-05-01 01:58:35 +00001496 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001497
1498 if (VG_(clo_verbosity) > 1)
1499 vg_show_counts();
1500
sewardjc0d8f682002-11-30 00:49:43 +00001501 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001502 VG_(print_UInstr_histogram)();
1503
sewardjde4a1d02002-03-22 01:27:54 +00001504 if (0) {
1505 VG_(message)(Vg_DebugMsg, "");
1506 VG_(message)(Vg_DebugMsg,
1507 "------ Valgrind's internal memory use stats follow ------" );
1508 VG_(mallocSanityCheckAll)();
1509 VG_(show_all_arena_stats)();
1510 VG_(message)(Vg_DebugMsg,
1511 "------ Valgrind's ExeContext management stats follow ------" );
1512 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001513 }
1514
njn25e49d8e72002-09-23 09:36:25 +00001515 if (VG_(clo_profile))
1516 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001517
1518 VG_(shutdown_logging)();
1519
sewardj3e1eb1f2002-05-18 13:14:17 +00001520 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1521 processes don't get traced into. Also mess up $libdir/valgrind
1522 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001523 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001524 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1525 VG_(getenv)("LD_PRELOAD"),
1526 VG_(getenv)("LD_LIBRARY_PATH")
1527 );
sewardjde4a1d02002-03-22 01:27:54 +00001528 }
1529
sewardj7e87e382002-05-03 19:09:05 +00001530 /* Decide how to exit. This depends on what the scheduler
1531 returned. */
1532 switch (src) {
1533 case VgSrc_ExitSyscall: /* the normal way out */
1534 vg_assert(VG_(last_run_tid) > 0
1535 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001536 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001537 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001538 /* The thread's %EBX at the time it did __NR_exit() will hold
1539 the arg to __NR_exit(), so we just do __NR_exit() with
1540 that arg. */
1541 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001542 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001543 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001544 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001545
sewardj7e87e382002-05-03 19:09:05 +00001546 case VgSrc_Deadlock:
1547 /* Just exit now. No point in continuing. */
1548 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001549 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001550 break;
1551
1552 case VgSrc_BbsDone:
1553 /* Tricky; we have to try and switch back to the real CPU.
1554 This is all very dodgy and won't work at all in the
1555 presence of threads, or if the client happened to be
1556 running a signal handler. */
1557 /* Prepare to restore state to the real CPU. */
1558 VG_(load_thread_state)(1 /* root thread */ );
1559 VG_(copy_baseBlock_to_m_state_static)();
1560
1561 /* This pushes a return address on the simulator's stack,
1562 which is abandoned. We call vg_sigshutdown_actions() at
1563 the end of vg_switch_to_real_CPU(), so as to ensure that
1564 the original stack and machine state is restored before
1565 the real signal mechanism is restored. */
1566 VG_(switch_to_real_CPU)();
1567
1568 default:
njne427a662002-10-02 11:08:25 +00001569 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001570 }
sewardjde4a1d02002-03-22 01:27:54 +00001571}
1572
1573
1574/* Debugging thing .. can be called from assembly with OYNK macro. */
1575void VG_(oynk) ( Int n )
1576{
1577 OINK(n);
1578}
1579
1580
1581/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1582 "valgrinq.so", which doesn't do anything. This is used to avoid
1583 tracing into child processes. To make this work the build system
1584 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001585
njn25e49d8e72002-09-23 09:36:25 +00001586 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1587 without it, child processes try to find valgrind.so symbols in the
1588 skin .so.
1589
sewardj78e25c92002-05-20 23:38:33 +00001590 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1591 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1592 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001593*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001594void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1595 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001596{
njn25e49d8e72002-09-23 09:36:25 +00001597 Char* p_prel = NULL;
1598 Char* sk_prel = NULL;
1599 Char* p_path = NULL;
1600 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001601 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1602 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001603
sewardj78e25c92002-05-20 23:38:33 +00001604 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1605
1606 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001607 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001608 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1609
njn25e49d8e72002-09-23 09:36:25 +00001610 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001611 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001612 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001613 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1614 goto mutancy;
1615 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1616 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001617 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001618 }
1619
sewardj78e25c92002-05-20 23:38:33 +00001620 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001621 if (sk_prel == NULL) goto mutancy;
1622
1623 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001624 if (p_path == NULL) goto mutancy;
1625
njn25e49d8e72002-09-23 09:36:25 +00001626 what = 4;
1627 {
1628 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1629 Char* p = sk_prel;
1630 while (*p != ':' && p > ld_preload_str) {
1631 *p = ' ';
1632 p--;
1633 }
1634 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1635 while (*p != ':' && *p != '\0') {
1636 *p = ' ';
1637 p++;
1638 }
1639 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1640 *p = ' '; /* blank ending ':' */
1641 }
1642
sewardj78e25c92002-05-20 23:38:33 +00001643 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001644 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001645 if (p_prel[7] != 'd') goto mutancy;
1646 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001647
1648 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1649 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1650 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001651 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001652 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001653 if (p_path[0] != '/') goto mutancy;
1654 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001655 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001656 if (p_path[7] != 'd') goto mutancy;
1657 p_path[7] = 'q';
1658 return;
1659
1660 mutancy:
1661 VG_(printf)(
1662 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1663 " what = %d\n"
1664 " ld_preload_str = `%s'\n"
1665 " ld_library_path_str = `%s'\n"
1666 " p_prel = `%s'\n"
1667 " p_path = `%s'\n"
1668 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001669 what, ld_preload_str, ld_library_path_str,
1670 p_prel, p_path, VG_LIBDIR
1671 );
sewardjc26b4482002-07-13 12:20:35 +00001672 VG_(printf)(
1673 "\n"
1674 "Note that this is often caused by mis-installation of valgrind.\n"
1675 "Correct installation procedure is:\n"
1676 " ./configure --prefix=/install/dir\n"
1677 " make install\n"
1678 "And then use /install/dir/bin/valgrind\n"
1679 "Moving the installation directory elsewhere after 'make install'\n"
1680 "will cause the above error. Hand-editing the paths in the shell\n"
1681 "scripts is also likely to cause problems.\n"
1682 "\n"
1683 );
njne427a662002-10-02 11:08:25 +00001684 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001685}
1686
sewardj3e1eb1f2002-05-18 13:14:17 +00001687
sewardjde4a1d02002-03-22 01:27:54 +00001688/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1689 it to attach to this process. Called if the user requests this
1690 service after an error has been shown, so she can poke around and
1691 look at parameters, memory, etc. You can't meaningfully get GDB to
1692 continue the program, though; to continue, quit GDB. */
1693extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1694{
sewardje6a25242002-04-21 22:03:07 +00001695 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001696 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001697
1698#define TO_STRING(x) TO_STRING2(x)
1699#define TO_STRING2(x) #x
1700
1701 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
njn17b85352003-04-18 12:54:24 +00001702 TO_STRING(GDB_PATH), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001703 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1704 res = VG_(system)(buf);
1705 if (res == 0) {
1706 VG_(message)(Vg_UserMsg, "");
1707 VG_(message)(Vg_UserMsg,
1708 "GDB has detached. Valgrind regains control. We continue.");
1709 } else {
1710 VG_(message)(Vg_UserMsg, "Apparently failed!");
1711 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001712 }
njn9315df32003-04-16 20:50:50 +00001713#undef TO_STRING
1714#undef TO_STRING2
sewardjde4a1d02002-03-22 01:27:54 +00001715}
1716
1717
1718/* Print some helpful-ish text about unimplemented things, and give
1719 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001720void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001721{
1722 VG_(message)(Vg_UserMsg, "");
1723 VG_(message)(Vg_UserMsg,
1724 "Valgrind detected that your program requires");
1725 VG_(message)(Vg_UserMsg,
1726 "the following unimplemented functionality:");
1727 VG_(message)(Vg_UserMsg, " %s", msg);
1728 VG_(message)(Vg_UserMsg,
1729 "This may be because the functionality is hard to implement,");
1730 VG_(message)(Vg_UserMsg,
1731 "or because no reasonable program would behave this way,");
1732 VG_(message)(Vg_UserMsg,
1733 "or because nobody has yet needed it. In any case, let me know");
1734 VG_(message)(Vg_UserMsg,
1735 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1736 VG_(message)(Vg_UserMsg,
1737 "");
1738 VG_(message)(Vg_UserMsg,
1739 "Valgrind has to exit now. Sorry. Bye!");
1740 VG_(message)(Vg_UserMsg,
1741 "");
sewardj15a43e12002-04-17 19:35:12 +00001742 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001743 VG_(exit)(1);
1744}
1745
1746
njn25e49d8e72002-09-23 09:36:25 +00001747/* ---------------------------------------------------------------------
1748 Sanity check machinery (permanently engaged).
1749 ------------------------------------------------------------------ */
1750
1751/* A fast sanity check -- suitable for calling circa once per
1752 millisecond. */
1753
1754void VG_(do_sanity_checks) ( Bool force_expensive )
1755{
1756 Int i;
1757
njn37cea302002-09-30 11:24:00 +00001758 VGP_PUSHCC(VgpCoreCheapSanity);
1759
njn25e49d8e72002-09-23 09:36:25 +00001760 if (VG_(sanity_level) < 1) return;
1761
1762 /* --- First do all the tests that we can do quickly. ---*/
1763
1764 VG_(sanity_fast_count)++;
1765
1766 /* Check that we haven't overrun our private stack. */
1767 for (i = 0; i < 10; i++) {
1768 vg_assert(VG_(stack)[i]
1769 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1770 vg_assert(VG_(stack)[10000-1-i]
1771 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1772 }
1773
1774 /* Check stuff pertaining to the memory check system. */
1775
1776 /* Check that nobody has spuriously claimed that the first or
1777 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001778 if (VG_(needs).sanity_checks) {
1779 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001780 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001781 VGP_POPCC(VgpSkinCheapSanity);
1782 }
njn25e49d8e72002-09-23 09:36:25 +00001783
1784 /* --- Now some more expensive checks. ---*/
1785
1786 /* Once every 25 times, check some more expensive stuff. */
1787 if ( force_expensive
1788 || VG_(sanity_level) > 1
1789 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1790
njn37cea302002-09-30 11:24:00 +00001791 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001792 VG_(sanity_slow_count)++;
1793
1794# if 0
1795 { void zzzmemscan(void); zzzmemscan(); }
1796# endif
1797
1798 if ((VG_(sanity_fast_count) % 250) == 0)
1799 VG_(sanity_check_tc_tt)();
1800
1801 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001802 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001803 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001804 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001805 }
1806 /*
1807 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1808 */
njn37cea302002-09-30 11:24:00 +00001809 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001810 }
1811
1812 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001813 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001814 /* Check sanity of the low-level memory manager. Note that bugs
1815 in the client's code can cause this to fail, so we don't do
1816 this check unless specially asked for. And because it's
1817 potentially very expensive. */
1818 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001819 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001820 }
njn37cea302002-09-30 11:24:00 +00001821 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001822}
sewardjde4a1d02002-03-22 01:27:54 +00001823/*--------------------------------------------------------------------*/
1824/*--- end vg_main.c ---*/
1825/*--------------------------------------------------------------------*/