blob: f70c5bc995b22d68ba0567236de878286a7f4559 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- C startup stuff, reached from vg_startup.S. ---*/
4/*--- vg_main.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32#include "vg_include.h"
sewardjde4a1d02002-03-22 01:27:54 +000033
34/* ---------------------------------------------------------------------
35 Compute offsets into baseBlock. See comments in vg_include.h.
36 ------------------------------------------------------------------ */
37
38/* The variables storing offsets. */
39
40#define INVALID_OFFSET (-1)
41
42Int VGOFF_(m_eax) = INVALID_OFFSET;
43Int VGOFF_(m_ecx) = INVALID_OFFSET;
44Int VGOFF_(m_edx) = INVALID_OFFSET;
45Int VGOFF_(m_ebx) = INVALID_OFFSET;
46Int VGOFF_(m_esp) = INVALID_OFFSET;
47Int VGOFF_(m_ebp) = INVALID_OFFSET;
48Int VGOFF_(m_esi) = INVALID_OFFSET;
49Int VGOFF_(m_edi) = INVALID_OFFSET;
50Int VGOFF_(m_eflags) = INVALID_OFFSET;
sewardjfa492d42002-12-08 18:20:01 +000051Int VGOFF_(m_dflag) = INVALID_OFFSET;
sewardjb91ae7f2003-04-29 23:50:00 +000052Int VGOFF_(m_ssestate) = INVALID_OFFSET;
sewardj92a59562002-09-30 00:53:10 +000053Int VGOFF_(ldt) = INVALID_OFFSET;
54Int VGOFF_(m_cs) = INVALID_OFFSET;
55Int VGOFF_(m_ss) = INVALID_OFFSET;
56Int VGOFF_(m_ds) = INVALID_OFFSET;
57Int VGOFF_(m_es) = INVALID_OFFSET;
58Int VGOFF_(m_fs) = INVALID_OFFSET;
59Int VGOFF_(m_gs) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000060Int VGOFF_(m_eip) = INVALID_OFFSET;
61Int VGOFF_(spillslots) = INVALID_OFFSET;
62Int VGOFF_(sh_eax) = INVALID_OFFSET;
63Int VGOFF_(sh_ecx) = INVALID_OFFSET;
64Int VGOFF_(sh_edx) = INVALID_OFFSET;
65Int VGOFF_(sh_ebx) = INVALID_OFFSET;
66Int VGOFF_(sh_esp) = INVALID_OFFSET;
67Int VGOFF_(sh_ebp) = INVALID_OFFSET;
68Int VGOFF_(sh_esi) = INVALID_OFFSET;
69Int VGOFF_(sh_edi) = INVALID_OFFSET;
70Int VGOFF_(sh_eflags) = INVALID_OFFSET;
njn25e49d8e72002-09-23 09:36:25 +000071
sewardjde4a1d02002-03-22 01:27:54 +000072Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
73Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
74Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
75Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
76Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
77Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
78Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
79Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
80Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
81Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
82Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
83Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
84Int VGOFF_(helper_CLD) = INVALID_OFFSET;
85Int VGOFF_(helper_STD) = INVALID_OFFSET;
86Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
sewardj7d78e782002-06-02 00:04:00 +000087Int VGOFF_(helper_CLC) = INVALID_OFFSET;
88Int VGOFF_(helper_STC) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000089Int VGOFF_(helper_shldl) = INVALID_OFFSET;
90Int VGOFF_(helper_shldw) = INVALID_OFFSET;
91Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
92Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
93Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
94Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
95Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000096Int VGOFF_(helper_bsf) = INVALID_OFFSET;
97Int VGOFF_(helper_bsr) = INVALID_OFFSET;
98Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
99Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
njnd6251f12003-06-03 13:38:51 +0000100Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +0000101Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +0000102Int VGOFF_(helper_DAA) = 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
njn0c7a5b52003-04-30 09:00:33 +0000136/* Align offset, in *bytes* */
137static void align_BaB ( UInt align )
138{
139 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
140 baB_off += (align-1);
141 baB_off &= ~(align-1);
142}
143
sewardjde4a1d02002-03-22 01:27:54 +0000144/* Allocate 1 word in baseBlock and set it to the given value. */
145static Int alloc_BaB_1_set ( Addr a )
146{
147 Int off = alloc_BaB(1);
148 VG_(baseBlock)[off] = (UInt)a;
149 return off;
150}
151
njn25e49d8e72002-09-23 09:36:25 +0000152/* Registers a function in compact_helper_addrs; compact_helper_offsets is
njn9b007f62003-04-07 14:40:25 +0000153 filled in later. */
njn25e49d8e72002-09-23 09:36:25 +0000154void VG_(register_compact_helper)(Addr a)
155{
156 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
157 VG_(printf)("Can only register %d compact helpers\n",
158 MAX_COMPACT_HELPERS);
njne427a662002-10-02 11:08:25 +0000159 VG_(core_panic)("Too many compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000160 }
161 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
162 VG_(n_compact_helpers)++;
163}
164
165/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
166 * is filled in later.
167 */
168void VG_(register_noncompact_helper)(Addr a)
169{
170 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
171 VG_(printf)("Can only register %d non-compact helpers\n",
172 MAX_NONCOMPACT_HELPERS);
173 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
njne427a662002-10-02 11:08:25 +0000174 VG_(core_panic)("Too many non-compact helpers registered");
njn25e49d8e72002-09-23 09:36:25 +0000175 }
176 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
177 VG_(n_noncompact_helpers)++;
178}
179
180/* Allocate offsets in baseBlock for the skin helpers */
sewardj05bcdcb2003-05-18 10:05:38 +0000181static
182void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
njn25e49d8e72002-09-23 09:36:25 +0000183{
sewardj05bcdcb2003-05-18 10:05:38 +0000184 UInt i;
185 for (i = 0; i < n; i++)
186 offsets[i] = alloc_BaB_1_set( addrs[i] );
njn25e49d8e72002-09-23 09:36:25 +0000187}
sewardjde4a1d02002-03-22 01:27:54 +0000188
njnf4ce3d32003-02-10 10:17:26 +0000189Bool VG_(need_to_handle_esp_assignment)(void)
190{
njn9b007f62003-04-07 14:40:25 +0000191 return ( VG_(track_events).new_mem_stack_4 ||
192 VG_(track_events).die_mem_stack_4 ||
193 VG_(track_events).new_mem_stack_8 ||
194 VG_(track_events).die_mem_stack_8 ||
195 VG_(track_events).new_mem_stack_12 ||
196 VG_(track_events).die_mem_stack_12 ||
197 VG_(track_events).new_mem_stack_16 ||
198 VG_(track_events).die_mem_stack_16 ||
199 VG_(track_events).new_mem_stack_32 ||
200 VG_(track_events).die_mem_stack_32 ||
201 VG_(track_events).new_mem_stack ||
202 VG_(track_events).die_mem_stack
203 );
njnf4ce3d32003-02-10 10:17:26 +0000204}
205
sewardjde4a1d02002-03-22 01:27:54 +0000206/* Here we assign actual offsets. It's important to get the most
207 popular referents within 128 bytes of the start, so we can take
208 advantage of short addressing modes relative to %ebp. Popularity
209 of offsets was measured on 22 Feb 02 running a KDE application, and
210 the slots rearranged accordingly, with a 1.5% reduction in total
211 size of translations. */
sewardjde4a1d02002-03-22 01:27:54 +0000212static void vg_init_baseBlock ( void )
213{
sewardjde4a1d02002-03-22 01:27:54 +0000214 /* Those with offsets under 128 are carefully chosen. */
215
216 /* WORD offsets in this column */
217 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
218 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
219 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
220 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
221 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
222 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
223 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
224 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
225 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
226
njn25e49d8e72002-09-23 09:36:25 +0000227 if (VG_(needs).shadow_regs) {
228 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
229 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
230 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
231 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
232 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
233 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
234 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
235 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
236 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
237 }
sewardjde4a1d02002-03-22 01:27:54 +0000238
njn25e49d8e72002-09-23 09:36:25 +0000239 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
240 * and on compact helpers registered */
njn4f9c9342002-04-29 16:03:24 +0000241
njn9b007f62003-04-07 14:40:25 +0000242 /* Make these most-frequently-called specialised ones compact, if they
243 are used. */
244 if (VG_(track_events).new_mem_stack_4)
245 VG_(register_compact_helper)( (Addr) VG_(track_events).new_mem_stack_4);
sewardjde4a1d02002-03-22 01:27:54 +0000246
njn9b007f62003-04-07 14:40:25 +0000247 if (VG_(track_events).die_mem_stack_4)
248 VG_(register_compact_helper)( (Addr) VG_(track_events).die_mem_stack_4);
249
250 /* (9 or 18) + n_compact_helpers */
njn25e49d8e72002-09-23 09:36:25 +0000251 /* Allocate slots for compact helpers */
252 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
253 VG_(compact_helper_offsets),
254 VG_(compact_helper_addrs));
sewardjde4a1d02002-03-22 01:27:54 +0000255
njn25e49d8e72002-09-23 09:36:25 +0000256 /* (9/10 or 18/19) + n_compact_helpers */
sewardjde4a1d02002-03-22 01:27:54 +0000257 VGOFF_(m_eip) = alloc_BaB(1);
258
259 /* There are currently 24 spill slots */
njn25e49d8e72002-09-23 09:36:25 +0000260 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
261 * boundary at >= 32 words, but most spills are to low numbered spill
262 * slots, so the ones above the boundary don't see much action. */
sewardjde4a1d02002-03-22 01:27:54 +0000263 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
264
njn25e49d8e72002-09-23 09:36:25 +0000265 /* I gave up counting at this point. Since they're above the
sewardjde4a1d02002-03-22 01:27:54 +0000266 short-amode-boundary, there's no point. */
267
sewardjfa492d42002-12-08 18:20:01 +0000268 VGOFF_(m_dflag) = alloc_BaB(1);
269
sewardjb91ae7f2003-04-29 23:50:00 +0000270 /* The FPU/SSE state. This _must_ be 16-byte aligned. */
njn0c7a5b52003-04-30 09:00:33 +0000271 align_BaB(16);
sewardjb91ae7f2003-04-29 23:50:00 +0000272 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
273 vg_assert(
274 ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)]))
275 % 16 )
276 == 0
277 );
sewardjde4a1d02002-03-22 01:27:54 +0000278
sewardj92a59562002-09-30 00:53:10 +0000279 /* This thread's LDT pointer, and segment registers. */
280 VGOFF_(ldt) = alloc_BaB(1);
281 VGOFF_(m_cs) = alloc_BaB(1);
282 VGOFF_(m_ss) = alloc_BaB(1);
283 VGOFF_(m_ds) = alloc_BaB(1);
284 VGOFF_(m_es) = alloc_BaB(1);
285 VGOFF_(m_fs) = alloc_BaB(1);
286 VGOFF_(m_gs) = alloc_BaB(1);
287
sewardje1042472002-09-30 12:33:11 +0000288 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
289
njn9b007f62003-04-07 14:40:25 +0000290#define REG(kind, size) \
291 if (VG_(track_events).kind##_mem_stack##size) \
292 VG_(register_noncompact_helper)( \
293 (Addr) VG_(track_events).kind##_mem_stack##size );
294
295 REG(new, _8);
296 REG(new, _12);
297 REG(new, _16);
298 REG(new, _32);
299 REG(new, );
300 REG(die, _8);
301 REG(die, _12);
302 REG(die, _16);
303 REG(die, _32);
304 REG(die, );
305#undef REG
306
307 if (VG_(need_to_handle_esp_assignment)())
308 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
309
sewardj92a59562002-09-30 00:53:10 +0000310 /* Helper functions. */
sewardjde4a1d02002-03-22 01:27:54 +0000311 VGOFF_(helper_idiv_64_32)
312 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
313 VGOFF_(helper_div_64_32)
314 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
315 VGOFF_(helper_idiv_32_16)
316 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
317 VGOFF_(helper_div_32_16)
318 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
319 VGOFF_(helper_idiv_16_8)
320 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
321 VGOFF_(helper_div_16_8)
322 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
323
324 VGOFF_(helper_imul_32_64)
325 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
326 VGOFF_(helper_mul_32_64)
327 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
328 VGOFF_(helper_imul_16_32)
329 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
330 VGOFF_(helper_mul_16_32)
331 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
332 VGOFF_(helper_imul_8_16)
333 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
334 VGOFF_(helper_mul_8_16)
335 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
336
337 VGOFF_(helper_CLD)
338 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
339 VGOFF_(helper_STD)
340 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
341 VGOFF_(helper_get_dirflag)
342 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
343
sewardj7d78e782002-06-02 00:04:00 +0000344 VGOFF_(helper_CLC)
345 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
sewardj73cf3bc2002-11-03 03:20:15 +0000346 VGOFF_(helper_STC)
sewardj7d78e782002-06-02 00:04:00 +0000347 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
348
sewardjde4a1d02002-03-22 01:27:54 +0000349 VGOFF_(helper_shldl)
350 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
351 VGOFF_(helper_shldw)
352 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
353 VGOFF_(helper_shrdl)
354 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
355 VGOFF_(helper_shrdw)
356 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
357
358 VGOFF_(helper_RDTSC)
359 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
360 VGOFF_(helper_CPUID)
361 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
362
sewardjde4a1d02002-03-22 01:27:54 +0000363 VGOFF_(helper_bsf)
364 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
365 VGOFF_(helper_bsr)
366 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
367
368 VGOFF_(helper_fstsw_AX)
369 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
370 VGOFF_(helper_SAHF)
371 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
njnd6251f12003-06-03 13:38:51 +0000372 VGOFF_(helper_LAHF)
373 = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000374 VGOFF_(helper_DAS)
375 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000376 VGOFF_(helper_DAA)
377 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
njn25e49d8e72002-09-23 09:36:25 +0000378
sewardj51096432002-12-14 23:59:09 +0000379 VGOFF_(helper_undefined_instruction)
380 = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
381
sewardj92a59562002-09-30 00:53:10 +0000382 /* Allocate slots for noncompact helpers */
njn25e49d8e72002-09-23 09:36:25 +0000383 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
384 VG_(noncompact_helper_offsets),
385 VG_(noncompact_helper_addrs));
njn25e49d8e72002-09-23 09:36:25 +0000386
njncc7bb472002-10-14 09:25:19 +0000387
388 /* Initialise slots that require it */
389 VG_(copy_m_state_static_to_baseBlock)();
390
391 /* Pretend the root thread has a completely empty LDT to start with. */
392 VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
393
394 /* Initialise shadow regs */
njn25e49d8e72002-09-23 09:36:25 +0000395 if (VG_(needs).shadow_regs) {
njn25e49d8e72002-09-23 09:36:25 +0000396 VG_(baseBlock)[VGOFF_(sh_esp)] =
397 VG_(baseBlock)[VGOFF_(sh_ebp)] =
398 VG_(baseBlock)[VGOFF_(sh_eax)] =
399 VG_(baseBlock)[VGOFF_(sh_ecx)] =
400 VG_(baseBlock)[VGOFF_(sh_edx)] =
401 VG_(baseBlock)[VGOFF_(sh_ebx)] =
402 VG_(baseBlock)[VGOFF_(sh_esi)] =
njnd3040452003-05-19 15:04:06 +0000403 VG_(baseBlock)[VGOFF_(sh_edi)] = 0;
404 VG_(baseBlock)[VGOFF_(sh_eflags)] = 0;
405 VG_TRACK( post_regs_write_init );
njncc7bb472002-10-14 09:25:19 +0000406 }
sewardjde4a1d02002-03-22 01:27:54 +0000407}
408
409
410/* ---------------------------------------------------------------------
411 Global entities which are not referenced from generated code.
412 ------------------------------------------------------------------ */
413
414/* The stack on which Valgrind runs. We can't use the same stack as
415 the simulatee -- that's an important design decision. */
njn6eba4ef2003-05-01 08:06:41 +0000416UInt VG_(stack)[VG_STACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000417
418/* Ditto our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000419UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000420
421/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000422__attribute__ ((aligned (16)))
423UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000424Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000425
426/* Counts downwards in vg_run_innerloop. */
427UInt VG_(dispatch_ctr);
428
sewardjde4a1d02002-03-22 01:27:54 +0000429
430/* 64-bit counter for the number of basic blocks done. */
431ULong VG_(bbs_done);
432/* 64-bit counter for the number of bbs to go before a debug exit. */
433ULong VG_(bbs_to_go);
434
sewardj7e87e382002-05-03 19:09:05 +0000435/* This is the ThreadId of the last thread the scheduler ran. */
436ThreadId VG_(last_run_tid) = 0;
437
njn25e49d8e72002-09-23 09:36:25 +0000438/* This is the argument to __NR_exit() supplied by the first thread to
439 call that syscall. We eventually pass that to __NR_exit() for
440 real. */
njn633de322003-05-12 20:40:13 +0000441Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000442
sewardj73cf3bc2002-11-03 03:20:15 +0000443/* Tell the logging mechanism whether we are logging to a file
444 descriptor or a socket descriptor. */
445Bool VG_(logging_to_filedes) = True;
446
sewardjb91ae7f2003-04-29 23:50:00 +0000447/* Is this a SSE/SSE2-capable CPU? If so, we had better save/restore
448 the SSE state all over the place. This is set up very early, in
449 vg_startup.S. We have to determine it early since we can't even
450 correctly snapshot the startup machine state without it. */
451/* Initially True. Safer to err on the side of SSEness and get SIGILL
daywalker7e73e5f2003-07-04 16:18:15 +0000452 than to not notice for some reason that we have SSE and get weird
sewardjb91ae7f2003-04-29 23:50:00 +0000453 errors later on. */
454Bool VG_(have_ssestate) = True;
455
sewardjde4a1d02002-03-22 01:27:54 +0000456
457/* ---------------------------------------------------------------------
458 Counters, for informational purposes only.
459 ------------------------------------------------------------------ */
460
461/* Number of lookups which miss the fast tt helper. */
462UInt VG_(tt_fast_misses) = 0;
463
464
sewardjc0d8f682002-11-30 00:49:43 +0000465/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000466
sewardjde4a1d02002-03-22 01:27:54 +0000467/* Number and total o/t size of translations overall. */
468UInt VG_(overall_in_count) = 0;
469UInt VG_(overall_in_osize) = 0;
470UInt VG_(overall_in_tsize) = 0;
471/* Number and total o/t size of discards overall. */
472UInt VG_(overall_out_count) = 0;
473UInt VG_(overall_out_osize) = 0;
474UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000475/* The number of discards of TT/TC. */
476UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000477/* Counts of chain and unchain operations done. */
478UInt VG_(bb_enchain_count) = 0;
479UInt VG_(bb_dechain_count) = 0;
480/* Number of unchained jumps performed. */
481UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000482
483
484/* Counts pertaining to the register allocator. */
485
486/* total number of uinstrs input to reg-alloc */
487UInt VG_(uinstrs_prealloc) = 0;
488
489/* total number of uinstrs added due to spill code */
490UInt VG_(uinstrs_spill) = 0;
491
492/* number of bbs requiring spill code */
493UInt VG_(translations_needing_spill) = 0;
494
495/* total of register ranks over all translations */
496UInt VG_(total_reg_rank) = 0;
497
498
sewardjde4a1d02002-03-22 01:27:54 +0000499/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000500UInt VG_(sanity_fast_count) = 0;
501UInt VG_(sanity_slow_count) = 0;
502
sewardj2e93c502002-04-12 11:12:52 +0000503/* Counts pertaining to the scheduler. */
504UInt VG_(num_scheduling_events_MINOR) = 0;
505UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000506
507
508/* ---------------------------------------------------------------------
509 Values derived from command-line options.
510 ------------------------------------------------------------------ */
511
njn25e49d8e72002-09-23 09:36:25 +0000512/* Define, and set defaults. */
513Bool VG_(clo_error_limit) = True;
514Bool VG_(clo_GDB_attach) = False;
sewardj6024b212003-07-13 10:54:33 +0000515Char* VG_(clo_GDB_path) = GDB_PATH;
njn43c799e2003-04-08 00:08:52 +0000516Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +0000517Int VG_(sanity_level) = 1;
518Int VG_(clo_verbosity) = 1;
519Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +0000520Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +0000521
522/* See big comment in vg_include.h for meaning of these three. */
523VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
524Int VG_(clo_logfile_fd) = 2;
525Char* VG_(clo_logfile_name) = NULL;
526
sewardj6024b212003-07-13 10:54:33 +0000527Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +0000528Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000529Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +0000530Bool VG_(clo_profile) = False;
531Bool VG_(clo_single_step) = False;
532Bool VG_(clo_optimise) = True;
533UChar VG_(clo_trace_codegen) = 0; // 00000000b
534Bool VG_(clo_trace_syscalls) = False;
535Bool VG_(clo_trace_signals) = False;
536Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +0000537Bool VG_(clo_trace_sched) = False;
538Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +0000539ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +0000540Int VG_(clo_dump_error) = 0;
541Int VG_(clo_backtrace_size) = 4;
542Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +0000543Bool VG_(clo_run_libc_freeres) = True;
sewardj22854b92002-11-30 14:00:47 +0000544Bool VG_(clo_chain_bb) = True;
sewardj2370f3b2002-11-30 15:01:01 +0000545
sewardjde4a1d02002-03-22 01:27:54 +0000546/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
547 to behave. Initially we say False. */
548Bool VG_(running_on_simd_CPU) = False;
549
550/* Holds client's %esp at the point we gained control. */
551Addr VG_(esp_at_startup);
552
sewardjd5815ec2003-04-06 12:23:27 +0000553/* Indicates presence, and holds address of client's sysinfo page, a
554 feature of some modern kernels used to provide vsyscalls, etc. */
555Bool VG_(sysinfo_page_exists) = False;
556Addr VG_(sysinfo_page_addr) = 0;
557
sewardjde4a1d02002-03-22 01:27:54 +0000558/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
559 envp[] as extracted from the client's stack at startup-time. */
560Int VG_(client_argc);
561Char** VG_(client_argv);
562Char** VG_(client_envp);
563
564/* A place into which to copy the value of env var VG_ARGS, so we
565 don't have to modify the original. */
566static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
567
sewardjde4a1d02002-03-22 01:27:54 +0000568/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000569 Processing of command-line options.
570 ------------------------------------------------------------------ */
571
njn25e49d8e72002-09-23 09:36:25 +0000572void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +0000573{
574 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000575 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000576 VG_(clo_logfile_fd) = 2; /* stderr */
577 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
578 VG_(exit)(1);
579}
580
581static void config_error ( Char* msg )
582{
583 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000584 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +0000585 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000586 VG_(printf)(
587 "valgrind.so: Startup or configuration error:\n %s\n", msg);
588 VG_(printf)(
589 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000590 VG_(exit)(1);
591}
592
sewardja1679dd2002-05-10 22:31:40 +0000593static void args_grok_error ( Char* msg )
594{
595 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000596 VG_(clo_log_to) = VgLogTo_Fd;
sewardja1679dd2002-05-10 22:31:40 +0000597 VG_(clo_logfile_fd) = 2; /* stderr */
598 VG_(printf)("valgrind.so: When searching for "
599 "client's argc/argc/envp:\n\t%s\n", msg);
600 config_error("couldn't find client's argc/argc/envp");
601}
602
njn25e49d8e72002-09-23 09:36:25 +0000603static void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +0000604{
njn25e49d8e72002-09-23 09:36:25 +0000605 Char* usage1 =
606"usage: valgrind [options] prog-and-args\n"
607"\n"
608" core user options, with defaults in [ ], are:\n"
609" --help show this message\n"
610" --version show version\n"
611" --skin=<name> main task (skin to use) [Valgrind]\n"
612" -q --quiet run silently; only print error msgs\n"
613" -v --verbose be more verbose, incl counts of errors\n"
614" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
sewardj6024b212003-07-13 10:54:33 +0000615" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
njn43c799e2003-04-08 00:08:52 +0000616" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000617" --demangle=no|yes automatically demangle C++ names? [yes]\n"
618" --num-callers=<number> show <num> callers in stack traces [4]\n"
619" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000620" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
sewardj858964b2002-10-05 14:15:43 +0000621" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000622" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
sewardj4cf05692002-10-27 20:28:29 +0000623" --logfile=<file> log messages to <file>.pid<pid>\n"
sewardj6024b212003-07-13 10:54:33 +0000624" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
sewardj73cf3bc2002-11-03 03:20:15 +0000625" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
njn25e49d8e72002-09-23 09:36:25 +0000626" --suppressions=<filename> suppress errors described in\n"
627" suppressions file <filename>\n"
628" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
sewardj3d652a32002-10-20 18:11:49 +0000629" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
njn25e49d8e72002-09-23 09:36:25 +0000630"\n"
631" %s skin user options:\n";
njn7cf0bd32002-06-08 13:36:03 +0000632
njn7cf0bd32002-06-08 13:36:03 +0000633
njn25e49d8e72002-09-23 09:36:25 +0000634 Char* usage2 =
635"\n"
636" core options for debugging Valgrind itself are:\n"
637" --sanity-level=<number> level of sanity checking to do [1]\n"
638" --single-step=no|yes translate each instr separately? [no]\n"
639" --optimise=no|yes improve intermediate code? [yes]\n"
640" --profile=no|yes profile? (skin must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +0000641" --chain-bb=no|yes do basic-block chaining? [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +0000642" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
643" --trace-syscalls=no|yes show all system calls? [no]\n"
644" --trace-signals=no|yes show signal handling details? [no]\n"
645" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000646" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +0000647" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +0000648" --stop-after=<number> switch to real CPU after executing\n"
649" <number> basic blocks [infinity]\n"
650" --dump-error=<number> show translation for basic block\n"
651" associated with <number>'th\n"
652" error context [0=don't show any]\n"
653"\n"
njn3e884182003-04-15 13:03:23 +0000654" %s skin debugging options:\n";
655
656 Char* usage3 =
657"\n"
njn25e49d8e72002-09-23 09:36:25 +0000658" Extra options are read from env variable $VALGRIND_OPTS\n"
659"\n"
njn0e1b5142003-04-15 14:58:06 +0000660" Valgrind is Copyright (C) 2000-2003 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +0000661" and licensed under the GNU General Public License, version 2.\n"
662" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000663"\n"
664" Skins are copyright and licensed by their authors. See each\n"
665" skin's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000666"\n";
njn7cf0bd32002-06-08 13:36:03 +0000667
njnd04b7c62002-10-03 14:05:52 +0000668 VG_(printf)(usage1, VG_(details).name);
njn25e49d8e72002-09-23 09:36:25 +0000669 /* Don't print skin string directly for security, ha! */
670 if (VG_(needs).command_line_options)
njn3e884182003-04-15 13:03:23 +0000671 SK_(print_usage)();
njn25e49d8e72002-09-23 09:36:25 +0000672 else
673 VG_(printf)(" (none)\n");
njn3e884182003-04-15 13:03:23 +0000674 VG_(printf)(usage2, VG_(details).name);
675 if (VG_(needs).command_line_options)
676 SK_(print_debug_usage)();
677 else
678 VG_(printf)(" (none)\n");
679 VG_(printf)(usage3, VG_EMAIL_ADDR);
njn7cf0bd32002-06-08 13:36:03 +0000680
njn25e49d8e72002-09-23 09:36:25 +0000681 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +0000682 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +0000683 VG_(clo_logfile_fd) = 2; /* stderr */
684 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +0000685}
sewardjde4a1d02002-03-22 01:27:54 +0000686
sewardj1c1b1162003-02-23 01:25:51 +0000687
sewardj49e630d2003-04-23 21:18:52 +0000688/* Callback for looking for the stack segment. */
689Addr VG_(foundstack_start) = (Addr)NULL;
690UInt VG_(foundstack_size) = 0;
sewardj1c1b1162003-02-23 01:25:51 +0000691
692static void vg_findstack_callback ( Addr start, UInt size,
sewardj53fe4582003-02-23 01:41:17 +0000693 Char r, Char w, Char x,
694 UInt foffset, UChar* filename )
sewardj1c1b1162003-02-23 01:25:51 +0000695{
696 Addr lastword;
697 if (size == 0) return;
sewardj04421d02003-02-23 03:54:59 +0000698 if (r != 'r' || w != 'w'
699 /* || x != 'x' --not necessarily so on x86-64*/
700 ) return;
sewardj1c1b1162003-02-23 01:25:51 +0000701 lastword = start + size - 4;
sewardj53fe4582003-02-23 01:41:17 +0000702 if (start <= VG_(esp_at_startup)
703 && VG_(esp_at_startup) <= lastword) {
sewardj49e630d2003-04-23 21:18:52 +0000704 VG_(foundstack_start) = start;
705 VG_(foundstack_size) = size;
706 vg_assert(VG_(foundstack_size) > 0);
sewardj1c1b1162003-02-23 01:25:51 +0000707 }
708}
709
710
711
sewardjde4a1d02002-03-22 01:27:54 +0000712static void process_cmd_line_options ( void )
713{
njn25e49d8e72002-09-23 09:36:25 +0000714 Char* argv[M_VG_CMDLINE_OPTS];
sewardj05bcdcb2003-05-18 10:05:38 +0000715 Int argc;
njn25e49d8e72002-09-23 09:36:25 +0000716 Char* p;
717 Char* str;
718 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000719
720# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
sewardjde4a1d02002-03-22 01:27:54 +0000721
sewardjde4a1d02002-03-22 01:27:54 +0000722 eventually_logfile_fd = VG_(clo_logfile_fd);
723
724 /* Once logging is started, we can safely send messages pertaining
725 to failures in initialisation. */
726 VG_(startup_logging)();
727
sewardj19d81412002-06-03 01:10:40 +0000728 /* Check for sane path in ./configure --prefix=... */
729 if (VG_(strlen)(VG_LIBDIR) < 1
730 || VG_LIBDIR[0] != '/')
731 config_error("Please use absolute paths in "
732 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000733
sewardja1679dd2002-05-10 22:31:40 +0000734 /* (Suggested by Fabrice Bellard ... )
735 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000736 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000737 change less often than the libc ones. */
738 {
sewardj05bcdcb2003-05-18 10:05:38 +0000739 Int* sp;
sewardj1c1b1162003-02-23 01:25:51 +0000740
njn3e884182003-04-15 13:03:23 +0000741 /* Look for the stack segment by parsing /proc/self/maps and
sewardj53fe4582003-02-23 01:41:17 +0000742 looking for a section bracketing VG_(esp_at_startup) which
njn3e884182003-04-15 13:03:23 +0000743 has rwx permissions and no associated file. Note that this uses
744 the /proc/self/maps contents read at the start of VG_(main)(),
745 and doesn't re-read /proc/self/maps. */
sewardj1c1b1162003-02-23 01:25:51 +0000746
njn3e884182003-04-15 13:03:23 +0000747 VG_(read_procselfmaps)( vg_findstack_callback, /*read_from_file*/False );
sewardj53fe4582003-02-23 01:41:17 +0000748
sewardj49e630d2003-04-23 21:18:52 +0000749 /* Now foundstack_start and foundstack_size should delimit the stack. */
750 if (VG_(foundstack_size) == 0) {
sewardj53fe4582003-02-23 01:41:17 +0000751 args_grok_error("Cannot determine stack segment "
752 "from /proc/self/maps");
753 }
sewardj1c1b1162003-02-23 01:25:51 +0000754
755 if (0)
sewardj53fe4582003-02-23 01:41:17 +0000756 VG_(printf)("stack segment is %p .. %p\n",
sewardj49e630d2003-04-23 21:18:52 +0000757 VG_(foundstack_start),
758 VG_(foundstack_start) + VG_(foundstack_size) - 4 );
sewardj1c1b1162003-02-23 01:25:51 +0000759
sewardj49e630d2003-04-23 21:18:52 +0000760 sp = (UInt*)(VG_(foundstack_start) + VG_(foundstack_size) );
sewardj53fe4582003-02-23 01:41:17 +0000761 if ((((UInt)(sp)) % VKI_BYTES_PER_PAGE) != 0) {
762 args_grok_error("Stack segment is not page aligned?!");
763 }
sewardj1c1b1162003-02-23 01:25:51 +0000764
sewardj53fe4582003-02-23 01:41:17 +0000765 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
766 the elf interpreter table */
sewardj1c1b1162003-02-23 01:25:51 +0000767
sewardj38170912002-05-10 21:07:22 +0000768 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000769 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000770 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000771 sp--;
772 }
sewardj38170912002-05-10 21:07:22 +0000773
774 if (sp[2] == VKI_AT_BASE
775 && sp[0] == VKI_AT_PAGESZ
776 && sp[-2] == VKI_AT_PHNUM
777 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000778 && sp[-6] == VKI_AT_PHDR
779 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000780 if (0)
781 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000782 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000783 } else
784 if (sp[2] == VKI_AT_CLKTCK
785 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000786 && sp[-2] == VKI_AT_HWCAP
787 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000788 if (0)
789 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
790 sp -= 2;
791 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000792 if (sp[2] == VKI_AT_CLKTCK
793 && sp[0] == VKI_AT_PAGESZ
794 && sp[-2] == VKI_AT_HWCAP
sewardjd5815ec2003-04-06 12:23:27 +0000795 && sp[-4] == VKI_AT_SYSINFO
796 && sp[-4-1] == 0) {
797 if (0)
798 VG_(printf)("Looks like you've got a 2.4.X kernel with "
799 "a sysinfo page at %x here.\n", sp[-3]);
800 VG_(sysinfo_page_exists) = True;
801 VG_(sysinfo_page_addr) = sp[-3];
802 sp -= 4;
803 } else
804 if (sp[2] == VKI_AT_CLKTCK
805 && sp[0] == VKI_AT_PAGESZ
806 && sp[-2] == VKI_AT_HWCAP
sewardjce61d052002-07-25 00:49:51 +0000807 && sp[-4] == VKI_AT_USER_AUX_SEGMENT
808 && sp[-4-1] == 0) {
809 if (0)
810 VG_(printf)("Looks like you've got a R-H Limbo 2.4.X "
811 "kernel here.\n");
812 sp -= 4;
813 } else
814 if (sp[2] == VKI_AT_CLKTCK
815 && sp[0] == VKI_AT_PAGESZ
816 && sp[-2] == VKI_AT_HWCAP
sewardjd9c2d6d2002-05-18 11:55:05 +0000817 && sp[-2-20-1] == 0) {
818 if (0)
819 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
820 sp -= 22;
821 } else
sewardj8fdbeed2003-02-23 03:09:33 +0000822 if (sp[2] == VKI_AT_CLKTCK
823 && sp[0] == VKI_AT_PAGESZ
824 && sp[-2] == VKI_AT_HWCAP
825 && sp[-4-1] == 0) {
826 if (0)
sewardj8c4e6b12003-04-26 21:49:40 +0000827 VG_(printf)("Looks like a 2.5.43-2.5.67 kernel here.\n");
sewardj8fdbeed2003-02-23 03:09:33 +0000828 sp -= 4;
829 } else
sewardj8c4e6b12003-04-26 21:49:40 +0000830 if (sp[2] == VKI_AT_CLKTCK
831 && sp[0] == VKI_AT_PAGESZ
832 && sp[-2] == VKI_AT_HWCAP
833 && sp[-6] == VKI_AT_SYSINFO
834 && sp[-6-1] == 0) {
835 if (0)
836 VG_(printf)("Looks like a >= 2.5.68 kernel with "
837 "a sysinfo page at %x here.\n", sp[-5]);
838 VG_(sysinfo_page_exists) = True;
839 VG_(sysinfo_page_addr) = sp[-5];
840 sp -= 6;
841 } else
sewardja1679dd2002-05-10 22:31:40 +0000842 args_grok_error(
843 "ELF frame does not look like 2.2.X or 2.4.X.\n "
844 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
845 );
sewardj38170912002-05-10 21:07:22 +0000846
847 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000848 if (*sp != 0)
849 args_grok_error("can't find NULL at end of env[]");
850
sewardj38170912002-05-10 21:07:22 +0000851 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000852 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000853 while (True) {
854 sp --;
855 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000856 if (++ctr >= 1000)
857 args_grok_error(
858 "suspiciously many (1000) env[] entries; giving up");
859
sewardj38170912002-05-10 21:07:22 +0000860 }
861 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000862 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000863
sewardja1679dd2002-05-10 22:31:40 +0000864 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000865 VG_(client_argc) = 0;
866 while (True) {
867 sp--;
868 if (*sp == VG_(client_argc))
869 break;
870 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000871 if (++ctr >= 1000)
872 args_grok_error(
873 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000874 }
875
sewardja1679dd2002-05-10 22:31:40 +0000876 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000877 }
878
sewardjde4a1d02002-03-22 01:27:54 +0000879 /* Now that VG_(client_envp) has been set, we can extract the args
880 for Valgrind itself. Copy into global var so that we don't have to
881 write zeroes to the getenv'd value itself. */
882 str = VG_(getenv)("VG_ARGS");
883 argc = 0;
884
885 if (!str) {
886 config_error("Can't read options from env var VG_ARGS.");
887 }
888
889 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
890 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
891 }
892 VG_(strcpy)(vg_cmdline_copy, str);
893 str = NULL;
894
895 p = &vg_cmdline_copy[0];
896 while (True) {
897 while (ISSPACE(*p)) { *p = 0; p++; }
898 if (*p == 0) break;
899 if (argc < M_VG_CMDLINE_OPTS-1) {
900 argv[argc] = p; argc++;
901 } else {
902 config_error(
903 "Found more than M_CMDLINE_OPTS command-line opts.");
904 }
905 while (*p != 0 && !ISSPACE(*p)) p++;
906 }
907
908 for (i = 0; i < argc; i++) {
909
njn43c799e2003-04-08 00:08:52 +0000910 if (VG_CLO_STREQ(argv[i], "-v") ||
911 VG_CLO_STREQ(argv[i], "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000912 VG_(clo_verbosity)++;
njn43c799e2003-04-08 00:08:52 +0000913 else if (VG_CLO_STREQ(argv[i], "-q") ||
914 VG_CLO_STREQ(argv[i], "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000915 VG_(clo_verbosity)--;
916
njn43c799e2003-04-08 00:08:52 +0000917 else if (VG_CLO_STREQ(argv[i], "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +0000918 VG_(clo_error_limit) = True;
njn43c799e2003-04-08 00:08:52 +0000919 else if (VG_CLO_STREQ(argv[i], "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +0000920 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +0000921
njn43c799e2003-04-08 00:08:52 +0000922 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000923 VG_(clo_GDB_attach) = True;
njn43c799e2003-04-08 00:08:52 +0000924 else if (VG_CLO_STREQ(argv[i], "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000925 VG_(clo_GDB_attach) = False;
926
sewardj6024b212003-07-13 10:54:33 +0000927 else if (VG_CLO_STREQN(11,argv[i], "--gdb-path="))
928 VG_(clo_GDB_path) = &argv[i][11];
929
njn43c799e2003-04-08 00:08:52 +0000930 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=yes"))
931 VG_(clo_gen_suppressions) = True;
932 else if (VG_CLO_STREQ(argv[i], "--gen-suppressions=no"))
933 VG_(clo_gen_suppressions) = False;
934
935 else if (VG_CLO_STREQ(argv[i], "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000936 VG_(clo_demangle) = True;
njn43c799e2003-04-08 00:08:52 +0000937 else if (VG_CLO_STREQ(argv[i], "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000938 VG_(clo_demangle) = False;
939
njn43c799e2003-04-08 00:08:52 +0000940 else if (VG_CLO_STREQ(argv[i], "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000941 VG_(clo_trace_children) = True;
njn43c799e2003-04-08 00:08:52 +0000942 else if (VG_CLO_STREQ(argv[i], "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000943 VG_(clo_trace_children) = False;
944
njn43c799e2003-04-08 00:08:52 +0000945 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +0000946 VG_(clo_run_libc_freeres) = True;
njn43c799e2003-04-08 00:08:52 +0000947 else if (VG_CLO_STREQ(argv[i], "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +0000948 VG_(clo_run_libc_freeres) = False;
949
njn43c799e2003-04-08 00:08:52 +0000950 else if (VG_CLO_STREQN(15, argv[i], "--sanity-level="))
sewardjde4a1d02002-03-22 01:27:54 +0000951 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
952
njn43c799e2003-04-08 00:08:52 +0000953 else if (VG_CLO_STREQN(13, argv[i], "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +0000954 VG_(clo_log_to) = VgLogTo_Fd;
955 VG_(clo_logfile_name) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000956 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
sewardj4cf05692002-10-27 20:28:29 +0000957 }
958
njn43c799e2003-04-08 00:08:52 +0000959 else if (VG_CLO_STREQN(10, argv[i], "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +0000960 VG_(clo_log_to) = VgLogTo_File;
961 VG_(clo_logfile_name) = &argv[i][10];
962 }
sewardjde4a1d02002-03-22 01:27:54 +0000963
njn43c799e2003-04-08 00:08:52 +0000964 else if (VG_CLO_STREQN(12, argv[i], "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +0000965 VG_(clo_log_to) = VgLogTo_Socket;
966 VG_(clo_logfile_name) = &argv[i][12];
967 }
968
sewardj6024b212003-07-13 10:54:33 +0000969 else if (VG_CLO_STREQN(11, argv[i], "--input-fd="))
970 VG_(clo_input_fd) = (Int)VG_(atoll)(&argv[i][11]);
971
njn43c799e2003-04-08 00:08:52 +0000972 else if (VG_CLO_STREQN(15, argv[i], "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000973 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000974 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000975 VG_(message)(Vg_UserMsg,
976 "Increase VG_CLO_MAX_SFILES and recompile.");
njn25e49d8e72002-09-23 09:36:25 +0000977 VG_(bad_option)(argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000978 }
979 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
980 VG_(clo_n_suppressions)++;
981 }
njn43c799e2003-04-08 00:08:52 +0000982 else if (VG_CLO_STREQ(argv[i], "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +0000983 VG_(clo_profile) = True;
njn43c799e2003-04-08 00:08:52 +0000984 else if (VG_CLO_STREQ(argv[i], "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +0000985 VG_(clo_profile) = False;
986
njn43c799e2003-04-08 00:08:52 +0000987 else if (VG_CLO_STREQ(argv[i], "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +0000988 VG_(clo_chain_bb) = True;
njn43c799e2003-04-08 00:08:52 +0000989 else if (VG_CLO_STREQ(argv[i], "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +0000990 VG_(clo_chain_bb) = False;
991
njn43c799e2003-04-08 00:08:52 +0000992 else if (VG_CLO_STREQ(argv[i], "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000993 VG_(clo_single_step) = True;
njn43c799e2003-04-08 00:08:52 +0000994 else if (VG_CLO_STREQ(argv[i], "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +0000995 VG_(clo_single_step) = False;
996
njn43c799e2003-04-08 00:08:52 +0000997 else if (VG_CLO_STREQ(argv[i], "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +0000998 VG_(clo_optimise) = True;
njn43c799e2003-04-08 00:08:52 +0000999 else if (VG_CLO_STREQ(argv[i], "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001000 VG_(clo_optimise) = False;
1001
njn25e49d8e72002-09-23 09:36:25 +00001002 /* "vwxyz" --> 000zyxwv (binary) */
njn43c799e2003-04-08 00:08:52 +00001003 else if (VG_CLO_STREQN(16, argv[i], "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001004 Int j;
1005 char* opt = & argv[i][16];
1006
1007 if (5 != VG_(strlen)(opt)) {
1008 VG_(message)(Vg_UserMsg,
1009 "--trace-codegen argument must have 5 digits");
1010 VG_(bad_option)(argv[i]);
1011 }
1012 for (j = 0; j < 5; j++) {
1013 if ('0' == opt[j]) { /* do nothing */ }
1014 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1015 else {
1016 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1017 "contain 0s and 1s");
1018 VG_(bad_option)(argv[i]);
1019 }
1020 }
1021 }
sewardjde4a1d02002-03-22 01:27:54 +00001022
njn43c799e2003-04-08 00:08:52 +00001023 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001024 VG_(clo_trace_syscalls) = True;
njn43c799e2003-04-08 00:08:52 +00001025 else if (VG_CLO_STREQ(argv[i], "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001026 VG_(clo_trace_syscalls) = False;
1027
njn43c799e2003-04-08 00:08:52 +00001028 else if (VG_CLO_STREQ(argv[i], "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001029 VG_(clo_trace_signals) = True;
njn43c799e2003-04-08 00:08:52 +00001030 else if (VG_CLO_STREQ(argv[i], "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001031 VG_(clo_trace_signals) = False;
1032
njn43c799e2003-04-08 00:08:52 +00001033 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001034 VG_(clo_trace_symtab) = True;
njn43c799e2003-04-08 00:08:52 +00001035 else if (VG_CLO_STREQ(argv[i], "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001036 VG_(clo_trace_symtab) = False;
1037
njn43c799e2003-04-08 00:08:52 +00001038 else if (VG_CLO_STREQ(argv[i], "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001039 VG_(clo_trace_sched) = True;
njn43c799e2003-04-08 00:08:52 +00001040 else if (VG_CLO_STREQ(argv[i], "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001041 VG_(clo_trace_sched) = False;
1042
njn43c799e2003-04-08 00:08:52 +00001043 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001044 VG_(clo_trace_pthread_level) = 0;
njn43c799e2003-04-08 00:08:52 +00001045 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001046 VG_(clo_trace_pthread_level) = 1;
njn43c799e2003-04-08 00:08:52 +00001047 else if (VG_CLO_STREQ(argv[i], "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001048 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001049
njn43c799e2003-04-08 00:08:52 +00001050 else if (VG_CLO_STREQN(14, argv[i], "--weird-hacks="))
sewardj8d365b52002-05-12 10:52:16 +00001051 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +00001052
njn43c799e2003-04-08 00:08:52 +00001053 else if (VG_CLO_STREQN(13, argv[i], "--stop-after="))
sewardjde4a1d02002-03-22 01:27:54 +00001054 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
1055
njn43c799e2003-04-08 00:08:52 +00001056 else if (VG_CLO_STREQN(13, argv[i], "--dump-error="))
sewardjde4a1d02002-03-22 01:27:54 +00001057 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
1058
njn43c799e2003-04-08 00:08:52 +00001059 else if (VG_CLO_STREQN(14, argv[i], "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001060 /* Make sure it's sane. */
1061 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
1062 if (VG_(clo_backtrace_size) < 2)
1063 VG_(clo_backtrace_size) = 2;
1064 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1065 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1066 }
1067
njn25e49d8e72002-09-23 09:36:25 +00001068 else if (VG_(needs).command_line_options) {
1069 Bool ok = SK_(process_cmd_line_option)(argv[i]);
1070 if (!ok)
1071 usage();
1072 }
sewardjde4a1d02002-03-22 01:27:54 +00001073 else
njn25e49d8e72002-09-23 09:36:25 +00001074 usage();
sewardjde4a1d02002-03-22 01:27:54 +00001075 }
1076
1077# undef ISSPACE
sewardjde4a1d02002-03-22 01:27:54 +00001078
njnf9ebf672003-05-12 21:41:30 +00001079 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001080 VG_(clo_verbosity) = 0;
1081
1082 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1083 VG_(message)(Vg_UserMsg, "");
1084 VG_(message)(Vg_UserMsg,
1085 "--gdb-attach=yes conflicts with --trace-children=yes");
1086 VG_(message)(Vg_UserMsg,
1087 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001088 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001089 }
1090
sewardj4cf05692002-10-27 20:28:29 +00001091 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1092 should be connected to whatever sink has been selected, and we
1093 indiscriminately chuck stuff into it without worrying what the
1094 nature of it is. Oh the wonder of Unix streams. */
1095
1096 /* So far we should be still attached to stderr, so we can show on
1097 the terminal any problems to do with processing command line
1098 opts. */
1099 vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
sewardj73cf3bc2002-11-03 03:20:15 +00001100 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001101
1102 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001103
sewardj4cf05692002-10-27 20:28:29 +00001104 case VgLogTo_Fd:
1105 vg_assert(VG_(clo_logfile_name) == NULL);
1106 VG_(clo_logfile_fd) = eventually_logfile_fd;
1107 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001108
sewardj4cf05692002-10-27 20:28:29 +00001109 case VgLogTo_File: {
1110 Char logfilename[1000];
1111 vg_assert(VG_(clo_logfile_name) != NULL);
1112 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1113 VG_(sprintf)(logfilename, "%s.pid%d",
1114 VG_(clo_logfile_name), VG_(getpid)() );
1115 eventually_logfile_fd
1116 = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY,
1117 VKI_S_IRUSR|VKI_S_IWUSR);
1118 if (eventually_logfile_fd != -1) {
1119 VG_(clo_logfile_fd) = eventually_logfile_fd;
1120 } else {
1121 VG_(message)(Vg_UserMsg,
1122 "Can't create/open log file `%s.pid%d'; giving up!",
1123 VG_(clo_logfile_name), VG_(getpid)());
1124 VG_(bad_option)(
1125 "--logfile=<file> didn't work out for some reason.");
1126 }
1127 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001128 }
1129
1130 case VgLogTo_Socket: {
1131 vg_assert(VG_(clo_logfile_name) != NULL);
1132 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1133 eventually_logfile_fd
1134 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1135 if (eventually_logfile_fd == -1) {
1136 VG_(message)(Vg_UserMsg,
1137 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1138 VG_(message)(Vg_UserMsg,
1139 "of `%s'; giving up!", VG_(clo_logfile_name) );
1140 VG_(bad_option)(
1141 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001142 }
sewardj73cf3bc2002-11-03 03:20:15 +00001143 if (eventually_logfile_fd == -2) {
1144 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001145 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001146 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001147 VG_(message)(Vg_UserMsg,
1148 "Log messages will sent to stderr instead." );
1149 VG_(message)(Vg_UserMsg,
1150 "" );
1151 /* We don't change anything here. */
1152 } else {
1153 vg_assert(eventually_logfile_fd > 0);
1154 VG_(clo_logfile_fd) = eventually_logfile_fd;
1155 VG_(logging_to_filedes) = False;
1156 }
sewardj73cf3bc2002-11-03 03:20:15 +00001157 break;
1158 }
1159
sewardj4cf05692002-10-27 20:28:29 +00001160 }
1161
1162 /* Ok, the logging sink is running now. Print a suitable preamble.
1163 If logging to file or a socket, write details of parent PID and
1164 command line args, to help people trying to interpret the
1165 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001166
sewardj83adf412002-05-01 01:25:45 +00001167 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001168 /* Skin details */
1169 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1170 VG_(details).name,
1171 NULL == VG_(details).version ? "" : "-",
1172 NULL == VG_(details).version
1173 ? (Char*)"" : VG_(details).version,
1174 VG_(details).description);
1175 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001176
njnd04b7c62002-10-03 14:05:52 +00001177 /* Core details */
1178 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001179 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001180 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001181 VG_(message)(Vg_UserMsg,
njn0e1b5142003-04-15 14:58:06 +00001182 "Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001183 }
1184
sewardj4cf05692002-10-27 20:28:29 +00001185 if (VG_(clo_log_to) != VgLogTo_Fd) {
1186 VG_(message)(Vg_UserMsg, "");
1187 VG_(message)(Vg_UserMsg,
1188 "My PID = %d, parent PID = %d. Prog and args are:",
1189 VG_(getpid)(), VG_(getppid)() );
1190 for (i = 0; i < VG_(client_argc); i++)
1191 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1192 }
1193
sewardjde4a1d02002-03-22 01:27:54 +00001194 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001195 if (VG_(clo_log_to) != VgLogTo_Fd)
1196 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001197 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1198 for (i = 0; i < argc; i++) {
1199 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1200 }
1201 }
1202
njn25e49d8e72002-09-23 09:36:25 +00001203 if (VG_(clo_n_suppressions) == 0 &&
1204 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001205 config_error("No error-suppression files were specified.");
1206 }
sewardj4cf05692002-10-27 20:28:29 +00001207
njn6a230532003-07-21 10:38:23 +00001208 if (VG_(clo_gen_suppressions) &&
1209 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1210 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1211 " as it doesn't generate errors.");
1212 }
1213
sewardjde4a1d02002-03-22 01:27:54 +00001214}
1215
sewardjde4a1d02002-03-22 01:27:54 +00001216/* ---------------------------------------------------------------------
1217 Copying to/from m_state_static.
1218 ------------------------------------------------------------------ */
1219
sewardjb91ae7f2003-04-29 23:50:00 +00001220/* See comment about this in vg_include.h. Change only with
1221 great care.
1222*/
1223__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001224UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1225 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001226 + 1 /* %eflags */
1227 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001228 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001229 ];
1230
sewardjfa492d42002-12-08 18:20:01 +00001231UInt VG_(insertDflag)(UInt eflags, Int d)
1232{
1233 vg_assert(d == 1 || d == -1);
1234 eflags &= ~EFlagD;
1235
1236 if (d < 0)
1237 eflags |= EFlagD;
1238
1239 return eflags;
1240}
1241
1242Int VG_(extractDflag)(UInt eflags)
1243{
1244 Int ret;
1245
1246 if (eflags & EFlagD)
1247 ret = -1;
1248 else
1249 ret = 1;
1250
1251 return ret;
1252}
1253
sewardjde4a1d02002-03-22 01:27:54 +00001254void VG_(copy_baseBlock_to_m_state_static) ( void )
1255{
1256 Int i;
sewardj92a59562002-09-30 00:53:10 +00001257 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1258 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1259 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1260 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1261 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1262 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001263
sewardj92a59562002-09-30 00:53:10 +00001264 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1265 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1266 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1267 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1268 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1269 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1270 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1271 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1272
sewardjb91ae7f2003-04-29 23:50:00 +00001273 VG_(m_state_static)[56/4]
1274 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1275 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001276 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001277
sewardjb91ae7f2003-04-29 23:50:00 +00001278 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001279 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001280 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001281}
1282
1283
1284void VG_(copy_m_state_static_to_baseBlock) ( void )
1285{
1286 Int i;
sewardj92a59562002-09-30 00:53:10 +00001287 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1288 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1289 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1290 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1291 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1292 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001293
sewardj92a59562002-09-30 00:53:10 +00001294 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1295 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1296 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1297 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1298 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1299 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1300 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1301 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1302
sewardjb91ae7f2003-04-29 23:50:00 +00001303 VG_(baseBlock)[VGOFF_(m_eflags)]
1304 = VG_(m_state_static)[56/4] & ~EFlagD;
1305 VG_(baseBlock)[VGOFF_(m_dflag)]
1306 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001307
sewardj92a59562002-09-30 00:53:10 +00001308 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001309
sewardjb91ae7f2003-04-29 23:50:00 +00001310 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1311 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001312 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001313}
1314
njn25e49d8e72002-09-23 09:36:25 +00001315Addr VG_(get_stack_pointer) ( void )
1316{
1317 return VG_(baseBlock)[VGOFF_(m_esp)];
1318}
1319
1320/* Some random tests needed for leak checking */
1321
1322Bool VG_(within_stack)(Addr a)
1323{
1324 if (a >= ((Addr)(&VG_(stack)))
1325 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1326 return True;
1327 else
1328 return False;
1329}
1330
sewardjecf8e102003-07-12 12:11:39 +00001331Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001332{
1333 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001334 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001335 return True;
sewardjecf8e102003-07-12 12:11:39 +00001336
1337 if (a >= ((Addr)(&VG_(threads)[0]))
1338 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1339 return True;
1340
1341 return False;
njn25e49d8e72002-09-23 09:36:25 +00001342}
sewardjde4a1d02002-03-22 01:27:54 +00001343
1344/* ---------------------------------------------------------------------
1345 Show accumulated counts.
1346 ------------------------------------------------------------------ */
1347
njn25e49d8e72002-09-23 09:36:25 +00001348static __inline__ Int safe_idiv(Int a, Int b)
1349{
1350 return (b == 0 ? 0 : a / b);
1351}
1352
sewardjde4a1d02002-03-22 01:27:54 +00001353static void vg_show_counts ( void )
1354{
1355 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001356 " TT/TC: %d tc sectors discarded.",
1357 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001358 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001359 " %d chainings, %d unchainings.",
1360 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1361 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001362 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001363 VG_(overall_in_count),
1364 VG_(overall_in_osize),
1365 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001366 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1367 VG_(message)(Vg_DebugMsg,
1368 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001369 VG_(overall_out_count),
1370 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001371 VG_(overall_out_tsize),
1372 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001373 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001374 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001375 VG_(bbs_done),
1376 VG_(unchained_jumps_done),
1377 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1378 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1379 );
1380
1381 VG_(message)(Vg_DebugMsg,
1382 " %d/%d major/minor sched events. %d tt_fast misses.",
1383 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001384 VG_(num_scheduling_events_MINOR),
1385 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001386
sewardjde4a1d02002-03-22 01:27:54 +00001387 VG_(message)(Vg_DebugMsg,
1388 "reg-alloc: %d t-req-spill, "
1389 "%d+%d orig+spill uis, %d total-reg-r.",
1390 VG_(translations_needing_spill),
1391 VG_(uinstrs_prealloc),
1392 VG_(uinstrs_spill),
1393 VG_(total_reg_rank) );
1394 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001395 " sanity: %d cheap, %d expensive checks.",
1396 VG_(sanity_fast_count),
1397 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001398 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001399}
1400
1401
1402/* ---------------------------------------------------------------------
1403 Main!
1404 ------------------------------------------------------------------ */
1405
1406/* Where we jump to once Valgrind has got control, and the real
1407 machine's state has been copied to the m_state_static. */
1408
1409void VG_(main) ( void )
1410{
sewardj2e93c502002-04-12 11:12:52 +00001411 Int i;
1412 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001413 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001414
njn0c7a5b52003-04-30 09:00:33 +00001415 if (0) {
1416 if (VG_(have_ssestate))
1417 VG_(printf)("Looks like a SSE-capable CPU\n");
1418 else
1419 VG_(printf)("Looks like a MMX-only CPU\n");
1420 }
sewardjb91ae7f2003-04-29 23:50:00 +00001421
njn27f1a382002-11-08 15:48:16 +00001422 /* Check skin and core versions are compatible */
1423 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1424 VG_(printf)("Error:\n"
1425 " Skin and core interface versions do not match.\n"
1426 " Interface version used by core is: %d.%d\n"
1427 " Interface version used by skin is: %d.%d\n"
1428 " The major version numbers must match.\n",
1429 VG_CORE_INTERFACE_MAJOR_VERSION,
1430 VG_CORE_INTERFACE_MINOR_VERSION,
1431 VG_(skin_interface_major_version),
1432 VG_(skin_interface_minor_version));
1433 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1434 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1435 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1436 else
1437 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1438 VG_(printf)(" Aborting, sorry.\n");
1439 VG_(exit)(1);
1440 }
1441
sewardjde4a1d02002-03-22 01:27:54 +00001442 /* Set up our stack sanity-check words. */
1443 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001444 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1445 VG_(stack)[VG_STACK_SIZE_W-1-i]
1446 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001447 }
1448
njn3e884182003-04-15 13:03:23 +00001449 /* Read /proc/self/maps into a buffer. Must be before:
1450 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1451 superblocks are not erroneously identified as being owned by the
1452 client, which would be bad.
1453 - init_memory(): that's where the buffer is parsed
1454 - init_tt_tc(): so the anonymous mmaps for the translation table and
1455 translation cache aren't identified as part of the client, which would
1456 waste > 20M of virtual address space, and be bad.
1457 */
1458 VG_(read_procselfmaps_contents)();
1459
sewardj1c1b1162003-02-23 01:25:51 +00001460 /* Hook to delay things long enough so we can get the pid and
1461 attach GDB in another shell. */
1462 if (0) {
1463 Int p, q;
1464 VG_(printf)("pid=%d\n", VG_(getpid)());
1465 for (p = 0; p < 50000; p++)
1466 for (q = 0; q < 50000; q++) ;
1467 }
1468
njn25e49d8e72002-09-23 09:36:25 +00001469 /* Setup stuff that depends on the skin. Must be before:
1470 - vg_init_baseBlock(): to register helpers
1471 - process_cmd_line_options(): to register skin name and description,
1472 and turn on/off 'command_line_options' need
1473 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001474 */
njn810086f2002-11-14 12:42:47 +00001475 SK_(pre_clo_init)();
1476 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001477
njncc7bb472002-10-14 09:25:19 +00001478 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001479 process_cmd_line_options();
1480
njn3e884182003-04-15 13:03:23 +00001481 /* Do post command-line processing initialisation. Must be before:
1482 - vg_init_baseBlock(): to register any more helpers
1483 */
njncc7bb472002-10-14 09:25:19 +00001484 SK_(post_clo_init)();
1485
njn3e884182003-04-15 13:03:23 +00001486 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001487 vg_init_baseBlock();
1488
sewardj018f7622002-05-15 21:13:39 +00001489 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001490 baseBlock into VG_(threads)[1]. Must be before:
1491 - VG_(sigstartup_actions)()
1492 */
sewardj018f7622002-05-15 21:13:39 +00001493 VG_(scheduler_init)();
1494
1495 /* Initialise the signal handling subsystem, temporarily parking
1496 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001497 VG_(sigstartup_actions)();
1498
sewardj018f7622002-05-15 21:13:39 +00001499 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001500 if (VG_(clo_profile))
1501 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001502
sewardj5f07b662002-04-23 16:52:51 +00001503 /* Start calibration of our RDTSC-based clock. */
1504 VG_(start_rdtsc_calibration)();
1505
njn3e884182003-04-15 13:03:23 +00001506 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001507 VGP_PUSHCC(VgpInitMem);
1508 VG_(init_memory)();
1509 VGP_POPCC(VgpInitMem);
1510
1511 /* Read the list of errors to suppress. This should be found in
1512 the file specified by vg_clo_suppressions. */
1513 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1514 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001515
sewardj5f07b662002-04-23 16:52:51 +00001516 /* End calibration of our RDTSC-based clock, leaving it as long as
1517 we can. */
1518 VG_(end_rdtsc_calibration)();
1519
njn3e884182003-04-15 13:03:23 +00001520 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001521 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001522
1523 if (VG_(clo_verbosity) == 1) {
1524 VG_(message)(Vg_UserMsg,
1525 "For more details, rerun with: -v");
1526 }
1527
sewardj25c7c3a2003-07-10 00:17:58 +00001528 /* Force a read of the debug info so that we can look for
1529 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001530 VG_(setup_code_redirect_table)();
1531
sewardjde4a1d02002-03-22 01:27:54 +00001532 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1533 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001534 if (VG_(clo_verbosity) > 0)
1535 VG_(message)(Vg_UserMsg, "");
1536
1537 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001538
sewardj018f7622002-05-15 21:13:39 +00001539 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001540 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001541 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001542 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001543 VGP_POPCC(VgpSched);
1544 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001545
1546 if (VG_(clo_verbosity) > 0)
1547 VG_(message)(Vg_UserMsg, "");
1548
sewardj2e93c502002-04-12 11:12:52 +00001549 if (src == VgSrc_Deadlock) {
1550 VG_(message)(Vg_UserMsg,
1551 "Warning: pthread scheduler exited due to deadlock");
1552 }
1553
njn25e49d8e72002-09-23 09:36:25 +00001554 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001555 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001556
njn7d9f94d2003-04-22 21:41:40 +00001557 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001558
sewardj0c3b53f2002-05-01 01:58:35 +00001559 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001560
1561 if (VG_(clo_verbosity) > 1)
1562 vg_show_counts();
1563
sewardjc0d8f682002-11-30 00:49:43 +00001564 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001565 VG_(print_UInstr_histogram)();
1566
sewardjde4a1d02002-03-22 01:27:54 +00001567 if (0) {
1568 VG_(message)(Vg_DebugMsg, "");
1569 VG_(message)(Vg_DebugMsg,
1570 "------ Valgrind's internal memory use stats follow ------" );
1571 VG_(mallocSanityCheckAll)();
1572 VG_(show_all_arena_stats)();
1573 VG_(message)(Vg_DebugMsg,
1574 "------ Valgrind's ExeContext management stats follow ------" );
1575 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001576 }
1577
njn25e49d8e72002-09-23 09:36:25 +00001578 if (VG_(clo_profile))
1579 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001580
1581 VG_(shutdown_logging)();
1582
sewardj3e1eb1f2002-05-18 13:14:17 +00001583 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1584 processes don't get traced into. Also mess up $libdir/valgrind
1585 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001586 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1587 pointless when we are just about to VgSrc_ExitSyscall. So don't
1588 bother in that case. */
1589 if ((!VG_(clo_trace_children))
1590 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001591 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1592 VG_(getenv)("LD_PRELOAD"),
1593 VG_(getenv)("LD_LIBRARY_PATH")
1594 );
sewardjde4a1d02002-03-22 01:27:54 +00001595 }
1596
sewardj7e87e382002-05-03 19:09:05 +00001597 /* Decide how to exit. This depends on what the scheduler
1598 returned. */
1599 switch (src) {
1600 case VgSrc_ExitSyscall: /* the normal way out */
1601 vg_assert(VG_(last_run_tid) > 0
1602 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001603 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001604 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001605 /* The thread's %EBX at the time it did __NR_exit() will hold
1606 the arg to __NR_exit(), so we just do __NR_exit() with
1607 that arg. */
1608 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001609 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001610 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001611 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001612
sewardj7e87e382002-05-03 19:09:05 +00001613 case VgSrc_Deadlock:
1614 /* Just exit now. No point in continuing. */
1615 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001616 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001617 break;
1618
1619 case VgSrc_BbsDone:
1620 /* Tricky; we have to try and switch back to the real CPU.
1621 This is all very dodgy and won't work at all in the
1622 presence of threads, or if the client happened to be
1623 running a signal handler. */
1624 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001625 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001626 VG_(load_thread_state)(1 /* root thread */ );
1627 VG_(copy_baseBlock_to_m_state_static)();
1628
1629 /* This pushes a return address on the simulator's stack,
1630 which is abandoned. We call vg_sigshutdown_actions() at
1631 the end of vg_switch_to_real_CPU(), so as to ensure that
1632 the original stack and machine state is restored before
1633 the real signal mechanism is restored. */
1634 VG_(switch_to_real_CPU)();
1635
1636 default:
njne427a662002-10-02 11:08:25 +00001637 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001638 }
sewardjde4a1d02002-03-22 01:27:54 +00001639}
1640
1641
1642/* Debugging thing .. can be called from assembly with OYNK macro. */
1643void VG_(oynk) ( Int n )
1644{
1645 OINK(n);
1646}
1647
1648
1649/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1650 "valgrinq.so", which doesn't do anything. This is used to avoid
1651 tracing into child processes. To make this work the build system
1652 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001653
njn25e49d8e72002-09-23 09:36:25 +00001654 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1655 without it, child processes try to find valgrind.so symbols in the
1656 skin .so.
1657
sewardj78e25c92002-05-20 23:38:33 +00001658 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1659 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1660 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001661*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001662void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1663 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001664{
njn42e23f22003-05-05 12:47:25 +00001665 Char* vg_prel = NULL;
1666 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001667 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001668 Char* p;
1669 Char* coredir_first;
1670 Char* coredir_last;
1671 Int coredir_len;
1672 Int i;
1673 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001674
njn42e23f22003-05-05 12:47:25 +00001675#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001676
njn42e23f22003-05-05 12:47:25 +00001677 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001678
njn42e23f22003-05-05 12:47:25 +00001679 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1680
njnc2f5bb02003-07-23 09:40:50 +00001681 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1682 LD_LIBRARY_PATH = "<coredir>:Y" */
1683
njn42e23f22003-05-05 12:47:25 +00001684 /* Setting up, finding things */
1685
1686 /* LD_PRELOAD: Search for "valgrind.so" */
1687 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1688
1689 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001690 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001691 if (NULL == vg_prel) {
1692 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001693 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001694 }
1695
njnc2f5bb02003-07-23 09:40:50 +00001696 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001697 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001698
njn42e23f22003-05-05 12:47:25 +00001699 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1700 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1701 coredir_first = p+1;
1702 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001703 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001704
1705 /* LD_PRELOAD: find "vgskin_foo.so" */
1706 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1707 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001708
njnc2f5bb02003-07-23 09:40:50 +00001709 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001710 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001711 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1712 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001713 *coredir_last = '/'; /* Undo zero-termination */
1714
1715 /* Changing things */
1716
1717 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1718 if (vg_prel[7] != 'd') MUTANCY(6);
1719 vg_prel[7] = 'q';
1720
njnc2f5bb02003-07-23 09:40:50 +00001721 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1722 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1723 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001724 while (*p != ':' && p >= ld_preload_str) {
1725 *p = ' ';
1726 p--;
njn25e49d8e72002-09-23 09:36:25 +00001727 }
njnc2f5bb02003-07-23 09:40:50 +00001728 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1729 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001730 p = sk_prel;
1731 while (*p != ':' && *p != '\0') {
1732 *p = ' ';
1733 p++;
1734 }
1735 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001736
njnc2f5bb02003-07-23 09:40:50 +00001737 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001738 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001739 coredir2[i] = ' ';
njn42e23f22003-05-05 12:47:25 +00001740
1741 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001742
sewardj78e25c92002-05-20 23:38:33 +00001743 return;
1744
njn42e23f22003-05-05 12:47:25 +00001745
1746mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001747 VG_(printf)(
1748 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1749 " what = %d\n"
1750 " ld_preload_str = `%s'\n"
1751 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001752 " vg_prel = `%s'\n"
1753 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001754 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001755 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001756 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001757 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001758 );
sewardjc26b4482002-07-13 12:20:35 +00001759 VG_(printf)(
1760 "\n"
1761 "Note that this is often caused by mis-installation of valgrind.\n"
1762 "Correct installation procedure is:\n"
1763 " ./configure --prefix=/install/dir\n"
1764 " make install\n"
1765 "And then use /install/dir/bin/valgrind\n"
1766 "Moving the installation directory elsewhere after 'make install'\n"
1767 "will cause the above error. Hand-editing the paths in the shell\n"
1768 "scripts is also likely to cause problems.\n"
1769 "\n"
1770 );
njne427a662002-10-02 11:08:25 +00001771 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001772}
1773
sewardj3e1eb1f2002-05-18 13:14:17 +00001774
sewardjde4a1d02002-03-22 01:27:54 +00001775/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1776 it to attach to this process. Called if the user requests this
1777 service after an error has been shown, so she can poke around and
1778 look at parameters, memory, etc. You can't meaningfully get GDB to
1779 continue the program, though; to continue, quit GDB. */
1780extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1781{
sewardje6a25242002-04-21 22:03:07 +00001782 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001783 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001784
njn9315df32003-04-16 20:50:50 +00001785 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001786 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001787 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1788 res = VG_(system)(buf);
1789 if (res == 0) {
1790 VG_(message)(Vg_UserMsg, "");
1791 VG_(message)(Vg_UserMsg,
1792 "GDB has detached. Valgrind regains control. We continue.");
1793 } else {
1794 VG_(message)(Vg_UserMsg, "Apparently failed!");
1795 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001796 }
sewardjde4a1d02002-03-22 01:27:54 +00001797}
1798
1799
1800/* Print some helpful-ish text about unimplemented things, and give
1801 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001802void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001803{
1804 VG_(message)(Vg_UserMsg, "");
1805 VG_(message)(Vg_UserMsg,
1806 "Valgrind detected that your program requires");
1807 VG_(message)(Vg_UserMsg,
1808 "the following unimplemented functionality:");
1809 VG_(message)(Vg_UserMsg, " %s", msg);
1810 VG_(message)(Vg_UserMsg,
1811 "This may be because the functionality is hard to implement,");
1812 VG_(message)(Vg_UserMsg,
1813 "or because no reasonable program would behave this way,");
1814 VG_(message)(Vg_UserMsg,
1815 "or because nobody has yet needed it. In any case, let me know");
1816 VG_(message)(Vg_UserMsg,
1817 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1818 VG_(message)(Vg_UserMsg,
1819 "");
1820 VG_(message)(Vg_UserMsg,
1821 "Valgrind has to exit now. Sorry. Bye!");
1822 VG_(message)(Vg_UserMsg,
1823 "");
sewardj15a43e12002-04-17 19:35:12 +00001824 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001825 VG_(exit)(1);
1826}
1827
1828
njn25e49d8e72002-09-23 09:36:25 +00001829/* ---------------------------------------------------------------------
1830 Sanity check machinery (permanently engaged).
1831 ------------------------------------------------------------------ */
1832
1833/* A fast sanity check -- suitable for calling circa once per
1834 millisecond. */
1835
1836void VG_(do_sanity_checks) ( Bool force_expensive )
1837{
1838 Int i;
1839
njn37cea302002-09-30 11:24:00 +00001840 VGP_PUSHCC(VgpCoreCheapSanity);
1841
njn25e49d8e72002-09-23 09:36:25 +00001842 if (VG_(sanity_level) < 1) return;
1843
1844 /* --- First do all the tests that we can do quickly. ---*/
1845
1846 VG_(sanity_fast_count)++;
1847
1848 /* Check that we haven't overrun our private stack. */
1849 for (i = 0; i < 10; i++) {
1850 vg_assert(VG_(stack)[i]
1851 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00001852 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
1853 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00001854 }
1855
1856 /* Check stuff pertaining to the memory check system. */
1857
1858 /* Check that nobody has spuriously claimed that the first or
1859 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001860 if (VG_(needs).sanity_checks) {
1861 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001862 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001863 VGP_POPCC(VgpSkinCheapSanity);
1864 }
njn25e49d8e72002-09-23 09:36:25 +00001865
1866 /* --- Now some more expensive checks. ---*/
1867
1868 /* Once every 25 times, check some more expensive stuff. */
1869 if ( force_expensive
1870 || VG_(sanity_level) > 1
1871 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1872
njn37cea302002-09-30 11:24:00 +00001873 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001874 VG_(sanity_slow_count)++;
1875
1876# if 0
1877 { void zzzmemscan(void); zzzmemscan(); }
1878# endif
1879
1880 if ((VG_(sanity_fast_count) % 250) == 0)
1881 VG_(sanity_check_tc_tt)();
1882
1883 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001884 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001885 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001886 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001887 }
1888 /*
1889 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1890 */
njn37cea302002-09-30 11:24:00 +00001891 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001892 }
1893
1894 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001895 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001896 /* Check sanity of the low-level memory manager. Note that bugs
1897 in the client's code can cause this to fail, so we don't do
1898 this check unless specially asked for. And because it's
1899 potentially very expensive. */
1900 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001901 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001902 }
njn37cea302002-09-30 11:24:00 +00001903 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001904}
sewardjde4a1d02002-03-22 01:27:54 +00001905/*--------------------------------------------------------------------*/
1906/*--- end vg_main.c ---*/
1907/*--------------------------------------------------------------------*/