commit b5dde4a2ff59cc87390a33d85c7bf0ad6443cb6c Author: iraisr Date: Wed Mar 30 17:53:03 2016 +0000 Run __gnu_cxx::__freeres() cleanup function available from libstdc++ when available, similar to existing __libc_freeres(). New option --run-cxx-freeres= can be used to change whether this cleanup function is called or not. Note that __gnu_cxx::__freeres() is currently available only in gcc 6. It is not yet decided what to do about libstdc++ from gcc 5. Tracked under https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69945 for libstdc++. Fixes BZ#345307 (partially). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15840 a5019735-40e9-0310-863c-91ae7b9d1cf9 diff --git a/coregrind/m_clientstate.c b/coregrind/m_clientstate.c index 7cbc7c7..296d658 100644 --- a/coregrind/m_clientstate.c +++ b/coregrind/m_clientstate.c @@ -106,9 +106,9 @@ HChar* VG_(name_of_launcher) = NULL; Int VG_(fd_soft_limit) = -1; Int VG_(fd_hard_limit) = -1; -/* Useful addresses extracted from the client */ -/* Where is the __libc_freeres_wrapper routine we made? */ -Addr VG_(client___libc_freeres_wrapper) = 0; +/* Useful addresses extracted from the client. */ +/* Where is the freeres_wrapper routine we made? */ +Addr VG_(client_freeres_wrapper) = 0; /* x86-linux only: where is glibc's _dl_sysinfo_int80 function? Finding it isn't essential, but knowing where it is does sometimes diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 54997bd..8cfaf82 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -36,6 +36,7 @@ #include "pub_core_clientstate.h" #include "pub_core_aspacemgr.h" #include "pub_core_aspacehl.h" +#include "pub_core_clreq.h" #include "pub_core_commandline.h" #include "pub_core_debuglog.h" #include "pub_core_errormgr.h" @@ -176,6 +177,8 @@ static void usage_NORETURN ( Bool debug_help ) " --vgdb-shadow-registers=no|yes let gdb see the shadow registers [no]\n" " --vgdb-prefix= prefix for vgdb FIFOs [%s]\n" " --run-libc-freeres=no|yes free up glibc memory at exit on Linux? [yes]\n" +" --run-cxx-freeres=no|yes free up libstdc++ memory at exit on Linux\n" +" and Solaris? [yes]\n" " --sim-hints=hint1,hint2,... activate unusual sim behaviours [none] \n" " where hint is one of:\n" " lax-ioctls lax-doors fuse-compatible enable-outer\n" @@ -644,6 +647,7 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, else if VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns)) {} else if VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres)) {} + else if VG_BOOL_CLO(arg, "--run-cxx-freeres", VG_(clo_run_cxx_freeres)) {} else if VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main)) {} else if VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp)) {} else if VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds)) {} @@ -2560,8 +2564,8 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) So don't. The final_tidyup call makes a bit of a nonsense of the ExitProcess - case, since it will run the libc_freeres function, thus allowing - other lurking threads to run again. Hmm. */ + case, since it will run __gnu_cxx::__freeres and libc_freeres functions, + thus allowing other lurking threads to run again. Hmm. */ static void shutdown_actions_NORETURN( ThreadId tid, @@ -2584,8 +2588,8 @@ void shutdown_actions_NORETURN( ThreadId tid, // jrs: Huh? but they surely are already gone VG_(reap_threads)(tid); - // Clean the client up before the final report - // this causes the libc_freeres function to run + // Clean the client up before the final report. + // This causes __gnu_cxx::__freeres and libc_freeres functions to run. final_tidyup(tid); /* be paranoid */ @@ -2600,9 +2604,9 @@ void shutdown_actions_NORETURN( ThreadId tid, // that none of the other threads ever run again. vg_assert( VG_(count_living_threads)() >= 1 ); - // Clean the client up before the final report - // this causes the libc_freeres function to run - // perhaps this is unsafe, as per comment above + // Clean the client up before the final report. + // This causes __gnu_cxx::__freeres and libc_freeres functions to run. + // Perhaps this is unsafe, as per comment above. final_tidyup(tid); /* be paranoid */ @@ -2742,63 +2746,141 @@ void shutdown_actions_NORETURN( ThreadId tid, /* -------------------- */ /* Final clean-up before terminating the process. - Clean up the client by calling __libc_freeres() (if requested) - This is Linux-specific? - GrP fixme glibc-specific, anyway + Clean up the client by calling __gnu_cxx::__freeres() (if requested) + and __libc_freeres() (if requested). */ static void final_tidyup(ThreadId tid) { -#if !defined(VGO_darwin) - Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper); +#if defined(VGO_linux) || defined(VGO_solaris) + Addr freeres_wrapper = VG_(client_freeres_wrapper); vg_assert(VG_(is_running_thread)(tid)); - - if ( !VG_(needs).libc_freeres || - !VG_(clo_run_libc_freeres) || - 0 == __libc_freeres_wrapper ) - return; /* can't/won't do it */ + + if (freeres_wrapper == 0) { + return; /* can't do it */ + } + + Vg_FreeresToRun to_run = 0; + if (VG_(needs).cxx_freeres && VG_(clo_run_cxx_freeres)) { + to_run |= VG_RUN__GNU_CXX__FREERES; + } + + if (VG_(needs).libc_freeres && VG_(clo_run_libc_freeres)) { + to_run |= VG_RUN__LIBC_FREERES; + } + + if (to_run == 0) { + return; /* won't do it */ + } # if defined(VGP_ppc64be_linux) - Addr r2 = VG_(get_tocptr)( __libc_freeres_wrapper ); + Addr r2 = VG_(get_tocptr)(freeres_wrapper); if (r2 == 0) { VG_(message)(Vg_UserMsg, - "Caught __NR_exit, but can't run __libc_freeres()\n"); + "Caught __NR_exit, but can't run __gnu_cxx::__freeres()\n"); VG_(message)(Vg_UserMsg, - " since cannot establish TOC pointer for it.\n"); + " or __libc_freeres() since cannot establish TOC pointer " + "for it.\n"); return; } # endif if (VG_(clo_verbosity) > 2 || VG_(clo_trace_syscalls) || - VG_(clo_trace_sched)) - VG_(message)(Vg_DebugMsg, - "Caught __NR_exit; running __libc_freeres()\n"); + VG_(clo_trace_sched)) { + + vg_assert(to_run > 0); + vg_assert(to_run <= (VG_RUN__GNU_CXX__FREERES | VG_RUN__LIBC_FREERES)); + + const HChar *msgs[] = {"__gnu_cxx::__freeres()", "__libc_freeres()", + "__gnu_cxx::__freeres and __libc_freeres()"}; + VG_(message)(Vg_DebugMsg, + "Caught __NR_exit; running %s wrapper\n", msgs[to_run - 1]); + } - /* set thread context to point to libc_freeres_wrapper */ - /* ppc64be-linux note: __libc_freeres_wrapper gives us the real + /* set thread context to point to freeres_wrapper */ + /* ppc64be-linux note: freeres_wrapper gives us the real function entry point, not a fn descriptor, so can use it directly. However, we need to set R2 (the toc pointer) appropriately. */ - VG_(set_IP)(tid, __libc_freeres_wrapper); + VG_(set_IP)(tid, freeres_wrapper); # if defined(VGP_ppc64be_linux) VG_(threads)[tid].arch.vex.guest_GPR2 = r2; # elif defined(VGP_ppc64le_linux) /* setting GPR2 but not really needed, GPR12 is needed */ - VG_(threads)[tid].arch.vex.guest_GPR2 = __libc_freeres_wrapper; - VG_(threads)[tid].arch.vex.guest_GPR12 = __libc_freeres_wrapper; + VG_(threads)[tid].arch.vex.guest_GPR2 = freeres_wrapper; + VG_(threads)[tid].arch.vex.guest_GPR12 = freeres_wrapper; # endif /* mips-linux note: we need to set t9 */ # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) - VG_(threads)[tid].arch.vex.guest_r25 = __libc_freeres_wrapper; + VG_(threads)[tid].arch.vex.guest_r25 = freeres_wrapper; # endif + /* Pass a parameter to freeres_wrapper(). */ +# if defined(VGA_x86) + Addr sp = VG_(threads)[tid].arch.vex.guest_ESP; + sp = sp - sizeof(UWord); + *((UWord *) sp) = to_run; + VG_TRACK(post_mem_write, Vg_CoreClientReq, tid, sp, sizeof(UWord)); + VG_(threads)[tid].arch.vex.guest_ESP = sp; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestX86State, guest_ESP), + sizeof(VG_(threads)[tid].arch.vex.guest_ESP)); +# elif defined(VGA_amd64) + VG_(threads)[tid].arch.vex.guest_RDI = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestAMD64State, guest_RDI), + sizeof(VG_(threads)[tid].arch.vex.guest_RDI)); +# elif defined(VGA_arm) + VG_(threads)[tid].arch.vex.guest_R0 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestARMState, guest_R0), + sizeof(VG_(threads)[tid].arch.vex.guest_R0)); +# elif defined(VGA_arm64) + VG_(threads)[tid].arch.vex.guest_X0 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestARM64State, guest_X0), + sizeof(VG_(threads)[tid].arch.vex.guest_X0)); +# elif defined(VGA_mips32) + VG_(threads)[tid].arch.vex.guest_r4 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestMIPS32State, guest_r4), + sizeof(VG_(threads)[tid].arch.vex.guest_r4)); +# elif defined(VGA_mips64) + VG_(threads)[tid].arch.vex.guest_r4 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestMIPS64State, guest_r4), + sizeof(VG_(threads)[tid].arch.vex.guest_r4)); +# elif defined(VGA_ppc32) + VG_(threads)[tid].arch.vex.guest_GPR3 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestPPC32State, guest_GPR3), + sizeof(VG_(threads)[tid].arch.vex.guest_GPR3)); +# elif defined(VGA_ppc64be) || defined(VGA_ppc64le) + VG_(threads)[tid].arch.vex.guest_GPR3 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestPPC64State, guest_GPR3), + sizeof(VG_(threads)[tid].arch.vex.guest_GPR3)); +# elif defined(VGA_s390x) + VG_(threads)[tid].arch.vex.guest_r2 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestS390XState, guest_r2), + sizeof(VG_(threads)[tid].arch.vex.guest_r2)); +# elif defined(VGA_tilegx) + VG_(threads)[tid].arch.vex.guest_r0 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestTILEGXState, guest_r0), + sizeof(VG_(threads)[tid].arch.vex.guest_r0)); +#else + I_die_here : architecture missing in m_main.c +#endif + /* Block all blockable signals by copying the real block state into - the thread's block state*/ + the thread's block state */ VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask); VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask; - /* and restore handlers to default */ + /* and restore handlers to default. */ VG_(set_default_handler)(VKI_SIGSEGV); VG_(set_default_handler)(VKI_SIGBUS); VG_(set_default_handler)(VKI_SIGILL); @@ -2806,11 +2888,11 @@ static void final_tidyup(ThreadId tid) // We were exiting, so assert that... vg_assert(VG_(is_exiting)(tid)); - // ...but now we're not again + // ...but now we're not again. VG_(threads)[tid].exitreason = VgSrc_None; - // run until client thread exits - ideally with LIBC_FREERES_DONE, - // but exit/exitgroup/signal will do + // Run until client thread exits - ideally with FREERES_DONE, + // but exit/exitgroup/signal will do. VG_(scheduler)(tid); vg_assert(VG_(is_exiting)(tid)); diff --git a/coregrind/m_options.c b/coregrind/m_options.c index 7e920e0..83d6018 100644 --- a/coregrind/m_options.c +++ b/coregrind/m_options.c @@ -121,6 +121,7 @@ Bool VG_(clo_read_inline_info) = False; // Or should be put it to True by defa Bool VG_(clo_read_var_info) = False; XArray *VG_(clo_req_tsyms); // array of strings Bool VG_(clo_run_libc_freeres) = True; +Bool VG_(clo_run_cxx_freeres) = True; Bool VG_(clo_track_fds) = False; Bool VG_(clo_show_below_main)= False; Bool VG_(clo_show_emwarns) = False; diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index dae47f1..62cb45a 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -49,7 +49,7 @@ #include "pub_core_machine.h" // VG_(fnptr_to_fnentry) #include "pub_core_aspacemgr.h" // VG_(am_find_nsegment) #include "pub_core_xarray.h" -#include "pub_core_clientstate.h" // VG_(client___libc_freeres_wrapper) +#include "pub_core_clientstate.h" // VG_(client_freeres_wrapper) #include "pub_core_demangle.h" // VG_(maybe_Z_demangle) #include "pub_core_libcproc.h" // VG_(libdir) @@ -1688,7 +1688,7 @@ void handle_maybe_load_notifier( const HChar* soname, return; if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0) - VG_(client___libc_freeres_wrapper) = addr; + VG_(client_freeres_wrapper) = addr; else if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0) iFuncWrapper = addr; diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 1234d56..9aa854d 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -1744,12 +1744,13 @@ static Bool os_client_request(ThreadId tid, UWord *args) vg_assert(VG_(is_running_thread)(tid)); switch(args[0]) { - case VG_USERREQ__LIBC_FREERES_DONE: + case VG_USERREQ__FREERES_DONE: /* This is equivalent to an exit() syscall, but we don't set the exitcode (since it might already be set) */ if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) VG_(message)(Vg_DebugMsg, - "__libc_freeres() done; really quitting!\n"); + "__gnu_cxx::__freeres() and __libc_freeres() wrapper " + "done; really quitting!\n"); VG_(threads)[tid].exitreason = VgSrc_ExitThread; break; diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c index 6971a47..38bc7c2 100644 --- a/coregrind/m_tooliface.c +++ b/coregrind/m_tooliface.c @@ -88,6 +88,7 @@ VgNeeds VG_(needs) = { .core_errors = False, .tool_errors = False, .libc_freeres = False, + .cxx_freeres = False, .superblock_discards = False, .command_line_options = False, .client_requests = False, @@ -216,6 +217,7 @@ Bool VG_(sanity_check_needs)(const HChar** failmsg) // These ones don't require any tool-supplied functions NEEDS(libc_freeres) +NEEDS(cxx_freeres) NEEDS(core_errors) NEEDS(var_info) diff --git a/coregrind/pub_core_clientstate.h b/coregrind/pub_core_clientstate.h index 215dfb2..ddd1c09 100644 --- a/coregrind/pub_core_clientstate.h +++ b/coregrind/pub_core_clientstate.h @@ -90,9 +90,9 @@ extern HChar* VG_(name_of_launcher); extern Int VG_(fd_soft_limit); extern Int VG_(fd_hard_limit); -/* Useful addresses extracted from the client */ -/* Where is the __libc_freeres_wrapper routine we made? */ -extern Addr VG_(client___libc_freeres_wrapper); +/* Useful addresses extracted from the client. */ +/* Where is the freeres_wrapper routine we made? */ +extern Addr VG_(client_freeres_wrapper); /* x86-linux only: where is ld.so's _dl_sysinfo_int80 function? Finding it isn't essential, but knowing where it is does sometimes diff --git a/coregrind/pub_core_clreq.h b/coregrind/pub_core_clreq.h index 45c48c3..ce1493c 100644 --- a/coregrind/pub_core_clreq.h +++ b/coregrind/pub_core_clreq.h @@ -41,8 +41,8 @@ // used to be many more internal client requests. typedef enum { - /* Denote the finish of __libc_freeres_wrapper(). Also causes exit. */ - VG_USERREQ__LIBC_FREERES_DONE = 0x3029, + /* Denote the finish of freeres_wrapper(). Also causes exit. */ + VG_USERREQ__FREERES_DONE = 0x3029, /* Get the tool's malloc-wrapping functions */ VG_USERREQ__GET_MALLOCFUNCS = 0x3030, @@ -55,6 +55,18 @@ typedef } Vg_InternalClientRequest; + +/* Which freeres functions to run in the freeres_wrapper(). + It is possible to run both. */ +typedef enum { + /* Run __gnu_cxx::__freeres(). */ + VG_RUN__GNU_CXX__FREERES = 1, + + /* Run __libc_freeres(). */ + VG_RUN__LIBC_FREERES = 2 + +} Vg_FreeresToRun; + // Function for printing from code within Valgrind, but which runs on the // sim'd CPU. Must be a function rather than macros so that va_list can // be used. diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h index 2a45c6b..7a887fc 100644 --- a/coregrind/pub_core_options.h +++ b/coregrind/pub_core_options.h @@ -281,6 +281,13 @@ extern Bool VG_(clo_track_fds); cannot be overridden from the command line. */ extern Bool VG_(clo_run_libc_freeres); +/* Should we run __gnu_cxx::__freeres at exit for C++ programs? + Default: YES. Note this is subservient to VG_(needs).cxx_freeres; + if the latter says False, then the setting of VG_(clo_run_cxx_freeres) + is ignored. Ie if a tool says no, I don't want this to run, that + cannot be overridden from the command line. */ +extern Bool VG_(clo_run_cxx_freeres); + /* Should we show VEX emulation warnings? Default: NO */ extern Bool VG_(clo_show_emwarns); diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h index 41da986..83758a8 100644 --- a/coregrind/pub_core_tooliface.h +++ b/coregrind/pub_core_tooliface.h @@ -81,6 +81,7 @@ extern VgDetails VG_(details); typedef struct { Bool libc_freeres; + Bool cxx_freeres; Bool core_errors; Bool tool_errors; Bool superblock_discards; diff --git a/coregrind/vg_preloaded.c b/coregrind/vg_preloaded.c index 2ea7a7a..2f53a7d 100644 --- a/coregrind/vg_preloaded.c +++ b/coregrind/vg_preloaded.c @@ -47,29 +47,47 @@ #include "pub_core_debuginfo.h" // Needed for pub_core_redir.h #include "pub_core_redir.h" // For VG_NOTIFY_ON_LOAD -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_solaris) /* --------------------------------------------------------------------- - Hook for running __libc_freeres once the program exits. + Hook for running __gnu_cxx::__freeres() and __libc_freeres() once + the program exits. ------------------------------------------------------------------ */ -void VG_NOTIFY_ON_LOAD(freeres)( void ); -void VG_NOTIFY_ON_LOAD(freeres)( void ) +void VG_NOTIFY_ON_LOAD(freeres)(Vg_FreeresToRun to_run); +void VG_NOTIFY_ON_LOAD(freeres)(Vg_FreeresToRun to_run) { # if !defined(__UCLIBC__) \ && !defined(VGPV_arm_linux_android) \ && !defined(VGPV_x86_linux_android) \ && !defined(VGPV_mips32_linux_android) \ && !defined(VGPV_arm64_linux_android) + + /* g++ mangled __gnu_cxx::__freeres yields -> _ZN9__gnu_cxx9__freeresEv */ + extern void _ZN9__gnu_cxx9__freeresEv(void) __attribute__((weak)); + if (((to_run & VG_RUN__GNU_CXX__FREERES) != 0) && + (_ZN9__gnu_cxx9__freeresEv != NULL)) { + _ZN9__gnu_cxx9__freeresEv(); + } + +# if defined(VGO_linux) + /* __libc_freeres() not yet available on Solaris. */ extern void __libc_freeres(void); - __libc_freeres(); + if ((to_run & VG_RUN__LIBC_FREERES) != 0) { + __libc_freeres(); + } # endif - VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LIBC_FREERES_DONE, - 0, 0, 0, 0, 0); +# endif + + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREERES_DONE, 0, 0, 0, 0, 0); /*NOTREACHED*/ *(volatile int *)0 = 'x'; } +#endif // VGO_linux || VGO_solaris + +#if defined(VGO_linux) + /* --------------------------------------------------------------------- Wrapper for indirect functions which need to be redirected. ------------------------------------------------------------------ */ diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index 758e2f4..7628836 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -1930,6 +1930,37 @@ need to use them. + + + + + + This option is only relevant when running Valgrind on Linux + or Solaris C++ programs. + + The GNU Standard C++ library (libstdc++.so), + which is used by all C++ programs compiled with g++, 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 kernel reclaims + all process resources when a process exits anyway, so it would + just slow things down. + + The gcc authors realised that this behaviour causes leak + checkers, such as Valgrind, to falsely report leaks in libstdc++, when + a leak check is done at exit. In order to avoid this, they + provided a routine called __gnu_cxx::__freeres + specifically to make libstdc++ release all memory it has allocated. + Memcheck therefore tries to run + __gnu_cxx::__freeres at exit. + + For the sake of flexibility and unforeseen problems with + __gnu_cxx::__freeres, option + exists, + although at the cost of possibly falsely reporting space leaks in + libstdc++.so. + + + diff --git a/exp-dhat/dh_main.c b/exp-dhat/dh_main.c index e636ccb..3476cd9 100644 --- a/exp-dhat/dh_main.c +++ b/exp-dhat/dh_main.c @@ -1358,6 +1358,7 @@ static void dh_pre_clo_init(void) //zz // Needs. VG_(needs_libc_freeres)(); + VG_(needs_cxx_freeres)(); VG_(needs_command_line_options)(dh_process_cmd_line_option, dh_print_usage, dh_print_debug_usage); diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h index 8df00b5..f7805e9 100644 --- a/include/pub_tool_tooliface.h +++ b/include/pub_tool_tooliface.h @@ -263,6 +263,9 @@ extern void VG_(details_bug_reports_to) ( const HChar* bug_reports_to ); /* Should __libc_freeres() be run? Bugs in it can crash the tool. */ extern void VG_(needs_libc_freeres) ( void ); +/* Should __gnu_cxx::__freeres() be run? Bugs in it can crash the tool. */ +extern void VG_(needs_cxx_freeres) ( void ); + /* Want to have errors detected by Valgrind's core reported? Includes: - pthread API errors (many; eg. unlocking a non-locked mutex) [currently disabled] diff --git a/massif/ms_main.c b/massif/ms_main.c index 66f9be9..628a37b 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -2569,6 +2569,7 @@ static void ms_pre_clo_init(void) // Needs. VG_(needs_libc_freeres)(); + VG_(needs_cxx_freeres)(); VG_(needs_command_line_options)(ms_process_cmd_line_option, ms_print_usage, ms_print_debug_usage); diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index 99421f5..5464a06 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -7745,6 +7745,7 @@ static void mc_pre_clo_init(void) MC_(print_extra_suppression_use), MC_(update_extra_suppression_use)); VG_(needs_libc_freeres) (); + VG_(needs_cxx_freeres) (); VG_(needs_command_line_options)(mc_process_cmd_line_options, mc_print_usage, mc_print_debug_usage); diff --git a/none/tests/cmdline1.stdout.exp b/none/tests/cmdline1.stdout.exp index cc25a16..0faec69 100644 --- a/none/tests/cmdline1.stdout.exp +++ b/none/tests/cmdline1.stdout.exp @@ -90,6 +90,8 @@ usage: valgrind [options] prog-and-args --vgdb-shadow-registers=no|yes let gdb see the shadow registers [no] --vgdb-prefix= prefix for vgdb FIFOs [.../vgdb-pipe] --run-libc-freeres=no|yes free up glibc memory at exit on Linux? [yes] + --run-cxx-freeres=no|yes free up libstdc++ memory at exit on Linux + and Solaris? [yes] --sim-hints=hint1,hint2,... activate unusual sim behaviours [none] where hint is one of: lax-ioctls lax-doors fuse-compatible enable-outer diff --git a/none/tests/cmdline2.stdout.exp b/none/tests/cmdline2.stdout.exp index 580fa19..b124f20 100644 --- a/none/tests/cmdline2.stdout.exp +++ b/none/tests/cmdline2.stdout.exp @@ -90,6 +90,8 @@ usage: valgrind [options] prog-and-args --vgdb-shadow-registers=no|yes let gdb see the shadow registers [no] --vgdb-prefix= prefix for vgdb FIFOs [.../vgdb-pipe] --run-libc-freeres=no|yes free up glibc memory at exit on Linux? [yes] + --run-cxx-freeres=no|yes free up libstdc++ memory at exit on Linux + and Solaris? [yes] --sim-hints=hint1,hint2,... activate unusual sim behaviours [none] where hint is one of: lax-ioctls lax-doors fuse-compatible enable-outer