blob: 69079b7719e965aeebcaca16b3ce78f006311d04 [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
11 Copyright (C) 2000-2002 Julian Seward
12 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"
632" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
633" 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
660/* Callback for lookiing for the stackl segment. */
661static Addr vg_foundstack_start = (Addr)NULL;
662static UInt vg_foundstack_size = 0;
663
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) {
676 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
721 /* Now vg_foundstack_start and vg_foundstack_size
722 should delimit the stack. */
723 if (vg_foundstack_size == 0) {
724 args_grok_error("Cannot determine stack segment "
725 "from /proc/self/maps");
726 }
sewardj1c1b1162003-02-23 01:25:51 +0000727
728 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000729 VG_(printf)("stack segment is %p .. %p\n",
730 vg_foundstack_start,
731 vg_foundstack_start + vg_foundstack_size - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000732
sewardj53fe4582003-02-23 01:41:17 +0000733 sp = (UInt*)(vg_foundstack_start + vg_foundstack_size);
734 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
735 args_grok_error("Stack segment is not page aligned?!");
736 }
sewardj1c1b1162003-02-23 01:25:51 +0000737
sewardj53fe4582003-02-23 01:41:17 +0000738 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
739 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000740
sewardj38170912002-05-10 21:07:22 +0000741 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000742 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000743 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000744 sp--;
745 }
sewardj38170912002-05-10 21:07:22 +0000746
747 if (sp[2] == VKI_AT_BASE
748 && sp[0] == VKI_AT_PAGESZ
749 && sp[-2] == VKI_AT_PHNUM
750 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000751 && sp[-6] == VKI_AT_PHDR
752 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000753 if (0)
754 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000755 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000756 } else
757 if (sp[2] == VKI_AT_CLKTCK
758 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000759 && sp[-2] == VKI_AT_HWCAP
760 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000761 if (0)
762 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
763 sp -= 2;
764 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000765 if (sp[2] == VKI_AT_CLKTCK
766 && sp[0] == VKI_AT_PAGESZ
767 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000768 && sp[-4] == VKI_AT_SYSINFO
769 && sp[-4-1] == 0) {
770 if (0)
771 VG_(printf)("Looks like you've got a 2.4.X kernel with "
772 "a sysinfo page at %x here.\n", sp[-3]);
773 VG_(sysinfo_page_exists) = True;
774 VG_(sysinfo_page_addr) = sp[-3];
775 sp -= 4;
776 } else
777 if (sp[2] == VKI_AT_CLKTCK
778 && sp[0] == VKI_AT_PAGESZ
779 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000780 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
781 && sp[-4-1] == 0) {
782 if (0)
783 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
784 "kernel here.\n");
785 sp -= 4;
786 } else
787 if (sp[2] == VKI_AT_CLKTCK
788 && sp[0] == VKI_AT_PAGESZ
789 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000790 && sp[-2-20-1] == 0) {
791 if (0)
792 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
793 sp -= 22;
794 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000795 if (sp[2] == VKI_AT_CLKTCK
796 && sp[0] == VKI_AT_PAGESZ
797 && sp[-2] == VKI_AT_HWCAP
798 && sp[-4-1] == 0) {
799 if (0)
800 VG_(printf)("Looks like a >> 2.5.43 kernel here.\n");
801 sp -= 4;
802 } else
sewardja1679dd2002-05-10 22:31:40 +0000803 args_grok_error(
804 "ELF frame does not look like 2.2.X or 2.4.X.\n "
805 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
806 );
sewardj38170912002-05-10 21:07:22 +0000807
808 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000809 if (*sp != 0)
810 args_grok_error("can't find NULL at end of env[]");
811
sewardj38170912002-05-10 21:07:22 +0000812 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000813 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000814 while (True) {
815 sp --;
816 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000817 if (++ctr >= 1000)
818 args_grok_error(
819 "suspiciously many (1000) env[] entries; giving up");
820
sewardj38170912002-05-10 21:07:22 +0000821 }
822 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000823 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000824
sewardja1679dd2002-05-10 22:31:40 +0000825 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000826 VG_(client_argc) = 0;
827 while (True) {
828 sp--;
829 if (*sp == VG_(client_argc))
830 break;
831 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000832 if (++ctr >= 1000)
833 args_grok_error(
834 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000835 }
836
sewardja1679dd2002-05-10 22:31:40 +0000837 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000838 }
839
sewardjde4a1d02002-03-22 01:27:54 +0000840 /* Now that VG_(client_envp) has been set, we can extract the args
841 for Valgrind itself. Copy into global var so that we don't have to
842 write zeroes to the getenv'd value itself. */
843 str = VG_(getenv)("VG_ARGS");
844 argc = 0;
845
846 if (!str) {
847 config_error("Can't read options from env var VG_ARGS.");
848 }
849
850 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
851 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
852 }
853 VG_(strcpy)(vg_cmdline_copy, str);
854 str = NULL;
855
856 p = &vg_cmdline_copy[0];
857 while (True) {
858 while (ISSPACE(*p)) { *p = 0; p++; }
859 if (*p == 0) break;
860 if (argc < M_VG_CMDLINE_OPTS-1) {
861 argv[argc] = p; argc++;
862 } else {
863 config_error(
864 "Found more than M_CMDLINE_OPTS command-line opts.");
865 }
866 while (*p != 0 && !ISSPACE(*p)) p++;
867 }
868
869 for (i = 0; i < argc; i++) {
870
njn43c799e2003-04-08 00:08:52 +0000871 if (VG_CLO_STREQ(argv[i], "-v") ||
872 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000873 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000874 else if (VG_CLO_STREQ(argv[i], "-q") ||
875 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000876 VG_(clo_verbosity)--;
877
njn43c799e2003-04-08 00:08:52 +0000878 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000879 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000880 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000881 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000882
njn43c799e2003-04-08 00:08:52 +0000883 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000884 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000885 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000886 VG_(clo_GDB_attach) = False;
887
njn43c799e2003-04-08 00:08:52 +0000888 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
889 VG_(clo_gen_suppressions) = True;
890 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
891 VG_(clo_gen_suppressions) = False;
892
893 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000894 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000895 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000896 VG_(clo_demangle) = False;
897
njn43c799e2003-04-08 00:08:52 +0000898 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000899 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000900 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000901 VG_(clo_trace_children) = False;
902
njn43c799e2003-04-08 00:08:52 +0000903 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000904 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000905 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000906 VG_(clo_run_libc_freeres) = False;
907
njn43c799e2003-04-08 00:08:52 +0000908 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000909 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
910
njn43c799e2003-04-08 00:08:52 +0000911 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000912 VG_(clo_log_to) = VgLogTo_Fd;
913 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000914 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000915 }
916
njn43c799e2003-04-08 00:08:52 +0000917 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000918 VG_(clo_log_to) = VgLogTo_File;
919 VG_(clo_logfile_name) = &argv[i][10];
920 }
sewardjde4a1d02002-03-22 01:27:54 +0000921
njn43c799e2003-04-08 00:08:52 +0000922 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000923 VG_(clo_log_to) = VgLogTo_Socket;
924 VG_(clo_logfile_name) = &argv[i][12];
925 }
926
njn43c799e2003-04-08 00:08:52 +0000927 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000928 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000929 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000930 VG_(message)(Vg_UserMsg,
931 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000932 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000933 }
934 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
935 VG_(clo_n_suppressions)++;
936 }
njn43c799e2003-04-08 00:08:52 +0000937 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000938 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000939 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000940 VG_(clo_profile) = False;
941
njn43c799e2003-04-08 00:08:52 +0000942 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000943 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000944 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000945 VG_(clo_chain_bb) = False;
946
njn43c799e2003-04-08 00:08:52 +0000947 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000948 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000949 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000950 VG_(clo_single_step) = False;
951
njn43c799e2003-04-08 00:08:52 +0000952 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000953 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000954 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000955 VG_(clo_optimise) = False;
956
njn25e49d8e72002-09-23 09:36:25 +0000957 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +0000958 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +0000959 Int j;
960 char* opt = & argv[i][16];
961
962 if (5 != VG_(strlen)(opt)) {
963 VG_(message)(Vg_UserMsg,
964 "--trace-codegen argument must have 5 digits");
965 VG_(bad_option)(argv[i]);
966 }
967 for (j = 0; j < 5; j++) {
968 if ('0' == opt[j]) { /* do nothing */ }
969 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
970 else {
971 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
972 "contain 0s and 1s");
973 VG_(bad_option)(argv[i]);
974 }
975 }
976 }
sewardjde4a1d02002-03-22 01:27:54 +0000977
njn43c799e2003-04-08 00:08:52 +0000978 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000979 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +0000980 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000981 VG_(clo_trace_syscalls) = False;
982
njn43c799e2003-04-08 00:08:52 +0000983 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000984 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +0000985 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000986 VG_(clo_trace_signals) = False;
987
njn43c799e2003-04-08 00:08:52 +0000988 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000989 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +0000990 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000991 VG_(clo_trace_symtab) = False;
992
njn43c799e2003-04-08 00:08:52 +0000993 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +0000994 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +0000995 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +0000996 VG_(clo_trace_sched) = False;
997
njn43c799e2003-04-08 00:08:52 +0000998 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +0000999 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001000 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001001 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001002 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001003 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001004
njn43c799e2003-04-08 00:08:52 +00001005 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001006 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001007
njn43c799e2003-04-08 00:08:52 +00001008 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001009 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1010
njn43c799e2003-04-08 00:08:52 +00001011 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001012 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1013
njn43c799e2003-04-08 00:08:52 +00001014 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001015 /* Make sure it's sane. */
1016 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1017 if (VG_(clo_backtrace_size) < 2)
1018 VG_(clo_backtrace_size) = 2;
1019 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1020 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1021 }
1022
njn25e49d8e72002-09-23 09:36:25 +00001023 else if (VG_(needs).command_line_options) {
1024 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1025 if (!ok)
1026 usage();
1027 }
sewardjde4a1d02002-03-22 01:27:54 +00001028 else
njn25e49d8e72002-09-23 09:36:25 +00001029 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001030 }
1031
1032# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001033
1034 if (VG_(clo_verbosity < 0))
1035 VG_(clo_verbosity) = 0;
1036
1037 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1038 VG_(message)(Vg_UserMsg, "");
1039 VG_(message)(Vg_UserMsg,
1040 "--gdb-attach=yes conflicts with --trace-children=yes");
1041 VG_(message)(Vg_UserMsg,
1042 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001043 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001044 }
1045
sewardj4cf05692002-10-27 20:28:29 +00001046 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1047 should be connected to whatever sink has been selected, and we
1048 indiscriminately chuck stuff into it without worrying what the
1049 nature of it is. Oh the wonder of Unix streams. */
1050
1051 /* So far we should be still attached to stderr, so we can show on
1052 the terminal any problems to do with processing command line
1053 opts. */
1054 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001055 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001056
1057 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001058
sewardj4cf05692002-10-27 20:28:29 +00001059 case VgLogTo_Fd:
1060 vg_assert(VG_(clo_logfile_name) == NULL);
1061 VG_(clo_logfile_fd) = eventually_logfile_fd;
1062 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001063
sewardj4cf05692002-10-27 20:28:29 +00001064 case VgLogTo_File: {
1065 Char logfilename[1000];
1066 vg_assert(VG_(clo_logfile_name) != NULL);
1067 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1068 VG_(sprintf)(logfilename, "%s.pid%d",
1069 VG_(clo_logfile_name), VG_(getpid)() );
1070 eventually_logfile_fd
1071 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1072 VKI_S_IRUSR|VKI_S_IWUSR);
1073 if (eventually_logfile_fd != -1) {
1074 VG_(clo_logfile_fd) = eventually_logfile_fd;
1075 } else {
1076 VG_(message)(Vg_UserMsg,
1077 "Can't create/open log file `%s.pid%d'; giving up!",
1078 VG_(clo_logfile_name), VG_(getpid)());
1079 VG_(bad_option)(
1080 "--logfile=<file> didn't work out for some reason.");
1081 }
1082 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001083 }
1084
1085 case VgLogTo_Socket: {
1086 vg_assert(VG_(clo_logfile_name) != NULL);
1087 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1088 eventually_logfile_fd
1089 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1090 if (eventually_logfile_fd == -1) {
1091 VG_(message)(Vg_UserMsg,
1092 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1093 VG_(message)(Vg_UserMsg,
1094 "of `%s'; giving up!", VG_(clo_logfile_name) );
1095 VG_(bad_option)(
1096 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001097 }
sewardj73cf3bc2002-11-03 03:20:15 +00001098 if (eventually_logfile_fd == -2) {
1099 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001100 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001101 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001102 VG_(message)(Vg_UserMsg,
1103 "Log messages will sent to stderr instead." );
1104 VG_(message)(Vg_UserMsg,
1105 "" );
1106 /* We don't change anything here. */
1107 } else {
1108 vg_assert(eventually_logfile_fd > 0);
1109 VG_(clo_logfile_fd) = eventually_logfile_fd;
1110 VG_(logging_to_filedes) = False;
1111 }
sewardj73cf3bc2002-11-03 03:20:15 +00001112 break;
1113 }
1114
sewardj4cf05692002-10-27 20:28:29 +00001115 }
1116
1117 /* Ok, the logging sink is running now. Print a suitable preamble.
1118 If logging to file or a socket, write details of parent PID and
1119 command line args, to help people trying to interpret the
1120 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001121
sewardj83adf412002-05-01 01:25:45 +00001122 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001123 /* Skin details */
1124 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1125 VG_(details).name,
1126 NULL == VG_(details).version ? "" : "-",
1127 NULL == VG_(details).version
1128 ? (Char*)"" : VG_(details).version,
1129 VG_(details).description);
1130 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001131
njnd04b7c62002-10-03 14:05:52 +00001132 /* Core details */
1133 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001134 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001135 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001136 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001137 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001138 }
1139
sewardj4cf05692002-10-27 20:28:29 +00001140 if (VG_(clo_log_to) != VgLogTo_Fd) {
1141 VG_(message)(Vg_UserMsg, "");
1142 VG_(message)(Vg_UserMsg,
1143 "My PID = %d, parent PID = %d. Prog and args are:",
1144 VG_(getpid)(), VG_(getppid)() );
1145 for (i = 0; i < VG_(client_argc); i++)
1146 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1147 }
1148
sewardjde4a1d02002-03-22 01:27:54 +00001149 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001150 if (VG_(clo_log_to) != VgLogTo_Fd)
1151 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001152 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1153 for (i = 0; i < argc; i++) {
1154 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1155 }
1156 }
1157
njn25e49d8e72002-09-23 09:36:25 +00001158 if (VG_(clo_n_suppressions) == 0 &&
1159 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001160 config_error("No error-suppression files were specified.");
1161 }
sewardj4cf05692002-10-27 20:28:29 +00001162
sewardjde4a1d02002-03-22 01:27:54 +00001163}
1164
sewardjde4a1d02002-03-22 01:27:54 +00001165/* ---------------------------------------------------------------------
1166 Copying to/from m_state_static.
1167 ------------------------------------------------------------------ */
1168
sewardj92a59562002-09-30 00:53:10 +00001169UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1170 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001171 + 1 /* %eflags */
1172 + 1 /* %eip */
1173 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1174 ];
1175
sewardjfa492d42002-12-08 18:20:01 +00001176UInt VG_(insertDflag)(UInt eflags, Int d)
1177{
1178 vg_assert(d == 1 || d == -1);
1179 eflags &= ~EFlagD;
1180
1181 if (d < 0)
1182 eflags |= EFlagD;
1183
1184 return eflags;
1185}
1186
1187Int VG_(extractDflag)(UInt eflags)
1188{
1189 Int ret;
1190
1191 if (eflags & EFlagD)
1192 ret = -1;
1193 else
1194 ret = 1;
1195
1196 return ret;
1197}
1198
sewardjde4a1d02002-03-22 01:27:54 +00001199void VG_(copy_baseBlock_to_m_state_static) ( void )
1200{
1201 Int i;
sewardj92a59562002-09-30 00:53:10 +00001202 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1203 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1204 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1205 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1206 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1207 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001208
sewardj92a59562002-09-30 00:53:10 +00001209 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1210 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1211 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1212 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1213 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1214 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1215 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1216 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1217
sewardjfa492d42002-12-08 18:20:01 +00001218 VG_(m_state_static)[56/4] = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1219 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001220 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001221
1222 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001223 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001224 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1225}
1226
1227
1228void VG_(copy_m_state_static_to_baseBlock) ( void )
1229{
1230 Int i;
sewardj92a59562002-09-30 00:53:10 +00001231 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1232 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1233 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1234 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1235 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1236 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001237
sewardj92a59562002-09-30 00:53:10 +00001238 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1239 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1240 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1241 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1242 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1243 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1244 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1245 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1246
sewardjfa492d42002-12-08 18:20:01 +00001247 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4] & ~EFlagD;
1248 VG_(baseBlock)[VGOFF_(m_dflag)] = VG_(extractDflag)(VG_(m_state_static)[56/4]);
1249
sewardj92a59562002-09-30 00:53:10 +00001250 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001251
1252 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1253 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001254 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001255}
1256
njn25e49d8e72002-09-23 09:36:25 +00001257Addr VG_(get_stack_pointer) ( void )
1258{
1259 return VG_(baseBlock)[VGOFF_(m_esp)];
1260}
1261
1262/* Some random tests needed for leak checking */
1263
1264Bool VG_(within_stack)(Addr a)
1265{
1266 if (a >= ((Addr)(&VG_(stack)))
1267 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1268 return True;
1269 else
1270 return False;
1271}
1272
1273Bool VG_(within_m_state_static)(Addr a)
1274{
1275 if (a >= ((Addr)(&VG_(m_state_static)))
1276 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1277 return True;
1278 else
1279 return False;
1280}
sewardjde4a1d02002-03-22 01:27:54 +00001281
1282/* ---------------------------------------------------------------------
1283 Show accumulated counts.
1284 ------------------------------------------------------------------ */
1285
njn25e49d8e72002-09-23 09:36:25 +00001286static __inline__ Int safe_idiv(Int a, Int b)
1287{
1288 return (b == 0 ? 0 : a / b);
1289}
1290
sewardjde4a1d02002-03-22 01:27:54 +00001291static void vg_show_counts ( void )
1292{
1293 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001294 " TT/TC: %d tc sectors discarded.",
1295 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001296 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001297 " %d chainings, %d unchainings.",
1298 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1299 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001300 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001301 VG_(overall_in_count),
1302 VG_(overall_in_osize),
1303 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001304 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1305 VG_(message)(Vg_DebugMsg,
1306 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001307 VG_(overall_out_count),
1308 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001309 VG_(overall_out_tsize),
1310 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001311 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001312 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001313 VG_(bbs_done),
1314 VG_(unchained_jumps_done),
1315 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1316 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1317 );
1318
1319 VG_(message)(Vg_DebugMsg,
1320 " %d/%d major/minor sched events. %d tt_fast misses.",
1321 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001322 VG_(num_scheduling_events_MINOR),
1323 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001324
sewardjde4a1d02002-03-22 01:27:54 +00001325 VG_(message)(Vg_DebugMsg,
1326 "reg-alloc: %d t-req-spill, "
1327 "%d+%d orig+spill uis, %d total-reg-r.",
1328 VG_(translations_needing_spill),
1329 VG_(uinstrs_prealloc),
1330 VG_(uinstrs_spill),
1331 VG_(total_reg_rank) );
1332 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001333 " sanity: %d cheap, %d expensive checks.",
1334 VG_(sanity_fast_count),
1335 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001336 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001337}
1338
1339
1340/* ---------------------------------------------------------------------
1341 Main!
1342 ------------------------------------------------------------------ */
1343
1344/* Where we jump to once Valgrind has got control, and the real
1345 machine's state has been copied to the m_state_static. */
1346
1347void VG_(main) ( void )
1348{
sewardj2e93c502002-04-12 11:12:52 +00001349 Int i;
1350 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001351 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001352
njn27f1a382002-11-08 15:48:16 +00001353 /* Check skin and core versions are compatible */
1354 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1355 VG_(printf)("Error:\n"
1356 " Skin and core interface versions do not match.\n"
1357 " Interface version used by core is: %d.%d\n"
1358 " Interface version used by skin is: %d.%d\n"
1359 " The major version numbers must match.\n",
1360 VG_CORE_INTERFACE_MAJOR_VERSION,
1361 VG_CORE_INTERFACE_MINOR_VERSION,
1362 VG_(skin_interface_major_version),
1363 VG_(skin_interface_minor_version));
1364 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1365 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1366 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1367 else
1368 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1369 VG_(printf)(" Aborting, sorry.\n");
1370 VG_(exit)(1);
1371 }
1372
sewardjde4a1d02002-03-22 01:27:54 +00001373 /* Set up our stack sanity-check words. */
1374 for (i = 0; i < 10; i++) {
1375 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1376 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1377 }
1378
njn3e884182003-04-15 13:03:23 +00001379 /* Read /proc/self/maps into a buffer. Must be before:
1380 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1381 superblocks are not erroneously identified as being owned by the
1382 client, which would be bad.
1383 - init_memory(): that's where the buffer is parsed
1384 - init_tt_tc(): so the anonymous mmaps for the translation table and
1385 translation cache aren't identified as part of the client, which would
1386 waste > 20M of virtual address space, and be bad.
1387 */
1388 VG_(read_procselfmaps_contents)();
1389
sewardj1c1b1162003-02-23 01:25:51 +00001390 /* Hook to delay things long enough so we can get the pid and
1391 attach GDB in another shell. */
1392 if (0) {
1393 Int p, q;
1394 VG_(printf)("pid=%d\n", VG_(getpid)());
1395 for (p = 0; p < 50000; p++)
1396 for (q = 0; q < 50000; q++) ;
1397 }
1398
njn25e49d8e72002-09-23 09:36:25 +00001399 /* Setup stuff that depends on the skin. Must be before:
1400 - vg_init_baseBlock(): to register helpers
1401 - process_cmd_line_options(): to register skin name and description,
1402 and turn on/off 'command_line_options' need
1403 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001404 */
njn810086f2002-11-14 12:42:47 +00001405 SK_(pre_clo_init)();
1406 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001407
njncc7bb472002-10-14 09:25:19 +00001408 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001409 process_cmd_line_options();
1410
njn3e884182003-04-15 13:03:23 +00001411 /* Do post command-line processing initialisation. Must be before:
1412 - vg_init_baseBlock(): to register any more helpers
1413 */
njncc7bb472002-10-14 09:25:19 +00001414 SK_(post_clo_init)();
1415
njn3e884182003-04-15 13:03:23 +00001416 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001417 vg_init_baseBlock();
1418
sewardj018f7622002-05-15 21:13:39 +00001419 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001420 baseBlock into VG_(threads)[1]. Must be before:
1421 - VG_(sigstartup_actions)()
1422 */
sewardj018f7622002-05-15 21:13:39 +00001423 VG_(scheduler_init)();
1424
1425 /* Initialise the signal handling subsystem, temporarily parking
1426 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001427 VG_(sigstartup_actions)();
1428
sewardj018f7622002-05-15 21:13:39 +00001429 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001430 if (VG_(clo_profile))
1431 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001432
sewardj5f07b662002-04-23 16:52:51 +00001433 /* Start calibration of our RDTSC-based clock. */
1434 VG_(start_rdtsc_calibration)();
1435
njn3e884182003-04-15 13:03:23 +00001436 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001437 VGP_PUSHCC(VgpInitMem);
1438 VG_(init_memory)();
1439 VGP_POPCC(VgpInitMem);
1440
1441 /* Read the list of errors to suppress. This should be found in
1442 the file specified by vg_clo_suppressions. */
1443 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1444 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001445
sewardj5f07b662002-04-23 16:52:51 +00001446 /* End calibration of our RDTSC-based clock, leaving it as long as
1447 we can. */
1448 VG_(end_rdtsc_calibration)();
1449
njn3e884182003-04-15 13:03:23 +00001450 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001451 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001452
1453 if (VG_(clo_verbosity) == 1) {
1454 VG_(message)(Vg_UserMsg,
1455 "For more details, rerun with: -v");
1456 }
1457
1458 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1459 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001460 if (VG_(clo_verbosity) > 0)
1461 VG_(message)(Vg_UserMsg, "");
1462
1463 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001464
sewardj018f7622002-05-15 21:13:39 +00001465 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001466 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001467 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001468 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001469 VGP_POPCC(VgpSched);
1470 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001471
1472 if (VG_(clo_verbosity) > 0)
1473 VG_(message)(Vg_UserMsg, "");
1474
sewardj2e93c502002-04-12 11:12:52 +00001475 if (src == VgSrc_Deadlock) {
1476 VG_(message)(Vg_UserMsg,
1477 "Warning: pthread scheduler exited due to deadlock");
1478 }
1479
njn25e49d8e72002-09-23 09:36:25 +00001480 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001481 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001482
njn25e49d8e72002-09-23 09:36:25 +00001483 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001484
sewardj0c3b53f2002-05-01 01:58:35 +00001485 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001486
1487 if (VG_(clo_verbosity) > 1)
1488 vg_show_counts();
1489
sewardjc0d8f682002-11-30 00:49:43 +00001490 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001491 VG_(print_UInstr_histogram)();
1492
sewardjde4a1d02002-03-22 01:27:54 +00001493 if (0) {
1494 VG_(message)(Vg_DebugMsg, "");
1495 VG_(message)(Vg_DebugMsg,
1496 "------ Valgrind's internal memory use stats follow ------" );
1497 VG_(mallocSanityCheckAll)();
1498 VG_(show_all_arena_stats)();
1499 VG_(message)(Vg_DebugMsg,
1500 "------ Valgrind's ExeContext management stats follow ------" );
1501 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001502 }
1503
njn25e49d8e72002-09-23 09:36:25 +00001504 if (VG_(clo_profile))
1505 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001506
1507 VG_(shutdown_logging)();
1508
sewardj3e1eb1f2002-05-18 13:14:17 +00001509 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1510 processes don't get traced into. Also mess up $libdir/valgrind
1511 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001512 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001513 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1514 VG_(getenv)("LD_PRELOAD"),
1515 VG_(getenv)("LD_LIBRARY_PATH")
1516 );
sewardjde4a1d02002-03-22 01:27:54 +00001517 }
1518
sewardj7e87e382002-05-03 19:09:05 +00001519 /* Decide how to exit. This depends on what the scheduler
1520 returned. */
1521 switch (src) {
1522 case VgSrc_ExitSyscall: /* the normal way out */
1523 vg_assert(VG_(last_run_tid) > 0
1524 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001525 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001526 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001527 /* The thread's %EBX at the time it did __NR_exit() will hold
1528 the arg to __NR_exit(), so we just do __NR_exit() with
1529 that arg. */
1530 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001531 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001532 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001533 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001534
sewardj7e87e382002-05-03 19:09:05 +00001535 case VgSrc_Deadlock:
1536 /* Just exit now. No point in continuing. */
1537 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001538 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001539 break;
1540
1541 case VgSrc_BbsDone:
1542 /* Tricky; we have to try and switch back to the real CPU.
1543 This is all very dodgy and won't work at all in the
1544 presence of threads, or if the client happened to be
1545 running a signal handler. */
1546 /* Prepare to restore state to the real CPU. */
1547 VG_(load_thread_state)(1 /* root thread */ );
1548 VG_(copy_baseBlock_to_m_state_static)();
1549
1550 /* This pushes a return address on the simulator's stack,
1551 which is abandoned. We call vg_sigshutdown_actions() at
1552 the end of vg_switch_to_real_CPU(), so as to ensure that
1553 the original stack and machine state is restored before
1554 the real signal mechanism is restored. */
1555 VG_(switch_to_real_CPU)();
1556
1557 default:
njne427a662002-10-02 11:08:25 +00001558 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001559 }
sewardjde4a1d02002-03-22 01:27:54 +00001560}
1561
1562
1563/* Debugging thing .. can be called from assembly with OYNK macro. */
1564void VG_(oynk) ( Int n )
1565{
1566 OINK(n);
1567}
1568
1569
1570/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1571 "valgrinq.so", which doesn't do anything. This is used to avoid
1572 tracing into child processes. To make this work the build system
1573 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001574
njn25e49d8e72002-09-23 09:36:25 +00001575 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1576 without it, child processes try to find valgrind.so symbols in the
1577 skin .so.
1578
sewardj78e25c92002-05-20 23:38:33 +00001579 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1580 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1581 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001582*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001583void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1584 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001585{
njn25e49d8e72002-09-23 09:36:25 +00001586 Char* p_prel = NULL;
1587 Char* sk_prel = NULL;
1588 Char* p_path = NULL;
1589 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001590 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1591 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001592
sewardj78e25c92002-05-20 23:38:33 +00001593 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1594
1595 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001596 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001597 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1598
njn25e49d8e72002-09-23 09:36:25 +00001599 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001600 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001601 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001602 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1603 goto mutancy;
1604 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1605 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001606 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001607 }
1608
sewardj78e25c92002-05-20 23:38:33 +00001609 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001610 if (sk_prel == NULL) goto mutancy;
1611
1612 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001613 if (p_path == NULL) goto mutancy;
1614
njn25e49d8e72002-09-23 09:36:25 +00001615 what = 4;
1616 {
1617 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1618 Char* p = sk_prel;
1619 while (*p != ':' && p > ld_preload_str) {
1620 *p = ' ';
1621 p--;
1622 }
1623 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1624 while (*p != ':' && *p != '\0') {
1625 *p = ' ';
1626 p++;
1627 }
1628 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1629 *p = ' '; /* blank ending ':' */
1630 }
1631
sewardj78e25c92002-05-20 23:38:33 +00001632 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001633 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001634 if (p_prel[7] != 'd') goto mutancy;
1635 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001636
1637 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1638 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1639 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001640 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001641 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001642 if (p_path[0] != '/') goto mutancy;
1643 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001644 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001645 if (p_path[7] != 'd') goto mutancy;
1646 p_path[7] = 'q';
1647 return;
1648
1649 mutancy:
1650 VG_(printf)(
1651 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1652 " what = %d\n"
1653 " ld_preload_str = `%s'\n"
1654 " ld_library_path_str = `%s'\n"
1655 " p_prel = `%s'\n"
1656 " p_path = `%s'\n"
1657 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001658 what, ld_preload_str, ld_library_path_str,
1659 p_prel, p_path, VG_LIBDIR
1660 );
sewardjc26b4482002-07-13 12:20:35 +00001661 VG_(printf)(
1662 "\n"
1663 "Note that this is often caused by mis-installation of valgrind.\n"
1664 "Correct installation procedure is:\n"
1665 " ./configure --prefix=/install/dir\n"
1666 " make install\n"
1667 "And then use /install/dir/bin/valgrind\n"
1668 "Moving the installation directory elsewhere after 'make install'\n"
1669 "will cause the above error. Hand-editing the paths in the shell\n"
1670 "scripts is also likely to cause problems.\n"
1671 "\n"
1672 );
njne427a662002-10-02 11:08:25 +00001673 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001674}
1675
sewardj3e1eb1f2002-05-18 13:14:17 +00001676
sewardjde4a1d02002-03-22 01:27:54 +00001677/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1678 it to attach to this process. Called if the user requests this
1679 service after an error has been shown, so she can poke around and
1680 look at parameters, memory, etc. You can't meaningfully get GDB to
1681 continue the program, though; to continue, quit GDB. */
1682extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1683{
sewardje6a25242002-04-21 22:03:07 +00001684 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001685 UChar buf[100];
1686 VG_(sprintf)(buf,
1687 "/usr/bin/gdb -nw /proc/%d/exe %d",
1688 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001689 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1690 res = VG_(system)(buf);
1691 if (res == 0) {
1692 VG_(message)(Vg_UserMsg, "");
1693 VG_(message)(Vg_UserMsg,
1694 "GDB has detached. Valgrind regains control. We continue.");
1695 } else {
1696 VG_(message)(Vg_UserMsg, "Apparently failed!");
1697 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001698 }
sewardjde4a1d02002-03-22 01:27:54 +00001699}
1700
1701
1702/* Print some helpful-ish text about unimplemented things, and give
1703 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001704void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001705{
1706 VG_(message)(Vg_UserMsg, "");
1707 VG_(message)(Vg_UserMsg,
1708 "Valgrind detected that your program requires");
1709 VG_(message)(Vg_UserMsg,
1710 "the following unimplemented functionality:");
1711 VG_(message)(Vg_UserMsg, " %s", msg);
1712 VG_(message)(Vg_UserMsg,
1713 "This may be because the functionality is hard to implement,");
1714 VG_(message)(Vg_UserMsg,
1715 "or because no reasonable program would behave this way,");
1716 VG_(message)(Vg_UserMsg,
1717 "or because nobody has yet needed it. In any case, let me know");
1718 VG_(message)(Vg_UserMsg,
1719 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1720 VG_(message)(Vg_UserMsg,
1721 "");
1722 VG_(message)(Vg_UserMsg,
1723 "Valgrind has to exit now. Sorry. Bye!");
1724 VG_(message)(Vg_UserMsg,
1725 "");
sewardj15a43e12002-04-17 19:35:12 +00001726 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001727 VG_(exit)(1);
1728}
1729
1730
njn25e49d8e72002-09-23 09:36:25 +00001731/* ---------------------------------------------------------------------
1732 Sanity check machinery (permanently engaged).
1733 ------------------------------------------------------------------ */
1734
1735/* A fast sanity check -- suitable for calling circa once per
1736 millisecond. */
1737
1738void VG_(do_sanity_checks) ( Bool force_expensive )
1739{
1740 Int i;
1741
njn37cea302002-09-30 11:24:00 +00001742 VGP_PUSHCC(VgpCoreCheapSanity);
1743
njn25e49d8e72002-09-23 09:36:25 +00001744 if (VG_(sanity_level) < 1) return;
1745
1746 /* --- First do all the tests that we can do quickly. ---*/
1747
1748 VG_(sanity_fast_count)++;
1749
1750 /* Check that we haven't overrun our private stack. */
1751 for (i = 0; i < 10; i++) {
1752 vg_assert(VG_(stack)[i]
1753 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1754 vg_assert(VG_(stack)[10000-1-i]
1755 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1756 }
1757
1758 /* Check stuff pertaining to the memory check system. */
1759
1760 /* Check that nobody has spuriously claimed that the first or
1761 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001762 if (VG_(needs).sanity_checks) {
1763 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001764 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001765 VGP_POPCC(VgpSkinCheapSanity);
1766 }
njn25e49d8e72002-09-23 09:36:25 +00001767
1768 /* --- Now some more expensive checks. ---*/
1769
1770 /* Once every 25 times, check some more expensive stuff. */
1771 if ( force_expensive
1772 || VG_(sanity_level) > 1
1773 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1774
njn37cea302002-09-30 11:24:00 +00001775 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001776 VG_(sanity_slow_count)++;
1777
1778# if 0
1779 { void zzzmemscan(void); zzzmemscan(); }
1780# endif
1781
1782 if ((VG_(sanity_fast_count) % 250) == 0)
1783 VG_(sanity_check_tc_tt)();
1784
1785 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001786 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001787 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001788 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001789 }
1790 /*
1791 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1792 */
njn37cea302002-09-30 11:24:00 +00001793 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001794 }
1795
1796 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001797 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001798 /* Check sanity of the low-level memory manager. Note that bugs
1799 in the client's code can cause this to fail, so we don't do
1800 this check unless specially asked for. And because it's
1801 potentially very expensive. */
1802 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001803 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001804 }
njn37cea302002-09-30 11:24:00 +00001805 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001806}
sewardjde4a1d02002-03-22 01:27:54 +00001807/*--------------------------------------------------------------------*/
1808/*--- end vg_main.c ---*/
1809/*--------------------------------------------------------------------*/