blob: a80a79fd389549f52401f3c7d08cec40592de7de [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
13 Julian_Seward@muraroa.demon.co.uk
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file LICENSE.
31*/
32
33#include "vg_include.h"
34#include "vg_constants.h"
35#include "vg_version.h"
36
37
38/* ---------------------------------------------------------------------
39 Compute offsets into baseBlock. See comments in vg_include.h.
40 ------------------------------------------------------------------ */
41
42/* The variables storing offsets. */
43
44#define INVALID_OFFSET (-1)
45
46Int VGOFF_(m_eax) = INVALID_OFFSET;
47Int VGOFF_(m_ecx) = INVALID_OFFSET;
48Int VGOFF_(m_edx) = INVALID_OFFSET;
49Int VGOFF_(m_ebx) = INVALID_OFFSET;
50Int VGOFF_(m_esp) = INVALID_OFFSET;
51Int VGOFF_(m_ebp) = INVALID_OFFSET;
52Int VGOFF_(m_esi) = INVALID_OFFSET;
53Int VGOFF_(m_edi) = INVALID_OFFSET;
54Int VGOFF_(m_eflags) = INVALID_OFFSET;
55Int VGOFF_(m_fpustate) = INVALID_OFFSET;
56Int VGOFF_(m_eip) = INVALID_OFFSET;
57Int VGOFF_(spillslots) = INVALID_OFFSET;
58Int VGOFF_(sh_eax) = INVALID_OFFSET;
59Int VGOFF_(sh_ecx) = INVALID_OFFSET;
60Int VGOFF_(sh_edx) = INVALID_OFFSET;
61Int VGOFF_(sh_ebx) = INVALID_OFFSET;
62Int VGOFF_(sh_esp) = INVALID_OFFSET;
63Int VGOFF_(sh_ebp) = INVALID_OFFSET;
64Int VGOFF_(sh_esi) = INVALID_OFFSET;
65Int VGOFF_(sh_edi) = INVALID_OFFSET;
66Int VGOFF_(sh_eflags) = INVALID_OFFSET;
67Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
68Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
69Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
70Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
71Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
72Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
73Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
74Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
75Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
76Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
77Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
78Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
79Int VGOFF_(helper_CLD) = INVALID_OFFSET;
80Int VGOFF_(helper_STD) = INVALID_OFFSET;
81Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
82Int 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;
89Int VGOFF_(helper_bt) = INVALID_OFFSET;
90Int VGOFF_(helper_bts) = INVALID_OFFSET;
91Int VGOFF_(helper_btr) = INVALID_OFFSET;
92Int VGOFF_(helper_btc) = INVALID_OFFSET;
93Int VGOFF_(helper_bsf) = INVALID_OFFSET;
94Int VGOFF_(helper_bsr) = INVALID_OFFSET;
95Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
96Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
sewardj4d0ab1f2002-03-24 10:00:09 +000097Int VGOFF_(helper_DAS) = INVALID_OFFSET;
sewardjde4a1d02002-03-22 01:27:54 +000098Int VGOFF_(helper_value_check4_fail) = INVALID_OFFSET;
99Int VGOFF_(helper_value_check2_fail) = INVALID_OFFSET;
100Int VGOFF_(helper_value_check1_fail) = INVALID_OFFSET;
101Int VGOFF_(helper_value_check0_fail) = INVALID_OFFSET;
102Int VGOFF_(helper_do_syscall) = INVALID_OFFSET;
103Int VGOFF_(helper_do_client_request) = INVALID_OFFSET;
104Int VGOFF_(helperc_LOADV4) = INVALID_OFFSET;
105Int VGOFF_(helperc_LOADV2) = INVALID_OFFSET;
106Int VGOFF_(helperc_LOADV1) = INVALID_OFFSET;
107Int VGOFF_(helperc_STOREV4) = INVALID_OFFSET;
108Int VGOFF_(helperc_STOREV2) = INVALID_OFFSET;
109Int VGOFF_(helperc_STOREV1) = INVALID_OFFSET;
110Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET;
111Int VGOFF_(fpu_write_check) = INVALID_OFFSET;
112Int VGOFF_(fpu_read_check) = INVALID_OFFSET;
113Int VGOFF_(helper_request_normal_exit) = INVALID_OFFSET;
114
115
116/* This is the actual defn of baseblock. */
117UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
118
119/* Words. */
120static Int baB_off = 0;
121
122/* Returns the offset, in words. */
123static Int alloc_BaB ( Int words )
124{
125 Int off = baB_off;
126 baB_off += words;
127 if (baB_off >= VG_BASEBLOCK_WORDS)
128 VG_(panic)( "alloc_BaB: baseBlock is too small");
129
130 return off;
131}
132
133/* Allocate 1 word in baseBlock and set it to the given value. */
134static Int alloc_BaB_1_set ( Addr a )
135{
136 Int off = alloc_BaB(1);
137 VG_(baseBlock)[off] = (UInt)a;
138 return off;
139}
140
141
142/* Here we assign actual offsets. It's important to get the most
143 popular referents within 128 bytes of the start, so we can take
144 advantage of short addressing modes relative to %ebp. Popularity
145 of offsets was measured on 22 Feb 02 running a KDE application, and
146 the slots rearranged accordingly, with a 1.5% reduction in total
147 size of translations. */
148
149static void vg_init_baseBlock ( void )
150{
151 baB_off = 0;
152
153 /* Those with offsets under 128 are carefully chosen. */
154
155 /* WORD offsets in this column */
156 /* 0 */ VGOFF_(m_eax) = alloc_BaB(1);
157 /* 1 */ VGOFF_(m_ecx) = alloc_BaB(1);
158 /* 2 */ VGOFF_(m_edx) = alloc_BaB(1);
159 /* 3 */ VGOFF_(m_ebx) = alloc_BaB(1);
160 /* 4 */ VGOFF_(m_esp) = alloc_BaB(1);
161 /* 5 */ VGOFF_(m_ebp) = alloc_BaB(1);
162 /* 6 */ VGOFF_(m_esi) = alloc_BaB(1);
163 /* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
164 /* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
165
166 /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
167 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
168 /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
169 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
170 /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
171 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
172 /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
173 /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
174 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
175
176 /* 18 */
177 VGOFF_(helper_value_check4_fail)
178 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check4_fail) );
179 /* 19 */
180 VGOFF_(helper_value_check0_fail)
181 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check0_fail) );
182
183 /* 20 */
184 VGOFF_(helperc_STOREV4)
185 = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV4) );
186 /* 21 */
187 VGOFF_(helperc_STOREV1)
188 = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV1) );
189
190 /* 22 */
191 VGOFF_(helperc_LOADV4)
192 = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV4) );
193 /* 23 */
194 VGOFF_(helperc_LOADV1)
195 = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV1) );
196
197 /* 24 */
198 VGOFF_(handle_esp_assignment)
199 = alloc_BaB_1_set( (Addr) & VGM_(handle_esp_assignment) );
200
201 /* 25 */
202 VGOFF_(m_eip) = alloc_BaB(1);
203
204 /* There are currently 24 spill slots */
205 /* 26 .. 49 This overlaps the magic boundary at >= 32 words, but
206 most spills are to low numbered spill slots, so the ones above
207 the boundary don't see much action. */
208 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
209
210 /* These two pushed beyond the boundary because 2-byte transactions
211 are rare. */
212 /* 50 */
213 VGOFF_(helperc_STOREV2)
214 = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV2) );
215 /* 51 */
216 VGOFF_(helperc_LOADV2)
217 = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV2) );
218
219 /* 52 */
220 VGOFF_(fpu_write_check)
221 = alloc_BaB_1_set( (Addr) & VGM_(fpu_write_check) );
222 /* 53 */
223 VGOFF_(fpu_read_check)
224 = alloc_BaB_1_set( (Addr) & VGM_(fpu_read_check) );
225
226 /* Actually I don't think these two are ever used. */
227 /* 54 */
228 VGOFF_(helper_value_check2_fail)
229 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check2_fail) );
230 /* 55 */
231 VGOFF_(helper_value_check1_fail)
232 = alloc_BaB_1_set( (Addr) & VG_(helper_value_check1_fail) );
233
234 /* I gave up counting at this point. Since they're way above the
235 short-amode-boundary, there's no point. */
236
237 VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
238
239 VGOFF_(helper_idiv_64_32)
240 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
241 VGOFF_(helper_div_64_32)
242 = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
243 VGOFF_(helper_idiv_32_16)
244 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
245 VGOFF_(helper_div_32_16)
246 = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
247 VGOFF_(helper_idiv_16_8)
248 = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
249 VGOFF_(helper_div_16_8)
250 = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
251
252 VGOFF_(helper_imul_32_64)
253 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
254 VGOFF_(helper_mul_32_64)
255 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
256 VGOFF_(helper_imul_16_32)
257 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
258 VGOFF_(helper_mul_16_32)
259 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
260 VGOFF_(helper_imul_8_16)
261 = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
262 VGOFF_(helper_mul_8_16)
263 = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
264
265 VGOFF_(helper_CLD)
266 = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
267 VGOFF_(helper_STD)
268 = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
269 VGOFF_(helper_get_dirflag)
270 = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
271
272 VGOFF_(helper_shldl)
273 = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
274 VGOFF_(helper_shldw)
275 = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
276 VGOFF_(helper_shrdl)
277 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
278 VGOFF_(helper_shrdw)
279 = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
280
281 VGOFF_(helper_RDTSC)
282 = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
283 VGOFF_(helper_CPUID)
284 = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
285
286 VGOFF_(helper_bt)
287 = alloc_BaB_1_set( (Addr) & VG_(helper_bt) );
288 VGOFF_(helper_bts)
289 = alloc_BaB_1_set( (Addr) & VG_(helper_bts) );
290 VGOFF_(helper_btr)
291 = alloc_BaB_1_set( (Addr) & VG_(helper_btr) );
292 VGOFF_(helper_btc)
293 = alloc_BaB_1_set( (Addr) & VG_(helper_btc) );
294
295 VGOFF_(helper_bsf)
296 = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
297 VGOFF_(helper_bsr)
298 = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
299
300 VGOFF_(helper_fstsw_AX)
301 = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
302 VGOFF_(helper_SAHF)
303 = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
sewardj4d0ab1f2002-03-24 10:00:09 +0000304 VGOFF_(helper_DAS)
305 = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
sewardjde4a1d02002-03-22 01:27:54 +0000306
307 VGOFF_(helper_request_normal_exit)
308 = alloc_BaB_1_set( (Addr) & VG_(helper_request_normal_exit) );
309
310 VGOFF_(helper_do_syscall)
311 = alloc_BaB_1_set( (Addr) & VG_(helper_do_syscall) );
312 VGOFF_(helper_do_client_request)
313 = alloc_BaB_1_set( (Addr) & VG_(helper_do_client_request) );
314}
315
316
317/* ---------------------------------------------------------------------
318 Global entities which are not referenced from generated code.
319 ------------------------------------------------------------------ */
320
321/* The stack on which Valgrind runs. We can't use the same stack as
322 the simulatee -- that's an important design decision. */
323UInt VG_(stack)[10000];
324
325/* Ditto our signal delivery stack. */
326UInt VG_(sigstack)[10000];
327
328/* Saving stuff across system calls. */
329UInt VG_(real_fpu_state_saved_over_syscall_d1)[VG_SIZE_OF_FPUSTATE_W];
330UInt VG_(real_fpu_state_saved_over_syscall_d2)[VG_SIZE_OF_FPUSTATE_W];
331Addr VG_(esp_saved_over_syscall_d1);
332Addr VG_(esp_saved_over_syscall_d2);
333
334/* Counts downwards in vg_run_innerloop. */
335UInt VG_(dispatch_ctr);
336
337/* If vg_dispatch_ctr is set to 1 to force a stop, its
338 previous value is saved here. */
339UInt VG_(dispatch_ctr_SAVED);
340
341/* This is why vg_run_innerloop() exited. */
342UInt VG_(interrupt_reason);
343
344/* vg_oursignalhandler() might longjmp(). Here's the jmp_buf. */
345jmp_buf VG_(toploop_jmpbuf);
346/* ... and if so, here's the signal which caused it to do so. */
347Int VG_(longjmpd_on_signal);
348
349/* 64-bit counter for the number of basic blocks done. */
350ULong VG_(bbs_done);
351/* 64-bit counter for the number of bbs to go before a debug exit. */
352ULong VG_(bbs_to_go);
353
354/* Produce debugging output? */
355Bool VG_(disassemble) = False;
356
357/* The current LRU epoch. */
358UInt VG_(current_epoch) = 0;
359
360
361/* ---------------------------------------------------------------------
362 Counters, for informational purposes only.
363 ------------------------------------------------------------------ */
364
365/* Number of lookups which miss the fast tt helper. */
366UInt VG_(tt_fast_misses) = 0;
367
368
369/* Counts for LRU informational messages. */
370
371/* Number and total o/t size of new translations this epoch. */
372UInt VG_(this_epoch_in_count) = 0;
373UInt VG_(this_epoch_in_osize) = 0;
374UInt VG_(this_epoch_in_tsize) = 0;
375/* Number and total o/t size of discarded translations this epoch. */
376UInt VG_(this_epoch_out_count) = 0;
377UInt VG_(this_epoch_out_osize) = 0;
378UInt VG_(this_epoch_out_tsize) = 0;
379/* Number and total o/t size of translations overall. */
380UInt VG_(overall_in_count) = 0;
381UInt VG_(overall_in_osize) = 0;
382UInt VG_(overall_in_tsize) = 0;
383/* Number and total o/t size of discards overall. */
384UInt VG_(overall_out_count) = 0;
385UInt VG_(overall_out_osize) = 0;
386UInt VG_(overall_out_tsize) = 0;
387
388/* The number of LRU-clearings of TT/TC. */
389UInt VG_(number_of_lrus) = 0;
390
391
392/* Counts pertaining to the register allocator. */
393
394/* total number of uinstrs input to reg-alloc */
395UInt VG_(uinstrs_prealloc) = 0;
396
397/* total number of uinstrs added due to spill code */
398UInt VG_(uinstrs_spill) = 0;
399
400/* number of bbs requiring spill code */
401UInt VG_(translations_needing_spill) = 0;
402
403/* total of register ranks over all translations */
404UInt VG_(total_reg_rank) = 0;
405
406
407/* Counts pertaining to the self-modifying-code detection machinery. */
408
409/* Total number of writes checked. */
410UInt VG_(smc_total_check4s) = 0;
411
412/* Number of writes which the fast smc check couldn't show were
413 harmless. */
414UInt VG_(smc_cache_passed) = 0;
415
416/* Numnber of writes which really did write on original code. */
417UInt VG_(smc_fancy_passed) = 0;
418
419/* Number of translations discarded as a result. */
420UInt VG_(smc_discard_count) = 0;
421
422
423/* Counts pertaining to internal sanity checking. */
424
425UInt VG_(sanity_fast_count) = 0;
426UInt VG_(sanity_slow_count) = 0;
427
428
429
430/* ---------------------------------------------------------------------
431 Values derived from command-line options.
432 ------------------------------------------------------------------ */
433
434Bool VG_(clo_GDB_attach);
435Int VG_(sanity_level);
436Int VG_(clo_verbosity);
437Bool VG_(clo_demangle);
438Bool VG_(clo_leak_check);
439Bool VG_(clo_show_reachable);
440Int VG_(clo_leak_resolution);
441Bool VG_(clo_sloppy_malloc);
442Bool VG_(clo_partial_loads_ok);
443Bool VG_(clo_trace_children);
444Int VG_(clo_logfile_fd);
445Int VG_(clo_freelist_vol);
446Bool VG_(clo_workaround_gcc296_bugs);
447Int VG_(clo_n_suppressions);
448Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
449Bool VG_(clo_single_step);
450Bool VG_(clo_optimise);
451Bool VG_(clo_instrument);
452Bool VG_(clo_cleanup);
453Bool VG_(clo_client_perms);
454Int VG_(clo_smc_check);
455Bool VG_(clo_trace_syscalls);
456Bool VG_(clo_trace_signals);
457Bool VG_(clo_trace_symtab);
458Bool VG_(clo_trace_malloc);
459ULong VG_(clo_stop_after);
460Int VG_(clo_dump_error);
461Int VG_(clo_backtrace_size);
462
463/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
464 to behave. Initially we say False. */
465Bool VG_(running_on_simd_CPU) = False;
466
467/* Holds client's %esp at the point we gained control. */
468Addr VG_(esp_at_startup);
469
470/* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
471 envp[] as extracted from the client's stack at startup-time. */
472Int VG_(client_argc);
473Char** VG_(client_argv);
474Char** VG_(client_envp);
475
476/* A place into which to copy the value of env var VG_ARGS, so we
477 don't have to modify the original. */
478static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
479
480
481/* ---------------------------------------------------------------------
482 Top level simulation loop.
483 ------------------------------------------------------------------ */
484
485/* Create a translation of the client basic block beginning at
486 orig_addr, and add it to the translation cache & translation table.
487 This probably doesn't really belong here, but, hey ... */
488void VG_(create_translation_for) ( Addr orig_addr )
489{
490 Addr trans_addr;
491 TTEntry tte;
492 Int orig_size, trans_size;
493 /* Ensure there is space to hold a translation. */
494 VG_(maybe_do_lru_pass)();
495 VG_(translate)( orig_addr, &orig_size, &trans_addr, &trans_size );
496 /* Copy data at trans_addr into the translation cache.
497 Returned pointer is to the code, not to the 4-byte
498 header. */
499 /* Since the .orig_size and .trans_size fields are
500 UShort, be paranoid. */
501 vg_assert(orig_size > 0 && orig_size < 65536);
502 vg_assert(trans_size > 0 && trans_size < 65536);
503 tte.orig_size = orig_size;
504 tte.orig_addr = orig_addr;
505 tte.trans_size = trans_size;
506 tte.trans_addr = VG_(copy_to_transcache)
507 ( trans_addr, trans_size );
508 tte.mru_epoch = VG_(current_epoch);
509 /* Free the intermediary -- was allocated by VG_(emit_code). */
510 VG_(jitfree)( (void*)trans_addr );
511 /* Add to trans tab and set back pointer. */
512 VG_(add_to_trans_tab) ( &tte );
513 /* Update stats. */
514 VG_(this_epoch_in_count) ++;
515 VG_(this_epoch_in_osize) += orig_size;
516 VG_(this_epoch_in_tsize) += trans_size;
517 VG_(overall_in_count) ++;
518 VG_(overall_in_osize) += orig_size;
519 VG_(overall_in_tsize) += trans_size;
520 /* Record translated area for SMC detection. */
521 VG_(smc_mark_original) (
522 VG_(baseBlock)[VGOFF_(m_eip)], orig_size );
523}
524
525
526/* Runs the client program from %EIP (baseBlock[off_eip]) until it
527 asks to exit, or until vg_bbs_to_go jumps have happened (the latter
528 case is for debugging). */
529
530void VG_(toploop) ( void )
531{
532 volatile UInt dispatch_ctr_SAVED;
533 volatile Int done_this_time;
534
535 /* For the LRU structures, records when the epoch began. */
536 volatile ULong epoch_started_at = 0;
537
538 while (True) {
539 next_outer_loop:
540
541 /* Age the LRU structures if an epoch has been completed. */
542 if (VG_(bbs_done) - epoch_started_at >= VG_BBS_PER_EPOCH) {
543 VG_(current_epoch)++;
544 epoch_started_at = VG_(bbs_done);
545 if (VG_(clo_verbosity) > 2) {
546 UInt tt_used, tc_used;
547 VG_(get_tt_tc_used) ( &tt_used, &tc_used );
548 VG_(message)(Vg_UserMsg,
549 "%lu bbs, in: %d (%d -> %d), out %d (%d -> %d), TT %d, TC %d",
550 VG_(bbs_done),
551 VG_(this_epoch_in_count),
552 VG_(this_epoch_in_osize),
553 VG_(this_epoch_in_tsize),
554 VG_(this_epoch_out_count),
555 VG_(this_epoch_out_osize),
556 VG_(this_epoch_out_tsize),
557 tt_used, tc_used
558 );
559 }
560 VG_(this_epoch_in_count) = 0;
561 VG_(this_epoch_in_osize) = 0;
562 VG_(this_epoch_in_tsize) = 0;
563 VG_(this_epoch_out_count) = 0;
564 VG_(this_epoch_out_osize) = 0;
565 VG_(this_epoch_out_tsize) = 0;
566 }
567
568 /* Figure out how many bbs to ask vg_run_innerloop to do. */
569 if (VG_(bbs_to_go) >= VG_SIGCHECK_INTERVAL)
570 VG_(dispatch_ctr) = 1 + VG_SIGCHECK_INTERVAL;
571 else
572 VG_(dispatch_ctr) = 1 + (UInt)VG_(bbs_to_go);
573
574 /* ... and remember what we asked for. */
575 dispatch_ctr_SAVED = VG_(dispatch_ctr);
576
577 /* Now have a go at doing them. */
578 VG_(interrupt_reason) = VG_Y_SIGCHECK;
579 if (__builtin_setjmp(VG_(toploop_jmpbuf)) == 0) {
580 /* try this ... */
581 VG_(run_innerloop)();
582 /* We get here if the client didn't take a fault. */
583 switch (VG_(interrupt_reason)) {
584 case VG_Y_SIGCHECK:
585 /* The counter fell to zero and no other situation has
586 been detected. */
587 vg_assert(VG_(dispatch_ctr) == 0);
588 done_this_time = dispatch_ctr_SAVED - 1;
589 VG_(bbs_to_go) -= (ULong)done_this_time;
590 VG_(bbs_done) += (ULong)done_this_time;
591 /* Exit if the debug run has ended. */
592 if (VG_(bbs_to_go) == 0) goto debug_stop;
593 VG_(deliver_signals)();
594 VG_(do_sanity_checks)(False);
595 goto next_outer_loop;
596 case VG_Y_EXIT:
597 /* The target program tried to exit. */
598 done_this_time = dispatch_ctr_SAVED - VG_(dispatch_ctr_SAVED);
599 done_this_time --;
600 VG_(bbs_to_go) -= (ULong)done_this_time;
601 VG_(bbs_done) += (ULong)done_this_time;
602 return;
603 case VG_Y_SMC:
604 /* A write to original code was detected. */
605 done_this_time = dispatch_ctr_SAVED - VG_(dispatch_ctr_SAVED);
606 VG_(bbs_to_go) -= (ULong)done_this_time;
607 VG_(bbs_done) += (ULong)done_this_time;
608 VG_(flush_transtab)();
609 goto next_outer_loop;
610 case VG_Y_TRANSLATE: {
611 /* Need to provide a translation of code at vg_m_eip. */
612 done_this_time = dispatch_ctr_SAVED - VG_(dispatch_ctr);
613 vg_assert(done_this_time > 0);
614 done_this_time --;
615 VG_(bbs_to_go) -= (ULong)done_this_time;
616 VG_(bbs_done) += (ULong)done_this_time;
617 VG_(create_translation_for)(VG_(baseBlock)[VGOFF_(m_eip)]);
618 goto next_outer_loop;
619 }
620 default:
621 VG_(panic)("vg_toploop: invalid interrupt reason");
622 }
623 } else {
624 /* We get here if the client took a fault, which caused our
625 signal handler to longjmp. */
626 done_this_time = dispatch_ctr_SAVED - VG_(dispatch_ctr);
627 VG_(bbs_to_go) -= (ULong)done_this_time;
628 VG_(bbs_done) += (ULong)done_this_time;
629 if (VG_(interrupt_reason) == VG_Y_EXIT) return;
630 VG_(deliver_signals)();
631 VG_(do_sanity_checks)(False);
632 VG_(unblock_host_signal)(VG_(longjmpd_on_signal));
633 }
634 }
635
636 /* NOTREACHED */
637
638 debug_stop:
639 /* If we exited because of a debug stop, print the translation
640 of the last block executed -- by translating it again, and
641 throwing away the result. */
642 VG_(printf)(
643 "======vvvvvvvv====== LAST TRANSLATION ======vvvvvvvv======\n");
644 VG_(translate)( VG_(baseBlock)[VGOFF_(m_eip)], NULL, NULL, NULL );
645 VG_(printf)("\n");
646 VG_(printf)(
647 "======^^^^^^^^====== LAST TRANSLATION ======^^^^^^^^======\n");
648}
649
650
651/* ---------------------------------------------------------------------
652 Processing of command-line options.
653 ------------------------------------------------------------------ */
654
655static void bad_option ( Char* opt )
656{
657 VG_(shutdown_logging)();
658 VG_(clo_logfile_fd) = 2; /* stderr */
659 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
660 VG_(exit)(1);
661}
662
663static void config_error ( Char* msg )
664{
665 VG_(shutdown_logging)();
666 VG_(clo_logfile_fd) = 2; /* stderr */
667 VG_(printf)("valgrind.so: Startup or configuration error:\n\t%s\n", msg);
668 VG_(printf)("valgrind.so: Unable to start up properly. Giving up.\n");
669 VG_(exit)(1);
670}
671
672
673static void process_cmd_line_options ( void )
674{
675 UChar* argv[M_VG_CMDLINE_OPTS];
676 UInt argc;
677 UChar* p;
678 UChar* str;
679 Int i, eventually_logfile_fd;
680
681# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
682# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
683# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
684
685 /* Set defaults. */
686 VG_(clo_GDB_attach) = False;
687 VG_(sanity_level) = 1;
688 VG_(clo_verbosity) = 1;
689 VG_(clo_demangle) = True;
690 VG_(clo_leak_check) = False;
691 VG_(clo_show_reachable) = False;
692 VG_(clo_leak_resolution) = 2;
693 VG_(clo_sloppy_malloc) = False;
694 VG_(clo_partial_loads_ok) = True;
695 VG_(clo_trace_children) = False;
696 VG_(clo_logfile_fd) = 2; /* stderr */
697 VG_(clo_freelist_vol) = 1000000;
698 VG_(clo_workaround_gcc296_bugs) = False;
699 VG_(clo_n_suppressions) = 0;
700 VG_(clo_single_step) = False;
701 VG_(clo_optimise) = True;
702 VG_(clo_instrument) = True;
703 VG_(clo_cleanup) = True;
704 VG_(clo_client_perms) = False;
705 VG_(clo_smc_check) = /* VG_CLO_SMC_SOME */ VG_CLO_SMC_NONE;
706 VG_(clo_trace_syscalls) = False;
707 VG_(clo_trace_signals) = False;
708 VG_(clo_trace_symtab) = False;
709 VG_(clo_trace_malloc) = False;
710 VG_(clo_stop_after) = 1000000000000LL;
711 VG_(clo_dump_error) = 0;
712 VG_(clo_backtrace_size) = 4;
713
714 eventually_logfile_fd = VG_(clo_logfile_fd);
715
716 /* Once logging is started, we can safely send messages pertaining
717 to failures in initialisation. */
718 VG_(startup_logging)();
719
720 /* Magically find the client's argc/argv/envp. This kludge is
721 entirely dependent on the stack layout imposed by libc at
722 startup. Hence the magic offsets. Then check (heuristically)
723 that the results are plausible. There must be a better way to
724 do this ... */
725
726# if 0
727 /* Use this to search for the correct offsets if the tests below
728 barf. */
729 { Int i;
730 VG_(printf)("startup %%esp is %p\n", VG_(esp_at_startup) );
731 for (i = 0; i < 10; i++) {
732 Char* p = ((Char**)VG_(esp_at_startup))[i];
733 VG_(printf)("%d: %p\n", i, p);
734 }
735 }
736# endif
737
738 /* These offsets (5,6,7) are right for my RedHat 7.2 (glibc-2.2.4)
739 box. */
740
741 VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [5] );
742 VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [6] );
743 VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [7] );
744
745 if ( ((UInt)VG_(client_argc)) > 0 &&
746 ((UInt)VG_(client_argc)) < 10000 &&
747 (Addr)VG_(client_argv) >= 0x8000000 &&
748 (Addr)VG_(client_envp) >= 0x8000000)
749 goto argc_argv_envp_OK;
750
751 /* If that's no good, try some other offsets discovered by KDE
752 folks on 8 Feb 02:
753 For glibc > 2.2.4 the offset 9/10/11 did the trick. Coolo found
754 out those, on I think a Caldera 3.1 with glibc 2.2.4 -- the same
755 offsets worked for on a debian sid with glibc 2.2.5. */
756
757 VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [9] );
758 VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [10] );
759 VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [11] );
760
761 if ( ((UInt)VG_(client_argc)) > 0 &&
762 ((UInt)VG_(client_argc)) < 10000 &&
763 (Addr)VG_(client_argv) >= 0x8000000 &&
764 (Addr)VG_(client_envp) >= 0x8000000)
765 goto argc_argv_envp_OK;
766
767 /* Doesn't look promising. Try offsets for RedHat 6.2
768 (glibc-2.1.3) instead. In this case, the argv and envp vectors
769 are actually on the stack (bizarrely). */
770
771 VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [4] );
772 VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [5] );
773 VG_(client_envp)
774 = (Char**) & ( ((void**)VG_(esp_at_startup)) [6 + VG_(client_argc)] );
775
776 if ( ((UInt)VG_(client_argc)) > 0 &&
777 ((UInt)VG_(client_argc)) < 10000 &&
778 (Addr)VG_(client_argv) >= 0x8000000 &&
779 (Addr)VG_(client_envp) >= 0x8000000)
780 goto argc_argv_envp_OK;
781
782 /* Here's yet another variant, from <hansen> (irc.kde.org). */
783
784 VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [9] );
785 VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [10] );
786 VG_(client_envp)
787 = (Char**) & ( ((void**)VG_(esp_at_startup)) [11 + VG_(client_argc)] );
788
789 if ( ((UInt)VG_(client_argc)) > 0 &&
790 ((UInt)VG_(client_argc)) < 10000 &&
791 (Addr)VG_(client_argv) >= 0x8000000 &&
792 (Addr)VG_(client_envp) >= 0x8000000)
793 goto argc_argv_envp_OK;
794
795 /* VG_(printf)("%d %p %p\n", VG_(client_argc), VG_(client_argv),
796 VG_(client_envp));
797 */
798 /* We're hosed. Give up :-( */
799 config_error(
800 "Can't get plausible values for client's argc/argv/envp.\n\t"
801 "You may be able to fix this; see process_cmd_line_options()\n\t"
802 "in vg_main.c"
803 );
804 /* NOTREACHED */
805
806 argc_argv_envp_OK:
807
808 /* Now that VG_(client_envp) has been set, we can extract the args
809 for Valgrind itself. Copy into global var so that we don't have to
810 write zeroes to the getenv'd value itself. */
811 str = VG_(getenv)("VG_ARGS");
812 argc = 0;
813
814 if (!str) {
815 config_error("Can't read options from env var VG_ARGS.");
816 }
817
818 if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) {
819 config_error("Command line length exceeds M_CMDLINE_STRLEN.");
820 }
821 VG_(strcpy)(vg_cmdline_copy, str);
822 str = NULL;
823
824 p = &vg_cmdline_copy[0];
825 while (True) {
826 while (ISSPACE(*p)) { *p = 0; p++; }
827 if (*p == 0) break;
828 if (argc < M_VG_CMDLINE_OPTS-1) {
829 argv[argc] = p; argc++;
830 } else {
831 config_error(
832 "Found more than M_CMDLINE_OPTS command-line opts.");
833 }
834 while (*p != 0 && !ISSPACE(*p)) p++;
835 }
836
837 for (i = 0; i < argc; i++) {
838
839 if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
840 VG_(clo_verbosity)++;
841 else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
842 VG_(clo_verbosity)--;
843
844 else if (STREQ(argv[i], "--gdb-attach=yes"))
845 VG_(clo_GDB_attach) = True;
846 else if (STREQ(argv[i], "--gdb-attach=no"))
847 VG_(clo_GDB_attach) = False;
848
849 else if (STREQ(argv[i], "--demangle=yes"))
850 VG_(clo_demangle) = True;
851 else if (STREQ(argv[i], "--demangle=no"))
852 VG_(clo_demangle) = False;
853
854 else if (STREQ(argv[i], "--partial-loads-ok=yes"))
855 VG_(clo_partial_loads_ok) = True;
856 else if (STREQ(argv[i], "--partial-loads-ok=no"))
857 VG_(clo_partial_loads_ok) = False;
858
859 else if (STREQ(argv[i], "--leak-check=yes"))
860 VG_(clo_leak_check) = True;
861 else if (STREQ(argv[i], "--leak-check=no"))
862 VG_(clo_leak_check) = False;
863
864 else if (STREQ(argv[i], "--show-reachable=yes"))
865 VG_(clo_show_reachable) = True;
866 else if (STREQ(argv[i], "--show-reachable=no"))
867 VG_(clo_show_reachable) = False;
868
869 else if (STREQ(argv[i], "--leak-resolution=low"))
870 VG_(clo_leak_resolution) = 2;
871 else if (STREQ(argv[i], "--leak-resolution=med"))
872 VG_(clo_leak_resolution) = 4;
873 else if (STREQ(argv[i], "--leak-resolution=high"))
874 VG_(clo_leak_resolution) = VG_DEEPEST_BACKTRACE;
875
876 else if (STREQ(argv[i], "--sloppy-malloc=yes"))
877 VG_(clo_sloppy_malloc) = True;
878 else if (STREQ(argv[i], "--sloppy-malloc=no"))
879 VG_(clo_sloppy_malloc) = False;
880
881 else if (STREQ(argv[i], "--trace-children=yes"))
882 VG_(clo_trace_children) = True;
883 else if (STREQ(argv[i], "--trace-children=no"))
884 VG_(clo_trace_children) = False;
885
886 else if (STREQ(argv[i], "--workaround-gcc296-bugs=yes"))
887 VG_(clo_workaround_gcc296_bugs) = True;
888 else if (STREQ(argv[i], "--workaround-gcc296-bugs=no"))
889 VG_(clo_workaround_gcc296_bugs) = False;
890
891 else if (STREQN(15, argv[i], "--sanity-level="))
892 VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
893
894 else if (STREQN(13, argv[i], "--logfile-fd="))
895 eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
896
897 else if (STREQN(15, argv[i], "--freelist-vol=")) {
898 VG_(clo_freelist_vol) = (Int)VG_(atoll)(&argv[i][15]);
899 if (VG_(clo_freelist_vol) < 0) VG_(clo_freelist_vol) = 2;
900 }
901
902 else if (STREQN(15, argv[i], "--suppressions=")) {
903 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
904 VG_(message)(Vg_UserMsg, "Too many logfiles specified.");
905 VG_(message)(Vg_UserMsg,
906 "Increase VG_CLO_MAX_SFILES and recompile.");
907 bad_option(argv[i]);
908 }
909 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
910 VG_(clo_n_suppressions)++;
911 }
912 else if (STREQ(argv[i], "--single-step=yes"))
913 VG_(clo_single_step) = True;
914 else if (STREQ(argv[i], "--single-step=no"))
915 VG_(clo_single_step) = False;
916
917 else if (STREQ(argv[i], "--optimise=yes"))
918 VG_(clo_optimise) = True;
919 else if (STREQ(argv[i], "--optimise=no"))
920 VG_(clo_optimise) = False;
921
922 else if (STREQ(argv[i], "--instrument=yes"))
923 VG_(clo_instrument) = True;
924 else if (STREQ(argv[i], "--instrument=no"))
925 VG_(clo_instrument) = False;
926
927 else if (STREQ(argv[i], "--cleanup=yes"))
928 VG_(clo_cleanup) = True;
929 else if (STREQ(argv[i], "--cleanup=no"))
930 VG_(clo_cleanup) = False;
931
932 else if (STREQ(argv[i], "--client-perms=yes"))
933 VG_(clo_client_perms) = True;
934 else if (STREQ(argv[i], "--client-perms=no"))
935 VG_(clo_client_perms) = False;
936
937 else if (STREQ(argv[i], "--smc-check=none"))
938 VG_(clo_smc_check) = VG_CLO_SMC_NONE;
939 else if (STREQ(argv[i], "--smc-check=some"))
940 VG_(clo_smc_check) = VG_CLO_SMC_SOME;
941 else if (STREQ(argv[i], "--smc-check=all"))
942 VG_(clo_smc_check) = VG_CLO_SMC_ALL;
943
944 else if (STREQ(argv[i], "--trace-syscalls=yes"))
945 VG_(clo_trace_syscalls) = True;
946 else if (STREQ(argv[i], "--trace-syscalls=no"))
947 VG_(clo_trace_syscalls) = False;
948
949 else if (STREQ(argv[i], "--trace-signals=yes"))
950 VG_(clo_trace_signals) = True;
951 else if (STREQ(argv[i], "--trace-signals=no"))
952 VG_(clo_trace_signals) = False;
953
954 else if (STREQ(argv[i], "--trace-symtab=yes"))
955 VG_(clo_trace_symtab) = True;
956 else if (STREQ(argv[i], "--trace-symtab=no"))
957 VG_(clo_trace_symtab) = False;
958
959 else if (STREQ(argv[i], "--trace-malloc=yes"))
960 VG_(clo_trace_malloc) = True;
961 else if (STREQ(argv[i], "--trace-malloc=no"))
962 VG_(clo_trace_malloc) = False;
963
964 else if (STREQN(13, argv[i], "--stop-after="))
965 VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]);
966
967 else if (STREQN(13, argv[i], "--dump-error="))
968 VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]);
969
970 else if (STREQN(14, argv[i], "--num-callers=")) {
971 /* Make sure it's sane. */
972 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]);
973 if (VG_(clo_backtrace_size) < 2)
974 VG_(clo_backtrace_size) = 2;
975 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
976 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
977 }
978
979 else
980 bad_option(argv[i]);
981 }
982
983# undef ISSPACE
984# undef STREQ
985# undef STREQN
986
987 if (VG_(clo_verbosity < 0))
988 VG_(clo_verbosity) = 0;
989
990 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
991 VG_(message)(Vg_UserMsg, "");
992 VG_(message)(Vg_UserMsg,
993 "--gdb-attach=yes conflicts with --trace-children=yes");
994 VG_(message)(Vg_UserMsg,
995 "Please choose one or the other, but not both.");
996 bad_option("--gdb-attach=yes and --trace-children=yes");
997 }
998
999 if (VG_(clo_client_perms) && !VG_(clo_instrument)) {
1000 VG_(message)(Vg_UserMsg, "");
1001 VG_(message)(Vg_UserMsg,
1002 "--client-perms=yes requires --instrument=yes");
1003 bad_option("--client-perms=yes without --instrument=yes");
1004 }
1005
1006 if (VG_(clo_client_perms))
1007 vg_assert(VG_(clo_instrument));
1008
1009 VG_(clo_logfile_fd) = eventually_logfile_fd;
1010
1011# define STRINGIFY(xx) __STRING(xx)
1012 if (VG_(clo_verbosity > 0))
1013 VG_(message)(Vg_UserMsg,
1014 "valgrind-%s, a memory error detector for x86 GNU/Linux.",
1015 STRINGIFY(VG_VERSION));
1016# undef STRINGIFY
1017 if (VG_(clo_verbosity > 0))
1018 VG_(message)(Vg_UserMsg,
1019 "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.");
1020 if (VG_(clo_verbosity) > 1) {
1021 VG_(message)(Vg_UserMsg, "Startup, with flags:");
1022 for (i = 0; i < argc; i++) {
1023 VG_(message)(Vg_UserMsg, " %s", argv[i]);
1024 }
1025 }
1026
1027 if (VG_(clo_n_suppressions) == 0) {
1028 config_error("No error-suppression files were specified.");
1029 }
1030}
1031
1032
1033/* ---------------------------------------------------------------------
1034 Copying to/from m_state_static.
1035 ------------------------------------------------------------------ */
1036
1037UInt VG_(m_state_static) [8 /* int regs, in Intel order */
1038 + 1 /* %eflags */
1039 + 1 /* %eip */
1040 + VG_SIZE_OF_FPUSTATE_W /* FPU state */
1041 ];
1042
1043void VG_(copy_baseBlock_to_m_state_static) ( void )
1044{
1045 Int i;
1046 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_eax)];
1047 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
1048 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_edx)];
1049 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
1050 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_esp)];
1051 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
1052 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_esi)];
1053 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_edi)];
1054
1055 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_eflags)];
1056 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_eip)];
1057
1058 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1059 VG_(m_state_static)[40/4 + i]
1060 = VG_(baseBlock)[VGOFF_(m_fpustate) + i];
1061}
1062
1063
1064void VG_(copy_m_state_static_to_baseBlock) ( void )
1065{
1066 Int i;
1067 VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[ 0/4];
1068 VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[ 4/4];
1069 VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[ 8/4];
1070 VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[12/4];
1071 VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[16/4];
1072 VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[20/4];
1073 VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[24/4];
1074 VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[28/4];
1075
1076 VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[32/4];
1077 VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[36/4];
1078
1079 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
1080 VG_(baseBlock)[VGOFF_(m_fpustate) + i]
1081 = VG_(m_state_static)[40/4 + i];
1082}
1083
1084
1085/* ---------------------------------------------------------------------
1086 Show accumulated counts.
1087 ------------------------------------------------------------------ */
1088
1089static void vg_show_counts ( void )
1090{
1091 VG_(message)(Vg_DebugMsg,
1092 " dispatch: %lu basic blocks, %d tt_fast misses.",
1093 VG_(bbs_done), VG_(tt_fast_misses));
1094 VG_(message)(Vg_DebugMsg,
1095 "translate: new %d (%d -> %d), discard %d (%d -> %d).",
1096 VG_(overall_in_count),
1097 VG_(overall_in_osize),
1098 VG_(overall_in_tsize),
1099 VG_(overall_out_count),
1100 VG_(overall_out_osize),
1101 VG_(overall_out_tsize) );
1102 VG_(message)(Vg_DebugMsg,
1103 " lru: %d epochs, %d clearings.",
1104 VG_(current_epoch),
1105 VG_(number_of_lrus) );
1106 VG_(message)(Vg_DebugMsg,
1107 "reg-alloc: %d t-req-spill, "
1108 "%d+%d orig+spill uis, %d total-reg-r.",
1109 VG_(translations_needing_spill),
1110 VG_(uinstrs_prealloc),
1111 VG_(uinstrs_spill),
1112 VG_(total_reg_rank) );
1113 VG_(message)(Vg_DebugMsg,
1114 "smc-check: %d checks, %d fast pass, "
1115 "%d slow pass, %d discards.",
1116 VG_(smc_total_check4s),
1117 VG_(smc_cache_passed),
1118 VG_(smc_fancy_passed),
1119 VG_(smc_discard_count) );
1120 VG_(message)(Vg_DebugMsg,
1121 " sanity: %d cheap, %d expensive checks.",
1122 VG_(sanity_fast_count),
1123 VG_(sanity_slow_count) );
1124}
1125
1126
1127/* ---------------------------------------------------------------------
1128 Main!
1129 ------------------------------------------------------------------ */
1130
1131/* Where we jump to once Valgrind has got control, and the real
1132 machine's state has been copied to the m_state_static. */
1133
1134void VG_(main) ( void )
1135{
1136 Int i;
1137
1138 /* Set up our stack sanity-check words. */
1139 for (i = 0; i < 10; i++) {
1140 VG_(stack)[i] = (UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1;
1141 VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
1142 }
1143
1144 /* Set up baseBlock offsets and copy the saved machine's state into
1145 it. */
1146 vg_init_baseBlock();
1147 VG_(copy_m_state_static_to_baseBlock)();
1148
1149 /* Process Valgrind's command-line opts (from env var VG_OPTS). */
1150 process_cmd_line_options();
1151
1152 /* Initialise the signal handling subsystem. */
1153 VG_(sigstartup_actions)();
1154
1155# ifdef VG_PROFILE
1156 VGP_(init_profiling)();
1157# endif
1158
1159 if (VG_(clo_instrument)) {
1160 VGP_PUSHCC(VgpInitAudit);
1161 VGM_(init_memory_audit)();
1162 VGP_POPCC;
1163 VGP_PUSHCC(VgpReadSyms);
1164 VG_(read_symbols)();
1165 VGP_POPCC;
1166 }
1167
1168 /* This should come after init_memory_audit; otherwise the latter
1169 carefully sets up the permissions maps to cover the anonymous
1170 mmaps for the translation table and translation cache, which
1171 wastes > 20M of virtual address space. */
1172 VG_(init_transtab_and_SMC)();
1173
1174 if (VG_(clo_verbosity) == 1) {
1175 VG_(message)(Vg_UserMsg,
1176 "For more details, rerun with: -v");
1177 }
1178
1179 /* Now it is safe for malloc et al in vg_clientmalloc.c to act
1180 instrumented-ly. */
1181 VG_(running_on_simd_CPU) = True;
1182 if (VG_(clo_instrument)) {
1183 VGM_(make_readable) ( (Addr)&VG_(running_on_simd_CPU), 1 );
1184 VGM_(make_readable) ( (Addr)&VG_(clo_instrument), 1 );
1185 VGM_(make_readable) ( (Addr)&VG_(clo_trace_malloc), 1 );
1186 VGM_(make_readable) ( (Addr)&VG_(clo_sloppy_malloc), 1 );
1187 }
1188
1189 if (VG_(clo_verbosity) > 0)
1190 VG_(message)(Vg_UserMsg, "");
1191
1192 VG_(bbs_to_go) = VG_(clo_stop_after);
1193 VG_(toploop)();
1194
1195 if (VG_(clo_verbosity) > 0)
1196 VG_(message)(Vg_UserMsg, "");
1197
1198 if (VG_(clo_instrument)) {
1199 VG_(show_all_errors)();
1200 VG_(clientmalloc_done)();
1201 if (VG_(clo_verbosity) == 1) {
1202 VG_(message)(Vg_UserMsg,
1203 "For counts of detected errors, rerun with: -v");
1204 }
1205 if (VG_(clo_leak_check)) VG_(detect_memory_leaks)();
1206 }
1207 VG_(running_on_simd_CPU) = False;
1208
1209 VG_(do_sanity_checks)(True /*include expensive checks*/ );
1210
1211 if (VG_(clo_verbosity) > 1)
1212 vg_show_counts();
1213
1214 if (0) {
1215 VG_(message)(Vg_DebugMsg, "");
1216 VG_(message)(Vg_DebugMsg,
1217 "------ Valgrind's internal memory use stats follow ------" );
1218 VG_(mallocSanityCheckAll)();
1219 VG_(show_all_arena_stats)();
1220 VG_(message)(Vg_DebugMsg,
1221 "------ Valgrind's ExeContext management stats follow ------" );
1222 VG_(show_ExeContext_stats)();
1223 VG_(message)(Vg_DebugMsg,
1224 "------ Valgrind's client block stats follow ---------------" );
1225 VG_(show_client_block_stats)();
1226 }
1227
1228# ifdef VG_PROFILE
1229 VGP_(done_profiling)();
1230# endif
1231
1232 VG_(done_prof_mem)();
1233
1234 VG_(shutdown_logging)();
1235
1236 /* In LD_PRELOAD, convert "valgrind.so" into "valgrinq.so", so that
1237 child processes don't get traced into. Also done on simulated
1238 execve system call. */
1239 if (!VG_(clo_trace_children)) {
1240 VG_(mash_LD_PRELOAD_string)(VG_(getenv)("LD_PRELOAD"));
1241 }
1242
1243 /* Prepare to restore state to the real CPU. */
1244 VG_(copy_baseBlock_to_m_state_static)();
1245
1246 /* This pushes a return address on the simulator's stack, which
1247 is abandoned. We call vg_sigshutdown_actions() at the end
1248 of vg_switch_to_real_CPU(), so as to ensure that the original
1249 stack and machine state is restored before the real signal
1250 mechanism is restored.
1251 */
1252 VG_(switch_to_real_CPU)();
1253}
1254
1255
1256/* Debugging thing .. can be called from assembly with OYNK macro. */
1257void VG_(oynk) ( Int n )
1258{
1259 OINK(n);
1260}
1261
1262
1263/* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to
1264 "valgrinq.so", which doesn't do anything. This is used to avoid
1265 tracing into child processes. To make this work the build system
1266 also supplies a dummy file, "valgrinq.so".
1267*/
1268void VG_(mash_LD_PRELOAD_string)( Char* ld_preload_str )
1269{
1270 Char* p;
1271 if (ld_preload_str == NULL)
1272 return;
1273 p = VG_(strstr)(ld_preload_str, "valgrind.so");
1274 if (p == NULL)
1275 return;
1276 p[7] = 'q';
1277}
1278
1279/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
1280 it to attach to this process. Called if the user requests this
1281 service after an error has been shown, so she can poke around and
1282 look at parameters, memory, etc. You can't meaningfully get GDB to
1283 continue the program, though; to continue, quit GDB. */
1284extern void VG_(start_GDB_whilst_on_client_stack) ( void )
1285{
1286 UChar buf[100];
1287 VG_(sprintf)(buf,
1288 "/usr/bin/gdb -nw /proc/%d/exe %d",
1289 VG_(getpid)(), VG_(getpid)());
1290 VG_(printf)("starting GDB with cmd: %s\n", buf);
1291 VG_(mash_LD_PRELOAD_string)(VG_(getenv)("LD_PRELOAD"));
1292 { /* HACK ALERT */
1293 extern int system ( const char * );
1294 system(buf);
1295 /* end of HACK ALERT */
1296 }
1297 VG_(message)(Vg_UserMsg, "");
1298 VG_(message)(Vg_UserMsg,
1299 "GDB has detached. Valgrind regains control. We continue.");
1300}
1301
1302
1303/* Print some helpful-ish text about unimplemented things, and give
1304 up. */
1305extern void VG_(unimplemented) ( Char* msg )
1306{
1307 VG_(message)(Vg_UserMsg, "");
1308 VG_(message)(Vg_UserMsg,
1309 "Valgrind detected that your program requires");
1310 VG_(message)(Vg_UserMsg,
1311 "the following unimplemented functionality:");
1312 VG_(message)(Vg_UserMsg, " %s", msg);
1313 VG_(message)(Vg_UserMsg,
1314 "This may be because the functionality is hard to implement,");
1315 VG_(message)(Vg_UserMsg,
1316 "or because no reasonable program would behave this way,");
1317 VG_(message)(Vg_UserMsg,
1318 "or because nobody has yet needed it. In any case, let me know");
1319 VG_(message)(Vg_UserMsg,
1320 "(jseward@acm.org) and/or try to work around the problem, if you can.");
1321 VG_(message)(Vg_UserMsg,
1322 "");
1323 VG_(message)(Vg_UserMsg,
1324 "Valgrind has to exit now. Sorry. Bye!");
1325 VG_(message)(Vg_UserMsg,
1326 "");
1327 VG_(exit)(1);
1328}
1329
1330
1331/*-------------------------------------------------------------*/
1332/*--- Replace some C lib things with equivs which don't get ---*/
1333/*--- spurious value warnings. THEY RUN ON SIMD CPU! ---*/
1334/*-------------------------------------------------------------*/
1335
1336char* strrchr ( const char* s, int c )
1337{
1338 UChar ch = (UChar)((UInt)c);
1339 UChar* p = (UChar*)s;
1340 UChar* last = NULL;
1341 while (True) {
1342 if (*p == ch) last = p;
1343 if (*p == 0) return last;
1344 p++;
1345 }
1346}
1347
1348char* strchr ( const char* s, int c )
1349{
1350 UChar ch = (UChar)((UInt)c);
1351 UChar* p = (UChar*)s;
1352 while (True) {
1353 if (*p == ch) return p;
1354 if (*p == 0) return NULL;
1355 p++;
1356 }
1357}
1358
1359char* strcat ( char* dest, const char* src )
1360{
1361 Char* dest_orig = dest;
1362 while (*dest) dest++;
1363 while (*src) *dest++ = *src++;
1364 *dest = 0;
1365 return dest_orig;
1366}
1367
1368unsigned int strlen ( const char* str )
1369{
1370 UInt i = 0;
1371 while (str[i] != 0) i++;
1372 return i;
1373}
1374
1375char* strcpy ( char* dest, const char* src )
1376{
1377 Char* dest_orig = dest;
1378 while (*src) *dest++ = *src++;
1379 *dest = 0;
1380 return dest_orig;
1381}
1382
1383int strncmp ( const char* s1, const char* s2, unsigned int nmax )
1384{
1385 unsigned int n = 0;
1386 while (True) {
1387 if (n >= nmax) return 0;
1388 if (*s1 == 0 && *s2 == 0) return 0;
1389 if (*s1 == 0) return -1;
1390 if (*s2 == 0) return 1;
1391
1392 if (*(UChar*)s1 < *(UChar*)s2) return -1;
1393 if (*(UChar*)s1 > *(UChar*)s2) return 1;
1394
1395 s1++; s2++; n++;
1396 }
1397}
1398
1399int strcmp ( const char* s1, const char* s2 )
1400{
1401 while (True) {
1402 if (*s1 == 0 && *s2 == 0) return 0;
1403 if (*s1 == 0) return -1;
1404 if (*s2 == 0) return 1;
1405
1406 if (*(char*)s1 < *(char*)s2) return -1;
1407 if (*(char*)s1 > *(char*)s2) return 1;
1408
1409 s1++; s2++;
1410 }
1411}
1412
1413void* memchr(const void *s, int c, unsigned int n)
1414{
1415 unsigned int i;
1416 UChar c0 = (UChar)c;
1417 UChar* p = (UChar*)s;
1418 for (i = 0; i < n; i++)
1419 if (p[i] == c0) return (void*)(&p[i]);
1420 return NULL;
1421}
1422
1423void* memcpy( void *dst, const void *src, unsigned int len )
1424{
1425 register char *d;
1426 register char *s;
1427 if ( dst > src ) {
1428 d = (char *)dst + len - 1;
1429 s = (char *)src + len - 1;
1430 while ( len-- )
1431 *d-- = *s--;
1432 } else if ( dst < src ) {
1433 d = (char *)dst;
1434 s = (char *)src;
1435 while ( len-- )
1436 *d++ = *s++;
1437 }
1438 return dst;
1439}
1440
1441/*--------------------------------------------------------------------*/
1442/*--- end vg_main.c ---*/
1443/*--------------------------------------------------------------------*/