From 0b6178bf3385577ebb01bcc21142857b45d5c119 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 3 Apr 2016 20:47:59 +0200 Subject: [PATCH] Add valgrind-3.11.0-cxx-freeres.patch --- valgrind-3.11.0-cxx-freeres.patch | 614 ++++++++++++++++++++++++++++++ valgrind.spec | 8 + 2 files changed, 622 insertions(+) create mode 100644 valgrind-3.11.0-cxx-freeres.patch diff --git a/valgrind-3.11.0-cxx-freeres.patch b/valgrind-3.11.0-cxx-freeres.patch new file mode 100644 index 0000000..98b4177 --- /dev/null +++ b/valgrind-3.11.0-cxx-freeres.patch @@ -0,0 +1,614 @@ +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 diff --git a/valgrind.spec b/valgrind.spec index 001b7fa..5dcff73 100644 --- a/valgrind.spec +++ b/valgrind.spec @@ -129,6 +129,10 @@ Patch26: valgrind-3.11.0-arm64-ldr-literal-test.patch # KDE#360425 - arm64 unsupported instruction ldpsw Patch27: valgrind-3.11.0-arm64-ldpsw.patch +# KDE#345307 - still reachable memory in libstdc++ from gcc 6 +# Note that workaround (patch25) is still needed for gcc 5 +Patch28: valgrind-3.11.0-cxx-freeres.patch + %if %{build_multilib} # Ensure glibc{,-devel} is installed for both multilib arches BuildRequires: /lib/libc.so.6 /usr/lib/libc.so /lib64/libc.so.6 /usr/lib64/libc.so @@ -264,6 +268,7 @@ chmod 755 memcheck/tests/arm64-linux/filter_stderr %patch25 -p1 %patch26 -p1 %patch27 -p1 +%patch28 -p1 %build # We need to use the software collection compiler and binutils if available. @@ -456,6 +461,9 @@ echo ===============END TESTING=============== %endif %changelog +* Sun Apr 03 2016 Mark Wielaard +- Add valgrind-3.11.0-cxx-freeres.patch (#1312647) + * Mon Mar 14 2016 Mark Wielaard - 3.11.0-18 - Update valgrind-3.11.0-libstdc++-supp.patch. - Add valgrind-3.11.0-arm64-ldr-literal-test.patch.