From: Philippe Waroquiers Date: Sat, 17 Sep 2022 20:45:17 +0000 (+0200) Subject: Add abexit in --vgdb-stopat. fix 459031 --error-exitcode doc. Add lwpid in thread_wra... X-Git-Tag: VALGRIND_3_20_0~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e489f319742496d41c4b39e07108e64511f68819;p=thirdparty%2Fvalgrind.git Add abexit in --vgdb-stopat. fix 459031 --error-exitcode doc. Add lwpid in thread_wrapper tracing. Note that this modifies files on darwin/solaris/bsd but I only did a linux build so possibly this commit might cause a compilation error, that should then be trivial to fix. Also added memmem test in the list of ignored files. --- diff --git a/.gitignore b/.gitignore index d816acf815..01d47ebf85 100644 --- a/.gitignore +++ b/.gitignore @@ -914,6 +914,7 @@ /memcheck/tests/memalign2 /memcheck/tests/memalign_test /memcheck/tests/memcmptest +/memcheck/tests/memmem /memcheck/tests/mempool /memcheck/tests/mempool2 /memcheck/tests/metadata diff --git a/NEWS b/NEWS index a16cd82bd5..76311f9d2b 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,9 @@ AMD64/macOS 10.13 and nanoMIPS/Linux. * ==================== CORE CHANGES =================== +* The option "--vgdb-stop-at=event1,event2,..." accepts the new value abexit. + This indicates to invoke gdbserver when your program exits abnormally + (i.e. with a non zero exit code). * Fix Rust v0 name demangling. * The Linux rseq syscall is now implemented as (silently) returning ENOSYS. * Add FreeBSD syscall wrappers for __specialfd and __realpathat. @@ -47,6 +50,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. n-i-bz Implement vgdb invoker on FreeBSD 458845 PowerPC: The L field for the dcbf and sync instruction should be 3 bits in ISA 3.1. +459031 Documentation on --error-exitcode incomplete To see details of a given bug, visit https://bugs.kde.org/show_bug.cgi?id=XXXXXX diff --git a/coregrind/m_main.c b/coregrind/m_main.c index f12ba01b5f..25882e7cea 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -109,7 +109,7 @@ static void usage_NORETURN ( int need_help ) " and follow the on-screen directions\n" " --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]\n" " where event is one of:\n" -" startup exit valgrindabexit all none\n" +" startup exit abexit valgrindabexit all none\n" " --track-fds=no|yes|all track open file descriptors? [no]\n" " all includes reporting stdin, stdout and stderr\n" " --time-stamp=no|yes add timestamps to log messages? [no]\n" @@ -554,7 +554,7 @@ static void process_option (Clo_Mode mode, else if VG_INT_CLOM (cloPD, arg, "--vgdb-poll", VG_(clo_vgdb_poll)) {} else if VG_INT_CLOM (cloPD, arg, "--vgdb-error", VG_(clo_vgdb_error)) {} else if VG_USET_CLOM (cloPD, arg, "--vgdb-stop-at", - "startup,exit,valgrindabexit", + "startup,exit,abexit,valgrindabexit", VG_(clo_vgdb_stop_at)) {} else if VG_STR_CLO (arg, "--vgdb-prefix", VG_(clo_vgdb_prefix)) { VG_(arg_vgdb_prefix) = arg; @@ -2190,6 +2190,21 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) vg_assert(0); } +/* Return the exit code to use when tid exits, depending on the tid os_state + exit code and the clo options controlling valgrind exit code. */ +static +Int tid_exit_code (ThreadId tid) +{ + if (VG_(clo_error_exitcode) > 0 && VG_(get_n_errs_found)() > 0) + /* Change the application return code to user's return code, + if an error was found */ + return VG_(clo_error_exitcode); + else + /* otherwise, return the client's exit code, in the normal + way. */ + return VG_(threads)[tid].os_state.exitcode; +} + /* Do everything which needs doing when the last thread exits or when a thread exits requesting a complete process exit. @@ -2256,8 +2271,14 @@ void shutdown_actions_NORETURN( ThreadId tid, } /* Final call to gdbserver, if requested. */ - if (VG_(gdbserver_stop_at) (VgdbStopAt_Exit)) { - VG_(umsg)("(action at exit) vgdb me ... \n"); + if (VG_(gdbserver_stop_at) (VgdbStopAt_Abexit) + && tid_exit_code (tid) != 0) { + VG_(umsg)("(action at abexit, exit code %d) vgdb me ... \n", + tid_exit_code (tid)); + VG_(gdbserver) (tid); + } else if (VG_(gdbserver_stop_at) (VgdbStopAt_Exit)) { + VG_(umsg)("(action at exit, exit code %d) vgdb me ... \n", + tid_exit_code (tid)); VG_(gdbserver) (tid); } VG_(threads)[tid].status = VgTs_Empty; @@ -2362,16 +2383,7 @@ void shutdown_actions_NORETURN( ThreadId tid, switch (tids_schedretcode) { case VgSrc_ExitThread: /* the normal way out (Linux, Solaris) */ case VgSrc_ExitProcess: /* the normal way out (Darwin) */ - /* Change the application return code to user's return code, - if an error was found */ - if (VG_(clo_error_exitcode) > 0 - && VG_(get_n_errs_found)() > 0) { - VG_(client_exit)( VG_(clo_error_exitcode) ); - } else { - /* otherwise, return the client's exit code, in the normal - way. */ - VG_(client_exit)( VG_(threads)[tid].os_state.exitcode ); - } + VG_(client_exit)(tid_exit_code (tid)); /* NOT ALIVE HERE! */ VG_(core_panic)("entered the afterlife in main() -- ExitT/P"); break; /* what the hell :) */ diff --git a/coregrind/m_syswrap/syswrap-darwin.c b/coregrind/m_syswrap/syswrap-darwin.c index 5861b3985e..c5c9b603b6 100644 --- a/coregrind/m_syswrap/syswrap-darwin.c +++ b/coregrind/m_syswrap/syswrap-darwin.c @@ -87,11 +87,12 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) { VgSchedReturnCode ret; ThreadId tid = (ThreadId)tidW; + Int lwpid = VG_(gettid)(); ThreadState* tst = VG_(get_ThreadState)(tid); - VG_(debugLog)(1, "syswrap-darwin", - "thread_wrapper(tid=%u): entry\n", - tid); + VG_(debugLog)(1, "syswrap-darwin", + "thread_wrapper(tid=%u,lwpid=%d): entry\n", + tid, lwpid); vg_assert(tst->status == VgTs_Init); @@ -107,7 +108,7 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) VG_TRACK(pre_thread_first_insn, tid); - tst->os_state.lwpid = VG_(gettid)(); + tst->os_state.lwpid = lwpid; tst->os_state.threadgroup = VG_(getpid)(); /* Thread created with all signals blocked; scheduler will set the @@ -116,13 +117,13 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) ret = VG_(scheduler)(tid); vg_assert(VG_(is_exiting)(tid)); - + vg_assert(tst->status == VgTs_Runnable); vg_assert(VG_(is_running_thread)(tid)); - VG_(debugLog)(1, "syswrap-darwin", - "thread_wrapper(tid=%u): done\n", - tid); + VG_(debugLog)(1, "syswrap-darwin", + "thread_wrapper(tid=%u,lwpid=%d): done\n", + tid, lwpid); /* Return to caller, still holding the lock. */ return ret; diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 375057fecb..518eaf0871 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -78,11 +78,12 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) { VgSchedReturnCode ret; ThreadId tid = (ThreadId)tidW; + Int lwpid = VG_(gettid)(); ThreadState* tst = VG_(get_ThreadState)(tid); VG_(debugLog)(1, "syswrap-freebsd", - "thread_wrapper(tid=%u): entry\n", - tid); + "thread_wrapper(tid=%u,lwpid=%d): entry\n", + tid, lwpid); vg_assert(tst->status == VgTs_Init); @@ -98,7 +99,7 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) VG_TRACK(pre_thread_first_insn, tid); - tst->os_state.lwpid = VG_(gettid)(); + tst->os_state.lwpid = lwpid; /* Set the threadgroup for real. This overwrites the provisional value set in do_clone(). See comments in do_clone for background, also #226116. */ tst->os_state.threadgroup = VG_(getpid)(); @@ -114,8 +115,8 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) vg_assert(VG_(is_running_thread)(tid)); VG_(debugLog)(1, "syswrap-freebsd", - "thread_wrapper(tid=%u): exit, schedreturncode %s\n", - tid, VG_(name_of_VgSchedReturnCode)(ret)); + "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n", + tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret)); /* Return to caller, still holding the lock. */ return ret; diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index adc3132118..35724660e5 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -70,11 +70,12 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) { VgSchedReturnCode ret; ThreadId tid = (ThreadId)tidW; + Int lwpid = VG_(gettid)(); ThreadState* tst = VG_(get_ThreadState)(tid); - VG_(debugLog)(1, "syswrap-linux", - "thread_wrapper(tid=%u): entry\n", - tid); + VG_(debugLog)(1, "syswrap-linux", + "thread_wrapper(tid=%u,lwpid=%d): entry\n", + tid, lwpid); vg_assert(tst->status == VgTs_Init); @@ -90,7 +91,7 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) VG_TRACK(pre_thread_first_insn, tid); - tst->os_state.lwpid = VG_(gettid)(); + tst->os_state.lwpid = lwpid; /* Set the threadgroup for real. This overwrites the provisional value set in do_clone(). See comments in do_clone for background, also #226116. */ tst->os_state.threadgroup = VG_(getpid)(); @@ -101,13 +102,13 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) ret = VG_(scheduler)(tid); vg_assert(VG_(is_exiting)(tid)); - + vg_assert(tst->status == VgTs_Runnable); vg_assert(VG_(is_running_thread)(tid)); - VG_(debugLog)(1, "syswrap-linux", - "thread_wrapper(tid=%u): exit, schedreturncode %s\n", - tid, VG_(name_of_VgSchedReturnCode)(ret)); + VG_(debugLog)(1, "syswrap-linux", + "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n", + tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret)); /* Return to caller, still holding the lock. */ return ret; diff --git a/coregrind/m_syswrap/syswrap-solaris.c b/coregrind/m_syswrap/syswrap-solaris.c index 992fbeb9c4..1464674690 100644 --- a/coregrind/m_syswrap/syswrap-solaris.c +++ b/coregrind/m_syswrap/syswrap-solaris.c @@ -98,11 +98,12 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) { VgSchedReturnCode ret; ThreadId tid = (ThreadId)tidW; + Int lwpid = VG_(gettid)(); ThreadState *tst = VG_(get_ThreadState)(tid); VG_(debugLog)(1, "syswrap-solaris", - "thread_wrapper(tid=%u): entry\n", - tid); + "thread_wrapper(tid=%u,lwpid=%d): entry\n", + tid, lwpid); vg_assert(tst->status == VgTs_Init); @@ -124,7 +125,7 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) here would be way too early - new thread has no stack, yet. */ } - tst->os_state.lwpid = VG_(gettid)(); + tst->os_state.lwpid = lwpid; tst->os_state.threadgroup = VG_(getpid)(); /* Thread created with all signals blocked; scheduler will set the @@ -138,8 +139,8 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) vg_assert(VG_(is_running_thread)(tid)); VG_(debugLog)(1, "syswrap-solaris", - "thread_wrapper(tid=%u): exit, schedreturncode %s\n", - tid, VG_(name_of_VgSchedReturnCode)(ret)); + "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n", + tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret)); /* Return to caller, still holding the lock. */ return ret; diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h index 22875c824b..e2ea1dc5b1 100644 --- a/coregrind/pub_core_options.h +++ b/coregrind/pub_core_options.h @@ -79,10 +79,11 @@ extern Int VG_(clo_vgdb_poll); /* Specify when Valgrind gdbserver stops the execution and wait for a GDB to connect. */ typedef - enum { // Stop : - VgdbStopAt_Startup, // just before the client starts to execute. - VgdbStopAt_Exit, // just before the client exits. - VgdbStopAt_ValgrindAbExit // on abnormal valgrind exit. + enum { // Stop just before ... + VgdbStopAt_Startup, // ... the client starts to execute. + VgdbStopAt_Exit, // ... the client exits with any exit code.. + VgdbStopAt_Abexit, // ... the client exits with a non 0 exit code. + VgdbStopAt_ValgrindAbExit // ... an abnormal valgrind exit. } VgdbStopAt; // Build mask to check or set VgdbStop_At a membership diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index 1cb4e8e579..8136c2e089 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -848,13 +848,17 @@ in most cases. We group the available options by rough categories. for other events, specified in one of the following ways: a comma separated list of one or more of - . + . The values - respectively indicate to - invoke gdbserver before your program is executed, after the - last instruction of your program, on Valgrind abnormal exit - (e.g. internal error, out of memory, ...). + respectively indicate to invoke + gdbserver before your program is executed, after the last instruction + of your program, on Valgrind abnormal exit (e.g. internal error, out + of memory, ...). + + The option is similar to + but tells to invoke gdbserver only when your application exits abnormally + (i.e. with an exit code different of 0). Note: and will both cause Valgrind @@ -866,7 +870,7 @@ in most cases. We group the available options by rough categories. to specify the complete set. It is equivalent to - . + . for the empty set. @@ -1239,7 +1243,11 @@ that can report errors, e.g. Memcheck, but not Cachegrind. that value is returned instead, if Valgrind detects any errors. This is useful for using Valgrind as part of an automated test suite, since it makes it easy to detect test cases for which - Valgrind has reported errors, just by inspecting return codes. + Valgrind has reported errors, just by inspecting return codes. + When set to a nonzero value and Valgrind detects no error, + the return value of Valgrind will be the return value of the + program being simulated. + diff --git a/gdbserver_tests/nlgone_exit.stderr.exp b/gdbserver_tests/nlgone_exit.stderr.exp index ec9ce0d31c..752b414361 100644 --- a/gdbserver_tests/nlgone_exit.stderr.exp +++ b/gdbserver_tests/nlgone_exit.stderr.exp @@ -5,5 +5,5 @@ Nulgrind, the minimal Valgrind tool starting ... exiting ... -(action at exit) vgdb me ... +(action at exit, exit code 1) vgdb me ... diff --git a/none/tests/cmdline1.stdout.exp b/none/tests/cmdline1.stdout.exp index ca74f7bd89..6a3405090b 100644 --- a/none/tests/cmdline1.stdout.exp +++ b/none/tests/cmdline1.stdout.exp @@ -24,7 +24,7 @@ usage: valgrind [options] prog-and-args and follow the on-screen directions --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none] where event is one of: - startup exit valgrindabexit all none + startup exit abexit valgrindabexit all none --track-fds=no|yes|all track open file descriptors? [no] all includes reporting stdin, stdout and stderr --time-stamp=no|yes add timestamps to log messages? [no] diff --git a/none/tests/cmdline2.stdout.exp b/none/tests/cmdline2.stdout.exp index 0da944f5a0..95e9e96f83 100644 --- a/none/tests/cmdline2.stdout.exp +++ b/none/tests/cmdline2.stdout.exp @@ -24,7 +24,7 @@ usage: valgrind [options] prog-and-args and follow the on-screen directions --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none] where event is one of: - startup exit valgrindabexit all none + startup exit abexit valgrindabexit all none --track-fds=no|yes|all track open file descriptors? [no] all includes reporting stdin, stdout and stderr --time-stamp=no|yes add timestamps to log messages? [no]