From: Julian Seward Date: Wed, 28 Sep 2005 10:47:38 +0000 (+0000) Subject: Get rid of pub_core_main.h, so that m_main is not imported by anyone, X-Git-Tag: svn/VALGRIND_3_1_0~422 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b98ac01c9f0dc862ce4cfe1ace1fa229bb4a431f;p=thirdparty%2Fvalgrind.git Get rid of pub_core_main.h, so that m_main is not imported by anyone, and so is not part of a module cycle. This requires a moderately grotty hack of passing a continuation-function pointer in a global variable. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4806 --- diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 2296abefd6..bae2988f1d 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -48,7 +48,6 @@ noinst_HEADERS = \ pub_core_libcproc.h \ pub_core_libcsignal.h \ pub_core_machine.h \ - pub_core_main.h \ pub_core_mallocfree.h \ pub_core_options.h \ pub_core_oset.h \ diff --git a/coregrind/m_main.c b/coregrind/m_main.c index a0886059f9..50a50fa047 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -44,7 +44,6 @@ #include "pub_core_libcsignal.h" #include "pub_core_syscall.h" // VG_(strerror) #include "pub_core_machine.h" -#include "pub_core_main.h" #include "pub_core_mallocfree.h" #include "pub_core_options.h" #include "pub_core_profile.h" @@ -1823,6 +1822,16 @@ void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total ) static Addr sp_at_startup = 0; +/* --- Forwards decls to do with shutdown --- */ + +static void final_tidyup(ThreadId tid); + +/* Do everything which needs doing when the last thread exits */ +static +void shutdown_actions_NORETURN( ThreadId tid, + VgSchedReturnCode tids_schedretcode ); + +/* --- end of Forwards decls to do with shutdown --- */ /* TODO: GIVE THIS A PROPER HOME @@ -1860,8 +1869,6 @@ static Addr* get_seg_starts ( /*OUT*/Int* n_acquired ) - - Int main(Int argc, HChar **argv, HChar **envp) { HChar* toolname = "memcheck"; // default to Memcheck @@ -2480,67 +2487,33 @@ Int main(Int argc, HChar **argv, HChar **envp) } VG_(debugLog)(1, "main", "Running thread 1\n"); + /* As a result of the following call, the last thread standing - eventually winds up running VG_(shutdown_actions_NORETURN) just - below. */ + eventually winds up running shutdown_actions_NORETURN + just below. Unfortunately, simply exporting said function + causes m_main to be part of a module cycle, which is pretty + nonsensical. So instead of doing that, the address of said + function is stored in a global variable 'owned' by m_syswrap, + and it uses that function pointer to get back here when it needs + to. */ + + /* Set continuation address. */ + VG_(address_of_m_main_shutdown_actions_NORETURN) + = & shutdown_actions_NORETURN; + + /* Run the first thread, eventually ending up at the continuation + address. */ VG_(main_thread_wrapper_NORETURN)(1); /*NOTREACHED*/ vg_assert(0); } +/* Do everything which needs doing when the last thread exits. */ -/* Final clean-up before terminating the process. - Clean up the client by calling __libc_freeres() (if requested) - This is Linux-specific? -*/ -static void final_tidyup(ThreadId tid) -{ - Addr __libc_freeres_wrapper; - - vg_assert(VG_(is_running_thread)(tid)); - - if ( !VG_(needs).libc_freeres || - !VG_(clo_run_libc_freeres) || - 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) ) - return; /* can't/won't do it */ - - if (VG_(clo_verbosity) > 2 || - VG_(clo_trace_syscalls) || - VG_(clo_trace_sched)) - VG_(message)(Vg_DebugMsg, - "Caught __NR_exit; running __libc_freeres()"); - - /* point thread context to point to libc_freeres_wrapper */ - VG_(set_IP)(tid, __libc_freeres_wrapper); - // XXX should we use a special stack? - - /* Block all blockable signals by copying the real block state into - 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 */ - VG_(set_default_handler)(VKI_SIGSEGV); - VG_(set_default_handler)(VKI_SIGBUS); - VG_(set_default_handler)(VKI_SIGILL); - VG_(set_default_handler)(VKI_SIGFPE); - - // We were exiting, so assert that... - vg_assert(VG_(is_exiting)(tid)); - // ...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 - VG_(scheduler)(tid); - - vg_assert(VG_(is_exiting)(tid)); -} - -/* Do everything which needs doing when the last thread exits */ -void VG_(shutdown_actions_NORETURN) ( ThreadId tid, - VgSchedReturnCode tids_schedretcode ) +static +void shutdown_actions_NORETURN( ThreadId tid, + VgSchedReturnCode tids_schedretcode ) { VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n"); @@ -2646,6 +2619,56 @@ void VG_(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? +*/ +static void final_tidyup(ThreadId tid) +{ + Addr __libc_freeres_wrapper; + + vg_assert(VG_(is_running_thread)(tid)); + + if ( !VG_(needs).libc_freeres || + !VG_(clo_run_libc_freeres) || + 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) ) + return; /* can't/won't do it */ + + if (VG_(clo_verbosity) > 2 || + VG_(clo_trace_syscalls) || + VG_(clo_trace_sched)) + VG_(message)(Vg_DebugMsg, + "Caught __NR_exit; running __libc_freeres()"); + + /* point thread context to point to libc_freeres_wrapper */ + VG_(set_IP)(tid, __libc_freeres_wrapper); + // XXX should we use a special stack? + + /* Block all blockable signals by copying the real block state into + 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 */ + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(set_default_handler)(VKI_SIGBUS); + VG_(set_default_handler)(VKI_SIGILL); + VG_(set_default_handler)(VKI_SIGFPE); + + // We were exiting, so assert that... + vg_assert(VG_(is_exiting)(tid)); + // ...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 + VG_(scheduler)(tid); + + vg_assert(VG_(is_exiting)(tid)); +} + /*====================================================================*/ /*=== Getting to main() alive ===*/ diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index 6eafac3b2a..309cdcbb05 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -38,7 +38,6 @@ #include "pub_core_libcprint.h" #include "pub_core_libcproc.h" #include "pub_core_libcsignal.h" -#include "pub_core_main.h" #include "pub_core_scheduler.h" #include "pub_core_sigframe.h" #include "pub_core_signals.h" @@ -133,8 +132,9 @@ static void run_a_thread_NORETURN ( Word tidW ) (ULong)tidW); /* We are the last one standing. Keep hold of the lock and - carry on to show final tool results, then exit the entire system. */ - VG_(shutdown_actions_NORETURN)(tid, src); + carry on to show final tool results, then exit the entire system. + Use the continuation pointer set at startup in m_main. */ + ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); } else { diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index eac7239561..0816e50163 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -42,7 +42,6 @@ #include "pub_core_libcprint.h" #include "pub_core_libcproc.h" #include "pub_core_libcsignal.h" -#include "pub_core_main.h" #include "pub_core_mallocfree.h" #include "pub_core_options.h" #include "pub_core_scheduler.h" diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 3bf1efcd5f..821164ed87 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -1153,6 +1153,20 @@ VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, } +/* --------------------------------------------------------------------- + A place to store the where-to-call-when-really-done pointer + ------------------------------------------------------------------ */ + +// When the final thread is done, where shall I call to shutdown the +// system cleanly? Is set once at startup (in m_main) and never +// changes after that. Is basically a pointer to the exit +// continuation. This is all just a nasty hack to avoid calling +// directly from m_syswrap to m_main at exit, since that would cause +// m_main to become part of a module cycle, which is silly. +void (* VG_(address_of_m_main_shutdown_actions_NORETURN) ) + (ThreadId,VgSchedReturnCode) + = NULL; + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c index 648fb02f52..0bac456af9 100644 --- a/coregrind/m_syswrap/syswrap-ppc32-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c @@ -37,7 +37,6 @@ #include "pub_core_libcprint.h" #include "pub_core_libcproc.h" #include "pub_core_libcsignal.h" -#include "pub_core_main.h" // For VG_(shutdown_actions_NORETURN)() #include "pub_core_options.h" #include "pub_core_scheduler.h" #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)() @@ -158,8 +157,9 @@ static void run_a_thread_NORETURN ( Word tidW ) (ULong)tidW); /* We are the last one standing. Keep hold of the lock and - carry on to show final tool results, then exit the entire system. */ - VG_(shutdown_actions_NORETURN)(tid, src); + carry on to show final tool results, then exit the entire system. + Use the continuation pointer set at startup in m_main. */ + ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); } else { VG_(debugLog)(1, "syswrap-ppc32-linux", diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 778f9b7384..6f39f47b64 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -43,7 +43,6 @@ #include "pub_core_libcprint.h" #include "pub_core_libcproc.h" #include "pub_core_libcsignal.h" -#include "pub_core_main.h" // For VG_(shutdown_actions_NORETURN)() #include "pub_core_mallocfree.h" #include "pub_core_options.h" #include "pub_core_scheduler.h" @@ -140,8 +139,9 @@ static void run_a_thread_NORETURN ( Word tidW ) (ULong)tidW); /* We are the last one standing. Keep hold of the lock and - carry on to show final tool results, then exit the entire system. */ - VG_(shutdown_actions_NORETURN)(tid, src); + carry on to show final tool results, then exit the entire system. + Use the continuation pointer set at startup in m_main. */ + ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); } else { diff --git a/coregrind/pub_core_main.h b/coregrind/pub_core_main.h deleted file mode 100644 index c8bbec6f9b..0000000000 --- a/coregrind/pub_core_main.h +++ /dev/null @@ -1,52 +0,0 @@ - -/*--------------------------------------------------------------------*/ -/*--- The main module. pub_core_main.h ---*/ -/*--------------------------------------------------------------------*/ - -/* - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2005 Julian Seward - jseward@acm.org - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. - - The GNU General Public License is contained in the file COPYING. -*/ - -#ifndef __PUB_CORE_MAIN_H -#define __PUB_CORE_MAIN_H - -//-------------------------------------------------------------------- -// PURPOSE: This module is the main module, ie. the one holding main(). -// It arguably shouldn't export anything to other modules, since it depends -// on almost every other module! But currently it exports quite a few -// things. -//-------------------------------------------------------------------- - -// Do everything which needs doing before the process finally ends, -// like printing reports, etc -extern void VG_(shutdown_actions_NORETURN) ( - ThreadId tid, - VgSchedReturnCode tids_schedretcode - ); - -#endif // __PUB_CORE_MAIN_H - -/*--------------------------------------------------------------------*/ -/*--- end ---*/ -/*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_syswrap.h b/coregrind/pub_core_syswrap.h index 2c03321ff4..0cedba1ac3 100644 --- a/coregrind/pub_core_syswrap.h +++ b/coregrind/pub_core_syswrap.h @@ -66,6 +66,15 @@ extern void VG_(cleanup_thread) ( ThreadArchState* ); extern void VG_(init_preopened_fds) ( void ); extern void VG_(show_open_fds) ( void ); +// When the final thread is done, where shall I call to shutdown the +// system cleanly? Is set once at startup (in m_main) and never +// changes after that. Is basically a pointer to the exit +// continuation. This is all just a nasty hack to avoid calling +// directly from m_syswrap to m_main at exit, since that would cause +// m_main to become part of a module cycle, which is silly. +extern void (* VG_(address_of_m_main_shutdown_actions_NORETURN) ) + (ThreadId,VgSchedReturnCode); + #endif // __PUB_CORE_SYSWRAP_H /*--------------------------------------------------------------------*/