#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"
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
-
-
Int main(Int argc, HChar **argv, HChar **envp)
{
HChar* toolname = "memcheck"; // default to Memcheck
}
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");
}
}
+/* -------------------- */
+
+/* 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 ===*/
+++ /dev/null
-
-/*--------------------------------------------------------------------*/
-/*--- 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 ---*/
-/*--------------------------------------------------------------------*/