Files updated, added and removed in order to turn the ERASER branch into HEAD
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1086 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index 5cce13d..582b652 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -26,12 +26,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
- The GNU General Public License is contained in the file LICENSE.
+ The GNU General Public License is contained in the file COPYING.
*/
#include "vg_include.h"
-#include "vg_constants.h"
-
/* ---------------------------------------------------------------------
Compute offsets into baseBlock. See comments in vg_include.h.
@@ -62,6 +60,7 @@
Int VGOFF_(sh_esi) = INVALID_OFFSET;
Int VGOFF_(sh_edi) = INVALID_OFFSET;
Int VGOFF_(sh_eflags) = INVALID_OFFSET;
+
Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
@@ -92,25 +91,25 @@
Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
Int VGOFF_(helper_DAS) = INVALID_OFFSET;
Int VGOFF_(helper_DAA) = INVALID_OFFSET;
-Int VGOFF_(helper_value_check4_fail) = INVALID_OFFSET;
-Int VGOFF_(helper_value_check2_fail) = INVALID_OFFSET;
-Int VGOFF_(helper_value_check1_fail) = INVALID_OFFSET;
-Int VGOFF_(helper_value_check0_fail) = INVALID_OFFSET;
-Int VGOFF_(helperc_LOADV4) = INVALID_OFFSET;
-Int VGOFF_(helperc_LOADV2) = INVALID_OFFSET;
-Int VGOFF_(helperc_LOADV1) = INVALID_OFFSET;
-Int VGOFF_(helperc_STOREV4) = INVALID_OFFSET;
-Int VGOFF_(helperc_STOREV2) = INVALID_OFFSET;
-Int VGOFF_(helperc_STOREV1) = INVALID_OFFSET;
Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET;
-Int VGOFF_(fpu_write_check) = INVALID_OFFSET;
-Int VGOFF_(fpu_read_check) = INVALID_OFFSET;
-Int VGOFF_(cachesim_log_non_mem_instr) = INVALID_OFFSET;
-Int VGOFF_(cachesim_log_mem_instr) = INVALID_OFFSET;
+
+/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
+ * increased too much, they won't really be compact any more... */
+#define MAX_COMPACT_HELPERS 8
+#define MAX_NONCOMPACT_HELPERS 8
+
+UInt VG_(n_compact_helpers) = 0;
+UInt VG_(n_noncompact_helpers) = 0;
+
+Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
+Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
+Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
+Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
/* This is the actual defn of baseblock. */
UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
+
/* Words. */
static Int baB_off = 0;
@@ -133,6 +132,41 @@
return off;
}
+/* Registers a function in compact_helper_addrs; compact_helper_offsets is
+ * filled in later.
+ */
+void VG_(register_compact_helper)(Addr a)
+{
+ if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
+ VG_(printf)("Can only register %d compact helpers\n",
+ MAX_COMPACT_HELPERS);
+ VG_(panic)("Too many compact helpers registered");
+ }
+ VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
+ VG_(n_compact_helpers)++;
+}
+
+/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
+ * is filled in later.
+ */
+void VG_(register_noncompact_helper)(Addr a)
+{
+ if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
+ VG_(printf)("Can only register %d non-compact helpers\n",
+ MAX_NONCOMPACT_HELPERS);
+ VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
+ VG_(panic)("Too many non-compact helpers registered");
+ }
+ VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
+ VG_(n_noncompact_helpers)++;
+}
+
+/* Allocate offsets in baseBlock for the skin helpers */
+static void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
+{
+ Int i;
+ for (i = 0; i < n; i++) offsets[i] = alloc_BaB_1_set( addrs[i] );
+}
/* Here we assign actual offsets. It's important to get the most
popular referents within 128 bytes of the start, so we can take
@@ -143,8 +177,6 @@
static void vg_init_baseBlock ( void )
{
- baB_off = 0;
-
/* Those with offsets under 128 are carefully chosen. */
/* WORD offsets in this column */
@@ -158,82 +190,42 @@
/* 7 */ VGOFF_(m_edi) = alloc_BaB(1);
/* 8 */ VGOFF_(m_eflags) = alloc_BaB(1);
- /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
- /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
- /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
- /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
- /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
- /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
- /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
- /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
- /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
+ if (VG_(needs).shadow_regs) {
+ /* 9 */ VGOFF_(sh_eax) = alloc_BaB(1);
+ /* 10 */ VGOFF_(sh_ecx) = alloc_BaB(1);
+ /* 11 */ VGOFF_(sh_edx) = alloc_BaB(1);
+ /* 12 */ VGOFF_(sh_ebx) = alloc_BaB(1);
+ /* 13 */ VGOFF_(sh_esp) = alloc_BaB(1);
+ /* 14 */ VGOFF_(sh_ebp) = alloc_BaB(1);
+ /* 15 */ VGOFF_(sh_esi) = alloc_BaB(1);
+ /* 16 */ VGOFF_(sh_edi) = alloc_BaB(1);
+ /* 17 */ VGOFF_(sh_eflags) = alloc_BaB(1);
+ }
- /* 17a */
- VGOFF_(cachesim_log_non_mem_instr)
- = alloc_BaB_1_set( (Addr) & VG_(cachesim_log_non_mem_instr) );
- /* 17b */
- VGOFF_(cachesim_log_mem_instr)
- = alloc_BaB_1_set( (Addr) & VG_(cachesim_log_mem_instr) );
+ /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
+ * and on compact helpers registered */
- /* 18 */
- VGOFF_(helper_value_check4_fail)
- = alloc_BaB_1_set( (Addr) & VG_(helper_value_check4_fail) );
- /* 19 */
- VGOFF_(helper_value_check0_fail)
- = alloc_BaB_1_set( (Addr) & VG_(helper_value_check0_fail) );
+ /* (9 or 18) + n_compact_helpers */
+ /* Register VG_(handle_esp_assignment) if needed. */
+ if (VG_(track_events).new_mem_stack_aligned ||
+ VG_(track_events).die_mem_stack_aligned)
+ VG_(register_compact_helper)( (Addr) & VG_(handle_esp_assignment) );
- /* 20 */
- VGOFF_(helperc_STOREV4)
- = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV4) );
- /* 21 */
- VGOFF_(helperc_STOREV1)
- = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV1) );
+ /* Allocate slots for compact helpers */
+ assign_helpers_in_baseBlock(VG_(n_compact_helpers),
+ VG_(compact_helper_offsets),
+ VG_(compact_helper_addrs));
- /* 22 */
- VGOFF_(helperc_LOADV4)
- = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV4) );
- /* 23 */
- VGOFF_(helperc_LOADV1)
- = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV1) );
-
- /* 24 */
- VGOFF_(handle_esp_assignment)
- = alloc_BaB_1_set( (Addr) & VGM_(handle_esp_assignment) );
-
- /* 25 */
+ /* (9/10 or 18/19) + n_compact_helpers */
VGOFF_(m_eip) = alloc_BaB(1);
/* There are currently 24 spill slots */
- /* 26 .. 49 This overlaps the magic boundary at >= 32 words, but
- most spills are to low numbered spill slots, so the ones above
- the boundary don't see much action. */
+ /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
+ * boundary at >= 32 words, but most spills are to low numbered spill
+ * slots, so the ones above the boundary don't see much action. */
VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
- /* These two pushed beyond the boundary because 2-byte transactions
- are rare. */
- /* 50 */
- VGOFF_(helperc_STOREV2)
- = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV2) );
- /* 51 */
- VGOFF_(helperc_LOADV2)
- = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV2) );
-
- /* 52 */
- VGOFF_(fpu_write_check)
- = alloc_BaB_1_set( (Addr) & VGM_(fpu_write_check) );
- /* 53 */
- VGOFF_(fpu_read_check)
- = alloc_BaB_1_set( (Addr) & VGM_(fpu_read_check) );
-
- /* Actually I don't think these two are ever used. */
- /* 54 */
- VGOFF_(helper_value_check2_fail)
- = alloc_BaB_1_set( (Addr) & VG_(helper_value_check2_fail) );
- /* 55 */
- VGOFF_(helper_value_check1_fail)
- = alloc_BaB_1_set( (Addr) & VG_(helper_value_check1_fail) );
-
- /* I gave up counting at this point. Since they're way above the
+ /* I gave up counting at this point. Since they're above the
short-amode-boundary, there's no point. */
VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W);
@@ -303,6 +295,31 @@
= alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
VGOFF_(helper_DAA)
= alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
+
+ /* Allocate slots for compact helpers */
+ assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
+ VG_(noncompact_helper_offsets),
+ VG_(noncompact_helper_addrs));
+}
+
+static void vg_init_shadow_regs ( void )
+{
+ if (VG_(needs).shadow_regs) {
+ UInt eflags;
+
+ SK_(written_shadow_regs_values) ( & VG_(written_shadow_reg), & eflags );
+ VG_(baseBlock)[VGOFF_(sh_esp)] =
+ VG_(baseBlock)[VGOFF_(sh_ebp)] =
+ VG_(baseBlock)[VGOFF_(sh_eax)] =
+ VG_(baseBlock)[VGOFF_(sh_ecx)] =
+ VG_(baseBlock)[VGOFF_(sh_edx)] =
+ VG_(baseBlock)[VGOFF_(sh_ebx)] =
+ VG_(baseBlock)[VGOFF_(sh_esi)] =
+ VG_(baseBlock)[VGOFF_(sh_edi)] = VG_(written_shadow_reg);
+ VG_(baseBlock)[VGOFF_(sh_eflags)] = eflags;
+
+ } else
+ VG_(written_shadow_reg) = VG_UNUSED_SHADOW_REG_VALUE;
}
@@ -330,15 +347,17 @@
/* 64-bit counter for the number of bbs to go before a debug exit. */
ULong VG_(bbs_to_go);
-/* Produce debugging output? */
-Bool VG_(disassemble) = False;
-
/* The current LRU epoch. */
UInt VG_(current_epoch) = 0;
/* This is the ThreadId of the last thread the scheduler ran. */
ThreadId VG_(last_run_tid) = 0;
+/* This is the argument to __NR_exit() supplied by the first thread to
+ call that syscall. We eventually pass that to __NR_exit() for
+ real. */
+UInt VG_(exitcode) = 0;
+
/* ---------------------------------------------------------------------
Counters, for informational purposes only.
@@ -396,46 +415,111 @@
/* ---------------------------------------------------------------------
+ Skin data structure initialisation
+ ------------------------------------------------------------------ */
+
+/* Init with default values. */
+VgNeeds VG_(needs) = {
+ .name = NULL,
+ .description = NULL,
+
+ .core_errors = False,
+ .skin_errors = False,
+ .run_libc_freeres = False,
+
+ .sizeof_shadow_block = 0,
+
+ .basic_block_discards = False,
+ .shadow_regs = False,
+ .command_line_options = False,
+ .client_requests = False,
+ .extended_UCode = False,
+ .syscall_wrapper = False,
+ .alternative_free = False,
+ .sanity_checks = False,
+};
+
+VgTrackEvents VG_(track_events) = {
+ /* Memory events */
+ .new_mem_startup = NULL,
+ .new_mem_heap = NULL,
+ .new_mem_stack = NULL,
+ .new_mem_stack_aligned = NULL,
+ .new_mem_stack_signal = NULL,
+ .new_mem_brk = NULL,
+ .new_mem_mmap = NULL,
+
+ .copy_mem_heap = NULL,
+ .change_mem_mprotect = NULL,
+
+ .ban_mem_heap = NULL,
+ .ban_mem_stack = NULL,
+
+ .die_mem_heap = NULL,
+ .die_mem_stack = NULL,
+ .die_mem_stack_aligned = NULL,
+ .die_mem_stack_signal = NULL,
+ .die_mem_brk = NULL,
+ .die_mem_munmap = NULL,
+
+ .bad_free = NULL,
+ .mismatched_free = NULL,
+
+ .pre_mem_read = NULL,
+ .pre_mem_read_asciiz = NULL,
+ .pre_mem_write = NULL,
+ .post_mem_write = NULL,
+
+ /* Mutex events */
+ .post_mutex_lock = NULL,
+ .post_mutex_unlock = NULL,
+};
+
+static void sanity_check_needs ( void )
+{
+#define CHECK_NOT(var, value) \
+ if ((var)==(value)) { \
+ VG_(printf)("\n`%s' not initialised\n", VG__STRING(var)); \
+ VG_(skin_error)("Uninitialised needs field\n"); \
+ }
+
+ CHECK_NOT(VG_(needs).name, NULL);
+ CHECK_NOT(VG_(needs).description, NULL);
+
+#undef CHECK_NOT
+#undef INVALID_Bool
+}
+
+/* ---------------------------------------------------------------------
Values derived from command-line options.
------------------------------------------------------------------ */
-Bool VG_(clo_error_limit);
-Bool VG_(clo_check_addrVs);
-Bool VG_(clo_GDB_attach);
-Int VG_(sanity_level);
-Int VG_(clo_verbosity);
-Bool VG_(clo_demangle);
-Bool VG_(clo_leak_check);
-Bool VG_(clo_show_reachable);
-Int VG_(clo_leak_resolution);
-Bool VG_(clo_sloppy_malloc);
-Int VG_(clo_alignment);
-Bool VG_(clo_partial_loads_ok);
-Bool VG_(clo_trace_children);
-Int VG_(clo_logfile_fd);
-Int VG_(clo_freelist_vol);
-Bool VG_(clo_workaround_gcc296_bugs);
-Int VG_(clo_n_suppressions);
+/* Define, and set defaults. */
+Bool VG_(clo_error_limit) = True;
+Bool VG_(clo_GDB_attach) = False;
+Int VG_(sanity_level) = 1;
+Int VG_(clo_verbosity) = 1;
+Bool VG_(clo_demangle) = True;
+Bool VG_(clo_sloppy_malloc) = False;
+Int VG_(clo_alignment) = 4;
+Bool VG_(clo_trace_children) = False;
+Int VG_(clo_logfile_fd) = 2;
+Int VG_(clo_n_suppressions) = 0;
Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
-Bool VG_(clo_single_step);
-Bool VG_(clo_optimise);
-Bool VG_(clo_instrument);
-Bool VG_(clo_cleanup);
-Bool VG_(clo_cachesim);
-cache_t VG_(clo_I1_cache);
-cache_t VG_(clo_D1_cache);
-cache_t VG_(clo_L2_cache);
-Int VG_(clo_smc_check);
-Bool VG_(clo_trace_syscalls);
-Bool VG_(clo_trace_signals);
-Bool VG_(clo_trace_symtab);
-Bool VG_(clo_trace_malloc);
-Bool VG_(clo_trace_sched);
-Int VG_(clo_trace_pthread_level);
-ULong VG_(clo_stop_after);
-Int VG_(clo_dump_error);
-Int VG_(clo_backtrace_size);
-Char* VG_(clo_weird_hacks);
+Bool VG_(clo_profile) = False;
+Bool VG_(clo_single_step) = False;
+Bool VG_(clo_optimise) = True;
+UChar VG_(clo_trace_codegen) = 0; // 00000000b
+Bool VG_(clo_trace_syscalls) = False;
+Bool VG_(clo_trace_signals) = False;
+Bool VG_(clo_trace_symtab) = False;
+Bool VG_(clo_trace_malloc) = False;
+Bool VG_(clo_trace_sched) = False;
+Int VG_(clo_trace_pthread_level) = 0;
+ULong VG_(clo_stop_after) = 1000000000000LL;
+Int VG_(clo_dump_error) = 0;
+Int VG_(clo_backtrace_size) = 4;
+Char* VG_(clo_weird_hacks) = NULL;
/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
to behave. Initially we say False. */
@@ -454,12 +538,11 @@
don't have to modify the original. */
static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN];
-
/* ---------------------------------------------------------------------
Processing of command-line options.
------------------------------------------------------------------ */
-static void bad_option ( Char* opt )
+void VG_(bad_option) ( Char* opt )
{
VG_(shutdown_logging)();
VG_(clo_logfile_fd) = 2; /* stderr */
@@ -487,91 +570,85 @@
config_error("couldn't find client's argc/argc/envp");
}
-static void parse_cache_opt ( cache_t* cache, char* orig_opt, int opt_len )
+static void usage ( void )
{
- int i1, i2, i3;
- int i;
- char *opt = VG_(strdup)(VG_AR_PRIVATE, orig_opt);
+ Char* usage1 =
+"usage: valgrind [options] prog-and-args\n"
+"\n"
+" core user options, with defaults in [ ], are:\n"
+" --help show this message\n"
+" --version show version\n"
+" --skin=<name> main task (skin to use) [Valgrind]\n"
+" -q --quiet run silently; only print error msgs\n"
+" -v --verbose be more verbose, incl counts of errors\n"
+" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
+" --demangle=no|yes automatically demangle C++ names? [yes]\n"
+" --num-callers=<number> show <num> callers in stack traces [4]\n"
+" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
+" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
+" --alignment=<number> set minimum alignment of allocations [4]\n"
+" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
+" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
+" --suppressions=<filename> suppress errors described in\n"
+" suppressions file <filename>\n"
+" --weird-hacks=hack1,hack2,... [no hacks selected]\n"
+" recognised hacks are: ioctl-VTIME truncate-writes\n"
+"\n"
+" %s skin user options:\n";
- i = i1 = opt_len;
- /* Option looks like "--I1=65536,2,64".
- * Find commas, replace with NULs to make three independent
- * strings, then extract numbers. Yuck. */
- while (VG_(isdigit)(opt[i])) i++;
- if (',' == opt[i]) {
- opt[i++] = '\0';
- i2 = i;
- } else goto bad;
- while (VG_(isdigit)(opt[i])) i++;
- if (',' == opt[i]) {
- opt[i++] = '\0';
- i3 = i;
- } else goto bad;
- while (VG_(isdigit)(opt[i])) i++;
- if ('\0' != opt[i]) goto bad;
+ Char* usage2 =
+"\n"
+" core options for debugging Valgrind itself are:\n"
+" --sanity-level=<number> level of sanity checking to do [1]\n"
+" --single-step=no|yes translate each instr separately? [no]\n"
+" --optimise=no|yes improve intermediate code? [yes]\n"
+" --profile=no|yes profile? (skin must be built for it) [no]\n"
+" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
+" --trace-syscalls=no|yes show all system calls? [no]\n"
+" --trace-signals=no|yes show signal handling details? [no]\n"
+" --trace-symtab=no|yes show symbol table details? [no]\n"
+" --trace-malloc=no|yes show client malloc details? [no]\n"
+" --trace-sched=no|yes show thread scheduler details? [no]\n"
+" --trace-pthread=none|some|all show pthread event details? [no]\n"
+" --stop-after=<number> switch to real CPU after executing\n"
+" <number> basic blocks [infinity]\n"
+" --dump-error=<number> show translation for basic block\n"
+" associated with <number>'th\n"
+" error context [0=don't show any]\n"
+"\n"
+" Extra options are read from env variable $VALGRIND_OPTS\n"
+"\n"
+" Valgrind is Copyright (C) 2000-2002 Julian Seward\n"
+" and licensed under the GNU General Public License, version 2.\n"
+" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
+"\n";
- cache->size = (Int)VG_(atoll)(opt + i1);
- cache->assoc = (Int)VG_(atoll)(opt + i2);
- cache->line_size = (Int)VG_(atoll)(opt + i3);
+ VG_(printf)(usage1, VG_(needs).name);
+ /* Don't print skin string directly for security, ha! */
+ if (VG_(needs).command_line_options)
+ VG_(printf)("%s", SK_(usage)());
+ else
+ VG_(printf)(" (none)\n");
+ VG_(printf)(usage2, VG_EMAIL_ADDR);
- VG_(free)(VG_AR_PRIVATE, opt);
- return;
-
- bad:
- bad_option(orig_opt);
+ VG_(shutdown_logging)();
+ VG_(clo_logfile_fd) = 2; /* stderr */
+ VG_(exit)(1);
}
static void process_cmd_line_options ( void )
{
- UChar* argv[M_VG_CMDLINE_OPTS];
- UInt argc;
- UChar* p;
- UChar* str;
- Int i, eventually_logfile_fd, ctr;
+ Char* argv[M_VG_CMDLINE_OPTS];
+ UInt argc;
+ Char* p;
+ Char* str;
+ Int i, eventually_logfile_fd, ctr;
# define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
# define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2)))
# define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn)))
- /* Set defaults. */
- VG_(clo_error_limit) = True;
- VG_(clo_check_addrVs) = True;
- VG_(clo_GDB_attach) = False;
- VG_(sanity_level) = 1;
- VG_(clo_verbosity) = 1;
- VG_(clo_demangle) = True;
- VG_(clo_leak_check) = False;
- VG_(clo_show_reachable) = False;
- VG_(clo_leak_resolution) = 2;
- VG_(clo_sloppy_malloc) = False;
- VG_(clo_alignment) = 4;
- VG_(clo_partial_loads_ok) = True;
- VG_(clo_trace_children) = False;
- VG_(clo_logfile_fd) = 2; /* stderr */
- VG_(clo_freelist_vol) = 1000000;
- VG_(clo_workaround_gcc296_bugs) = False;
- VG_(clo_n_suppressions) = 0;
- VG_(clo_single_step) = False;
- VG_(clo_optimise) = True;
- VG_(clo_instrument) = True;
- VG_(clo_cachesim) = False;
- VG_(clo_I1_cache) = UNDEFINED_CACHE;
- VG_(clo_D1_cache) = UNDEFINED_CACHE;
- VG_(clo_L2_cache) = UNDEFINED_CACHE;
- VG_(clo_cleanup) = True;
- VG_(clo_smc_check) = /* VG_CLO_SMC_SOME */ VG_CLO_SMC_NONE;
- VG_(clo_trace_syscalls) = False;
- VG_(clo_trace_signals) = False;
- VG_(clo_trace_symtab) = False;
- VG_(clo_trace_malloc) = False;
- VG_(clo_trace_sched) = False;
- VG_(clo_trace_pthread_level) = 0;
- VG_(clo_stop_after) = 1000000000000LL;
- VG_(clo_dump_error) = 0;
- VG_(clo_backtrace_size) = 4;
- VG_(clo_weird_hacks) = NULL;
-
eventually_logfile_fd = VG_(clo_logfile_fd);
/* Once logging is started, we can safely send messages pertaining
@@ -603,7 +680,10 @@
if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
VG_STARTUP_STACK_BASE_3 )) {
sp = (UInt*)VG_STARTUP_STACK_BASE_3;
-
+ } else
+ if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup),
+ VG_STARTUP_STACK_BASE_4 )) {
+ sp = (UInt*)VG_STARTUP_STACK_BASE_4;
} else {
args_grok_error(
"startup %esp is not near any VG_STARTUP_STACK_BASE_*\n "
@@ -723,7 +803,7 @@
for (i = 0; i < argc; i++) {
- if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
+ if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose"))
VG_(clo_verbosity)++;
else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet"))
VG_(clo_verbosity)--;
@@ -733,11 +813,6 @@
else if (STREQ(argv[i], "--error-limit=no"))
VG_(clo_error_limit) = False;
- else if (STREQ(argv[i], "--check-addrVs=yes"))
- VG_(clo_check_addrVs) = True;
- else if (STREQ(argv[i], "--check-addrVs=no"))
- VG_(clo_check_addrVs) = False;
-
else if (STREQ(argv[i], "--gdb-attach=yes"))
VG_(clo_GDB_attach) = True;
else if (STREQ(argv[i], "--gdb-attach=no"))
@@ -748,28 +823,6 @@
else if (STREQ(argv[i], "--demangle=no"))
VG_(clo_demangle) = False;
- else if (STREQ(argv[i], "--partial-loads-ok=yes"))
- VG_(clo_partial_loads_ok) = True;
- else if (STREQ(argv[i], "--partial-loads-ok=no"))
- VG_(clo_partial_loads_ok) = False;
-
- else if (STREQ(argv[i], "--leak-check=yes"))
- VG_(clo_leak_check) = True;
- else if (STREQ(argv[i], "--leak-check=no"))
- VG_(clo_leak_check) = False;
-
- else if (STREQ(argv[i], "--show-reachable=yes"))
- VG_(clo_show_reachable) = True;
- else if (STREQ(argv[i], "--show-reachable=no"))
- VG_(clo_show_reachable) = False;
-
- else if (STREQ(argv[i], "--leak-resolution=low"))
- VG_(clo_leak_resolution) = 2;
- else if (STREQ(argv[i], "--leak-resolution=med"))
- VG_(clo_leak_resolution) = 4;
- else if (STREQ(argv[i], "--leak-resolution=high"))
- VG_(clo_leak_resolution) = VG_DEEPEST_BACKTRACE;
-
else if (STREQ(argv[i], "--sloppy-malloc=yes"))
VG_(clo_sloppy_malloc) = True;
else if (STREQ(argv[i], "--sloppy-malloc=no"))
@@ -783,32 +836,27 @@
else if (STREQ(argv[i], "--trace-children=no"))
VG_(clo_trace_children) = False;
- else if (STREQ(argv[i], "--workaround-gcc296-bugs=yes"))
- VG_(clo_workaround_gcc296_bugs) = True;
- else if (STREQ(argv[i], "--workaround-gcc296-bugs=no"))
- VG_(clo_workaround_gcc296_bugs) = False;
-
else if (STREQN(15, argv[i], "--sanity-level="))
VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
else if (STREQN(13, argv[i], "--logfile-fd="))
eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]);
- else if (STREQN(15, argv[i], "--freelist-vol=")) {
- VG_(clo_freelist_vol) = (Int)VG_(atoll)(&argv[i][15]);
- if (VG_(clo_freelist_vol) < 0) VG_(clo_freelist_vol) = 2;
- }
-
else if (STREQN(15, argv[i], "--suppressions=")) {
if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
- VG_(message)(Vg_UserMsg, "Too many logfiles specified.");
+ VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
VG_(message)(Vg_UserMsg,
"Increase VG_CLO_MAX_SFILES and recompile.");
- bad_option(argv[i]);
+ VG_(bad_option)(argv[i]);
}
VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15];
VG_(clo_n_suppressions)++;
}
+ else if (STREQ(argv[i], "--profile=yes"))
+ VG_(clo_profile) = True;
+ else if (STREQ(argv[i], "--profile=no"))
+ VG_(clo_profile) = False;
+
else if (STREQ(argv[i], "--single-step=yes"))
VG_(clo_single_step) = True;
else if (STREQ(argv[i], "--single-step=no"))
@@ -819,35 +867,26 @@
else if (STREQ(argv[i], "--optimise=no"))
VG_(clo_optimise) = False;
- else if (STREQ(argv[i], "--instrument=yes"))
- VG_(clo_instrument) = True;
- else if (STREQ(argv[i], "--instrument=no"))
- VG_(clo_instrument) = False;
-
- else if (STREQ(argv[i], "--cleanup=yes"))
- VG_(clo_cleanup) = True;
- else if (STREQ(argv[i], "--cleanup=no"))
- VG_(clo_cleanup) = False;
-
- else if (STREQ(argv[i], "--cachesim=yes"))
- VG_(clo_cachesim) = True;
- else if (STREQ(argv[i], "--cachesim=no"))
- VG_(clo_cachesim) = False;
-
- /* 5 is length of "--I1=" */
- else if (0 == VG_(strncmp)(argv[i], "--I1=", 5))
- parse_cache_opt(&VG_(clo_I1_cache), argv[i], 5);
- else if (0 == VG_(strncmp)(argv[i], "--D1=", 5))
- parse_cache_opt(&VG_(clo_D1_cache), argv[i], 5);
- else if (0 == VG_(strncmp)(argv[i], "--L2=", 5))
- parse_cache_opt(&VG_(clo_L2_cache), argv[i], 5);
-
- else if (STREQ(argv[i], "--smc-check=none"))
- VG_(clo_smc_check) = VG_CLO_SMC_NONE;
- else if (STREQ(argv[i], "--smc-check=some"))
- VG_(clo_smc_check) = VG_CLO_SMC_SOME;
- else if (STREQ(argv[i], "--smc-check=all"))
- VG_(clo_smc_check) = VG_CLO_SMC_ALL;
+ /* "vwxyz" --> 000zyxwv (binary) */
+ else if (STREQN(16, argv[i], "--trace-codegen=")) {
+ Int j;
+ char* opt = & argv[i][16];
+
+ if (5 != VG_(strlen)(opt)) {
+ VG_(message)(Vg_UserMsg,
+ "--trace-codegen argument must have 5 digits");
+ VG_(bad_option)(argv[i]);
+ }
+ for (j = 0; j < 5; j++) {
+ if ('0' == opt[j]) { /* do nothing */ }
+ else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
+ else {
+ VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
+ "contain 0s and 1s");
+ VG_(bad_option)(argv[i]);
+ }
+ }
+ }
else if (STREQ(argv[i], "--trace-syscalls=yes"))
VG_(clo_trace_syscalls) = True;
@@ -899,8 +938,13 @@
VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
}
+ else if (VG_(needs).command_line_options) {
+ Bool ok = SK_(process_cmd_line_option)(argv[i]);
+ if (!ok)
+ usage();
+ }
else
- bad_option(argv[i]);
+ usage();
}
# undef ISSPACE
@@ -917,7 +961,7 @@
VG_(message)(Vg_UserMsg,
"Invalid --alignment= setting. "
"Should be a power of 2, >= 4, <= 4096.");
- bad_option("--alignment");
+ VG_(bad_option)("--alignment");
}
if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
@@ -926,26 +970,14 @@
"--gdb-attach=yes conflicts with --trace-children=yes");
VG_(message)(Vg_UserMsg,
"Please choose one or the other, but not both.");
- bad_option("--gdb-attach=yes and --trace-children=yes");
+ VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
}
VG_(clo_logfile_fd) = eventually_logfile_fd;
- /* Don't do memory checking if simulating the cache. */
- if (VG_(clo_cachesim)) {
- VG_(clo_instrument) = False;
- }
-
if (VG_(clo_verbosity > 0)) {
- if (VG_(clo_cachesim)) {
- VG_(message)(Vg_UserMsg,
- "cachegrind-%s, an I1/D1/L2 cache profiler for x86 GNU/Linux.",
- VERSION);
- } else {
- VG_(message)(Vg_UserMsg,
- "valgrind-%s, a memory error detector for x86 GNU/Linux.",
- VERSION);
- }
+ VG_(message)(Vg_UserMsg, "%s-%s, %s for x86 GNU/Linux.",
+ VG_(needs).name, VERSION, VG_(needs).description);
}
if (VG_(clo_verbosity > 0))
@@ -958,12 +990,12 @@
}
}
- if (VG_(clo_n_suppressions) == 0 && !VG_(clo_cachesim)) {
+ if (VG_(clo_n_suppressions) == 0 &&
+ (VG_(needs).core_errors || VG_(needs).skin_errors)) {
config_error("No error-suppression files were specified.");
}
}
-
/* ---------------------------------------------------------------------
Copying to/from m_state_static.
------------------------------------------------------------------ */
@@ -1015,11 +1047,40 @@
= VG_(m_state_static)[40/4 + i];
}
+Addr VG_(get_stack_pointer) ( void )
+{
+ return VG_(baseBlock)[VGOFF_(m_esp)];
+}
+
+/* Some random tests needed for leak checking */
+
+Bool VG_(within_stack)(Addr a)
+{
+ if (a >= ((Addr)(&VG_(stack)))
+ && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack)))
+ return True;
+ else
+ return False;
+}
+
+Bool VG_(within_m_state_static)(Addr a)
+{
+ if (a >= ((Addr)(&VG_(m_state_static)))
+ && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static)))
+ return True;
+ else
+ return False;
+}
/* ---------------------------------------------------------------------
Show accumulated counts.
------------------------------------------------------------------ */
+static __inline__ Int safe_idiv(Int a, Int b)
+{
+ return (b == 0 ? 0 : a / b);
+}
+
static void vg_show_counts ( void )
{
VG_(message)(Vg_DebugMsg,
@@ -1027,13 +1088,17 @@
VG_(current_epoch),
VG_(number_of_lrus) );
VG_(message)(Vg_DebugMsg,
- "translate: new %d (%d -> %d), discard %d (%d -> %d).",
+ "translate: new %d (%d -> %d; ratio %d:10)",
VG_(overall_in_count),
VG_(overall_in_osize),
VG_(overall_in_tsize),
+ safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
+ VG_(message)(Vg_DebugMsg,
+ " discard %d (%d -> %d; ratio %d:10).",
VG_(overall_out_count),
VG_(overall_out_osize),
- VG_(overall_out_tsize) );
+ VG_(overall_out_tsize),
+ safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
VG_(message)(Vg_DebugMsg,
" dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",
VG_(bbs_done), VG_(num_scheduling_events_MAJOR),
@@ -1050,6 +1115,7 @@
" sanity: %d cheap, %d expensive checks.",
VG_(sanity_fast_count),
VG_(sanity_slow_count) );
+ VG_(print_ccall_stats)();
}
@@ -1072,21 +1138,32 @@
VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321;
}
- /* Set up baseBlock offsets and copy the saved machine's state into
- it. */
+ /* Setup stuff that depends on the skin. Must be before:
+ - vg_init_baseBlock(): to register helpers
+ - process_cmd_line_options(): to register skin name and description,
+ and turn on/off 'command_line_options' need
+ - init_memory() (to setup memory event trackers).
+ */
+ SK_(pre_clo_init) ( & VG_(needs), & VG_(track_events) );
+ sanity_check_needs();
+
+ /* Set up baseBlock offsets and copy the saved machine's state into it. */
vg_init_baseBlock();
VG_(copy_m_state_static_to_baseBlock)();
+ vg_init_shadow_regs();
/* Process Valgrind's command-line opts (from env var VG_OPTS). */
process_cmd_line_options();
/* Hook to delay things long enough so we can get the pid and
attach GDB in another shell. */
- if (0) {
+#if 0
+ {
Int p, q;
for (p = 0; p < 50000; p++)
for (q = 0; q < 50000; q++) ;
}
+#endif
/* Initialise the scheduler, and copy the client's state from
baseBlock into VG_(threads)[1]. This has to come before signal
@@ -1098,31 +1175,34 @@
VG_(sigstartup_actions)();
/* Perhaps we're profiling Valgrind? */
-# ifdef VG_PROFILE
- VGP_(init_profiling)();
-# endif
+ if (VG_(clo_profile))
+ VGP_(init_profiling)();
/* Start calibration of our RDTSC-based clock. */
VG_(start_rdtsc_calibration)();
- if (VG_(clo_instrument) || VG_(clo_cachesim)) {
- VGP_PUSHCC(VgpInitAudit);
- VGM_(init_memory_audit)();
- VGP_POPCC;
- }
+ /* Do this here just to give rdtsc calibration more time */
+ SK_(post_clo_init)();
- VGP_PUSHCC(VgpReadSyms);
- VG_(read_symbols)();
- VGP_POPCC;
+ /* Must come after SK_(init) so memory handler accompaniments (eg.
+ * shadow memory) can be setup ok */
+ VGP_PUSHCC(VgpInitMem);
+ VG_(init_memory)();
+ VGP_POPCC(VgpInitMem);
+
+ /* Read the list of errors to suppress. This should be found in
+ the file specified by vg_clo_suppressions. */
+ if (VG_(needs).core_errors || VG_(needs).skin_errors)
+ VG_(load_suppressions)();
/* End calibration of our RDTSC-based clock, leaving it as long as
we can. */
VG_(end_rdtsc_calibration)();
- /* This should come after init_memory_audit; otherwise the latter
- carefully sets up the permissions maps to cover the anonymous
- mmaps for the translation table and translation cache, which
- wastes > 20M of virtual address space. */
+ /* This should come after init_memory_and_symbols(); otherwise the
+ latter carefully sets up the permissions maps to cover the
+ anonymous mmaps for the translation table and translation cache,
+ which wastes > 20M of virtual address space. */
VG_(init_tt_tc)();
if (VG_(clo_verbosity) == 1) {
@@ -1132,26 +1212,18 @@
/* Now it is safe for malloc et al in vg_clientmalloc.c to act
instrumented-ly. */
- VG_(running_on_simd_CPU) = True;
- if (VG_(clo_instrument)) {
- VGM_(make_readable) ( (Addr)&VG_(running_on_simd_CPU), 1 );
- VGM_(make_readable) ( (Addr)&VG_(clo_instrument), 1 );
- VGM_(make_readable) ( (Addr)&VG_(clo_trace_malloc), 1 );
- VGM_(make_readable) ( (Addr)&VG_(clo_sloppy_malloc), 1 );
- }
-
- if (VG_(clo_cachesim))
- VG_(init_cachesim)();
-
if (VG_(clo_verbosity) > 0)
VG_(message)(Vg_UserMsg, "");
VG_(bbs_to_go) = VG_(clo_stop_after);
+
/* Run! */
+ VG_(running_on_simd_CPU) = True;
VGP_PUSHCC(VgpSched);
src = VG_(scheduler)();
- VGP_POPCC;
+ VGP_POPCC(VgpSched);
+ VG_(running_on_simd_CPU) = False;
if (VG_(clo_verbosity) > 0)
VG_(message)(Vg_UserMsg, "");
@@ -1161,25 +1233,19 @@
"Warning: pthread scheduler exited due to deadlock");
}
- if (VG_(clo_instrument)) {
+ if (VG_(needs).core_errors || VG_(needs).skin_errors)
VG_(show_all_errors)();
- VG_(clientmalloc_done)();
- if (VG_(clo_verbosity) == 1) {
- VG_(message)(Vg_UserMsg,
- "For counts of detected errors, rerun with: -v");
- }
- if (VG_(clo_leak_check)) VG_(detect_memory_leaks)();
- }
- VG_(running_on_simd_CPU) = False;
- if (VG_(clo_cachesim))
- VG_(do_cachesim_results)(VG_(client_argc), VG_(client_argv));
+ SK_(fini)();
VG_(do_sanity_checks)( True /*include expensive checks*/ );
if (VG_(clo_verbosity) > 1)
vg_show_counts();
+ if (VG_(clo_verbosity) > 2)
+ VG_(print_UInstr_histogram)();
+
if (0) {
VG_(message)(Vg_DebugMsg, "");
VG_(message)(Vg_DebugMsg,
@@ -1189,16 +1255,10 @@
VG_(message)(Vg_DebugMsg,
"------ Valgrind's ExeContext management stats follow ------" );
VG_(show_ExeContext_stats)();
- VG_(message)(Vg_DebugMsg,
- "------ Valgrind's client block stats follow ---------------" );
- VG_(show_client_block_stats)();
}
-# ifdef VG_PROFILE
- VGP_(done_profiling)();
-# endif
-
- VG_(done_prof_mem)();
+ if (VG_(clo_profile))
+ VGP_(done_profiling)();
VG_(shutdown_logging)();
@@ -1220,9 +1280,10 @@
&& VG_(last_run_tid) < VG_N_THREADS);
tst = & VG_(threads)[VG_(last_run_tid)];
vg_assert(tst->status == VgTs_Runnable);
- /* The thread's %EBX will hold the arg to exit(), so we just
- do exit with that arg. */
- VG_(exit)( tst->m_ebx );
+ /* The thread's %EBX at the time it did __NR_exit() will hold
+ the arg to __NR_exit(), so we just do __NR_exit() with
+ that arg. */
+ VG_(exit)( VG_(exitcode) );
/* NOT ALIVE HERE! */
VG_(panic)("entered the afterlife in vg_main() -- ExitSyscall");
break; /* what the hell :) */
@@ -1267,6 +1328,10 @@
tracing into child processes. To make this work the build system
also supplies a dummy file, "valgrinq.so".
+ Also replace "vgskin_<foo>.so" with whitespace, for the same reason;
+ without it, child processes try to find valgrind.so symbols in the
+ skin .so.
+
Also look for $(libdir)/lib/valgrind in LD_LIBRARY_PATH and change
it to $(libdir)/lib/valgrinq, so as to make our libpthread.so
disappear.
@@ -1274,20 +1339,22 @@
void VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH) ( Char* ld_preload_str,
Char* ld_library_path_str )
{
- Char* p_prel = NULL;
- Char* p_path = NULL;
- Int what = 0;
+ Char* p_prel = NULL;
+ Char* sk_prel = NULL;
+ Char* p_path = NULL;
+ Int what = 0;
if (ld_preload_str == NULL || ld_library_path_str == NULL)
goto mutancy;
/* VG_(printf)("%s %s\n", ld_preload_str, ld_library_path_str); */
p_prel = VG_(strstr)(ld_preload_str, "valgrind.so");
+ sk_prel = VG_(strstr)(ld_preload_str, "vgskin_");
p_path = VG_(strstr)(ld_library_path_str, VG_LIBDIR);
+ what = 1;
if (p_prel == NULL) {
/* perhaps already happened? */
- what = 1;
if (VG_(strstr)(ld_preload_str, "valgrinq.so") == NULL)
goto mutancy;
if (VG_(strstr)(ld_library_path_str, "lib/valgrinq") == NULL)
@@ -1296,10 +1363,30 @@
}
what = 2;
+ if (sk_prel == NULL) goto mutancy;
+
+ what = 3;
if (p_path == NULL) goto mutancy;
+ what = 4;
+ {
+ /* Blank from "vgskin_" back to prev. LD_PRELOAD entry, or start */
+ Char* p = sk_prel;
+ while (*p != ':' && p > ld_preload_str) {
+ *p = ' ';
+ p--;
+ }
+ /* Blank from "vgskin_" to next LD_PRELOAD entry */
+ while (*p != ':' && *p != '\0') {
+ *p = ' ';
+ p++;
+ }
+ if (*p == '\0') goto mutancy; /* valgrind.so has disappeared?! */
+ *p = ' '; /* blank ending ':' */
+ }
+
/* in LD_PRELOAD, turn valgrind.so into valgrinq.so. */
- what = 3;
+ what = 5;
if (p_prel[7] != 'd') goto mutancy;
p_prel[7] = 'q';
@@ -1307,10 +1394,10 @@
.../lib/valgrind .../lib/valgrinq, which doesn't exist,
so that our own libpthread.so goes out of scope. */
p_path += VG_(strlen)(VG_LIBDIR);
- what = 4;
+ what = 6;
if (p_path[0] != '/') goto mutancy;
p_path++; /* step over / */
- what = 5;
+ what = 7;
if (p_path[7] != 'd') goto mutancy;
p_path[7] = 'q';
return;
@@ -1406,6 +1493,70 @@
}
+/* ---------------------------------------------------------------------
+ Sanity check machinery (permanently engaged).
+ ------------------------------------------------------------------ */
+
+/* A fast sanity check -- suitable for calling circa once per
+ millisecond. */
+
+void VG_(do_sanity_checks) ( Bool force_expensive )
+{
+ Int i;
+
+ if (VG_(sanity_level) < 1) return;
+
+ /* --- First do all the tests that we can do quickly. ---*/
+
+ VG_(sanity_fast_count)++;
+
+ /* Check that we haven't overrun our private stack. */
+ for (i = 0; i < 10; i++) {
+ vg_assert(VG_(stack)[i]
+ == ((UInt)(&VG_(stack)[i]) ^ 0xA4B3C2D1));
+ vg_assert(VG_(stack)[10000-1-i]
+ == ((UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321));
+ }
+
+ /* Check stuff pertaining to the memory check system. */
+
+ /* Check that nobody has spuriously claimed that the first or
+ last 16 pages of memory have become accessible [...] */
+ if (VG_(needs).sanity_checks)
+ vg_assert(SK_(cheap_sanity_check)());
+
+ /* --- Now some more expensive checks. ---*/
+
+ /* Once every 25 times, check some more expensive stuff. */
+ if ( force_expensive
+ || VG_(sanity_level) > 1
+ || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
+
+ VG_(sanity_slow_count)++;
+
+# if 0
+ { void zzzmemscan(void); zzzmemscan(); }
+# endif
+
+ if ((VG_(sanity_fast_count) % 250) == 0)
+ VG_(sanity_check_tc_tt)();
+
+ if (VG_(needs).sanity_checks) {
+ vg_assert(SK_(expensive_sanity_check)());
+ }
+ /*
+ if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
+ */
+ }
+
+ if (VG_(sanity_level) > 1) {
+ /* Check sanity of the low-level memory manager. Note that bugs
+ in the client's code can cause this to fail, so we don't do
+ this check unless specially asked for. And because it's
+ potentially very expensive. */
+ VG_(mallocSanityCheckAll)();
+ }
+}
/*--------------------------------------------------------------------*/
/*--- end vg_main.c ---*/
/*--------------------------------------------------------------------*/