From: Julian Seward Date: Sat, 2 Apr 2005 23:40:59 +0000 (+0000) Subject: In vg_memory.c, allow the stack-change threshold to be specified by a X-Git-Tag: svn/VALGRIND_3_0_0~806 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e735dde575d8c26392dcbc72d595762b447d8f5;p=thirdparty%2Fvalgrind.git In vg_memory.c, allow the stack-change threshold to be specified by a command-line flag (--max-stackframe=number), rather than hardwiring it to 2000000. This is helpful for dealing with unruly Fortran programs which want to allocate large arrays on the stack. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3512 --- diff --git a/coregrind/core.h b/coregrind/core.h index 3204d11460..fcfd1bf557 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -270,6 +270,10 @@ extern Bool VG_(clo_support_elan3); /* Should we show VEX emulation warnings? Default: NO */ extern Bool VG_(clo_show_emwarns); +/* How much does the stack pointer have to change before tools + consider a stack switch to have happened? Default: 2000000 bytes */ +extern Int VG_(clo_max_stackframe); + /* Set up the libc freeres wrapper */ extern void VGA_(intercept_libc_freeres_wrapper)(Addr); diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index c8e29ad5a7..ba8f21e96b 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -1446,6 +1446,7 @@ Bool VG_(clo_support_elan3) = False; Bool VG_(clo_branchpred) = False; Bool VG_(clo_model_pthreads) = False; Bool VG_(clo_show_emwarns) = False; +Int VG_(clo_max_stackframe) = 2000000; static Bool VG_(clo_wait_for_gdb) = False; @@ -1487,6 +1488,8 @@ static void usage ( Bool debug_help ) " --db-attach=no|yes start debugger when errors detected? [no]\n" " --db-command= command to start debugger [gdb -nw %%f %%p]\n" " --input-fd= file descriptor for input [0=stdin]\n" +" --max-stackframe= assume stack switch for SP changes larger\n" +" than bytes [2000000]\n" "\n"; Char* usage2 = @@ -1675,6 +1678,7 @@ static void process_cmd_line_options( UInt* client_auxv, const char* toolname ) else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck)) else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3)) else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns)) + else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe)) else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile)) else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres)) else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main)) diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c index d4d50d4ee0..e32986c450 100644 --- a/coregrind/vg_memory.c +++ b/coregrind/vg_memory.c @@ -1063,32 +1063,38 @@ Segment *VG_(find_segment_above_mapped)(Addr a) addresses below %esp are not live; those at and above it are. */ -/* Kludgey ... how much does %esp have to change before we reckon that - the application is switching stacks ? */ -#define VG_PLAUSIBLE_STACK_SIZE 8000000 -#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4) - /* This function gets called if new_mem_stack and/or die_mem_stack are tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4) isn't used in preference */ VGA_REGPARM(2) void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP ) { + static Int moans = 3; Word delta = (Word)new_SP - (Word)old_SP; - if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) { - /* %esp has changed by more than HUGE_DELTA. We take this to mean - that the application is switching to a new stack, for whatever - reason. + if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) { + /* SP has changed by more than some threshold amount (by + default, 2MB). We take this to mean that the application is + switching to a new stack, for whatever reason. JRS 20021001: following discussions with John Regehr, if a stack switch happens, it seems best not to mess at all with memory permissions. Seems to work well with Netscape 4.X. Really the only remaining difficulty is knowing exactly when a stack switch is happening. */ - if (VG_(clo_verbosity) > 1) - VG_(message)(Vg_UserMsg, "Warning: client switching stacks? " - "%%esp: %p --> %p", old_SP, new_SP); + if (VG_(clo_verbosity) > 0 && moans > 0) { + moans--; + VG_(message)(Vg_UserMsg, + "Warning: client switching stacks? " + "SP change: %p --> %p", old_SP, new_SP); + VG_(message)(Vg_UserMsg, + " to suppress, use: --max-stackframe=%d or greater", + (delta < 0 ? -delta : delta)); + if (moans == 0) + VG_(message)(Vg_UserMsg, + " further instances of this message " + "will not be shown."); + } } else if (delta < 0) { VG_TRACK( new_mem_stack, new_SP, -delta ); diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index b9f9587168..3a0e79cbf1 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -783,6 +783,38 @@ errors, e.g. Memcheck, but not Cachegrind. as the file name or socket details. + + --max-stackframe=<number> + [default=2000000] + + You may need to use this option if your program has large + stack-allocated arrays. Valgrind keeps track of your program's + stack pointer. If it changes by more than the threshold amount, + Valgrind assumes your program is switching to a different stack, + and Memcheck behaves differently than it would for a stack pointer + change smaller than the threshold. Usually this heuristic works + well. However, if your program allocates large structures on the + stack, this heuristic will be fooled, and Memcheck will + subsequently report large numbers of invalid stack accesses. This + option allows you to change the threshold to a different value. + + + You should only consider use of this flag if Valgrind's debug output + directs you to do so. In that case it will tell you the new + threshold you should specify. + + + In general, allocating large structures on the stack is a bad + idea, because (1) you can easily run out of stack space, + especially on systems with limited memory or which expect to + support large numbers of threads each with a small stack, and (2) + because the error checking performed by Memcheck is more effective + for heap-allocated data than for stack-allocated data. If you + have to use this flag, you may wish to consider rewriting your + code to allocate on the heap rather than on the stack. + + + --db-attach=no [default] --db-attach=yes