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