blob: 29cd3d631e0ba160e388070f6aecced60c867800 [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/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_include.h"
33#include "vg_constants.h"
sewardjde4a1d02002-03-22 01:27:54 +000034
35
36/* ---------------------------------------------------------------------
37 Compute offsets into baseBlock. See comments in vg_include.h.
38 ------------------------------------------------------------------ */
39
40/* The variables storing offsets. */
41
42#define INVALID_OFFSET (-1)
43
44Int VGOFF_(m_eax) = INVALID_OFFSET;
45Int VGOFF_(m_ecx) = INVALID_OFFSET;
46Int VGOFF_(m_edx) = INVALID_OFFSET;
47Int VGOFF_(m_ebx) = INVALID_OFFSET;
48Int VGOFF_(m_esp) = INVALID_OFFSET;
49Int VGOFF_(m_ebp) = INVALID_OFFSET;
50Int VGOFF_(m_esi) = INVALID_OFFSET;
51Int VGOFF_(m_edi) = INVALID_OFFSET;
52Int VGOFF_(m_eflags) = INVALID_OFFSET;
53Int VGOFF_(m_fpustate) = INVALID_OFFSET;
54Int VGOFF_(m_eip) = INVALID_OFFSET;
55Int VGOFF_(spillslots) = INVALID_OFFSET;
56Int VGOFF_(sh_eax) = INVALID_OFFSET;
57Int VGOFF_(sh_ecx) = INVALID_OFFSET;
58Int VGOFF_(sh_edx) = INVALID_OFFSET;
59Int VGOFF_(sh_ebx) = INVALID_OFFSET;
60Int VGOFF_(sh_esp) = INVALID_OFFSET;
61Int VGOFF_(sh_ebp) = INVALID_OFFSET;
62Int VGOFF_(sh_esi) = INVALID_OFFSET;
63Int VGOFF_(sh_edi) = INVALID_OFFSET;
64Int VGOFF_(sh_eflags) = INVALID_OFFSET;
65Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
66Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
67Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
68Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
69Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
70Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
71Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
72Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
73Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
74Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
75Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
76Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
77Int VGOFF_(helper_CLD) = INVALID_OFFSET;
78Int VGOFF_(helper_STD) = INVALID_OFFSET;
79Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
sewardj7d78e782002-06-02 00:04:00 +000080Int VGOFF_(helper_CLC) = INVALID_OFFSET;
81Int VGOFF_(helper_STC) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000082Int VGOFF_(helper_shldl) = INVALID_OFFSET;
83Int VGOFF_(helper_shldw) = INVALID_OFFSET;
84Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
85Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
86Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
87Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
88Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000089Int VGOFF_(helper_bsf) = INVALID_OFFSET;
90Int VGOFF_(helper_bsr) = INVALID_OFFSET;
91Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
92Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +000093Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjfe8a1662002-03-24 11:54:07 +000094Int VGOFF_(helper_DAA) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000095Int VGOFF_(helper_value_check4_fail) = INVALID_OFFSET;
96Int VGOFF_(helper_value_check2_fail) = INVALID_OFFSET;
97Int VGOFF_(helper_value_check1_fail) = INVALID_OFFSET;
98Int VGOFF_(helper_value_check0_fail) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000099Int VGOFF_(helperc_LOADV4) = INVALID_OFFSET;
100Int VGOFF_(helperc_LOADV2) = INVALID_OFFSET;
101Int VGOFF_(helperc_LOADV1) = INVALID_OFFSET;
102Int VGOFF_(helperc_STOREV4) = INVALID_OFFSET;
103Int VGOFF_(helperc_STOREV2) = INVALID_OFFSET;
104Int VGOFF_(helperc_STOREV1) = INVALID_OFFSET;
105Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET;
106Int VGOFF_(fpu_write_check) = INVALID_OFFSET;
107Int VGOFF_(fpu_read_check) = INVALID_OFFSET;
njn4f9c9342002-04-29 16:03:24 +0000108Int VGOFF_(cachesim_log_non_mem_instr) = INVALID_OFFSET;
109Int VGOFF_(cachesim_log_mem_instr) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +0000110
111/* This is the actual defn of baseblock. */
112UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
113
114/* Words. */
115static Int baB_off = 0;
116
117/* Returns the offset, in words. */
118static Int alloc_BaB ( Int words )
119{
120 Int off = baB_off;
121 baB_off += words;
122 if (baB_off >= VG_BASEBLOCK_WORDS)
123 VG_(panic)( "alloc_BaB: baseBlock is too small");
124
125 return off;
126}
127
128/* Allocate 1 word in baseBlock and set it to the given value. */
129static Int alloc_BaB_1_set ( Addr a )
130{
131 Int off = alloc_BaB(1);
132 VG_(baseBlock)[off] = (UInt)a;
133 return off;
134}
135
136
137/* Here we assign actual offsets. It's important to get the most
138 popular referents within 128 bytes of the start, so we can take
139 advantage of short addressing modes relative to %ebp. Popularity
140 of offsets was measured on 22 Feb 02 running a KDE application, and
141 the slots rearranged accordingly, with a 1.5% reduction in total
142 size of translations. */
143
144static void vg_init_baseBlock ( void )
145{
146 baB_off = 0;
147
148 /* Those with offsets under 128 are carefully chosen. */
149
150 /* WORD offsets in this column */
151 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
152 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
153 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
154 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
155 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
156 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
157 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
158 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
159 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
160
161 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
162 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
163 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
164 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
165 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
166 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
167 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
168 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
169 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
170
njn4f9c9342002-04-29 16:03:24 +0000171 /* 17a */
172 VGOFF_(cachesim_log_non_mem_instr)
173 = alloc_BaB_1_set( (Addr) & VG_(cachesim_log_non_mem_instr) );
174 /* 17b */
175 VGOFF_(cachesim_log_mem_instr)
176 = alloc_BaB_1_set( (Addr) & VG_(cachesim_log_mem_instr) );
177
sewardjde4a1d02002-03-22 01:27:54 +0000178 /* 18 */
179 VGOFF_(helper_value_check4_fail)
180 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check4_fail) );
181 /* 19 */
182 VGOFF_(helper_value_check0_fail)
183 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check0_fail) );
184
185 /* 20 */
186 VGOFF_(helperc_STOREV4)
187 = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV4) );
188 /* 21 */
189 VGOFF_(helperc_STOREV1)
190 = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV1) );
191
192 /* 22 */
193 VGOFF_(helperc_LOADV4)
194 = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV4) );
195 /* 23 */
196 VGOFF_(helperc_LOADV1)
197 = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV1) );
198
199 /* 24 */
200 VGOFF_(handle_esp_assignment)
201 = alloc_BaB_1_set( (Addr) & VGM_(handle_esp_assignment) );
202
203 /* 25 */
204 VGOFF_(m_eip) = alloc_BaB(1);
205
206 /* There are currently 24 spill slots */
207 /* 26 .. 49 This overlaps the magic boundary at >= 32 words, but
208 most spills are to low numbered spill slots, so the ones above
209 the boundary don't see much action. */
210 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
211
212 /* These two pushed beyond the boundary because 2-byte transactions
213 are rare. */
214 /* 50 */
215 VGOFF_(helperc_STOREV2)
216 = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV2) );
217 /* 51 */
218 VGOFF_(helperc_LOADV2)
219 = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV2) );
220
221 /* 52 */
222 VGOFF_(fpu_write_check)
223 = alloc_BaB_1_set( (Addr) & VGM_(fpu_write_check) );
224 /* 53 */
225 VGOFF_(fpu_read_check)
226 = alloc_BaB_1_set( (Addr) & VGM_(fpu_read_check) );
227
228 /* Actually I don't think these two are ever used. */
229 /* 54 */
230 VGOFF_(helper_value_check2_fail)
231 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check2_fail) );
232 /* 55 */
233 VGOFF_(helper_value_check1_fail)
234 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check1_fail) );
235
236 /* I gave up counting at this point. Since they're way above the
237 short-amode-boundary, there's no point. */
238
239 VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
240
241 VGOFF_(helper_idiv_64_32)
242 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
243 VGOFF_(helper_div_64_32)
244 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
245 VGOFF_(helper_idiv_32_16)
246 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
247 VGOFF_(helper_div_32_16)
248 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
249 VGOFF_(helper_idiv_16_8)
250 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
251 VGOFF_(helper_div_16_8)
252 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
253
254 VGOFF_(helper_imul_32_64)
255 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
256 VGOFF_(helper_mul_32_64)
257 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
258 VGOFF_(helper_imul_16_32)
259 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
260 VGOFF_(helper_mul_16_32)
261 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
262 VGOFF_(helper_imul_8_16)
263 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
264 VGOFF_(helper_mul_8_16)
265 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
266
267 VGOFF_(helper_CLD)
268 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
269 VGOFF_(helper_STD)
270 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
271 VGOFF_(helper_get_dirflag)
272 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
273
sewardj7d78e782002-06-02 00:04:00 +0000274 VGOFF_(helper_CLC)
275 = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
276 VGOFF_(helper_STC)
277 = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
278
sewardjde4a1d02002-03-22 01:27:54 +0000279 VGOFF_(helper_shldl)
280 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
281 VGOFF_(helper_shldw)
282 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
283 VGOFF_(helper_shrdl)
284 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
285 VGOFF_(helper_shrdw)
286 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
287
288 VGOFF_(helper_RDTSC)
289 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
290 VGOFF_(helper_CPUID)
291 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
292
sewardjde4a1d02002-03-22 01:27:54 +0000293 VGOFF_(helper_bsf)
294 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
295 VGOFF_(helper_bsr)
296 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
297
298 VGOFF_(helper_fstsw_AX)
299 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
300 VGOFF_(helper_SAHF)
301 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000302 VGOFF_(helper_DAS)
303 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjfe8a1662002-03-24 11:54:07 +0000304 VGOFF_(helper_DAA)
305 = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
sewardjde4a1d02002-03-22 01:27:54 +0000306}
307
308
309/* ---------------------------------------------------------------------
310 Global entities which are not referenced from generated code.
311 ------------------------------------------------------------------ */
312
313/* The stack on which Valgrind runs. We can't use the same stack as
314 the simulatee -- that's an important design decision. */
315UInt VG_(stack)[10000];
316
317/* Ditto our signal delivery stack. */
318UInt VG_(sigstack)[10000];
319
320/* Saving stuff across system calls. */
sewardj43c356f2002-06-02 00:21:08 +0000321UInt VG_(real_fpu_state_saved_over_syscall)[VG_SIZE_OF_FPUSTATE_W];
322Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000323
324/* Counts downwards in vg_run_innerloop. */
325UInt VG_(dispatch_ctr);
326
sewardjde4a1d02002-03-22 01:27:54 +0000327
328/* 64-bit counter for the number of basic blocks done. */
329ULong VG_(bbs_done);
330/* 64-bit counter for the number of bbs to go before a debug exit. */
331ULong VG_(bbs_to_go);
332
333/* Produce debugging output? */
334Bool VG_(disassemble) = False;
335
336/* The current LRU epoch. */
337UInt VG_(current_epoch) = 0;
338
sewardj7e87e382002-05-03 19:09:05 +0000339/* This is the ThreadId of the last thread the scheduler ran. */
340ThreadId VG_(last_run_tid) = 0;
341
sewardjde4a1d02002-03-22 01:27:54 +0000342
343/* ---------------------------------------------------------------------
344 Counters, for informational purposes only.
345 ------------------------------------------------------------------ */
346
347/* Number of lookups which miss the fast tt helper. */
348UInt VG_(tt_fast_misses) = 0;
349
350
351/* Counts for LRU informational messages. */
352
353/* Number and total o/t size of new translations this epoch. */
354UInt VG_(this_epoch_in_count) = 0;
355UInt VG_(this_epoch_in_osize) = 0;
356UInt VG_(this_epoch_in_tsize) = 0;
357/* Number and total o/t size of discarded translations this epoch. */
358UInt VG_(this_epoch_out_count) = 0;
359UInt VG_(this_epoch_out_osize) = 0;
360UInt VG_(this_epoch_out_tsize) = 0;
361/* Number and total o/t size of translations overall. */
362UInt VG_(overall_in_count) = 0;
363UInt VG_(overall_in_osize) = 0;
364UInt VG_(overall_in_tsize) = 0;
365/* Number and total o/t size of discards overall. */
366UInt VG_(overall_out_count) = 0;
367UInt VG_(overall_out_osize) = 0;
368UInt VG_(overall_out_tsize) = 0;
369
370/* The number of LRU-clearings of TT/TC. */
371UInt VG_(number_of_lrus) = 0;
372
373
374/* Counts pertaining to the register allocator. */
375
376/* total number of uinstrs input to reg-alloc */
377UInt VG_(uinstrs_prealloc) = 0;
378
379/* total number of uinstrs added due to spill code */
380UInt VG_(uinstrs_spill) = 0;
381
382/* number of bbs requiring spill code */
383UInt VG_(translations_needing_spill) = 0;
384
385/* total of register ranks over all translations */
386UInt VG_(total_reg_rank) = 0;
387
388
sewardjde4a1d02002-03-22 01:27:54 +0000389/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000390UInt VG_(sanity_fast_count) = 0;
391UInt VG_(sanity_slow_count) = 0;
392
sewardj2e93c502002-04-12 11:12:52 +0000393/* Counts pertaining to the scheduler. */
394UInt VG_(num_scheduling_events_MINOR) = 0;
395UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000396
397
398/* ---------------------------------------------------------------------
399 Values derived from command-line options.
400 ------------------------------------------------------------------ */
401
sewardj97ced732002-03-25 00:07:36 +0000402Bool VG_(clo_check_addrVs);
sewardjde4a1d02002-03-22 01:27:54 +0000403Bool VG_(clo_GDB_attach);
404Int VG_(sanity_level);
405Int VG_(clo_verbosity);
406Bool VG_(clo_demangle);
407Bool VG_(clo_leak_check);
408Bool VG_(clo_show_reachable);
409Int VG_(clo_leak_resolution);
410Bool VG_(clo_sloppy_malloc);
411Bool VG_(clo_partial_loads_ok);
412Bool VG_(clo_trace_children);
413Int VG_(clo_logfile_fd);
414Int VG_(clo_freelist_vol);
415Bool VG_(clo_workaround_gcc296_bugs);
416Int VG_(clo_n_suppressions);
417Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
418Bool VG_(clo_single_step);
419Bool VG_(clo_optimise);
420Bool VG_(clo_instrument);
421Bool VG_(clo_cleanup);
njn4f9c9342002-04-29 16:03:24 +0000422Bool VG_(clo_cachesim);
njn7cf0bd32002-06-08 13:36:03 +0000423cache_t VG_(clo_I1_cache);
424cache_t VG_(clo_D1_cache);
425cache_t VG_(clo_L2_cache);
sewardjde4a1d02002-03-22 01:27:54 +0000426Int VG_(clo_smc_check);
427Bool VG_(clo_trace_syscalls);
428Bool VG_(clo_trace_signals);
429Bool VG_(clo_trace_symtab);
430Bool VG_(clo_trace_malloc);
sewardj8937c812002-04-12 20:12:20 +0000431Bool VG_(clo_trace_sched);
sewardj45b4b372002-04-16 22:50:32 +0000432Int VG_(clo_trace_pthread_level);
sewardjde4a1d02002-03-22 01:27:54 +0000433ULong VG_(clo_stop_after);
434Int VG_(clo_dump_error);
435Int VG_(clo_backtrace_size);
sewardj8d365b52002-05-12 10:52:16 +0000436Char* VG_(clo_weird_hacks);
sewardjde4a1d02002-03-22 01:27:54 +0000437
438/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
439 to behave. Initially we say False. */
440Bool VG_(running_on_simd_CPU) = False;
441
442/* Holds client's %esp at the point we gained control. */
443Addr VG_(esp_at_startup);
444
445/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
446 envp[] as extracted from the client's stack at startup-time. */
447Int VG_(client_argc);
448Char** VG_(client_argv);
449Char** VG_(client_envp);
450
451/* A place into which to copy the value of env var VG_ARGS, so we
452 don't have to modify the original. */
453static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
454
455
456/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +0000457 Processing of command-line options.
458 ------------------------------------------------------------------ */
459
460static void bad_option ( Char* opt )
461{
462 VG_(shutdown_logging)();
463 VG_(clo_logfile_fd) = 2; /* stderr */
464 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
465 VG_(exit)(1);
466}
467
468static void config_error ( Char* msg )
469{
470 VG_(shutdown_logging)();
471 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +0000472 VG_(printf)(
473 "valgrind.so: Startup or configuration error:\n %s\n", msg);
474 VG_(printf)(
475 "valgrind.so: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000476 VG_(exit)(1);
477}
478
sewardja1679dd2002-05-10 22:31:40 +0000479static void args_grok_error ( Char* msg )
480{
481 VG_(shutdown_logging)();
482 VG_(clo_logfile_fd) = 2; /* stderr */
483 VG_(printf)("valgrind.so: When searching for "
484 "client's argc/argc/envp:\n\t%s\n", msg);
485 config_error("couldn't find client's argc/argc/envp");
486}
487
njn7cf0bd32002-06-08 13:36:03 +0000488static void parse_cache_opt ( cache_t* cache, char* orig_opt, int opt_len )
489{
490 int i1, i2, i3;
491 int i;
492 char *opt = VG_(strdup)(VG_AR_PRIVATE, orig_opt);
493
494 i = i1 = opt_len;
495
496 /* Option looks like "--I1=65536,2,64".
497 * Find commas, replace with NULs to make three independent
498 * strings, then extract numbers. Yuck. */
499 while (VG_(isdigit)(opt[i])) i++;
500 if (',' == opt[i]) {
501 opt[i++] = '\0';
502 i2 = i;
503 } else goto bad;
504 while (VG_(isdigit)(opt[i])) i++;
505 if (',' == opt[i]) {
506 opt[i++] = '\0';
507 i3 = i;
508 } else goto bad;
509 while (VG_(isdigit)(opt[i])) i++;
510 if ('\0' != opt[i]) goto bad;
511
512 cache->size = (Int)VG_(atoll)(opt + i1);
513 cache->assoc = (Int)VG_(atoll)(opt + i2);
514 cache->line_size = (Int)VG_(atoll)(opt + i3);
515
516 return;
517
518bad:
519 bad_option(orig_opt);
520}
sewardjde4a1d02002-03-22 01:27:54 +0000521
522static void process_cmd_line_options ( void )
523{
524 UChar* argv[M_VG_CMDLINE_OPTS];
525 UInt argc;
526 UChar* p;
527 UChar* str;
sewardja1679dd2002-05-10 22:31:40 +0000528 Int i, eventually_logfile_fd, ctr;
sewardjde4a1d02002-03-22 01:27:54 +0000529
530# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
531# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
532# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
533
534 /* Set defaults. */
sewardj97ced732002-03-25 00:07:36 +0000535 VG_(clo_check_addrVs) = True;
sewardjde4a1d02002-03-22 01:27:54 +0000536 VG_(clo_GDB_attach) = False;
537 VG_(sanity_level) = 1;
538 VG_(clo_verbosity) = 1;
539 VG_(clo_demangle) = True;
540 VG_(clo_leak_check) = False;
541 VG_(clo_show_reachable) = False;
542 VG_(clo_leak_resolution) = 2;
543 VG_(clo_sloppy_malloc) = False;
544 VG_(clo_partial_loads_ok) = True;
545 VG_(clo_trace_children) = False;
546 VG_(clo_logfile_fd) = 2; /* stderr */
547 VG_(clo_freelist_vol) = 1000000;
548 VG_(clo_workaround_gcc296_bugs) = False;
549 VG_(clo_n_suppressions) = 0;
550 VG_(clo_single_step) = False;
551 VG_(clo_optimise) = True;
552 VG_(clo_instrument) = True;
njn7cf0bd32002-06-08 13:36:03 +0000553 VG_(clo_cachesim) = False;
554 VG_(clo_I1_cache) = UNDEFINED_CACHE;
555 VG_(clo_D1_cache) = UNDEFINED_CACHE;
556 VG_(clo_L2_cache) = UNDEFINED_CACHE;
sewardjde4a1d02002-03-22 01:27:54 +0000557 VG_(clo_cleanup) = True;
sewardjde4a1d02002-03-22 01:27:54 +0000558 VG_(clo_smc_check) = /* VG_CLO_SMC_SOME */ VG_CLO_SMC_NONE;
559 VG_(clo_trace_syscalls) = False;
560 VG_(clo_trace_signals) = False;
561 VG_(clo_trace_symtab) = False;
562 VG_(clo_trace_malloc) = False;
sewardj8937c812002-04-12 20:12:20 +0000563 VG_(clo_trace_sched) = False;
sewardj45b4b372002-04-16 22:50:32 +0000564 VG_(clo_trace_pthread_level) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000565 VG_(clo_stop_after) = 1000000000000LL;
566 VG_(clo_dump_error) = 0;
567 VG_(clo_backtrace_size) = 4;
sewardj8d365b52002-05-12 10:52:16 +0000568 VG_(clo_weird_hacks) = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000569
570 eventually_logfile_fd = VG_(clo_logfile_fd);
571
572 /* Once logging is started, we can safely send messages pertaining
573 to failures in initialisation. */
574 VG_(startup_logging)();
575
sewardj19d81412002-06-03 01:10:40 +0000576 /* Check for sane path in ./configure --prefix=... */
577 if (VG_(strlen)(VG_LIBDIR) < 1
578 || VG_LIBDIR[0] != '/')
579 config_error("Please use absolute paths in "
580 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000581
sewardja1679dd2002-05-10 22:31:40 +0000582 /* (Suggested by Fabrice Bellard ... )
583 We look for the Linux ELF table and go down until we find the
njn7cf0bd32002-06-08 13:36:03 +0000584 envc & envp. It is not fool-proof, but these structures should
sewardj38170912002-05-10 21:07:22 +0000585 change less often than the libc ones. */
586 {
sewardja1679dd2002-05-10 22:31:40 +0000587 UInt* sp = 0; /* bogus init to keep gcc -O happy */
588
sewardj38170912002-05-10 21:07:22 +0000589 /* locate the top of the stack */
sewardja1679dd2002-05-10 22:31:40 +0000590 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
591 VG_STARTUP_STACK_BASE_1 )) {
592 sp = (UInt*)VG_STARTUP_STACK_BASE_1;
593 } else
594 if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
595 VG_STARTUP_STACK_BASE_2 )) {
596 sp = (UInt*)VG_STARTUP_STACK_BASE_2;
597 } else {
598 args_grok_error(
599 "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
600 "constants defined in vg_include.h. You should investigate."
601 );
602 }
603
sewardj38170912002-05-10 21:07:22 +0000604 /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in
605 the elf interpreter table */
606 sp -= 2;
sewardj38170912002-05-10 21:07:22 +0000607 while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) {
sewardja1679dd2002-05-10 22:31:40 +0000608 /* VG_(printf)("trying %p\n", sp); */
sewardj38170912002-05-10 21:07:22 +0000609 sp--;
610 }
sewardj38170912002-05-10 21:07:22 +0000611
612 if (sp[2] == VKI_AT_BASE
613 && sp[0] == VKI_AT_PAGESZ
614 && sp[-2] == VKI_AT_PHNUM
615 && sp[-4] == VKI_AT_PHENT
sewardjd9c2d6d2002-05-18 11:55:05 +0000616 && sp[-6] == VKI_AT_PHDR
617 && sp[-6-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000618 if (0)
619 VG_(printf)("Looks like you've got a 2.2.X kernel here.\n");
sewardj38170912002-05-10 21:07:22 +0000620 sp -= 6;
sewardja1679dd2002-05-10 22:31:40 +0000621 } else
622 if (sp[2] == VKI_AT_CLKTCK
623 && sp[0] == VKI_AT_PAGESZ
sewardjd9c2d6d2002-05-18 11:55:05 +0000624 && sp[-2] == VKI_AT_HWCAP
625 && sp[-2-1] == 0) {
sewardja1679dd2002-05-10 22:31:40 +0000626 if (0)
627 VG_(printf)("Looks like you've got a 2.4.X kernel here.\n");
628 sp -= 2;
629 } else
sewardjd9c2d6d2002-05-18 11:55:05 +0000630 if (sp[2] == VKI_AT_CLKTCK
631 && sp[0] == VKI_AT_PAGESZ
632 && sp[-2] == VKI_AT_HWCAP
633 && sp[-2-20-1] == 0) {
634 if (0)
635 VG_(printf)("Looks like you've got a early 2.4.X kernel here.\n");
636 sp -= 22;
637 } else
sewardja1679dd2002-05-10 22:31:40 +0000638 args_grok_error(
639 "ELF frame does not look like 2.2.X or 2.4.X.\n "
640 "See kernel sources linux/fs/binfmt_elf.c to make sense of this."
641 );
sewardj38170912002-05-10 21:07:22 +0000642
643 sp--;
sewardja1679dd2002-05-10 22:31:40 +0000644 if (*sp != 0)
645 args_grok_error("can't find NULL at end of env[]");
646
sewardj38170912002-05-10 21:07:22 +0000647 /* sp now points to NULL at the end of env[] */
sewardja1679dd2002-05-10 22:31:40 +0000648 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000649 while (True) {
650 sp --;
651 if (*sp == 0) break;
sewardja1679dd2002-05-10 22:31:40 +0000652 if (++ctr >= 1000)
653 args_grok_error(
654 "suspiciously many (1000) env[] entries; giving up");
655
sewardj38170912002-05-10 21:07:22 +0000656 }
657 /* sp now points to NULL at the end of argv[] */
sewardja1679dd2002-05-10 22:31:40 +0000658 VG_(client_envp) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000659
sewardja1679dd2002-05-10 22:31:40 +0000660 ctr = 0;
sewardj38170912002-05-10 21:07:22 +0000661 VG_(client_argc) = 0;
662 while (True) {
663 sp--;
664 if (*sp == VG_(client_argc))
665 break;
666 VG_(client_argc)++;
sewardja1679dd2002-05-10 22:31:40 +0000667 if (++ctr >= 1000)
668 args_grok_error(
669 "suspiciously many (1000) argv[] entries; giving up");
sewardj38170912002-05-10 21:07:22 +0000670 }
671
sewardja1679dd2002-05-10 22:31:40 +0000672 VG_(client_argv) = (Char**)(sp+1);
sewardj38170912002-05-10 21:07:22 +0000673 }
674
sewardjde4a1d02002-03-22 01:27:54 +0000675 /* Now that VG_(client_envp) has been set, we can extract the args
676 for Valgrind itself. Copy into global var so that we don't have to
677 write zeroes to the getenv'd value itself. */
678 str = VG_(getenv)("VG_ARGS");
679 argc = 0;
680
681 if (!str) {
682 config_error("Can't read options from env var VG_ARGS.");
683 }
684
685 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
686 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
687 }
688 VG_(strcpy)(vg_cmdline_copy, str);
689 str = NULL;
690
691 p = &vg_cmdline_copy[0];
692 while (True) {
693 while (ISSPACE(*p)) { *p = 0; p++; }
694 if (*p == 0) break;
695 if (argc < M_VG_CMDLINE_OPTS-1) {
696 argv[argc] = p; argc++;
697 } else {
698 config_error(
699 "Found more than M_CMDLINE_OPTS command-line opts.");
700 }
701 while (*p != 0 && !ISSPACE(*p)) p++;
702 }
703
704 for (i = 0; i < argc; i++) {
705
706 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
707 VG_(clo_verbosity)++;
708 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
709 VG_(clo_verbosity)--;
710
sewardj97ced732002-03-25 00:07:36 +0000711 else if (STREQ(argv[i], "--check-addrVs=yes"))
712 VG_(clo_check_addrVs) = True;
713 else if (STREQ(argv[i], "--check-addrVs=no"))
714 VG_(clo_check_addrVs) = False;
715
sewardjde4a1d02002-03-22 01:27:54 +0000716 else if (STREQ(argv[i], "--gdb-attach=yes"))
717 VG_(clo_GDB_attach) = True;
718 else if (STREQ(argv[i], "--gdb-attach=no"))
719 VG_(clo_GDB_attach) = False;
720
721 else if (STREQ(argv[i], "--demangle=yes"))
722 VG_(clo_demangle) = True;
723 else if (STREQ(argv[i], "--demangle=no"))
724 VG_(clo_demangle) = False;
725
726 else if (STREQ(argv[i], "--partial-loads-ok=yes"))
727 VG_(clo_partial_loads_ok) = True;
728 else if (STREQ(argv[i], "--partial-loads-ok=no"))
729 VG_(clo_partial_loads_ok) = False;
730
731 else if (STREQ(argv[i], "--leak-check=yes"))
732 VG_(clo_leak_check) = True;
733 else if (STREQ(argv[i], "--leak-check=no"))
734 VG_(clo_leak_check) = False;
735
736 else if (STREQ(argv[i], "--show-reachable=yes"))
737 VG_(clo_show_reachable) = True;
738 else if (STREQ(argv[i], "--show-reachable=no"))
739 VG_(clo_show_reachable) = False;
740
741 else if (STREQ(argv[i], "--leak-resolution=low"))
742 VG_(clo_leak_resolution) = 2;
743 else if (STREQ(argv[i], "--leak-resolution=med"))
744 VG_(clo_leak_resolution) = 4;
745 else if (STREQ(argv[i], "--leak-resolution=high"))
746 VG_(clo_leak_resolution) = VG_DEEPEST_BACKTRACE;
747
748 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
749 VG_(clo_sloppy_malloc) = True;
750 else if (STREQ(argv[i], "--sloppy-malloc=no"))
751 VG_(clo_sloppy_malloc) = False;
752
753 else if (STREQ(argv[i], "--trace-children=yes"))
754 VG_(clo_trace_children) = True;
755 else if (STREQ(argv[i], "--trace-children=no"))
756 VG_(clo_trace_children) = False;
757
758 else if (STREQ(argv[i], "--workaround-gcc296-bugs=yes"))
759 VG_(clo_workaround_gcc296_bugs) = True;
760 else if (STREQ(argv[i], "--workaround-gcc296-bugs=no"))
761 VG_(clo_workaround_gcc296_bugs) = False;
762
763 else if (STREQN(15, argv[i], "--sanity-level="))
764 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
765
766 else if (STREQN(13, argv[i], "--logfile-fd="))
767 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
768
769 else if (STREQN(15, argv[i], "--freelist-vol=")) {
770 VG_(clo_freelist_vol) = (Int)VG_(atoll)(&argv[i][15]);
771 if (VG_(clo_freelist_vol) < 0) VG_(clo_freelist_vol) = 2;
772 }
773
774 else if (STREQN(15, argv[i], "--suppressions=")) {
775 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
776 VG_(message)(Vg_UserMsg, "Too many logfiles specified.");
777 VG_(message)(Vg_UserMsg,
778 "Increase VG_CLO_MAX_SFILES and recompile.");
779 bad_option(argv[i]);
780 }
781 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
782 VG_(clo_n_suppressions)++;
783 }
784 else if (STREQ(argv[i], "--single-step=yes"))
785 VG_(clo_single_step) = True;
786 else if (STREQ(argv[i], "--single-step=no"))
787 VG_(clo_single_step) = False;
788
789 else if (STREQ(argv[i], "--optimise=yes"))
790 VG_(clo_optimise) = True;
791 else if (STREQ(argv[i], "--optimise=no"))
792 VG_(clo_optimise) = False;
793
794 else if (STREQ(argv[i], "--instrument=yes"))
795 VG_(clo_instrument) = True;
796 else if (STREQ(argv[i], "--instrument=no"))
797 VG_(clo_instrument) = False;
798
799 else if (STREQ(argv[i], "--cleanup=yes"))
800 VG_(clo_cleanup) = True;
801 else if (STREQ(argv[i], "--cleanup=no"))
802 VG_(clo_cleanup) = False;
803
njn4f9c9342002-04-29 16:03:24 +0000804 else if (STREQ(argv[i], "--cachesim=yes"))
805 VG_(clo_cachesim) = True;
806 else if (STREQ(argv[i], "--cachesim=no"))
807 VG_(clo_cachesim) = False;
808
njn7cf0bd32002-06-08 13:36:03 +0000809 /* 5 is length of "--I1=" */
810 else if (0 == VG_(strncmp)(argv[i], "--I1=", 5))
811 parse_cache_opt(&VG_(clo_I1_cache), argv[i], 5);
812 else if (0 == VG_(strncmp)(argv[i], "--D1=", 5))
813 parse_cache_opt(&VG_(clo_D1_cache), argv[i], 5);
814 else if (0 == VG_(strncmp)(argv[i], "--L2=", 5))
815 parse_cache_opt(&VG_(clo_L2_cache), argv[i], 5);
816
sewardjde4a1d02002-03-22 01:27:54 +0000817 else if (STREQ(argv[i], "--smc-check=none"))
818 VG_(clo_smc_check) = VG_CLO_SMC_NONE;
819 else if (STREQ(argv[i], "--smc-check=some"))
820 VG_(clo_smc_check) = VG_CLO_SMC_SOME;
821 else if (STREQ(argv[i], "--smc-check=all"))
822 VG_(clo_smc_check) = VG_CLO_SMC_ALL;
823
824 else if (STREQ(argv[i], "--trace-syscalls=yes"))
825 VG_(clo_trace_syscalls) = True;
826 else if (STREQ(argv[i], "--trace-syscalls=no"))
827 VG_(clo_trace_syscalls) = False;
828
829 else if (STREQ(argv[i], "--trace-signals=yes"))
830 VG_(clo_trace_signals) = True;
831 else if (STREQ(argv[i], "--trace-signals=no"))
832 VG_(clo_trace_signals) = False;
833
834 else if (STREQ(argv[i], "--trace-symtab=yes"))
835 VG_(clo_trace_symtab) = True;
836 else if (STREQ(argv[i], "--trace-symtab=no"))
837 VG_(clo_trace_symtab) = False;
838
839 else if (STREQ(argv[i], "--trace-malloc=yes"))
840 VG_(clo_trace_malloc) = True;
841 else if (STREQ(argv[i], "--trace-malloc=no"))
842 VG_(clo_trace_malloc) = False;
843
sewardj8937c812002-04-12 20:12:20 +0000844 else if (STREQ(argv[i], "--trace-sched=yes"))
845 VG_(clo_trace_sched) = True;
846 else if (STREQ(argv[i], "--trace-sched=no"))
847 VG_(clo_trace_sched) = False;
848
sewardj45b4b372002-04-16 22:50:32 +0000849 else if (STREQ(argv[i], "--trace-pthread=none"))
850 VG_(clo_trace_pthread_level) = 0;
851 else if (STREQ(argv[i], "--trace-pthread=some"))
852 VG_(clo_trace_pthread_level) = 1;
853 else if (STREQ(argv[i], "--trace-pthread=all"))
854 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +0000855
sewardj8d365b52002-05-12 10:52:16 +0000856 else if (STREQN(14, argv[i], "--weird-hacks="))
857 VG_(clo_weird_hacks) = &argv[i][14];
sewardj3984b852002-05-12 03:00:17 +0000858
sewardjde4a1d02002-03-22 01:27:54 +0000859 else if (STREQN(13, argv[i], "--stop-after="))
860 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
861
862 else if (STREQN(13, argv[i], "--dump-error="))
863 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
864
865 else if (STREQN(14, argv[i], "--num-callers=")) {
866 /* Make sure it's sane. */
867 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
868 if (VG_(clo_backtrace_size) < 2)
869 VG_(clo_backtrace_size) = 2;
870 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
871 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
872 }
873
874 else
875 bad_option(argv[i]);
876 }
877
878# undef ISSPACE
879# undef STREQ
880# undef STREQN
881
882 if (VG_(clo_verbosity < 0))
883 VG_(clo_verbosity) = 0;
884
885 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
886 VG_(message)(Vg_UserMsg, "");
887 VG_(message)(Vg_UserMsg,
888 "--gdb-attach=yes conflicts with --trace-children=yes");
889 VG_(message)(Vg_UserMsg,
890 "Please choose one or the other, but not both.");
891 bad_option("--gdb-attach=yes and --trace-children=yes");
892 }
893
sewardjde4a1d02002-03-22 01:27:54 +0000894 VG_(clo_logfile_fd) = eventually_logfile_fd;
895
njn4f9c9342002-04-29 16:03:24 +0000896 /* Don't do memory checking if simulating the cache. */
897 if (VG_(clo_cachesim)) {
898 VG_(clo_instrument) = False;
899 }
900
sewardj83adf412002-05-01 01:25:45 +0000901 if (VG_(clo_verbosity > 0)) {
902 if (VG_(clo_cachesim)) {
903 VG_(message)(Vg_UserMsg,
904 "cachegrind-%s, an I1/D1/L2 cache profiler for x86 GNU/Linux.",
905 VERSION);
906 } else {
907 VG_(message)(Vg_UserMsg,
908 "valgrind-%s, a memory error detector for x86 GNU/Linux.",
909 VERSION);
910 }
911 }
sewardj3b2736a2002-03-24 12:18:35 +0000912
sewardjde4a1d02002-03-22 01:27:54 +0000913 if (VG_(clo_verbosity > 0))
914 VG_(message)(Vg_UserMsg,
915 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
916 if (VG_(clo_verbosity) > 1) {
917 VG_(message)(Vg_UserMsg, "Startup, with flags:");
918 for (i = 0; i < argc; i++) {
919 VG_(message)(Vg_UserMsg, " %s", argv[i]);
920 }
921 }
922
sewardj83adf412002-05-01 01:25:45 +0000923 if (VG_(clo_n_suppressions) == 0 && !VG_(clo_cachesim)) {
sewardjde4a1d02002-03-22 01:27:54 +0000924 config_error("No error-suppression files were specified.");
925 }
926}
927
928
929/* ---------------------------------------------------------------------
930 Copying to/from m_state_static.
931 ------------------------------------------------------------------ */
932
933UInt VG_(m_state_static) [8 /* int regs, in Intel order */
934 + 1 /* %eflags */
935 + 1 /* %eip */
936 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
937 ];
938
939void VG_(copy_baseBlock_to_m_state_static) ( void )
940{
941 Int i;
942 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_eax)];
943 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
944 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_edx)];
945 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
946 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_esp)];
947 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
948 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_esi)];
949 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_edi)];
950
951 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
952 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_eip)];
953
954 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
955 VG_(m_state_static)[40/4 + i]
956 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
957}
958
959
960void VG_(copy_m_state_static_to_baseBlock) ( void )
961{
962 Int i;
963 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[ 0/4];
964 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[ 4/4];
965 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[ 8/4];
966 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[12/4];
967 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[16/4];
968 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[20/4];
969 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[24/4];
970 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[28/4];
971
972 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[32/4];
973 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[36/4];
974
975 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
976 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
977 = VG_(m_state_static)[40/4 + i];
978}
979
980
981/* ---------------------------------------------------------------------
982 Show accumulated counts.
983 ------------------------------------------------------------------ */
984
985static void vg_show_counts ( void )
986{
987 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +0000988 " lru: %d epochs, %d clearings.",
989 VG_(current_epoch),
990 VG_(number_of_lrus) );
sewardjde4a1d02002-03-22 01:27:54 +0000991 VG_(message)(Vg_DebugMsg,
992 "translate: new %d (%d -> %d), discard %d (%d -> %d).",
993 VG_(overall_in_count),
994 VG_(overall_in_osize),
995 VG_(overall_in_tsize),
996 VG_(overall_out_count),
997 VG_(overall_out_osize),
998 VG_(overall_out_tsize) );
999 VG_(message)(Vg_DebugMsg,
sewardj2e93c502002-04-12 11:12:52 +00001000 " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
1001 VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
1002 VG_(num_scheduling_events_MINOR),
1003 VG_(tt_fast_misses));
sewardjde4a1d02002-03-22 01:27:54 +00001004 VG_(message)(Vg_DebugMsg,
1005 "reg-alloc: %d t-req-spill, "
1006 "%d+%d orig+spill uis, %d total-reg-r.",
1007 VG_(translations_needing_spill),
1008 VG_(uinstrs_prealloc),
1009 VG_(uinstrs_spill),
1010 VG_(total_reg_rank) );
1011 VG_(message)(Vg_DebugMsg,
sewardjde4a1d02002-03-22 01:27:54 +00001012 " sanity: %d cheap, %d expensive checks.",
1013 VG_(sanity_fast_count),
1014 VG_(sanity_slow_count) );
1015}
1016
1017
1018/* ---------------------------------------------------------------------
1019 Main!
1020 ------------------------------------------------------------------ */
1021
1022/* Where we jump to once Valgrind has got control, and the real
1023 machine's state has been copied to the m_state_static. */
1024
1025void VG_(main) ( void )
1026{
sewardj2e93c502002-04-12 11:12:52 +00001027 Int i;
1028 VgSchedReturnCode src;
sewardj7e87e382002-05-03 19:09:05 +00001029 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001030
1031 /* Set up our stack sanity-check words. */
1032 for (i = 0; i < 10; i++) {
1033 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1034 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1035 }
1036
1037 /* Set up baseBlock offsets and copy the saved machine's state into
1038 it. */
1039 vg_init_baseBlock();
1040 VG_(copy_m_state_static_to_baseBlock)();
1041
1042 /* Process Valgrind's command-line opts (from env var VG_OPTS). */
1043 process_cmd_line_options();
1044
sewardj64039bb2002-06-03 00:58:18 +00001045 /* Hook to delay things long enough so we can get the pid and
1046 attach GDB in another shell. */
1047 if (0) {
1048 Int p, q;
1049 for (p = 0; p < 50000; p++)
1050 for (q = 0; q < 50000; q++) ;
1051 }
1052
sewardj018f7622002-05-15 21:13:39 +00001053 /* Initialise the scheduler, and copy the client's state from
1054 baseBlock into VG_(threads)[1]. This has to come before signal
1055 initialisations. */
1056 VG_(scheduler_init)();
1057
1058 /* Initialise the signal handling subsystem, temporarily parking
1059 the saved blocking-mask in saved_sigmask. */
sewardjde4a1d02002-03-22 01:27:54 +00001060 VG_(sigstartup_actions)();
1061
sewardj018f7622002-05-15 21:13:39 +00001062 /* Perhaps we're profiling Valgrind? */
sewardjde4a1d02002-03-22 01:27:54 +00001063# ifdef VG_PROFILE
1064 VGP_(init_profiling)();
1065# endif
1066
sewardj5f07b662002-04-23 16:52:51 +00001067 /* Start calibration of our RDTSC-based clock. */
1068 VG_(start_rdtsc_calibration)();
1069
njn4f9c9342002-04-29 16:03:24 +00001070 if (VG_(clo_instrument) || VG_(clo_cachesim)) {
sewardjde4a1d02002-03-22 01:27:54 +00001071 VGP_PUSHCC(VgpInitAudit);
1072 VGM_(init_memory_audit)();
1073 VGP_POPCC;
sewardjde4a1d02002-03-22 01:27:54 +00001074 }
1075
sewardj18d75132002-05-16 11:06:21 +00001076 VGP_PUSHCC(VgpReadSyms);
1077 VG_(read_symbols)();
1078 VGP_POPCC;
1079
sewardj5f07b662002-04-23 16:52:51 +00001080 /* End calibration of our RDTSC-based clock, leaving it as long as
1081 we can. */
1082 VG_(end_rdtsc_calibration)();
1083
sewardjde4a1d02002-03-22 01:27:54 +00001084 /* This should come after init_memory_audit; otherwise the latter
1085 carefully sets up the permissions maps to cover the anonymous
1086 mmaps for the translation table and translation cache, which
1087 wastes > 20M of virtual address space. */
sewardj18d75132002-05-16 11:06:21 +00001088 VG_(init_tt_tc)();
sewardjde4a1d02002-03-22 01:27:54 +00001089
1090 if (VG_(clo_verbosity) == 1) {
1091 VG_(message)(Vg_UserMsg,
1092 "For more details, rerun with: -v");
1093 }
1094
1095 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1096 instrumented-ly. */
1097 VG_(running_on_simd_CPU) = True;
1098 if (VG_(clo_instrument)) {
1099 VGM_(make_readable) ( (Addr)&VG_(running_on_simd_CPU), 1 );
1100 VGM_(make_readable) ( (Addr)&VG_(clo_instrument), 1 );
1101 VGM_(make_readable) ( (Addr)&VG_(clo_trace_malloc), 1 );
1102 VGM_(make_readable) ( (Addr)&VG_(clo_sloppy_malloc), 1 );
1103 }
1104
njn4f9c9342002-04-29 16:03:24 +00001105 if (VG_(clo_cachesim))
1106 VG_(init_cachesim)();
1107
sewardjde4a1d02002-03-22 01:27:54 +00001108 if (VG_(clo_verbosity) > 0)
1109 VG_(message)(Vg_UserMsg, "");
1110
1111 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardj2e93c502002-04-12 11:12:52 +00001112
sewardj018f7622002-05-15 21:13:39 +00001113 /* Run! */
sewardj671ff542002-05-07 09:25:30 +00001114 VGP_PUSHCC(VgpSched);
sewardj2e93c502002-04-12 11:12:52 +00001115 src = VG_(scheduler)();
sewardj671ff542002-05-07 09:25:30 +00001116 VGP_POPCC;
sewardjde4a1d02002-03-22 01:27:54 +00001117
1118 if (VG_(clo_verbosity) > 0)
1119 VG_(message)(Vg_UserMsg, "");
1120
sewardj2e93c502002-04-12 11:12:52 +00001121 if (src == VgSrc_Deadlock) {
1122 VG_(message)(Vg_UserMsg,
1123 "Warning: pthread scheduler exited due to deadlock");
1124 }
1125
sewardjde4a1d02002-03-22 01:27:54 +00001126 if (VG_(clo_instrument)) {
1127 VG_(show_all_errors)();
1128 VG_(clientmalloc_done)();
1129 if (VG_(clo_verbosity) == 1) {
1130 VG_(message)(Vg_UserMsg,
1131 "For counts of detected errors, rerun with: -v");
1132 }
1133 if (VG_(clo_leak_check)) VG_(detect_memory_leaks)();
1134 }
1135 VG_(running_on_simd_CPU) = False;
sewardj2e93c502002-04-12 11:12:52 +00001136
njn4f9c9342002-04-29 16:03:24 +00001137 if (VG_(clo_cachesim))
njn7cf0bd32002-06-08 13:36:03 +00001138 VG_(do_cachesim_results)(VG_(client_argc), VG_(client_argv));
njn4f9c9342002-04-29 16:03:24 +00001139
sewardj0c3b53f2002-05-01 01:58:35 +00001140 VG_(do_sanity_checks)( True /*include expensive checks*/ );
sewardjde4a1d02002-03-22 01:27:54 +00001141
1142 if (VG_(clo_verbosity) > 1)
1143 vg_show_counts();
1144
1145 if (0) {
1146 VG_(message)(Vg_DebugMsg, "");
1147 VG_(message)(Vg_DebugMsg,
1148 "------ Valgrind's internal memory use stats follow ------" );
1149 VG_(mallocSanityCheckAll)();
1150 VG_(show_all_arena_stats)();
1151 VG_(message)(Vg_DebugMsg,
1152 "------ Valgrind's ExeContext management stats follow ------" );
1153 VG_(show_ExeContext_stats)();
1154 VG_(message)(Vg_DebugMsg,
1155 "------ Valgrind's client block stats follow ---------------" );
1156 VG_(show_client_block_stats)();
1157 }
1158
1159# ifdef VG_PROFILE
1160 VGP_(done_profiling)();
1161# endif
1162
1163 VG_(done_prof_mem)();
1164
1165 VG_(shutdown_logging)();
1166
sewardj3e1eb1f2002-05-18 13:14:17 +00001167 /* Remove valgrind.so from a LD_PRELOAD=... string so child
1168 processes don't get traced into. Also mess up $libdir/valgrind
1169 so that our libpthread.so disappears from view. */
sewardjde4a1d02002-03-22 01:27:54 +00001170 if (!VG_(clo_trace_children)) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001171 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1172 VG_(getenv)("LD_PRELOAD"),
1173 VG_(getenv)("LD_LIBRARY_PATH")
1174 );
sewardjde4a1d02002-03-22 01:27:54 +00001175 }
1176
sewardj7e87e382002-05-03 19:09:05 +00001177 /* Decide how to exit. This depends on what the scheduler
1178 returned. */
1179 switch (src) {
1180 case VgSrc_ExitSyscall: /* the normal way out */
1181 vg_assert(VG_(last_run_tid) > 0
1182 && VG_(last_run_tid) < VG_N_THREADS);
sewardj018f7622002-05-15 21:13:39 +00001183 tst = & VG_(threads)[VG_(last_run_tid)];
sewardj7e87e382002-05-03 19:09:05 +00001184 vg_assert(tst->status == VgTs_Runnable);
1185 /* The thread's %EBX will hold the arg to exit(), so we just
1186 do exit with that arg. */
1187 VG_(exit)( tst->m_ebx );
1188 /* NOT ALIVE HERE! */
1189 VG_(panic)("entered the afterlife in vg_main() -- ExitSyscall");
1190 break; /* what the hell :) */
sewardjde4a1d02002-03-22 01:27:54 +00001191
sewardj7e87e382002-05-03 19:09:05 +00001192 case VgSrc_Deadlock:
1193 /* Just exit now. No point in continuing. */
1194 VG_(exit)(0);
1195 VG_(panic)("entered the afterlife in vg_main() -- Deadlock");
1196 break;
1197
1198 case VgSrc_BbsDone:
1199 /* Tricky; we have to try and switch back to the real CPU.
1200 This is all very dodgy and won't work at all in the
1201 presence of threads, or if the client happened to be
1202 running a signal handler. */
1203 /* Prepare to restore state to the real CPU. */
1204 VG_(load_thread_state)(1 /* root thread */ );
1205 VG_(copy_baseBlock_to_m_state_static)();
1206
1207 /* This pushes a return address on the simulator's stack,
1208 which is abandoned. We call vg_sigshutdown_actions() at
1209 the end of vg_switch_to_real_CPU(), so as to ensure that
1210 the original stack and machine state is restored before
1211 the real signal mechanism is restored. */
1212 VG_(switch_to_real_CPU)();
1213
1214 default:
1215 VG_(panic)("vg_main(): unexpected scheduler return code");
1216 }
sewardjde4a1d02002-03-22 01:27:54 +00001217}
1218
1219
1220/* Debugging thing .. can be called from assembly with OYNK macro. */
1221void VG_(oynk) ( Int n )
1222{
1223 OINK(n);
1224}
1225
1226
1227/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1228 "valgrinq.so", which doesn't do anything. This is used to avoid
1229 tracing into child processes. To make this work the build system
1230 also supplies a dummy file, "valgrinq.so".
sewardj78e25c92002-05-20 23:38:33 +00001231
1232 Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
1233 it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
1234 disappear.
sewardjde4a1d02002-03-22 01:27:54 +00001235*/
sewardj3e1eb1f2002-05-18 13:14:17 +00001236void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
1237 Char* ld_library_path_str )
sewardjde4a1d02002-03-22 01:27:54 +00001238{
sewardj78e25c92002-05-20 23:38:33 +00001239 Char* p_prel = NULL;
1240 Char* p_path = NULL;
1241 Int what = 0;
1242 if (ld_preload_str == NULL || ld_library_path_str == NULL)
1243 goto mutancy;
sewardj3e1eb1f2002-05-18 13:14:17 +00001244
sewardj78e25c92002-05-20 23:38:33 +00001245 /* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
1246
1247 p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
1248 p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
1249
1250 if (p_prel == NULL) {
sewardj3e1eb1f2002-05-18 13:14:17 +00001251 /* perhaps already happened? */
sewardj78e25c92002-05-20 23:38:33 +00001252 what = 1;
1253 if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
1254 goto mutancy;
1255 if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
1256 goto mutancy;
sewardjde4a1d02002-03-22 01:27:54 +00001257 return;
sewardj3e1eb1f2002-05-18 13:14:17 +00001258 }
1259
sewardj78e25c92002-05-20 23:38:33 +00001260 what = 2;
1261 if (p_path == NULL) goto mutancy;
1262
1263 /* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
1264 what = 3;
1265 if (p_prel[7] != 'd') goto mutancy;
1266 p_prel[7] = 'q';
sewardj3e1eb1f2002-05-18 13:14:17 +00001267
1268 /* in LD_LIBRARY_PATH, turn $libdir/valgrind (as configure'd) from
1269 .../lib/valgrind .../lib/valgrinq, which doesn't exist,
1270 so that our own libpthread.so goes out of scope. */
sewardj78e25c92002-05-20 23:38:33 +00001271 p_path += VG_(strlen)(VG_LIBDIR);
1272 what = 4;
1273 if (p_path[0] != '/') goto mutancy;
1274 p_path++; /* step over / */
1275 what = 5;
1276 if (p_path[7] != 'd') goto mutancy;
1277 p_path[7] = 'q';
1278 return;
1279
1280 mutancy:
1281 VG_(printf)(
1282 "\nVG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH): internal error:\n"
1283 " what = %d\n"
1284 " ld_preload_str = `%s'\n"
1285 " ld_library_path_str = `%s'\n"
1286 " p_prel = `%s'\n"
1287 " p_path = `%s'\n"
1288 " VG_LIBDIR = `%s'\n",
sewardj19d81412002-06-03 01:10:40 +00001289 what, ld_preload_str, ld_library_path_str,
1290 p_prel, p_path, VG_LIBDIR
1291 );
sewardj78e25c92002-05-20 23:38:33 +00001292 VG_(panic)("VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) failed\n");
sewardjde4a1d02002-03-22 01:27:54 +00001293}
1294
sewardj3e1eb1f2002-05-18 13:14:17 +00001295
sewardjde4a1d02002-03-22 01:27:54 +00001296/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1297 it to attach to this process. Called if the user requests this
1298 service after an error has been shown, so she can poke around and
1299 look at parameters, memory, etc. You can't meaningfully get GDB to
1300 continue the program, though; to continue, quit GDB. */
1301extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1302{
sewardje6a25242002-04-21 22:03:07 +00001303 Int res;
sewardjde4a1d02002-03-22 01:27:54 +00001304 UChar buf[100];
1305 VG_(sprintf)(buf,
1306 "/usr/bin/gdb -nw /proc/%d/exe %d",
1307 VG_(getpid)(), VG_(getpid)());
sewardje6a25242002-04-21 22:03:07 +00001308 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
1309 res = VG_(system)(buf);
1310 if (res == 0) {
1311 VG_(message)(Vg_UserMsg, "");
1312 VG_(message)(Vg_UserMsg,
1313 "GDB has detached. Valgrind regains control. We continue.");
1314 } else {
1315 VG_(message)(Vg_UserMsg, "Apparently failed!");
1316 VG_(message)(Vg_UserMsg, "");
sewardjde4a1d02002-03-22 01:27:54 +00001317 }
sewardjde4a1d02002-03-22 01:27:54 +00001318}
1319
1320
1321/* Print some helpful-ish text about unimplemented things, and give
1322 up. */
sewardjcfc39b22002-05-08 01:58:18 +00001323void VG_(unimplemented) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +00001324{
1325 VG_(message)(Vg_UserMsg, "");
1326 VG_(message)(Vg_UserMsg,
1327 "Valgrind detected that your program requires");
1328 VG_(message)(Vg_UserMsg,
1329 "the following unimplemented functionality:");
1330 VG_(message)(Vg_UserMsg, " %s", msg);
1331 VG_(message)(Vg_UserMsg,
1332 "This may be because the functionality is hard to implement,");
1333 VG_(message)(Vg_UserMsg,
1334 "or because no reasonable program would behave this way,");
1335 VG_(message)(Vg_UserMsg,
1336 "or because nobody has yet needed it. In any case, let me know");
1337 VG_(message)(Vg_UserMsg,
1338 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1339 VG_(message)(Vg_UserMsg,
1340 "");
1341 VG_(message)(Vg_UserMsg,
1342 "Valgrind has to exit now. Sorry. Bye!");
1343 VG_(message)(Vg_UserMsg,
1344 "");
sewardj15a43e12002-04-17 19:35:12 +00001345 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +00001346 VG_(exit)(1);
1347}
1348
1349
sewardjcfc39b22002-05-08 01:58:18 +00001350void VG_(nvidia_moan) ( void)
1351{
1352 VG_(message)(Vg_UserMsg,
1353 "The following failure _might_ be caused by linking to NVidia's\n "
1354 "libGL.so, so avoiding it, if you can, _might_ help you. For example,\n "
1355 "re-build any Qt libraries you are using without OpenGL support.");
1356}
1357
1358
sewardjde4a1d02002-03-22 01:27:54 +00001359/*--------------------------------------------------------------------*/
1360/*--- end vg_main.c ---*/
1361/*--------------------------------------------------------------------*/