blob: a8a8b60656a7a7bac079720907d6a410c12748a1 [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
njnfa1016e2003-09-25 17:54:11 +0000747 VG_(parse_procselfmaps)( vg_findstack_callback );
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]);
njn6c846552003-09-16 07:41:43 +00001062 if (VG_(clo_backtrace_size) < 1)
1063 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001064 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, "");
njn86dc2bc2003-09-09 07:26:21 +00001197 VG_(message)(Vg_UserMsg, "Command line");
1198 for (i = 0; i < VG_(client_argc); i++)
1199 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1200
sewardjde4a1d02002-03-22 01:27:54 +00001201 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1202 for (i = 0; i < argc; i++) {
1203 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1204 }
1205 }
1206
njn25e49d8e72002-09-23 09:36:25 +00001207 if (VG_(clo_n_suppressions) == 0 &&
1208 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
sewardjde4a1d02002-03-22 01:27:54 +00001209 config_error("No error-suppression files were specified.");
1210 }
sewardj4cf05692002-10-27 20:28:29 +00001211
njn6a230532003-07-21 10:38:23 +00001212 if (VG_(clo_gen_suppressions) &&
1213 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
1214 config_error("Can't use --gen-suppressions=yes with this skin,\n"
1215 " as it doesn't generate errors.");
1216 }
1217
sewardjde4a1d02002-03-22 01:27:54 +00001218}
1219
sewardjde4a1d02002-03-22 01:27:54 +00001220/* ---------------------------------------------------------------------
1221 Copying to/from m_state_static.
1222 ------------------------------------------------------------------ */
1223
sewardjb91ae7f2003-04-29 23:50:00 +00001224/* See comment about this in vg_include.h. Change only with
1225 great care.
1226*/
1227__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00001228UInt VG_(m_state_static) [6 /* segment regs, Intel order */
1229 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00001230 + 1 /* %eflags */
1231 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00001232 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00001233 ];
1234
sewardjfa492d42002-12-08 18:20:01 +00001235UInt VG_(insertDflag)(UInt eflags, Int d)
1236{
1237 vg_assert(d == 1 || d == -1);
1238 eflags &= ~EFlagD;
1239
1240 if (d < 0)
1241 eflags |= EFlagD;
1242
1243 return eflags;
1244}
1245
1246Int VG_(extractDflag)(UInt eflags)
1247{
1248 Int ret;
1249
1250 if (eflags & EFlagD)
1251 ret = -1;
1252 else
1253 ret = 1;
1254
1255 return ret;
1256}
1257
sewardjde4a1d02002-03-22 01:27:54 +00001258void VG_(copy_baseBlock_to_m_state_static) ( void )
1259{
1260 Int i;
sewardj92a59562002-09-30 00:53:10 +00001261 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
1262 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
1263 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
1264 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
1265 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
1266 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00001267
sewardj92a59562002-09-30 00:53:10 +00001268 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1269 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1270 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1271 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1272 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1273 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1274 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1275 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1276
sewardjb91ae7f2003-04-29 23:50:00 +00001277 VG_(m_state_static)[56/4]
1278 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
1279 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00001280 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00001281
sewardjb91ae7f2003-04-29 23:50:00 +00001282 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00001283 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00001284 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00001285}
1286
1287
1288void VG_(copy_m_state_static_to_baseBlock) ( void )
1289{
1290 Int i;
sewardj92a59562002-09-30 00:53:10 +00001291 VG_(baseBlock)[VGOFF_(m_cs)] = VG_(m_state_static)[ 0/4];
1292 VG_(baseBlock)[VGOFF_(m_ss)] = VG_(m_state_static)[ 4/4];
1293 VG_(baseBlock)[VGOFF_(m_ds)] = VG_(m_state_static)[ 8/4];
1294 VG_(baseBlock)[VGOFF_(m_es)] = VG_(m_state_static)[12/4];
1295 VG_(baseBlock)[VGOFF_(m_fs)] = VG_(m_state_static)[16/4];
1296 VG_(baseBlock)[VGOFF_(m_gs)] = VG_(m_state_static)[20/4];
sewardjde4a1d02002-03-22 01:27:54 +00001297
sewardj92a59562002-09-30 00:53:10 +00001298 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[24/4];
1299 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[28/4];
1300 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[32/4];
1301 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[36/4];
1302 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[40/4];
1303 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[44/4];
1304 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[48/4];
1305 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[52/4];
1306
sewardjb91ae7f2003-04-29 23:50:00 +00001307 VG_(baseBlock)[VGOFF_(m_eflags)]
1308 = VG_(m_state_static)[56/4] & ~EFlagD;
1309 VG_(baseBlock)[VGOFF_(m_dflag)]
1310 = VG_(extractDflag)(VG_(m_state_static)[56/4]);
sewardjfa492d42002-12-08 18:20:01 +00001311
sewardj92a59562002-09-30 00:53:10 +00001312 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[60/4];
sewardjde4a1d02002-03-22 01:27:54 +00001313
sewardjb91ae7f2003-04-29 23:50:00 +00001314 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1315 VG_(baseBlock)[VGOFF_(m_ssestate) + i]
sewardj92a59562002-09-30 00:53:10 +00001316 = VG_(m_state_static)[64/4 + i];
sewardjde4a1d02002-03-22 01:27:54 +00001317}
1318
njn25e49d8e72002-09-23 09:36:25 +00001319Addr VG_(get_stack_pointer) ( void )
1320{
1321 return VG_(baseBlock)[VGOFF_(m_esp)];
1322}
1323
1324/* Some random tests needed for leak checking */
1325
1326Bool VG_(within_stack)(Addr a)
1327{
1328 if (a >= ((Addr)(&VG_(stack)))
1329 && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
1330 return True;
1331 else
1332 return False;
1333}
1334
sewardjecf8e102003-07-12 12:11:39 +00001335Bool VG_(within_m_state_static_OR_threads)(Addr a)
njn25e49d8e72002-09-23 09:36:25 +00001336{
1337 if (a >= ((Addr)(&VG_(m_state_static)))
sewardjecf8e102003-07-12 12:11:39 +00001338 && a < ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
njn25e49d8e72002-09-23 09:36:25 +00001339 return True;
sewardjecf8e102003-07-12 12:11:39 +00001340
1341 if (a >= ((Addr)(&VG_(threads)[0]))
1342 && a < ((Addr)(&VG_(threads)[VG_N_THREADS])))
1343 return True;
1344
1345 return False;
njn25e49d8e72002-09-23 09:36:25 +00001346}
sewardjde4a1d02002-03-22 01:27:54 +00001347
1348/* ---------------------------------------------------------------------
1349 Show accumulated counts.
1350 ------------------------------------------------------------------ */
1351
njn25e49d8e72002-09-23 09:36:25 +00001352static __inline__ Int safe_idiv(Int a, Int b)
1353{
1354 return (b == 0 ? 0 : a / b);
1355}
1356
sewardjde4a1d02002-03-22 01:27:54 +00001357static void vg_show_counts ( void )
1358{
1359 VG_(message)(Vg_DebugMsg,
sewardjc0d8f682002-11-30 00:49:43 +00001360 " TT/TC: %d tc sectors discarded.",
1361 VG_(number_of_tc_discards) );
sewardjde4a1d02002-03-22 01:27:54 +00001362 VG_(message)(Vg_DebugMsg,
sewardj22854b92002-11-30 14:00:47 +00001363 " %d chainings, %d unchainings.",
1364 VG_(bb_enchain_count), VG_(bb_dechain_count) );
1365 VG_(message)(Vg_DebugMsg,
njn25e49d8e72002-09-23 09:36:25 +00001366 "translate: new %d (%d -> %d; ratio %d:10)",
sewardjde4a1d02002-03-22 01:27:54 +00001367 VG_(overall_in_count),
1368 VG_(overall_in_osize),
1369 VG_(overall_in_tsize),
njn25e49d8e72002-09-23 09:36:25 +00001370 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
1371 VG_(message)(Vg_DebugMsg,
1372 " discard %d (%d -> %d; ratio %d:10).",
sewardjde4a1d02002-03-22 01:27:54 +00001373 VG_(overall_out_count),
1374 VG_(overall_out_osize),
njn25e49d8e72002-09-23 09:36:25 +00001375 VG_(overall_out_tsize),
1376 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
sewardjde4a1d02002-03-22 01:27:54 +00001377 VG_(message)(Vg_DebugMsg,
njne0205ff2003-04-08 00:56:14 +00001378 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
sewardj22854b92002-11-30 14:00:47 +00001379 VG_(bbs_done),
1380 VG_(unchained_jumps_done),
1381 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
1382 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
1383 );
1384
1385 VG_(message)(Vg_DebugMsg,
1386 " %d/%d major/minor sched events. %d tt_fast misses.",
1387 VG_(num_scheduling_events_MAJOR),
sewardj2e93c502002-04-12 11:12:52 +00001388 VG_(num_scheduling_events_MINOR),
1389 VG_(tt_fast_misses));
sewardj22854b92002-11-30 14:00:47 +00001390
sewardjde4a1d02002-03-22 01:27:54 +00001391 VG_(message)(Vg_DebugMsg,
1392 "reg-alloc: %d t-req-spill, "
1393 "%d+%d orig+spill uis, %d total-reg-r.",
1394 VG_(translations_needing_spill),
1395 VG_(uinstrs_prealloc),
1396 VG_(uinstrs_spill),
1397 VG_(total_reg_rank) );
1398 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001399 " sanity: %d cheap, %d expensive checks.",
1400 VG_(sanity_fast_count),
1401 VG_(sanity_slow_count) );
njn25e49d8e72002-09-23 09:36:25 +00001402 VG_(print_ccall_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001403}
1404
1405
1406/* ---------------------------------------------------------------------
1407 Main!
1408 ------------------------------------------------------------------ */
1409
1410/* Where we jump to once Valgrind has got control, and the real
1411 machine's state has been copied to the m_state_static. */
1412
1413void VG_(main) ( void )
1414{
sewardj2e93c502002-04-12 11:12:52 +00001415 Int i;
1416 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001417 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001418
njn0c7a5b52003-04-30 09:00:33 +00001419 if (0) {
1420 if (VG_(have_ssestate))
1421 VG_(printf)("Looks like a SSE-capable CPU\n");
1422 else
1423 VG_(printf)("Looks like a MMX-only CPU\n");
1424 }
sewardjb91ae7f2003-04-29 23:50:00 +00001425
njn27f1a382002-11-08 15:48:16 +00001426 /* Check skin and core versions are compatible */
1427 if (VG_CORE_INTERFACE_MAJOR_VERSION != VG_(skin_interface_major_version)) {
1428 VG_(printf)("Error:\n"
1429 " Skin and core interface versions do not match.\n"
1430 " Interface version used by core is: %d.%d\n"
1431 " Interface version used by skin is: %d.%d\n"
1432 " The major version numbers must match.\n",
1433 VG_CORE_INTERFACE_MAJOR_VERSION,
1434 VG_CORE_INTERFACE_MINOR_VERSION,
1435 VG_(skin_interface_major_version),
1436 VG_(skin_interface_minor_version));
1437 VG_(printf)(" You need to at least recompile, and possibly update,\n");
1438 if (VG_CORE_INTERFACE_MAJOR_VERSION > VG_(skin_interface_major_version))
1439 VG_(printf)(" your skin to work with this version of Valgrind.\n");
1440 else
1441 VG_(printf)(" your version of Valgrind to work with this skin.\n");
1442 VG_(printf)(" Aborting, sorry.\n");
1443 VG_(exit)(1);
1444 }
1445
sewardjde4a1d02002-03-22 01:27:54 +00001446 /* Set up our stack sanity-check words. */
1447 for (i = 0; i < 10; i++) {
njn6eba4ef2003-05-01 08:06:41 +00001448 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1449 VG_(stack)[VG_STACK_SIZE_W-1-i]
1450 = (UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321;
sewardjde4a1d02002-03-22 01:27:54 +00001451 }
1452
njn3e884182003-04-15 13:03:23 +00001453 /* Read /proc/self/maps into a buffer. Must be before:
1454 - SK_(pre_clo_init)(): so that if it calls VG_(malloc)(), any mmap'd
1455 superblocks are not erroneously identified as being owned by the
1456 client, which would be bad.
1457 - init_memory(): that's where the buffer is parsed
1458 - init_tt_tc(): so the anonymous mmaps for the translation table and
1459 translation cache aren't identified as part of the client, which would
1460 waste > 20M of virtual address space, and be bad.
1461 */
njnfa1016e2003-09-25 17:54:11 +00001462 VG_(read_procselfmaps)();
njn3e884182003-04-15 13:03:23 +00001463
sewardj1c1b1162003-02-23 01:25:51 +00001464 /* Hook to delay things long enough so we can get the pid and
1465 attach GDB in another shell. */
1466 if (0) {
1467 Int p, q;
1468 VG_(printf)("pid=%d\n", VG_(getpid)());
1469 for (p = 0; p < 50000; p++)
1470 for (q = 0; q < 50000; q++) ;
1471 }
1472
njn25e49d8e72002-09-23 09:36:25 +00001473 /* Setup stuff that depends on the skin. Must be before:
1474 - vg_init_baseBlock(): to register helpers
1475 - process_cmd_line_options(): to register skin name and description,
1476 and turn on/off 'command_line_options' need
1477 - init_memory() (to setup memory event trackers).
njn3e884182003-04-15 13:03:23 +00001478 */
njn810086f2002-11-14 12:42:47 +00001479 SK_(pre_clo_init)();
1480 VG_(sanity_check_needs)();
njn25e49d8e72002-09-23 09:36:25 +00001481
njncc7bb472002-10-14 09:25:19 +00001482 /* Process Valgrind's command-line opts (from env var VG_ARGS). */
sewardjde4a1d02002-03-22 01:27:54 +00001483 process_cmd_line_options();
1484
njn3e884182003-04-15 13:03:23 +00001485 /* Do post command-line processing initialisation. Must be before:
1486 - vg_init_baseBlock(): to register any more helpers
1487 */
njncc7bb472002-10-14 09:25:19 +00001488 SK_(post_clo_init)();
1489
njn3e884182003-04-15 13:03:23 +00001490 /* Set up baseBlock offsets and copy the saved machine's state into it. */
njncc7bb472002-10-14 09:25:19 +00001491 vg_init_baseBlock();
1492
sewardj018f7622002-05-15 21:13:39 +00001493 /* Initialise the scheduler, and copy the client's state from
njn3e884182003-04-15 13:03:23 +00001494 baseBlock into VG_(threads)[1]. Must be before:
1495 - VG_(sigstartup_actions)()
1496 */
sewardj018f7622002-05-15 21:13:39 +00001497 VG_(scheduler_init)();
1498
1499 /* Initialise the signal handling subsystem, temporarily parking
1500 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001501 VG_(sigstartup_actions)();
1502
sewardj018f7622002-05-15 21:13:39 +00001503 /* Perhaps we're profiling Valgrind? */
njn25e49d8e72002-09-23 09:36:25 +00001504 if (VG_(clo_profile))
1505 VGP_(init_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001506
sewardj5f07b662002-04-23 16:52:51 +00001507 /* Start calibration of our RDTSC-based clock. */
1508 VG_(start_rdtsc_calibration)();
1509
njn3e884182003-04-15 13:03:23 +00001510 /* Parse /proc/self/maps to learn about startup segments. */
njn25e49d8e72002-09-23 09:36:25 +00001511 VGP_PUSHCC(VgpInitMem);
1512 VG_(init_memory)();
1513 VGP_POPCC(VgpInitMem);
1514
1515 /* Read the list of errors to suppress. This should be found in
1516 the file specified by vg_clo_suppressions. */
1517 if (VG_(needs).core_errors || VG_(needs).skin_errors)
1518 VG_(load_suppressions)();
sewardj18d75132002-05-16 11:06:21 +00001519
sewardj5f07b662002-04-23 16:52:51 +00001520 /* End calibration of our RDTSC-based clock, leaving it as long as
1521 we can. */
1522 VG_(end_rdtsc_calibration)();
1523
njn3e884182003-04-15 13:03:23 +00001524 /* Initialise translation table and translation cache. */
sewardj18d75132002-05-16 11:06:21 +00001525 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001526
1527 if (VG_(clo_verbosity) == 1) {
1528 VG_(message)(Vg_UserMsg,
1529 "For more details, rerun with: -v");
1530 }
1531
sewardj25c7c3a2003-07-10 00:17:58 +00001532 /* Force a read of the debug info so that we can look for
1533 glibc entry points to intercept. */
sewardj25c7c3a2003-07-10 00:17:58 +00001534 VG_(setup_code_redirect_table)();
1535
sewardjde4a1d02002-03-22 01:27:54 +00001536 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1537 instrumented-ly. */
sewardjde4a1d02002-03-22 01:27:54 +00001538 if (VG_(clo_verbosity) > 0)
1539 VG_(message)(Vg_UserMsg, "");
1540
1541 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001542
sewardj018f7622002-05-15 21:13:39 +00001543 /* Run! */
njn25e49d8e72002-09-23 09:36:25 +00001544 VG_(running_on_simd_CPU) = True;
sewardj671ff542002-05-07 09:25:30 +00001545 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001546 src = VG_(scheduler)();
njn25e49d8e72002-09-23 09:36:25 +00001547 VGP_POPCC(VgpSched);
1548 VG_(running_on_simd_CPU) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001549
1550 if (VG_(clo_verbosity) > 0)
1551 VG_(message)(Vg_UserMsg, "");
1552
sewardj2e93c502002-04-12 11:12:52 +00001553 if (src == VgSrc_Deadlock) {
1554 VG_(message)(Vg_UserMsg,
1555 "Warning: pthread scheduler exited due to deadlock");
1556 }
1557
njn25e49d8e72002-09-23 09:36:25 +00001558 if (VG_(needs).core_errors || VG_(needs).skin_errors)
sewardjde4a1d02002-03-22 01:27:54 +00001559 VG_(show_all_errors)();
sewardj2e93c502002-04-12 11:12:52 +00001560
njn7d9f94d2003-04-22 21:41:40 +00001561 SK_(fini)( VG_(exitcode) );
njn4f9c9342002-04-29 16:03:24 +00001562
sewardj0c3b53f2002-05-01 01:58:35 +00001563 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001564
1565 if (VG_(clo_verbosity) > 1)
1566 vg_show_counts();
1567
sewardjc0d8f682002-11-30 00:49:43 +00001568 if (VG_(clo_verbosity) > 3)
njn25e49d8e72002-09-23 09:36:25 +00001569 VG_(print_UInstr_histogram)();
1570
sewardjde4a1d02002-03-22 01:27:54 +00001571 if (0) {
1572 VG_(message)(Vg_DebugMsg, "");
1573 VG_(message)(Vg_DebugMsg,
1574 "------ Valgrind's internal memory use stats follow ------" );
1575 VG_(mallocSanityCheckAll)();
1576 VG_(show_all_arena_stats)();
1577 VG_(message)(Vg_DebugMsg,
1578 "------ Valgrind's ExeContext management stats follow ------" );
1579 VG_(show_ExeContext_stats)();
sewardjde4a1d02002-03-22 01:27:54 +00001580 }
1581
njn25e49d8e72002-09-23 09:36:25 +00001582 if (VG_(clo_profile))
1583 VGP_(done_profiling)();
sewardjde4a1d02002-03-22 01:27:54 +00001584
1585 VG_(shutdown_logging)();
1586
sewardj3e1eb1f2002-05-18 13:14:17 +00001587 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1588 processes don't get traced into. Also mess up $libdir/valgrind
1589 so that our libpthread.so disappears from view. */
sewardj44b60432003-04-26 22:29:25 +00001590 /* 26 Apr 03: doing this often causes trouble for no reason, and is
1591 pointless when we are just about to VgSrc_ExitSyscall. So don't
1592 bother in that case. */
1593 if ((!VG_(clo_trace_children))
1594 && src != VgSrc_ExitSyscall) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001595 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1596 VG_(getenv)("LD_PRELOAD"),
1597 VG_(getenv)("LD_LIBRARY_PATH")
1598 );
sewardjde4a1d02002-03-22 01:27:54 +00001599 }
1600
sewardj7e87e382002-05-03 19:09:05 +00001601 /* Decide how to exit. This depends on what the scheduler
1602 returned. */
1603 switch (src) {
1604 case VgSrc_ExitSyscall: /* the normal way out */
1605 vg_assert(VG_(last_run_tid) > 0
1606 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001607 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001608 vg_assert(tst->status == VgTs_Runnable);
njn25e49d8e72002-09-23 09:36:25 +00001609 /* The thread's %EBX at the time it did __NR_exit() will hold
1610 the arg to __NR_exit(), so we just do __NR_exit() with
1611 that arg. */
1612 VG_(exit)( VG_(exitcode) );
sewardj7e87e382002-05-03 19:09:05 +00001613 /* NOT ALIVE HERE! */
njne427a662002-10-02 11:08:25 +00001614 VG_(core_panic)("entered the afterlife in vg_main() -- ExitSyscall");
sewardj7e87e382002-05-03 19:09:05 +00001615 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001616
sewardj7e87e382002-05-03 19:09:05 +00001617 case VgSrc_Deadlock:
1618 /* Just exit now. No point in continuing. */
1619 VG_(exit)(0);
njne427a662002-10-02 11:08:25 +00001620 VG_(core_panic)("entered the afterlife in vg_main() -- Deadlock");
sewardj7e87e382002-05-03 19:09:05 +00001621 break;
1622
1623 case VgSrc_BbsDone:
1624 /* Tricky; we have to try and switch back to the real CPU.
1625 This is all very dodgy and won't work at all in the
1626 presence of threads, or if the client happened to be
1627 running a signal handler. */
1628 /* Prepare to restore state to the real CPU. */
sewardj839299f2003-06-14 11:57:59 +00001629 VG_(sigshutdown_actions)();
sewardj7e87e382002-05-03 19:09:05 +00001630 VG_(load_thread_state)(1 /* root thread */ );
1631 VG_(copy_baseBlock_to_m_state_static)();
1632
1633 /* This pushes a return address on the simulator's stack,
1634 which is abandoned. We call vg_sigshutdown_actions() at
1635 the end of vg_switch_to_real_CPU(), so as to ensure that
1636 the original stack and machine state is restored before
1637 the real signal mechanism is restored. */
1638 VG_(switch_to_real_CPU)();
1639
1640 default:
njne427a662002-10-02 11:08:25 +00001641 VG_(core_panic)("vg_main(): unexpected scheduler return code");
sewardj7e87e382002-05-03 19:09:05 +00001642 }
sewardjde4a1d02002-03-22 01:27:54 +00001643}
1644
1645
1646/* Debugging thing .. can be called from assembly with OYNK macro. */
1647void VG_(oynk) ( Int n )
1648{
1649 OINK(n);
1650}
1651
1652
1653/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1654 "valgrinq.so", which doesn't do anything. This is used to avoid
1655 tracing into child processes. To make this work the build system
1656 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001657
njn25e49d8e72002-09-23 09:36:25 +00001658 Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
1659 without it, child processes try to find valgrind.so symbols in the
1660 skin .so.
1661
sewardj78e25c92002-05-20 23:38:33 +00001662 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1663 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1664 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001665*/
sewardj45b672d2003-07-25 19:58:11 +00001666static void slideleft ( Char* s )
1667{
1668 vg_assert(s && (*s == ' ' || *s == ':'));
1669 while (True) {
1670 s[0] = s[1];
1671 if (s[0] == '\0') break;
1672 s++;
1673 }
1674}
1675
1676
sewardj3e1eb1f2002-05-18 13:14:17 +00001677void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1678 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001679{
njn42e23f22003-05-05 12:47:25 +00001680 Char* vg_prel = NULL;
1681 Char* sk_prel = NULL;
njnc2f5bb02003-07-23 09:40:50 +00001682 Char* coredir2 = NULL;
njn42e23f22003-05-05 12:47:25 +00001683 Char* p;
1684 Char* coredir_first;
1685 Char* coredir_last;
1686 Int coredir_len;
1687 Int i;
1688 Int what;
sewardj3e1eb1f2002-05-18 13:14:17 +00001689
njn42e23f22003-05-05 12:47:25 +00001690#define MUTANCY(n) { what = n; goto mutancy; }
sewardj78e25c92002-05-20 23:38:33 +00001691
njn42e23f22003-05-05 12:47:25 +00001692 if (ld_preload_str == NULL || ld_library_path_str == NULL) MUTANCY(0);
sewardj78e25c92002-05-20 23:38:33 +00001693
njn42e23f22003-05-05 12:47:25 +00001694 /* VG_(printf)("pre:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
1695
njnc2f5bb02003-07-23 09:40:50 +00001696 /* LD_PRELOAD = "<skindir>/vgskin_foo.so:<coredir>/valgrind.so:X"
1697 LD_LIBRARY_PATH = "<coredir>:Y" */
1698
njn42e23f22003-05-05 12:47:25 +00001699 /* Setting up, finding things */
1700
1701 /* LD_PRELOAD: Search for "valgrind.so" */
1702 vg_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1703
1704 /* LD_PRELOAD: if "valgrind.so" not found, has been done before;
njnc2f5bb02003-07-23 09:40:50 +00001705 "valgrinq.so" should be there instead. Then stop. */
njn42e23f22003-05-05 12:47:25 +00001706 if (NULL == vg_prel) {
1707 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL) MUTANCY(1);
sewardjde4a1d02002-03-22 01:27:54 +00001708 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001709 }
1710
njnc2f5bb02003-07-23 09:40:50 +00001711 /* LD_PRELOAD: find start of <coredir> */
njn42e23f22003-05-05 12:47:25 +00001712 p = vg_prel;
njn25e49d8e72002-09-23 09:36:25 +00001713
njn42e23f22003-05-05 12:47:25 +00001714 for (p = vg_prel; *p != ':' && p > ld_preload_str; p--) { }
1715 if (*p != ':') MUTANCY(2); /* skin.so entry must precede it */
1716 coredir_first = p+1;
1717 coredir_last = vg_prel - 1;
njnac2eb792003-07-23 09:22:02 +00001718 coredir_len = coredir_last - coredir_first;
njn42e23f22003-05-05 12:47:25 +00001719
1720 /* LD_PRELOAD: find "vgskin_foo.so" */
1721 sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
1722 if (sk_prel == NULL) MUTANCY(4);
sewardj78e25c92002-05-20 23:38:33 +00001723
njnc2f5bb02003-07-23 09:40:50 +00001724 /* LD_LIBRARY_PATH: find <coredir> */
njn42e23f22003-05-05 12:47:25 +00001725 *coredir_last = '\0'; /* Temporarily zero-terminate coredir */
njnc2f5bb02003-07-23 09:40:50 +00001726 coredir2 = VG_(strstr)(ld_library_path_str, coredir_first);
1727 if (coredir2 == NULL) MUTANCY(5);
njn42e23f22003-05-05 12:47:25 +00001728 *coredir_last = '/'; /* Undo zero-termination */
1729
1730 /* Changing things */
1731
1732 /* LD_PRELOAD: "valgrind.so" --> "valgrinq.so" */
1733 if (vg_prel[7] != 'd') MUTANCY(6);
1734 vg_prel[7] = 'q';
1735
njnc2f5bb02003-07-23 09:40:50 +00001736 /* LD_PRELOAD: "<skindir>/vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1737 " vgskin_foo.so:<coredir>/valgrinq.so:X" */
1738 p = sk_prel-1;
njn42e23f22003-05-05 12:47:25 +00001739 while (*p != ':' && p >= ld_preload_str) {
1740 *p = ' ';
1741 p--;
njn25e49d8e72002-09-23 09:36:25 +00001742 }
njnc2f5bb02003-07-23 09:40:50 +00001743 /* LD_PRELOAD: " vgskin_foo.so:<coredir>/valgrinq.so:X" -->
1744 " :<coredir>/valgrinq.so:X" */
njn42e23f22003-05-05 12:47:25 +00001745 p = sk_prel;
1746 while (*p != ':' && *p != '\0') {
1747 *p = ' ';
1748 p++;
1749 }
1750 if (*p == '\0') MUTANCY(7); /* valgrind.so has disappeared?! */
njn25e49d8e72002-09-23 09:36:25 +00001751
njnc2f5bb02003-07-23 09:40:50 +00001752 /* LD_LIBRARY_PATH: "<coredir>:Y" --> " :Y" */
njn42e23f22003-05-05 12:47:25 +00001753 for (i = 0; i < coredir_len; i++)
njnc2f5bb02003-07-23 09:40:50 +00001754 coredir2[i] = ' ';
sewardj45b672d2003-07-25 19:58:11 +00001755
1756 /* Zap the leading spaces and : in both strings. */
1757 while (ld_preload_str[0] == ' ') slideleft(ld_preload_str);
1758 if (ld_preload_str[0] == ':') slideleft(ld_preload_str);
1759
1760 while (ld_library_path_str[0] == ' ') slideleft(ld_library_path_str);
1761 if (ld_library_path_str[0] == ':') slideleft(ld_library_path_str);
1762
njn42e23f22003-05-05 12:47:25 +00001763 /* VG_(printf)("post:\n%s\n%s\n", ld_preload_str, ld_library_path_str); */
sewardj3e1eb1f2002-05-18 13:14:17 +00001764
sewardj78e25c92002-05-20 23:38:33 +00001765 return;
1766
njn42e23f22003-05-05 12:47:25 +00001767
1768mutancy:
sewardj78e25c92002-05-20 23:38:33 +00001769 VG_(printf)(
1770 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1771 " what = %d\n"
1772 " ld_preload_str = `%s'\n"
1773 " ld_library_path_str = `%s'\n"
njn42e23f22003-05-05 12:47:25 +00001774 " vg_prel = `%s'\n"
1775 " sk_prel = `%s'\n"
njnc2f5bb02003-07-23 09:40:50 +00001776 " coredir2 = `%s'\n"
sewardj78e25c92002-05-20 23:38:33 +00001777 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001778 what, ld_preload_str, ld_library_path_str,
njnc2f5bb02003-07-23 09:40:50 +00001779 vg_prel, sk_prel, coredir2, VG_LIBDIR
sewardj19d81412002-06-03 01:10:40 +00001780 );
sewardjc26b4482002-07-13 12:20:35 +00001781 VG_(printf)(
1782 "\n"
1783 "Note that this is often caused by mis-installation of valgrind.\n"
1784 "Correct installation procedure is:\n"
1785 " ./configure --prefix=/install/dir\n"
1786 " make install\n"
1787 "And then use /install/dir/bin/valgrind\n"
1788 "Moving the installation directory elsewhere after 'make install'\n"
1789 "will cause the above error. Hand-editing the paths in the shell\n"
1790 "scripts is also likely to cause problems.\n"
1791 "\n"
1792 );
njne427a662002-10-02 11:08:25 +00001793 VG_(core_panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001794}
1795
sewardj3e1eb1f2002-05-18 13:14:17 +00001796
sewardjde4a1d02002-03-22 01:27:54 +00001797/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1798 it to attach to this process. Called if the user requests this
1799 service after an error has been shown, so she can poke around and
1800 look at parameters, memory, etc. You can't meaningfully get GDB to
1801 continue the program, though; to continue, quit GDB. */
1802extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1803{
sewardje6a25242002-04-21 22:03:07 +00001804 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001805 UChar buf[100];
njn9315df32003-04-16 20:50:50 +00001806
njn9315df32003-04-16 20:50:50 +00001807 VG_(sprintf)(buf, "%s -nw /proc/%d/exe %d",
sewardj6024b212003-07-13 10:54:33 +00001808 VG_(clo_GDB_path), VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001809 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1810 res = VG_(system)(buf);
1811 if (res == 0) {
1812 VG_(message)(Vg_UserMsg, "");
1813 VG_(message)(Vg_UserMsg,
1814 "GDB has detached. Valgrind regains control. We continue.");
1815 } else {
1816 VG_(message)(Vg_UserMsg, "Apparently failed!");
1817 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001818 }
sewardjde4a1d02002-03-22 01:27:54 +00001819}
1820
1821
1822/* Print some helpful-ish text about unimplemented things, and give
1823 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001824void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001825{
1826 VG_(message)(Vg_UserMsg, "");
1827 VG_(message)(Vg_UserMsg,
1828 "Valgrind detected that your program requires");
1829 VG_(message)(Vg_UserMsg,
1830 "the following unimplemented functionality:");
1831 VG_(message)(Vg_UserMsg, " %s", msg);
1832 VG_(message)(Vg_UserMsg,
1833 "This may be because the functionality is hard to implement,");
1834 VG_(message)(Vg_UserMsg,
1835 "or because no reasonable program would behave this way,");
1836 VG_(message)(Vg_UserMsg,
1837 "or because nobody has yet needed it. In any case, let me know");
1838 VG_(message)(Vg_UserMsg,
1839 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1840 VG_(message)(Vg_UserMsg,
1841 "");
1842 VG_(message)(Vg_UserMsg,
1843 "Valgrind has to exit now. Sorry. Bye!");
1844 VG_(message)(Vg_UserMsg,
1845 "");
sewardj15a43e12002-04-17 19:35:12 +00001846 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001847 VG_(exit)(1);
1848}
1849
1850
njn25e49d8e72002-09-23 09:36:25 +00001851/* ---------------------------------------------------------------------
1852 Sanity check machinery (permanently engaged).
1853 ------------------------------------------------------------------ */
1854
1855/* A fast sanity check -- suitable for calling circa once per
1856 millisecond. */
1857
1858void VG_(do_sanity_checks) ( Bool force_expensive )
1859{
1860 Int i;
1861
njn37cea302002-09-30 11:24:00 +00001862 VGP_PUSHCC(VgpCoreCheapSanity);
1863
njn25e49d8e72002-09-23 09:36:25 +00001864 if (VG_(sanity_level) < 1) return;
1865
1866 /* --- First do all the tests that we can do quickly. ---*/
1867
1868 VG_(sanity_fast_count)++;
1869
1870 /* Check that we haven't overrun our private stack. */
1871 for (i = 0; i < 10; i++) {
1872 vg_assert(VG_(stack)[i]
1873 == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
njn6eba4ef2003-05-01 08:06:41 +00001874 vg_assert(VG_(stack)[VG_STACK_SIZE_W-1-i]
1875 == ((UInt)(&VG_(stack)[VG_STACK_SIZE_W-i-1]) ^ 0xABCD4321));
njn25e49d8e72002-09-23 09:36:25 +00001876 }
1877
1878 /* Check stuff pertaining to the memory check system. */
1879
1880 /* Check that nobody has spuriously claimed that the first or
1881 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00001882 if (VG_(needs).sanity_checks) {
1883 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001884 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001885 VGP_POPCC(VgpSkinCheapSanity);
1886 }
njn25e49d8e72002-09-23 09:36:25 +00001887
1888 /* --- Now some more expensive checks. ---*/
1889
1890 /* Once every 25 times, check some more expensive stuff. */
1891 if ( force_expensive
1892 || VG_(sanity_level) > 1
1893 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
1894
njn37cea302002-09-30 11:24:00 +00001895 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001896 VG_(sanity_slow_count)++;
1897
1898# if 0
1899 { void zzzmemscan(void); zzzmemscan(); }
1900# endif
1901
1902 if ((VG_(sanity_fast_count) % 250) == 0)
1903 VG_(sanity_check_tc_tt)();
1904
1905 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00001906 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001907 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00001908 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001909 }
1910 /*
1911 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
1912 */
njn37cea302002-09-30 11:24:00 +00001913 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001914 }
1915
1916 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00001917 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001918 /* Check sanity of the low-level memory manager. Note that bugs
1919 in the client's code can cause this to fail, so we don't do
1920 this check unless specially asked for. And because it's
1921 potentially very expensive. */
1922 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00001923 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00001924 }
njn37cea302002-09-30 11:24:00 +00001925 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00001926}
sewardjde4a1d02002-03-22 01:27:54 +00001927/*--------------------------------------------------------------------*/
1928/*--- end vg_main.c ---*/
1929/*--------------------------------------------------------------------*/