blob: a308c2b5e923cdbac634c3eee2bc0ff85b7b68a0 [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;
sewardjde4a1d02002-03-22 01:27:54 +0000102Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET;
sewardj51096432002-12-14 23:59:09 +0000103Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +0000104
105/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
106 * increased too much, they won't really be compact any more... */
107#define MAX_COMPACT_HELPERS 8
njnfedb7362003-02-24 10:21:45 +0000108#define MAX_NONCOMPACT_HELPERS 50
njn25e49d8e72002-09-23 09:36:25 +0000109
110UInt VG_(n_compact_helpers) = 0;
111UInt VG_(n_noncompact_helpers) = 0;
112
113Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
114Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
115Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
116Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
sewardjde4a1d02002-03-22 01:27:54 +0000117
118/* This is the actual defn of baseblock. */
119UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
120
njn25e49d8e72002-09-23 09:36:25 +0000121
sewardjde4a1d02002-03-22 01:27:54 +0000122/* Words. */
123static Int baB_off = 0;
124
125/* Returns the offset, in words. */
126static Int alloc_BaB ( Int words )
127{
128 Int off = baB_off;
129 baB_off += words;
130 if (baB_off >= VG_BASEBLOCK_WORDS)
njne427a662002-10-02 11:08:25 +0000131 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +0000132
133 return off;
134}
135
136/* Allocate 1 word in baseBlock and set it to the given value. */
137static Int alloc_BaB_1_set ( Addr a )
138{
139 Int off = alloc_BaB(1);
140 VG_(baseBlock)[off] = (UInt)a;
141 return off;
142}
143
njn25e49d8e72002-09-23 09:36:25 +0000144/* Registers a function in compact_helper_addrs; compact_helper_offsets is
145 * filled in later.
146 */
147void VG_(register_compact_helper)(Addr a)
148{
149 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
150 VG_(printf)("Can only register %d compact helpers\n",
151 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000152 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000153 }
154 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
155 VG_(n_compact_helpers)++;
156}
157
158/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
159 * is filled in later.
160 */
161void VG_(register_noncompact_helper)(Addr a)
162{
163 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
164 VG_(printf)("Can only register %d non-compact helpers\n",
165 MAX_NONCOMPACT_HELPERS);
166 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000167 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000168 }
169 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
170 VG_(n_noncompact_helpers)++;
171}
172
173/* Allocate offsets in baseBlock for the skin helpers */
174static void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
175{
176 Int i;
177 for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
178}
sewardjde4a1d02002-03-22 01:27:54 +0000179
njnf4ce3d32003-02-10 10:17:26 +0000180/* Will we need to call VG_(handle_esp_assignment)() ? */
181Bool VG_(need_to_handle_esp_assignment)(void)
182{
183 return (VG_(track_events).new_mem_stack ||
184 VG_(track_events).new_mem_stack_aligned ||
185 VG_(track_events).die_mem_stack ||
186 VG_(track_events).die_mem_stack_aligned);
187}
188
sewardjde4a1d02002-03-22 01:27:54 +0000189/* Here we assign actual offsets. It's important to get the most
190 popular referents within 128 bytes of the start, so we can take
191 advantage of short addressing modes relative to %ebp. Popularity
192 of offsets was measured on 22 Feb 02 running a KDE application, and
193 the slots rearranged accordingly, with a 1.5% reduction in total
194 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000195static void vg_init_baseBlock ( void )
196{
sewardjde4a1d02002-03-22 01:27:54 +0000197 /* Those with offsets under 128 are carefully chosen. */
198
199 /* WORD offsets in this column */
200 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
201 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
202 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
203 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
204 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
205 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
206 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
207 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
208 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
209
njn25e49d8e72002-09-23 09:36:25 +0000210 if (VG_(needs).shadow_regs) {
211 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
212 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
213 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
214 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
215 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
216 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
217 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
218 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
219 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
220 }
sewardjde4a1d02002-03-22 01:27:54 +0000221
njn25e49d8e72002-09-23 09:36:25 +0000222 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
223 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000224
njn25e49d8e72002-09-23 09:36:25 +0000225 /* (9 or 18) + n_compact_helpers */
226 /* Register VG_(handle_esp_assignment) if needed. */
njnf4ce3d32003-02-10 10:17:26 +0000227 if (VG_(need_to_handle_esp_assignment)())
njn25e49d8e72002-09-23 09:36:25 +0000228 VG_(register_compact_helper)( (Addr) & VG_(handle_esp_assignment) );
sewardjde4a1d02002-03-22 01:27:54 +0000229
njn25e49d8e72002-09-23 09:36:25 +0000230 /* Allocate slots for compact helpers */
231 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
232 VG_(compact_helper_offsets),
233 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000234
njn25e49d8e72002-09-23 09:36:25 +0000235 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000236 VGOFF_(m_eip) = alloc_BaB(1);
237
238 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000239 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
240 * boundary at >= 32 words, but most spills are to low numbered spill
241 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000242 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
243
njn25e49d8e72002-09-23 09:36:25 +0000244 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000245 short-amode-boundary, there's no point. */
246
sewardjfa492d42002-12-08 18:20:01 +0000247 VGOFF_(m_dflag) = alloc_BaB(1);
248
sewardjde4a1d02002-03-22 01:27:54 +0000249 VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
250
sewardj92a59562002-09-30 00:53:10 +0000251 /* This thread's LDT pointer, and segment registers. */
252 VGOFF_(ldt) = alloc_BaB(1);
253 VGOFF_(m_cs) = alloc_BaB(1);
254 VGOFF_(m_ss) = alloc_BaB(1);
255 VGOFF_(m_ds) = alloc_BaB(1);
256 VGOFF_(m_es) = alloc_BaB(1);
257 VGOFF_(m_fs) = alloc_BaB(1);
258 VGOFF_(m_gs) = alloc_BaB(1);
259
sewardje1042472002-09-30 12:33:11 +0000260 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
261
sewardj92a59562002-09-30 00:53:10 +0000262 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000263 VGOFF_(helper_idiv_64_32)
264 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
265 VGOFF_(helper_div_64_32)
266 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
267 VGOFF_(helper_idiv_32_16)
268 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
269 VGOFF_(helper_div_32_16)
270 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
271 VGOFF_(helper_idiv_16_8)
272 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
273 VGOFF_(helper_div_16_8)
274 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
275
276 VGOFF_(helper_imul_32_64)
277 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
278 VGOFF_(helper_mul_32_64)
279 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
280 VGOFF_(helper_imul_16_32)
281 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
282 VGOFF_(helper_mul_16_32)
283 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
284 VGOFF_(helper_imul_8_16)
285 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
286 VGOFF_(helper_mul_8_16)
287 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
288
289 VGOFF_(helper_CLD)
290 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
291 VGOFF_(helper_STD)
292 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
293 VGOFF_(helper_get_dirflag)
294 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
295
sewardj7d78e782002-06-02 00:04:00 +0000296 VGOFF_(helper_CLC)
297 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000298 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000299 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
300
sewardjde4a1d02002-03-22 01:27:54 +0000301 VGOFF_(helper_shldl)
302 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
303 VGOFF_(helper_shldw)
304 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
305 VGOFF_(helper_shrdl)
306 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
307 VGOFF_(helper_shrdw)
308 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
309
310 VGOFF_(helper_RDTSC)
311 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
312 VGOFF_(helper_CPUID)
313 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
314
sewardjde4a1d02002-03-22 01:27:54 +0000315 VGOFF_(helper_bsf)
316 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
317 VGOFF_(helper_bsr)
318 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
319
320 VGOFF_(helper_fstsw_AX)
321 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
322 VGOFF_(helper_SAHF)
323 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000324 VGOFF_(helper_DAS)
325 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000326 VGOFF_(helper_DAA)
327 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000328
sewardj51096432002-12-14 23:59:09 +0000329 VGOFF_(helper_undefined_instruction)
330 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
331
sewardj92a59562002-09-30 00:53:10 +0000332 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000333 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
334 VG_(noncompact_helper_offsets),
335 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000336
njncc7bb472002-10-14 09:25:19 +0000337
338 /* Initialise slots that require it */
339 VG_(copy_m_state_static_to_baseBlock)();
340
341 /* Pretend the root thread has a completely empty LDT to start with. */
342 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
343
344 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000345 if (VG_(needs).shadow_regs) {
346 UInt eflags;
347
348 SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
349 VG_(baseBlock)[VGOFF_(sh_esp)] =
350 VG_(baseBlock)[VGOFF_(sh_ebp)] =
351 VG_(baseBlock)[VGOFF_(sh_eax)] =
352 VG_(baseBlock)[VGOFF_(sh_ecx)] =
353 VG_(baseBlock)[VGOFF_(sh_edx)] =
354 VG_(baseBlock)[VGOFF_(sh_ebx)] =
355 VG_(baseBlock)[VGOFF_(sh_esi)] =
356 VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
357 VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
358
njncc7bb472002-10-14 09:25:19 +0000359 } else {
njn25e49d8e72002-09-23 09:36:25 +0000360 VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
njncc7bb472002-10-14 09:25:19 +0000361 }
sewardjde4a1d02002-03-22 01:27:54 +0000362}
363
364
365/* ---------------------------------------------------------------------
366 Global entities which are not referenced from generated code.
367 ------------------------------------------------------------------ */
368
369/* The stack on which Valgrind runs. We can't use the same stack as
370 the simulatee -- that's an important design decision. */
371UInt VG_(stack)[10000];
372
373/* Ditto our signal delivery stack. */
374UInt VG_(sigstack)[10000];
375
376/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000377UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
378Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000379
380/* Counts downwards in vg_run_innerloop. */
381UInt VG_(dispatch_ctr);
382
sewardjde4a1d02002-03-22 01:27:54 +0000383
384/* 64-bit counter for the number of basic blocks done. */
385ULong VG_(bbs_done);
386/* 64-bit counter for the number of bbs to go before a debug exit. */
387ULong VG_(bbs_to_go);
388
sewardj7e87e382002-05-03 19:09:05 +0000389/* This is the ThreadId of the last thread the scheduler ran. */
390ThreadId VG_(last_run_tid) = 0;
391
njn25e49d8e72002-09-23 09:36:25 +0000392/* This is the argument to __NR_exit() supplied by the first thread to
393 call that syscall. We eventually pass that to __NR_exit() for
394 real. */
395UInt VG_(exitcode) = 0;
396
sewardj73cf3bc2002-11-03 03:20:15 +0000397/* Tell the logging mechanism whether we are logging to a file
398 descriptor or a socket descriptor. */
399Bool VG_(logging_to_filedes) = True;
400
sewardjde4a1d02002-03-22 01:27:54 +0000401
402/* ---------------------------------------------------------------------
403 Counters, for informational purposes only.
404 ------------------------------------------------------------------ */
405
406/* Number of lookups which miss the fast tt helper. */
407UInt VG_(tt_fast_misses) = 0;
408
409
sewardjc0d8f682002-11-30 00:49:43 +0000410/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000411
sewardjde4a1d02002-03-22 01:27:54 +0000412/* Number and total o/t size of translations overall. */
413UInt VG_(overall_in_count) = 0;
414UInt VG_(overall_in_osize) = 0;
415UInt VG_(overall_in_tsize) = 0;
416/* Number and total o/t size of discards overall. */
417UInt VG_(overall_out_count) = 0;
418UInt VG_(overall_out_osize) = 0;
419UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000420/* The number of discards of TT/TC. */
421UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000422/* Counts of chain and unchain operations done. */
423UInt VG_(bb_enchain_count) = 0;
424UInt VG_(bb_dechain_count) = 0;
425/* Number of unchained jumps performed. */
426UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000427
428
429/* Counts pertaining to the register allocator. */
430
431/* total number of uinstrs input to reg-alloc */
432UInt VG_(uinstrs_prealloc) = 0;
433
434/* total number of uinstrs added due to spill code */
435UInt VG_(uinstrs_spill) = 0;
436
437/* number of bbs requiring spill code */
438UInt VG_(translations_needing_spill) = 0;
439
440/* total of register ranks over all translations */
441UInt VG_(total_reg_rank) = 0;
442
443
sewardjde4a1d02002-03-22 01:27:54 +0000444/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000445UInt VG_(sanity_fast_count) = 0;
446UInt VG_(sanity_slow_count) = 0;
447
sewardj2e93c502002-04-12 11:12:52 +0000448/* Counts pertaining to the scheduler. */
449UInt VG_(num_scheduling_events_MINOR) = 0;
450UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000451
452
453/* ---------------------------------------------------------------------
454 Values derived from command-line options.
455 ------------------------------------------------------------------ */
456
njn25e49d8e72002-09-23 09:36:25 +0000457/* Define, and set defaults. */
458Bool VG_(clo_error_limit) = True;
459Bool VG_(clo_GDB_attach) = False;
460Int VG_(sanity_level) = 1;
461Int VG_(clo_verbosity) = 1;
462Bool VG_(clo_demangle) = True;
463Bool VG_(clo_sloppy_malloc) = False;
464Int VG_(clo_alignment) = 4;
465Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000466
467/* See big comment in vg_include.h for meaning of these three. */
468VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
469Int VG_(clo_logfile_fd) = 2;
470Char* VG_(clo_logfile_name) = NULL;
471
njn25e49d8e72002-09-23 09:36:25 +0000472Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000473Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000474Bool VG_(clo_profile) = False;
475Bool VG_(clo_single_step) = False;
476Bool VG_(clo_optimise) = True;
477UChar VG_(clo_trace_codegen) = 0; // 00000000b
478Bool VG_(clo_trace_syscalls) = False;
479Bool VG_(clo_trace_signals) = False;
480Bool VG_(clo_trace_symtab) = False;
481Bool VG_(clo_trace_malloc) = False;
482Bool VG_(clo_trace_sched) = False;
483Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000484ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000485Int VG_(clo_dump_error) = 0;
486Int VG_(clo_backtrace_size) = 4;
487Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000488Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000489Bool VG_(clo_chain_bb) = True;
sewardj2370f3b2002-11-30 15:01:01 +0000490
sewardjde4a1d02002-03-22 01:27:54 +0000491
492/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
493 to behave. Initially we say False. */
494Bool VG_(running_on_simd_CPU) = False;
495
496/* Holds client's %esp at the point we gained control. */
497Addr VG_(esp_at_startup);
498
499/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
500 envp[] as extracted from the client's stack at startup-time. */
501Int VG_(client_argc);
502Char** VG_(client_argv);
503Char** VG_(client_envp);
504
505/* A place into which to copy the value of env var VG_ARGS, so we
506 don't have to modify the original. */
507static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
508
sewardjde4a1d02002-03-22 01:27:54 +0000509/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000510 Processing of command-line options.
511 ------------------------------------------------------------------ */
512
njn25e49d8e72002-09-23 09:36:25 +0000513void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000514{
515 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000516 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000517 VG_(clo_logfile_fd) = 2; /* stderr */
518 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
519 VG_(exit)(1);
520}
521
522static void config_error ( Char* msg )
523{
524 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000525 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000526 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000527 VG_(printf)(
528 "valgrind.so: Startup or configuration error:\n %s\n", msg);
529 VG_(printf)(
530 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000531 VG_(exit)(1);
532}
533
sewardja1679dd2002-05-10 22:31:40 +0000534static void args_grok_error ( Char* msg )
535{
536 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000537 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000538 VG_(clo_logfile_fd) = 2; /* stderr */
539 VG_(printf)("valgrind.so: When searching for "
540 "client's argc/argc/envp:\n\t%s\n", msg);
541 config_error("couldn't find client's argc/argc/envp");
542}
543
njn25e49d8e72002-09-23 09:36:25 +0000544static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000545{
njn25e49d8e72002-09-23 09:36:25 +0000546 Char* usage1 =
547"usage: valgrind [options] prog-and-args\n"
548"\n"
549" core user options, with defaults in [ ], are:\n"
550" --help show this message\n"
551" --version show version\n"
552" --skin=<name> main task (skin to use) [Valgrind]\n"
553" -q --quiet run silently; only print error msgs\n"
554" -v --verbose be more verbose, incl counts of errors\n"
555" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
556" --demangle=no|yes automatically demangle C++ names? [yes]\n"
557" --num-callers=<number> show <num> callers in stack traces [4]\n"
558" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
559" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
560" --alignment=<number> set minimum alignment of allocations [4]\n"
561" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000562" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000563" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000564" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000565" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000566" --suppressions=<filename> suppress errors described in\n"
567" suppressions file <filename>\n"
568" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000569" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000570"\n"
571" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000572
njn7cf0bd32002-06-08 13:36:03 +0000573
njn25e49d8e72002-09-23 09:36:25 +0000574 Char* usage2 =
575"\n"
576" core options for debugging Valgrind itself are:\n"
577" --sanity-level=<number> level of sanity checking to do [1]\n"
578" --single-step=no|yes translate each instr separately? [no]\n"
579" --optimise=no|yes improve intermediate code? [yes]\n"
580" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000581" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000582" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
583" --trace-syscalls=no|yes show all system calls? [no]\n"
584" --trace-signals=no|yes show signal handling details? [no]\n"
585" --trace-symtab=no|yes show symbol table details? [no]\n"
586" --trace-malloc=no|yes show client malloc details? [no]\n"
587" --trace-sched=no|yes show thread scheduler details? [no]\n"
588" --trace-pthread=none|some|all show pthread event details? [no]\n"
589" --stop-after=<number> switch to real CPU after executing\n"
590" <number> basic blocks [infinity]\n"
591" --dump-error=<number> show translation for basic block\n"
592" associated with <number>'th\n"
593" error context [0=don't show any]\n"
594"\n"
595" Extra options are read from env variable $VALGRIND_OPTS\n"
596"\n"
597" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
598" and licensed under the GNU General Public License, version 2.\n"
599" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000600"\n"
601" Skins are copyright and licensed by their authors. See each\n"
602" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000603"\n";
njn7cf0bd32002-06-08 13:36:03 +0000604
njnd04b7c62002-10-03 14:05:52 +0000605 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000606 /* Don't print skin string directly for security, ha! */
607 if (VG_(needs).command_line_options)
608 VG_(printf)("%s", SK_(usage)());
609 else
610 VG_(printf)(" (none)\n");
611 VG_(printf)(usage2, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000612
njn25e49d8e72002-09-23 09:36:25 +0000613 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000614 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000615 VG_(clo_logfile_fd) = 2; /* stderr */
616 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000617}
sewardjde4a1d02002-03-22 01:27:54 +0000618
sewardj1c1b1162003-02-23 01:25:51 +0000619
620/* Callback for lookiing for the stackl segment. */
621static Addr vg_foundstack_start = (Addr)NULL;
622static UInt vg_foundstack_size = 0;
623
624static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000625 Char r, Char w, Char x,
626 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000627{
628 Addr lastword;
629 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000630 if (r != 'r' || w != 'w'
631 /* || x != 'x' --not necessarily so on x86-64*/
632 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000633 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000634 if (start <= VG_(esp_at_startup)
635 && VG_(esp_at_startup) <= lastword) {
636 vg_foundstack_start = start;
637 vg_foundstack_size = size;
638 vg_assert(vg_foundstack_size > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000639 }
640}
641
642
643
sewardjde4a1d02002-03-22 01:27:54 +0000644static void process_cmd_line_options ( void )
645{
njn25e49d8e72002-09-23 09:36:25 +0000646 Char* argv[M_VG_CMDLINE_OPTS];
647 UInt argc;
648 Char* p;
649 Char* str;
650 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000651
652# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
653# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
654# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
655
sewardjde4a1d02002-03-22 01:27:54 +0000656 eventually_logfile_fd = VG_(clo_logfile_fd);
657
658 /* Once logging is started, we can safely send messages pertaining
659 to failures in initialisation. */
660 VG_(startup_logging)();
661
sewardj19d81412002-06-03 01:10:40 +0000662 /* Check for sane path in ./configure --prefix=... */
663 if (VG_(strlen)(VG_LIBDIR) < 1
664 || VG_LIBDIR[0] != '/')
665 config_error("Please use absolute paths in "
666 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000667
sewardja1679dd2002-05-10 22:31:40 +0000668 /* (Suggested by Fabrice Bellard ... )
669 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000670 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000671 change less often than the libc ones. */
672 {
sewardj53fe4582003-02-23 01:41:17 +0000673 UInt* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000674
sewardj53fe4582003-02-23 01:41:17 +0000675 /* Look for the stack segment by reading /proc/self/maps and
676 looking for a section bracketing VG_(esp_at_startup) which
677 has rwx permissions and no associated file. */
sewardj1c1b1162003-02-23 01:25:51 +0000678
679 VG_(read_procselfmaps)( vg_findstack_callback );
sewardj53fe4582003-02-23 01:41:17 +0000680
681 /* Now vg_foundstack_start and vg_foundstack_size
682 should delimit the stack. */
683 if (vg_foundstack_size == 0) {
684 args_grok_error("Cannot determine stack segment "
685 "from /proc/self/maps");
686 }
sewardj1c1b1162003-02-23 01:25:51 +0000687
688 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000689 VG_(printf)("stack segment is %p .. %p\n",
690 vg_foundstack_start,
691 vg_foundstack_start + vg_foundstack_size - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000692
sewardj53fe4582003-02-23 01:41:17 +0000693 sp = (UInt*)(vg_foundstack_start + vg_foundstack_size);
694 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
695 args_grok_error("Stack segment is not page aligned?!");
696 }
sewardj1c1b1162003-02-23 01:25:51 +0000697
sewardj53fe4582003-02-23 01:41:17 +0000698 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
699 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000700
sewardj38170912002-05-10 21:07:22 +0000701 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000702 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000703 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000704 sp--;
705 }
sewardj38170912002-05-10 21:07:22 +0000706
707 if (sp[2] == VKI_AT_BASE
708 && sp[0] == VKI_AT_PAGESZ
709 && sp[-2] == VKI_AT_PHNUM
710 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000711 && sp[-6] == VKI_AT_PHDR
712 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000713 if (0)
714 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000715 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000716 } else
717 if (sp[2] == VKI_AT_CLKTCK
718 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000719 && sp[-2] == VKI_AT_HWCAP
720 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000721 if (0)
722 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
723 sp -= 2;
724 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000725 if (sp[2] == VKI_AT_CLKTCK
726 && sp[0] == VKI_AT_PAGESZ
727 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000728 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
729 && sp[-4-1] == 0) {
730 if (0)
731 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
732 "kernel here.\n");
733 sp -= 4;
734 } else
735 if (sp[2] == VKI_AT_CLKTCK
736 && sp[0] == VKI_AT_PAGESZ
737 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000738 && sp[-2-20-1] == 0) {
739 if (0)
740 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
741 sp -= 22;
742 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000743 if (sp[2] == VKI_AT_CLKTCK
744 && sp[0] == VKI_AT_PAGESZ
745 && sp[-2] == VKI_AT_HWCAP
746 && sp[-4-1] == 0) {
747 if (0)
748 VG_(printf)("Looks like a >> 2.5.43 kernel here.\n");
749 sp -= 4;
750 } else
sewardja1679dd2002-05-10 22:31:40 +0000751 args_grok_error(
752 "ELF frame does not look like 2.2.X or 2.4.X.\n "
753 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
754 );
sewardj38170912002-05-10 21:07:22 +0000755
756 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000757 if (*sp != 0)
758 args_grok_error("can't find NULL at end of env[]");
759
sewardj38170912002-05-10 21:07:22 +0000760 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000761 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000762 while (True) {
763 sp --;
764 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000765 if (++ctr >= 1000)
766 args_grok_error(
767 "suspiciously many (1000) env[] entries; giving up");
768
sewardj38170912002-05-10 21:07:22 +0000769 }
770 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000771 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000772
sewardja1679dd2002-05-10 22:31:40 +0000773 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000774 VG_(client_argc) = 0;
775 while (True) {
776 sp--;
777 if (*sp == VG_(client_argc))
778 break;
779 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000780 if (++ctr >= 1000)
781 args_grok_error(
782 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000783 }
784
sewardja1679dd2002-05-10 22:31:40 +0000785 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000786 }
787
sewardjde4a1d02002-03-22 01:27:54 +0000788 /* Now that VG_(client_envp) has been set, we can extract the args
789 for Valgrind itself. Copy into global var so that we don't have to
790 write zeroes to the getenv'd value itself. */
791 str = VG_(getenv)("VG_ARGS");
792 argc = 0;
793
794 if (!str) {
795 config_error("Can't read options from env var VG_ARGS.");
796 }
797
798 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
799 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
800 }
801 VG_(strcpy)(vg_cmdline_copy, str);
802 str = NULL;
803
804 p = &vg_cmdline_copy[0];
805 while (True) {
806 while (ISSPACE(*p)) { *p = 0; p++; }
807 if (*p == 0) break;
808 if (argc < M_VG_CMDLINE_OPTS-1) {
809 argv[argc] = p; argc++;
810 } else {
811 config_error(
812 "Found more than M_CMDLINE_OPTS command-line opts.");
813 }
814 while (*p != 0 && !ISSPACE(*p)) p++;
815 }
816
817 for (i = 0; i < argc; i++) {
818
njn25e49d8e72002-09-23 09:36:25 +0000819 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000820 VG_(clo_verbosity)++;
821 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
822 VG_(clo_verbosity)--;
823
sewardj2e432902002-06-13 20:44:00 +0000824 else if (STREQ(argv[i], "--error-limit=yes"))
825 VG_(clo_error_limit) = True;
826 else if (STREQ(argv[i], "--error-limit=no"))
827 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000828
sewardjde4a1d02002-03-22 01:27:54 +0000829 else if (STREQ(argv[i], "--gdb-attach=yes"))
830 VG_(clo_GDB_attach) = True;
831 else if (STREQ(argv[i], "--gdb-attach=no"))
832 VG_(clo_GDB_attach) = False;
833
834 else if (STREQ(argv[i], "--demangle=yes"))
835 VG_(clo_demangle) = True;
836 else if (STREQ(argv[i], "--demangle=no"))
837 VG_(clo_demangle) = False;
838
sewardjde4a1d02002-03-22 01:27:54 +0000839 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
840 VG_(clo_sloppy_malloc) = True;
841 else if (STREQ(argv[i], "--sloppy-malloc=no"))
842 VG_(clo_sloppy_malloc) = False;
843
sewardj246d4662002-06-14 10:17:05 +0000844 else if (STREQN(12, argv[i], "--alignment="))
845 VG_(clo_alignment) = (Int)VG_(atoll)(&argv[i][12]);
846
sewardjde4a1d02002-03-22 01:27:54 +0000847 else if (STREQ(argv[i], "--trace-children=yes"))
848 VG_(clo_trace_children) = True;
849 else if (STREQ(argv[i], "--trace-children=no"))
850 VG_(clo_trace_children) = False;
851
sewardj858964b2002-10-05 14:15:43 +0000852 else if (STREQ(argv[i], "--run-libc-freeres=yes"))
853 VG_(clo_run_libc_freeres) = True;
854 else if (STREQ(argv[i], "--run-libc-freeres=no"))
855 VG_(clo_run_libc_freeres) = False;
856
sewardjde4a1d02002-03-22 01:27:54 +0000857 else if (STREQN(15, argv[i], "--sanity-level="))
858 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
859
sewardj4cf05692002-10-27 20:28:29 +0000860 else if (STREQN(13, argv[i], "--logfile-fd=")) {
861 VG_(clo_log_to) = VgLogTo_Fd;
862 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000863 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000864 }
865
866 else if (STREQN(10, argv[i], "--logfile=")) {
867 VG_(clo_log_to) = VgLogTo_File;
868 VG_(clo_logfile_name) = &argv[i][10];
869 }
sewardjde4a1d02002-03-22 01:27:54 +0000870
sewardj73cf3bc2002-11-03 03:20:15 +0000871 else if (STREQN(12, argv[i], "--logsocket=")) {
872 VG_(clo_log_to) = VgLogTo_Socket;
873 VG_(clo_logfile_name) = &argv[i][12];
874 }
875
sewardjde4a1d02002-03-22 01:27:54 +0000876 else if (STREQN(15, argv[i], "--suppressions=")) {
877 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000878 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000879 VG_(message)(Vg_UserMsg,
880 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000881 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000882 }
883 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
884 VG_(clo_n_suppressions)++;
885 }
njn25e49d8e72002-09-23 09:36:25 +0000886 else if (STREQ(argv[i], "--profile=yes"))
887 VG_(clo_profile) = True;
888 else if (STREQ(argv[i], "--profile=no"))
889 VG_(clo_profile) = False;
890
sewardj22854b92002-11-30 14:00:47 +0000891 else if (STREQ(argv[i], "--chain-bb=yes"))
892 VG_(clo_chain_bb) = True;
893 else if (STREQ(argv[i], "--chain-bb=no"))
894 VG_(clo_chain_bb) = False;
895
sewardjde4a1d02002-03-22 01:27:54 +0000896 else if (STREQ(argv[i], "--single-step=yes"))
897 VG_(clo_single_step) = True;
898 else if (STREQ(argv[i], "--single-step=no"))
899 VG_(clo_single_step) = False;
900
901 else if (STREQ(argv[i], "--optimise=yes"))
902 VG_(clo_optimise) = True;
903 else if (STREQ(argv[i], "--optimise=no"))
904 VG_(clo_optimise) = False;
905
njn25e49d8e72002-09-23 09:36:25 +0000906 /* "vwxyz" --> 000zyxwv (binary) */
907 else if (STREQN(16, argv[i], "--trace-codegen=")) {
908 Int j;
909 char* opt = & argv[i][16];
910
911 if (5 != VG_(strlen)(opt)) {
912 VG_(message)(Vg_UserMsg,
913 "--trace-codegen argument must have 5 digits");
914 VG_(bad_option)(argv[i]);
915 }
916 for (j = 0; j < 5; j++) {
917 if ('0' == opt[j]) { /* do nothing */ }
918 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
919 else {
920 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
921 "contain 0s and 1s");
922 VG_(bad_option)(argv[i]);
923 }
924 }
925 }
sewardjde4a1d02002-03-22 01:27:54 +0000926
927 else if (STREQ(argv[i], "--trace-syscalls=yes"))
928 VG_(clo_trace_syscalls) = True;
929 else if (STREQ(argv[i], "--trace-syscalls=no"))
930 VG_(clo_trace_syscalls) = False;
931
932 else if (STREQ(argv[i], "--trace-signals=yes"))
933 VG_(clo_trace_signals) = True;
934 else if (STREQ(argv[i], "--trace-signals=no"))
935 VG_(clo_trace_signals) = False;
936
937 else if (STREQ(argv[i], "--trace-symtab=yes"))
938 VG_(clo_trace_symtab) = True;
939 else if (STREQ(argv[i], "--trace-symtab=no"))
940 VG_(clo_trace_symtab) = False;
941
942 else if (STREQ(argv[i], "--trace-malloc=yes"))
943 VG_(clo_trace_malloc) = True;
944 else if (STREQ(argv[i], "--trace-malloc=no"))
945 VG_(clo_trace_malloc) = False;
946
sewardj8937c812002-04-12 20:12:20 +0000947 else if (STREQ(argv[i], "--trace-sched=yes"))
948 VG_(clo_trace_sched) = True;
949 else if (STREQ(argv[i], "--trace-sched=no"))
950 VG_(clo_trace_sched) = False;
951
sewardj45b4b372002-04-16 22:50:32 +0000952 else if (STREQ(argv[i], "--trace-pthread=none"))
953 VG_(clo_trace_pthread_level) = 0;
954 else if (STREQ(argv[i], "--trace-pthread=some"))
955 VG_(clo_trace_pthread_level) = 1;
956 else if (STREQ(argv[i], "--trace-pthread=all"))
957 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000958
sewardj8d365b52002-05-12 10:52:16 +0000959 else if (STREQN(14, argv[i], "--weird-hacks="))
960 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000961
sewardjde4a1d02002-03-22 01:27:54 +0000962 else if (STREQN(13, argv[i], "--stop-after="))
963 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
964
965 else if (STREQN(13, argv[i], "--dump-error="))
966 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
967
968 else if (STREQN(14, argv[i], "--num-callers=")) {
969 /* Make sure it's sane. */
970 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
971 if (VG_(clo_backtrace_size) < 2)
972 VG_(clo_backtrace_size) = 2;
973 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
974 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
975 }
976
njn25e49d8e72002-09-23 09:36:25 +0000977 else if (VG_(needs).command_line_options) {
978 Bool ok = SK_(process_cmd_line_option)(argv[i]);
979 if (!ok)
980 usage();
981 }
sewardjde4a1d02002-03-22 01:27:54 +0000982 else
njn25e49d8e72002-09-23 09:36:25 +0000983 usage();
sewardjde4a1d02002-03-22 01:27:54 +0000984 }
985
986# undef ISSPACE
987# undef STREQ
988# undef STREQN
989
990 if (VG_(clo_verbosity < 0))
991 VG_(clo_verbosity) = 0;
992
sewardj246d4662002-06-14 10:17:05 +0000993 if (VG_(clo_alignment) < 4
994 || VG_(clo_alignment) > 4096
995 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
996 VG_(message)(Vg_UserMsg, "");
997 VG_(message)(Vg_UserMsg,
998 "Invalid --alignment= setting. "
999 "Should be a power of 2, >= 4, <= 4096.");
njn25e49d8e72002-09-23 09:36:25 +00001000 VG_(bad_option)("--alignment");
sewardj246d4662002-06-14 10:17:05 +00001001 }
1002
sewardjde4a1d02002-03-22 01:27:54 +00001003 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1004 VG_(message)(Vg_UserMsg, "");
1005 VG_(message)(Vg_UserMsg,
1006 "--gdb-attach=yes conflicts with --trace-children=yes");
1007 VG_(message)(Vg_UserMsg,
1008 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001009 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001010 }
1011
sewardj4cf05692002-10-27 20:28:29 +00001012 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1013 should be connected to whatever sink has been selected, and we
1014 indiscriminately chuck stuff into it without worrying what the
1015 nature of it is. Oh the wonder of Unix streams. */
1016
1017 /* So far we should be still attached to stderr, so we can show on
1018 the terminal any problems to do with processing command line
1019 opts. */
1020 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001021 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001022
1023 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001024
sewardj4cf05692002-10-27 20:28:29 +00001025 case VgLogTo_Fd:
1026 vg_assert(VG_(clo_logfile_name) == NULL);
1027 VG_(clo_logfile_fd) = eventually_logfile_fd;
1028 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001029
sewardj4cf05692002-10-27 20:28:29 +00001030 case VgLogTo_File: {
1031 Char logfilename[1000];
1032 vg_assert(VG_(clo_logfile_name) != NULL);
1033 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1034 VG_(sprintf)(logfilename, "%s.pid%d",
1035 VG_(clo_logfile_name), VG_(getpid)() );
1036 eventually_logfile_fd
1037 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1038 VKI_S_IRUSR|VKI_S_IWUSR);
1039 if (eventually_logfile_fd != -1) {
1040 VG_(clo_logfile_fd) = eventually_logfile_fd;
1041 } else {
1042 VG_(message)(Vg_UserMsg,
1043 "Can't create/open log file `%s.pid%d'; giving up!",
1044 VG_(clo_logfile_name), VG_(getpid)());
1045 VG_(bad_option)(
1046 "--logfile=<file> didn't work out for some reason.");
1047 }
1048 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001049 }
1050
1051 case VgLogTo_Socket: {
1052 vg_assert(VG_(clo_logfile_name) != NULL);
1053 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1054 eventually_logfile_fd
1055 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1056 if (eventually_logfile_fd == -1) {
1057 VG_(message)(Vg_UserMsg,
1058 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1059 VG_(message)(Vg_UserMsg,
1060 "of `%s'; giving up!", VG_(clo_logfile_name) );
1061 VG_(bad_option)(
1062 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001063 }
sewardj73cf3bc2002-11-03 03:20:15 +00001064 if (eventually_logfile_fd == -2) {
1065 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001066 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001067 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001068 VG_(message)(Vg_UserMsg,
1069 "Log messages will sent to stderr instead." );
1070 VG_(message)(Vg_UserMsg,
1071 "" );
1072 /* We don't change anything here. */
1073 } else {
1074 vg_assert(eventually_logfile_fd > 0);
1075 VG_(clo_logfile_fd) = eventually_logfile_fd;
1076 VG_(logging_to_filedes) = False;
1077 }
sewardj73cf3bc2002-11-03 03:20:15 +00001078 break;
1079 }
1080
sewardj4cf05692002-10-27 20:28:29 +00001081 }
1082
1083 /* Ok, the logging sink is running now. Print a suitable preamble.
1084 If logging to file or a socket, write details of parent PID and
1085 command line args, to help people trying to interpret the
1086 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001087
sewardj83adf412002-05-01 01:25:45 +00001088 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001089 /* Skin details */
1090 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1091 VG_(details).name,
1092 NULL == VG_(details).version ? "" : "-",
1093 NULL == VG_(details).version
1094 ? (Char*)"" : VG_(details).version,
1095 VG_(details).description);
1096 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001097
njnd04b7c62002-10-03 14:05:52 +00001098 /* Core details */
1099 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001100 "Using valgrind-%s, a program instrumentation system for x86-linux.",
1101 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001102 VG_(message)(Vg_UserMsg,
sewardj4aa62ba2002-10-05 15:49:27 +00001103 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001104 }
1105
sewardj4cf05692002-10-27 20:28:29 +00001106 if (VG_(clo_log_to) != VgLogTo_Fd) {
1107 VG_(message)(Vg_UserMsg, "");
1108 VG_(message)(Vg_UserMsg,
1109 "My PID = %d, parent PID = %d. Prog and args are:",
1110 VG_(getpid)(), VG_(getppid)() );
1111 for (i = 0; i < VG_(client_argc); i++)
1112 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1113 }
1114
sewardjde4a1d02002-03-22 01:27:54 +00001115 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001116 if (VG_(clo_log_to) != VgLogTo_Fd)
1117 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001118 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1119 for (i = 0; i < argc; i++) {
1120 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1121 }
1122 }
1123
njn25e49d8e72002-09-23 09:36:25 +00001124 if (VG_(clo_n_suppressions) == 0 &&
1125 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001126 config_error("No error-suppression files were specified.");
1127 }
sewardj4cf05692002-10-27 20:28:29 +00001128
sewardjde4a1d02002-03-22 01:27:54 +00001129}
1130
sewardjde4a1d02002-03-22 01:27:54 +00001131/* ---------------------------------------------------------------------
1132 Copying to/from m_state_static.
1133 ------------------------------------------------------------------ */
1134
sewardj92a59562002-09-30 00:53:10 +00001135UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1136 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001137 + 1 /* %eflags */
1138 + 1 /* %eip */
1139 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1140 ];
1141
sewardjfa492d42002-12-08 18:20:01 +00001142UInt VG_(insertDflag)(UInt eflags, Int d)
1143{
1144 vg_assert(d == 1 || d == -1);
1145 eflags &= ~EFlagD;
1146
1147 if (d < 0)
1148 eflags |= EFlagD;
1149
1150 return eflags;
1151}
1152
1153Int VG_(extractDflag)(UInt eflags)
1154{
1155 Int ret;
1156
1157 if (eflags & EFlagD)
1158 ret = -1;
1159 else
1160 ret = 1;
1161
1162 return ret;
1163}
1164
sewardjde4a1d02002-03-22 01:27:54 +00001165void VG_(copy_baseBlock_to_m_state_static) ( void )
1166{
1167 Int i;
sewardj92a59562002-09-30 00:53:10 +00001168 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1169 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1170 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1171 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1172 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1173 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001174
sewardj92a59562002-09-30 00:53:10 +00001175 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1176 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1177 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1178 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1179 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1180 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1181 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1182 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1183
sewardjfa492d42002-12-08 18:20:01 +00001184 VG_(m_state_static)[56/4] = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1185 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001186 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001187
1188 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001189 VG_(m_state_static)[64/4 + i]
sewardjde4a1d02002-03-22 01:27:54 +00001190 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1191}
1192
1193
1194void VG_(copy_m_state_static_to_baseBlock) ( void )
1195{
1196 Int i;
sewardj92a59562002-09-30 00:53:10 +00001197 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1198 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1199 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1200 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1201 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1202 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001203
sewardj92a59562002-09-30 00:53:10 +00001204 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1205 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1206 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1207 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1208 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1209 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1210 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1211 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1212
sewardjfa492d42002-12-08 18:20:01 +00001213 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[56/4] & ~EFlagD;
1214 VG_(baseBlock)[VGOFF_(m_dflag)] = VG_(extractDflag)(VG_(m_state_static)[56/4]);
1215
sewardj92a59562002-09-30 00:53:10 +00001216 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001217
1218 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1219 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
sewardj92a59562002-09-30 00:53:10 +00001220 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001221}
1222
njn25e49d8e72002-09-23 09:36:25 +00001223Addr VG_(get_stack_pointer) ( void )
1224{
1225 return VG_(baseBlock)[VGOFF_(m_esp)];
1226}
1227
1228/* Some random tests needed for leak checking */
1229
1230Bool VG_(within_stack)(Addr a)
1231{
1232 if (a >= ((Addr)(&VG_(stack)))
1233 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1234 return True;
1235 else
1236 return False;
1237}
1238
1239Bool VG_(within_m_state_static)(Addr a)
1240{
1241 if (a >= ((Addr)(&VG_(m_state_static)))
1242 && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
1243 return True;
1244 else
1245 return False;
1246}
sewardjde4a1d02002-03-22 01:27:54 +00001247
1248/* ---------------------------------------------------------------------
1249 Show accumulated counts.
1250 ------------------------------------------------------------------ */
1251
njn25e49d8e72002-09-23 09:36:25 +00001252static __inline__ Int safe_idiv(Int a, Int b)
1253{
1254 return (b == 0 ? 0 : a / b);
1255}
1256
sewardjde4a1d02002-03-22 01:27:54 +00001257static void vg_show_counts ( void )
1258{
1259 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001260 " TT/TC: %d tc sectors discarded.",
1261 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001262 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001263 " %d chainings, %d unchainings.",
1264 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1265 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001266 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001267 VG_(overall_in_count),
1268 VG_(overall_in_osize),
1269 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001270 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1271 VG_(message)(Vg_DebugMsg,
1272 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001273 VG_(overall_out_count),
1274 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001275 VG_(overall_out_tsize),
1276 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001277 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001278 " dispatch: %lu jumps (bb entries), of which %u (%lu%%) were unchained.",
1279 VG_(bbs_done),
1280 VG_(unchained_jumps_done),
1281 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1282 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1283 );
1284
1285 VG_(message)(Vg_DebugMsg,
1286 " %d/%d major/minor sched events. %d tt_fast misses.",
1287 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001288 VG_(num_scheduling_events_MINOR),
1289 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001290
sewardjde4a1d02002-03-22 01:27:54 +00001291 VG_(message)(Vg_DebugMsg,
1292 "reg-alloc: %d t-req-spill, "
1293 "%d+%d orig+spill uis, %d total-reg-r.",
1294 VG_(translations_needing_spill),
1295 VG_(uinstrs_prealloc),
1296 VG_(uinstrs_spill),
1297 VG_(total_reg_rank) );
1298 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001299 " sanity: %d cheap, %d expensive checks.",
1300 VG_(sanity_fast_count),
1301 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001302 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001303}
1304
1305
1306/* ---------------------------------------------------------------------
1307 Main!
1308 ------------------------------------------------------------------ */
1309
1310/* Where we jump to once Valgrind has got control, and the real
1311 machine's state has been copied to the m_state_static. */
1312
1313void VG_(main) ( void )
1314{
sewardj2e93c502002-04-12 11:12:52 +00001315 Int i;
1316 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001317 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001318
njn27f1a382002-11-08 15:48:16 +00001319 /* Check skin and core versions are compatible */
1320 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1321 VG_(printf)("Error:\n"
1322 " Skin and core interface versions do not match.\n"
1323 " Interface version used by core is: %d.%d\n"
1324 " Interface version used by skin is: %d.%d\n"
1325 " The major version numbers must match.\n",
1326 VG_CORE_INTERFACE_MAJOR_VERSION,
1327 VG_CORE_INTERFACE_MINOR_VERSION,
1328 VG_(skin_interface_major_version),
1329 VG_(skin_interface_minor_version));
1330 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1331 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1332 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1333 else
1334 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1335 VG_(printf)(" Aborting, sorry.\n");
1336 VG_(exit)(1);
1337 }
1338
sewardjde4a1d02002-03-22 01:27:54 +00001339 /* Set up our stack sanity-check words. */
1340 for (i = 0; i < 10; i++) {
1341 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1342 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1343 }
1344
sewardj1c1b1162003-02-23 01:25:51 +00001345 /* Hook to delay things long enough so we can get the pid and
1346 attach GDB in another shell. */
1347 if (0) {
1348 Int p, q;
1349 VG_(printf)("pid=%d\n", VG_(getpid)());
1350 for (p = 0; p < 50000; p++)
1351 for (q = 0; q < 50000; q++) ;
1352 }
1353
njn25e49d8e72002-09-23 09:36:25 +00001354 /* Setup stuff that depends on the skin. Must be before:
1355 - vg_init_baseBlock(): to register helpers
1356 - process_cmd_line_options(): to register skin name and description,
1357 and turn on/off 'command_line_options' need
1358 - init_memory() (to setup memory event trackers).
1359 */
njn810086f2002-11-14 12:42:47 +00001360 SK_(pre_clo_init)();
1361 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001362
njncc7bb472002-10-14 09:25:19 +00001363 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001364 process_cmd_line_options();
1365
njncc7bb472002-10-14 09:25:19 +00001366 /* Do post command-line processing initialisation */
1367 SK_(post_clo_init)();
1368
1369 /* Set up baseBlock offsets and copy the saved machine's state into it.
1370 Comes after SK_(post_clo_init) in case it registers helpers. */
1371 vg_init_baseBlock();
1372
sewardj018f7622002-05-15 21:13:39 +00001373 /* Initialise the scheduler, and copy the client's state from
1374 baseBlock into VG_(threads)[1]. This has to come before signal
1375 initialisations. */
1376 VG_(scheduler_init)();
1377
1378 /* Initialise the signal handling subsystem, temporarily parking
1379 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001380 VG_(sigstartup_actions)();
1381
sewardj018f7622002-05-15 21:13:39 +00001382 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001383 if (VG_(clo_profile))
1384 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001385
sewardj5f07b662002-04-23 16:52:51 +00001386 /* Start calibration of our RDTSC-based clock. */
1387 VG_(start_rdtsc_calibration)();
1388
njn25e49d8e72002-09-23 09:36:25 +00001389 /* Must come after SK_(init) so memory handler accompaniments (eg.
1390 * shadow memory) can be setup ok */
1391 VGP_PUSHCC(VgpInitMem);
1392 VG_(init_memory)();
1393 VGP_POPCC(VgpInitMem);
1394
1395 /* Read the list of errors to suppress. This should be found in
1396 the file specified by vg_clo_suppressions. */
1397 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1398 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001399
sewardj5f07b662002-04-23 16:52:51 +00001400 /* End calibration of our RDTSC-based clock, leaving it as long as
1401 we can. */
1402 VG_(end_rdtsc_calibration)();
1403
njn25e49d8e72002-09-23 09:36:25 +00001404 /* This should come after init_memory_and_symbols(); otherwise the
1405 latter carefully sets up the permissions maps to cover the
1406 anonymous mmaps for the translation table and translation cache,
1407 which wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001408 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001409
1410 if (VG_(clo_verbosity) == 1) {
1411 VG_(message)(Vg_UserMsg,
1412 "For more details, rerun with: -v");
1413 }
1414
1415 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1416 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001417 if (VG_(clo_verbosity) > 0)
1418 VG_(message)(Vg_UserMsg, "");
1419
1420 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001421
sewardj018f7622002-05-15 21:13:39 +00001422 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001423 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001424 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001425 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001426 VGP_POPCC(VgpSched);
1427 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001428
1429 if (VG_(clo_verbosity) > 0)
1430 VG_(message)(Vg_UserMsg, "");
1431
sewardj2e93c502002-04-12 11:12:52 +00001432 if (src == VgSrc_Deadlock) {
1433 VG_(message)(Vg_UserMsg,
1434 "Warning: pthread scheduler exited due to deadlock");
1435 }
1436
njn25e49d8e72002-09-23 09:36:25 +00001437 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001438 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001439
njn25e49d8e72002-09-23 09:36:25 +00001440 SK_(fini)();
njn4f9c9342002-04-29 16:03:24 +00001441
sewardj0c3b53f2002-05-01 01:58:35 +00001442 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001443
1444 if (VG_(clo_verbosity) > 1)
1445 vg_show_counts();
1446
sewardjc0d8f682002-11-30 00:49:43 +00001447 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001448 VG_(print_UInstr_histogram)();
1449
sewardjde4a1d02002-03-22 01:27:54 +00001450 if (0) {
1451 VG_(message)(Vg_DebugMsg, "");
1452 VG_(message)(Vg_DebugMsg,
1453 "------ Valgrind's internal memory use stats follow ------" );
1454 VG_(mallocSanityCheckAll)();
1455 VG_(show_all_arena_stats)();
1456 VG_(message)(Vg_DebugMsg,
1457 "------ Valgrind's ExeContext management stats follow ------" );
1458 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001459 }
1460
njn25e49d8e72002-09-23 09:36:25 +00001461 if (VG_(clo_profile))
1462 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001463
1464 VG_(shutdown_logging)();
1465
sewardj3e1eb1f2002-05-18 13:14:17 +00001466 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1467 processes don't get traced into. Also mess up $libdir/valgrind
1468 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001469 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001470 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1471 VG_(getenv)("LD_PRELOAD"),
1472 VG_(getenv)("LD_LIBRARY_PATH")
1473 );
sewardjde4a1d02002-03-22 01:27:54 +00001474 }
1475
sewardj7e87e382002-05-03 19:09:05 +00001476 /* Decide how to exit. This depends on what the scheduler
1477 returned. */
1478 switch (src) {
1479 case VgSrc_ExitSyscall: /* the normal way out */
1480 vg_assert(VG_(last_run_tid) > 0
1481 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001482 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001483 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001484 /* The thread's %EBX at the time it did __NR_exit() will hold
1485 the arg to __NR_exit(), so we just do __NR_exit() with
1486 that arg. */
1487 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001488 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001489 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001490 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001491
sewardj7e87e382002-05-03 19:09:05 +00001492 case VgSrc_Deadlock:
1493 /* Just exit now. No point in continuing. */
1494 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001495 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001496 break;
1497
1498 case VgSrc_BbsDone:
1499 /* Tricky; we have to try and switch back to the real CPU.
1500 This is all very dodgy and won't work at all in the
1501 presence of threads, or if the client happened to be
1502 running a signal handler. */
1503 /* Prepare to restore state to the real CPU. */
1504 VG_(load_thread_state)(1 /* root thread */ );
1505 VG_(copy_baseBlock_to_m_state_static)();
1506
1507 /* This pushes a return address on the simulator's stack,
1508 which is abandoned. We call vg_sigshutdown_actions() at
1509 the end of vg_switch_to_real_CPU(), so as to ensure that
1510 the original stack and machine state is restored before
1511 the real signal mechanism is restored. */
1512 VG_(switch_to_real_CPU)();
1513
1514 default:
njne427a662002-10-02 11:08:25 +00001515 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001516 }
sewardjde4a1d02002-03-22 01:27:54 +00001517}
1518
1519
1520/* Debugging thing .. can be called from assembly with OYNK macro. */
1521void VG_(oynk) ( Int n )
1522{
1523 OINK(n);
1524}
1525
1526
1527/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1528 "valgrinq.so", which doesn't do anything. This is used to avoid
1529 tracing into child processes. To make this work the build system
1530 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001531
njn25e49d8e72002-09-23 09:36:25 +00001532 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1533 without it, child processes try to find valgrind.so symbols in the
1534 skin .so.
1535
sewardj78e25c92002-05-20 23:38:33 +00001536 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1537 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1538 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001539*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001540void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1541 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001542{
njn25e49d8e72002-09-23 09:36:25 +00001543 Char* p_prel = NULL;
1544 Char* sk_prel = NULL;
1545 Char* p_path = NULL;
1546 Int what = 0;
sewardj78e25c92002-05-20 23:38:33 +00001547 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1548 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001549
sewardj78e25c92002-05-20 23:38:33 +00001550 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1551
1552 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
njn25e49d8e72002-09-23 09:36:25 +00001553 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
sewardj78e25c92002-05-20 23:38:33 +00001554 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1555
njn25e49d8e72002-09-23 09:36:25 +00001556 what = 1;
sewardj78e25c92002-05-20 23:38:33 +00001557 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001558 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001559 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1560 goto mutancy;
1561 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1562 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001563 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001564 }
1565
sewardj78e25c92002-05-20 23:38:33 +00001566 what = 2;
njn25e49d8e72002-09-23 09:36:25 +00001567 if (sk_prel == NULL) goto mutancy;
1568
1569 what = 3;
sewardj78e25c92002-05-20 23:38:33 +00001570 if (p_path == NULL) goto mutancy;
1571
njn25e49d8e72002-09-23 09:36:25 +00001572 what = 4;
1573 {
1574 /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
1575 Char* p = sk_prel;
1576 while (*p != ':' && p > ld_preload_str) {
1577 *p = ' ';
1578 p--;
1579 }
1580 /* Blank from "vgskin_" to next LD_PRELOAD entry */
1581 while (*p != ':' && *p != '\0') {
1582 *p = ' ';
1583 p++;
1584 }
1585 if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
1586 *p = ' '; /* blank ending ':' */
1587 }
1588
sewardj78e25c92002-05-20 23:38:33 +00001589 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
njn25e49d8e72002-09-23 09:36:25 +00001590 what = 5;
sewardj78e25c92002-05-20 23:38:33 +00001591 if (p_prel[7] != 'd') goto mutancy;
1592 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001593
1594 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1595 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1596 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001597 p_path += VG_(strlen)(VG_LIBDIR);
njn25e49d8e72002-09-23 09:36:25 +00001598 what = 6;
sewardj78e25c92002-05-20 23:38:33 +00001599 if (p_path[0] != '/') goto mutancy;
1600 p_path++; /* step over / */
njn25e49d8e72002-09-23 09:36:25 +00001601 what = 7;
sewardj78e25c92002-05-20 23:38:33 +00001602 if (p_path[7] != 'd') goto mutancy;
1603 p_path[7] = 'q';
1604 return;
1605
1606 mutancy:
1607 VG_(printf)(
1608 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1609 " what = %d\n"
1610 " ld_preload_str = `%s'\n"
1611 " ld_library_path_str = `%s'\n"
1612 " p_prel = `%s'\n"
1613 " p_path = `%s'\n"
1614 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001615 what, ld_preload_str, ld_library_path_str,
1616 p_prel, p_path, VG_LIBDIR
1617 );
sewardjc26b4482002-07-13 12:20:35 +00001618 VG_(printf)(
1619 "\n"
1620 "Note that this is often caused by mis-installation of valgrind.\n"
1621 "Correct installation procedure is:\n"
1622 " ./configure --prefix=/install/dir\n"
1623 " make install\n"
1624 "And then use /install/dir/bin/valgrind\n"
1625 "Moving the installation directory elsewhere after 'make install'\n"
1626 "will cause the above error. Hand-editing the paths in the shell\n"
1627 "scripts is also likely to cause problems.\n"
1628 "\n"
1629 );
njne427a662002-10-02 11:08:25 +00001630 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001631}
1632
sewardj3e1eb1f2002-05-18 13:14:17 +00001633
sewardjde4a1d02002-03-22 01:27:54 +00001634/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1635 it to attach to this process. Called if the user requests this
1636 service after an error has been shown, so she can poke around and
1637 look at parameters, memory, etc. You can't meaningfully get GDB to
1638 continue the program, though; to continue, quit GDB. */
1639extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1640{
sewardje6a25242002-04-21 22:03:07 +00001641 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001642 UChar buf[100];
1643 VG_(sprintf)(buf,
1644 "/usr/bin/gdb -nw /proc/%d/exe %d",
1645 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001646 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1647 res = VG_(system)(buf);
1648 if (res == 0) {
1649 VG_(message)(Vg_UserMsg, "");
1650 VG_(message)(Vg_UserMsg,
1651 "GDB has detached. Valgrind regains control. We continue.");
1652 } else {
1653 VG_(message)(Vg_UserMsg, "Apparently failed!");
1654 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001655 }
sewardjde4a1d02002-03-22 01:27:54 +00001656}
1657
1658
1659/* Print some helpful-ish text about unimplemented things, and give
1660 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001661void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001662{
1663 VG_(message)(Vg_UserMsg, "");
1664 VG_(message)(Vg_UserMsg,
1665 "Valgrind detected that your program requires");
1666 VG_(message)(Vg_UserMsg,
1667 "the following unimplemented functionality:");
1668 VG_(message)(Vg_UserMsg, " %s", msg);
1669 VG_(message)(Vg_UserMsg,
1670 "This may be because the functionality is hard to implement,");
1671 VG_(message)(Vg_UserMsg,
1672 "or because no reasonable program would behave this way,");
1673 VG_(message)(Vg_UserMsg,
1674 "or because nobody has yet needed it. In any case, let me know");
1675 VG_(message)(Vg_UserMsg,
1676 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1677 VG_(message)(Vg_UserMsg,
1678 "");
1679 VG_(message)(Vg_UserMsg,
1680 "Valgrind has to exit now. Sorry. Bye!");
1681 VG_(message)(Vg_UserMsg,
1682 "");
sewardj15a43e12002-04-17 19:35:12 +00001683 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001684 VG_(exit)(1);
1685}
1686
1687
njn25e49d8e72002-09-23 09:36:25 +00001688/* ---------------------------------------------------------------------
1689 Sanity check machinery (permanently engaged).
1690 ------------------------------------------------------------------ */
1691
1692/* A fast sanity check -- suitable for calling circa once per
1693 millisecond. */
1694
1695void VG_(do_sanity_checks) ( Bool force_expensive )
1696{
1697 Int i;
1698
njn37cea302002-09-30 11:24:00 +00001699 VGP_PUSHCC(VgpCoreCheapSanity);
1700
njn25e49d8e72002-09-23 09:36:25 +00001701 if (VG_(sanity_level) < 1) return;
1702
1703 /* --- First do all the tests that we can do quickly. ---*/
1704
1705 VG_(sanity_fast_count)++;
1706
1707 /* Check that we haven't overrun our private stack. */
1708 for (i = 0; i < 10; i++) {
1709 vg_assert(VG_(stack)[i]
1710 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
1711 vg_assert(VG_(stack)[10000-1-i]
1712 == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
1713 }
1714
1715 /* Check stuff pertaining to the memory check system. */
1716
1717 /* Check that nobody has spuriously claimed that the first or
1718 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001719 if (VG_(needs).sanity_checks) {
1720 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001721 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001722 VGP_POPCC(VgpSkinCheapSanity);
1723 }
njn25e49d8e72002-09-23 09:36:25 +00001724
1725 /* --- Now some more expensive checks. ---*/
1726
1727 /* Once every 25 times, check some more expensive stuff. */
1728 if ( force_expensive
1729 || VG_(sanity_level) > 1
1730 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1731
njn37cea302002-09-30 11:24:00 +00001732 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001733 VG_(sanity_slow_count)++;
1734
1735# if 0
1736 { void zzzmemscan(void); zzzmemscan(); }
1737# endif
1738
1739 if ((VG_(sanity_fast_count) % 250) == 0)
1740 VG_(sanity_check_tc_tt)();
1741
1742 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001743 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001744 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001745 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001746 }
1747 /*
1748 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1749 */
njn37cea302002-09-30 11:24:00 +00001750 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001751 }
1752
1753 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001754 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001755 /* Check sanity of the low-level memory manager. Note that bugs
1756 in the client's code can cause this to fail, so we don't do
1757 this check unless specially asked for. And because it's
1758 potentially very expensive. */
1759 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001760 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001761 }
njn37cea302002-09-30 11:24:00 +00001762 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001763}
sewardjde4a1d02002-03-22 01:27:54 +00001764/*--------------------------------------------------------------------*/
1765/*--- end vg_main.c ---*/
1766/*--------------------------------------------------------------------*/