mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-05 11:10:21 +00:00
Implement, and document, the --run-libc-freeres=no|yes flag.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1186
This commit is contained in:
parent
d822464c4a
commit
b2ec9dae1b
@ -585,6 +585,33 @@ follows:
|
||||
in g++-3.0.4.
|
||||
</li><br><p>
|
||||
|
||||
<li><code>--run-libc-freeres=yes</code> [the default]<br>
|
||||
<code>--run-libc-freeres=no</code>
|
||||
<p>The GNU C library (<code>libc.so</code>), which is used by
|
||||
all programs, may allocate memory for its own uses. Usually it
|
||||
doesn't bother to free that memory when the program ends - there
|
||||
would be no point, since the Linux kernel reclaims all process
|
||||
resources when a process exits anyway, so it would just slow
|
||||
things down.
|
||||
<p>
|
||||
The glibc authors realised that this behaviour causes leak checkers, such
|
||||
as Valgrind, to falsely report leaks in glibc, when a leak check
|
||||
is done at exit. In order to avoid this, they provided a
|
||||
routine called <code>__libc_freeres</code> specifically to make
|
||||
glibc release all memory it has allocated. The MemCheck and
|
||||
AddrCheck skins (normal and lightweight valgrinding) therefore
|
||||
try and run <code>__libc_freeres</code> at exit.
|
||||
<p>
|
||||
Unfortunately, in some versions of glibc,
|
||||
<code>__libc_freeres</code> is sufficiently buggy to cause
|
||||
segmentation faults. This is particularly noticeable on Red Hat
|
||||
7.1. So this flag is provided in order to inhibit the run of
|
||||
<code>__libc_freeres</code>. If your program seems to run fine
|
||||
on valgrind, but segfaults at exit, you may find that
|
||||
<code>--run-libc-freeres=no</code> fixes that, although at the
|
||||
cost of possibly falsely reporting space leaks in
|
||||
<code>libc.so</code>.
|
||||
|
||||
<li><code>--error-limit=yes</code> [default]<br>
|
||||
<code>--error-limit=no</code> <p>When enabled, valgrind stops
|
||||
reporting errors after 30000 in total, or 300 different ones,
|
||||
@ -592,12 +619,6 @@ follows:
|
||||
from becoming a huge performance overhead in programs with many
|
||||
errors. </li><br><p>
|
||||
|
||||
<li><code>--cachesim=no</code> [default]<br>
|
||||
<code>--cachesim=yes</code> <p>When enabled, turns off memory
|
||||
checking, and turns on cache profiling. Cache profiling is
|
||||
described in detail in <a href="#cache">Section 7</a>.
|
||||
</li><br><p>
|
||||
|
||||
<li><code>--weird-hacks=hack1,hack2,...</code>
|
||||
Pass miscellaneous hints to Valgrind which slightly modify the
|
||||
simulated behaviour in nonstandard or dangerous ways, possibly
|
||||
|
||||
@ -584,7 +584,7 @@ void VG_(__libc_freeres_wrapper)( void )
|
||||
{
|
||||
int res;
|
||||
extern void __libc_freeres(void);
|
||||
//__libc_freeres();
|
||||
__libc_freeres();
|
||||
VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
|
||||
VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0);
|
||||
/*NOTREACHED*/
|
||||
|
||||
@ -204,6 +204,12 @@ extern Int VG_(clo_dump_error);
|
||||
extern Int VG_(clo_backtrace_size);
|
||||
/* Engage miscellaneous wierd hacks needed for some progs. */
|
||||
extern Char* VG_(clo_weird_hacks);
|
||||
/* Should we run __libc_freeres at exit? Sometimes causes crashes.
|
||||
Default: YES. Note this is subservient to VG_(needs).libc_freeres;
|
||||
if the latter says False, then the setting of VG_(clo_weird_hacks)
|
||||
is ignored. Ie if a skin says no, I don't want this to run, that
|
||||
cannot be overridden from the command line. */
|
||||
extern Bool VG_(clo_run_libc_freeres);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
@ -550,6 +550,7 @@ ULong VG_(clo_stop_after) = 1000000000000LL;
|
||||
Int VG_(clo_dump_error) = 0;
|
||||
Int VG_(clo_backtrace_size) = 4;
|
||||
Char* VG_(clo_weird_hacks) = NULL;
|
||||
Bool VG_(clo_run_libc_freeres) = True;
|
||||
|
||||
/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
|
||||
to behave. Initially we say False. */
|
||||
@ -618,6 +619,7 @@ static void usage ( void )
|
||||
" --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"
|
||||
" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
|
||||
" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
|
||||
" --suppressions=<filename> suppress errors described in\n"
|
||||
" suppressions file <filename>\n"
|
||||
@ -869,6 +871,11 @@ static void process_cmd_line_options ( void )
|
||||
else if (STREQ(argv[i], "--trace-children=no"))
|
||||
VG_(clo_trace_children) = False;
|
||||
|
||||
else if (STREQ(argv[i], "--run-libc-freeres=yes"))
|
||||
VG_(clo_run_libc_freeres) = True;
|
||||
else if (STREQ(argv[i], "--run-libc-freeres=no"))
|
||||
VG_(clo_run_libc_freeres) = False;
|
||||
|
||||
else if (STREQN(15, argv[i], "--sanity-level="))
|
||||
VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
|
||||
|
||||
|
||||
@ -1479,30 +1479,41 @@ VgSchedReturnCode VG_(scheduler) ( void )
|
||||
__libc_freeres does some invalid frees which crash
|
||||
the unprotected malloc/free system. */
|
||||
|
||||
/* If __NR_exit, remember the supplied argument. */
|
||||
if (VG_(threads)[tid].m_eax == __NR_exit)
|
||||
if (VG_(threads)[tid].m_eax == __NR_exit) {
|
||||
|
||||
/* If __NR_exit, remember the supplied argument. */
|
||||
VG_(exitcode) = VG_(threads)[tid].m_ebx; /* syscall arg1 */
|
||||
|
||||
if (VG_(threads)[tid].m_eax == __NR_exit
|
||||
&& ! VG_(needs).libc_freeres) {
|
||||
if (VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
|
||||
VG_(message)(Vg_DebugMsg,
|
||||
"Caught __NR_exit; quitting");
|
||||
}
|
||||
return VgSrc_ExitSyscall;
|
||||
/* Only run __libc_freeres if the skin says it's ok and
|
||||
it hasn't been overridden with --run-libc-freeres=no
|
||||
on the command line. */
|
||||
|
||||
if (VG_(needs).libc_freeres && VG_(clo_run_libc_freeres)) {
|
||||
|
||||
if (VG_(clo_verbosity) >= 2
|
||||
|| VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
|
||||
VG_(message)(Vg_DebugMsg,
|
||||
"Caught __NR_exit; running __libc_freeres()");
|
||||
}
|
||||
VG_(nuke_all_threads_except) ( tid );
|
||||
VG_(threads)[tid].m_eip = (UInt)(&VG_(__libc_freeres_wrapper));
|
||||
vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
|
||||
goto stage1; /* party on, dudes (but not for much longer :) */
|
||||
|
||||
} else {
|
||||
/* We won't run __libc_freeres; just exit now. */
|
||||
if (VG_(clo_verbosity) >= 2
|
||||
|| VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
|
||||
VG_(message)(Vg_DebugMsg,
|
||||
"Caught __NR_exit; quitting");
|
||||
}
|
||||
return VgSrc_ExitSyscall;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (VG_(threads)[tid].m_eax == __NR_exit) {
|
||||
vg_assert(VG_(needs).libc_freeres);
|
||||
if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
|
||||
VG_(message)(Vg_DebugMsg,
|
||||
"Caught __NR_exit; running __libc_freeres()");
|
||||
}
|
||||
VG_(nuke_all_threads_except) ( tid );
|
||||
VG_(threads)[tid].m_eip = (UInt)(&VG_(__libc_freeres_wrapper));
|
||||
vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
|
||||
goto stage1; /* party on, dudes (but not for much longer :) */
|
||||
}
|
||||
/* We've dealt with __NR_exit at this point. */
|
||||
vg_assert(VG_(threads)[tid].m_eax != __NR_exit);
|
||||
|
||||
/* Trap syscalls to __NR_sched_yield and just have this
|
||||
thread yield instead. Not essential, just an
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user