Modularised assertions and panics in m_libcassert.

As part of this, killed the VG_STRINGIFY macro, which was used to expand
out names like "VG_(foo)" and "vgPlain_foo" in assertion failure
messages.  This is good since we actually want the "VG_(foo)" form used
in these messages.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3842 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
new file mode 100644
index 0000000..b5c5373
--- /dev/null
+++ b/coregrind/m_libcassert.c
@@ -0,0 +1,194 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Assertions and panics.                        m_libcassert.c ---*/
+/*--------------------------------------------------------------------*/
+ 
+/*
+   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.
+*/
+
+#include "core.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_main.h"
+#include "pub_core_stacktrace.h"
+#include "pub_core_tooliface.h"
+
+/* ---------------------------------------------------------------------
+   Assertery.
+   ------------------------------------------------------------------ */
+
+#if defined(VGP_x86_linux)
+#  define GET_REAL_SP_AND_FP(sp, fp) \
+      asm("movl %%esp, %0;" \
+          "movl %%ebp, %1;" \
+          : "=r" (sp),\
+            "=r" (fp));
+#elif defined(VGP_amd64_linux)
+#  define GET_REAL_SP_AND_FP(sp, fp) \
+      asm("movq %%rsp, %0;" \
+          "movq %%rbp, %1;" \
+          : "=r" (sp),\
+            "=r" (fp));
+#else
+#  error Unknown platform
+#endif
+
+__attribute__ ((noreturn))
+static void report_and_quit ( const Char* report, Addr ip, Addr sp, Addr fp )
+{
+   #define BACKTRACE_DEPTH    100         // nice and deep!
+   Addr stacktop, ips[BACKTRACE_DEPTH];
+   ThreadState *tst;
+
+   tst = VG_(get_ThreadState)( VG_(get_lwp_tid)(VG_(gettid)()) );
+
+   // If necessary, fake up an ExeContext which is of our actual real CPU
+   // state.  Could cause problems if we got the panic/exception within the
+   // execontext/stack dump/symtab code.  But it's better than nothing.
+   if (0 == ip && 0 == sp && 0 == fp) {
+       ip = (Addr)__builtin_return_address(0);
+       GET_REAL_SP_AND_FP(sp, fp);
+   }
+
+   stacktop = tst->os_state.valgrind_stack_base + 
+              tst->os_state.valgrind_stack_szB;
+
+   VG_(get_StackTrace2)(ips, BACKTRACE_DEPTH, ip, sp, fp, sp, stacktop);
+   VG_(pp_StackTrace)  (ips, BACKTRACE_DEPTH);
+
+   VG_(printf)("\nBasic block ctr is approximately %llu\n", VG_(bbs_done) );
+
+   VG_(pp_sched_status)();
+   VG_(printf)("\n");
+   VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
+   VG_(printf)("It contains workarounds to several common problems.\n");
+   VG_(printf)("\n");
+   VG_(printf)("If that doesn't help, please report this bug to: %s\n\n", 
+               report);
+   VG_(printf)("In the bug report, send all the above text, the valgrind\n");
+   VG_(printf)("version, and what Linux distro you are using.  Thanks.\n\n");
+   VG_(exit)(1);
+
+   #undef BACKTRACE_DEPTH
+}
+
+void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file, 
+                        Int line, const Char* fn, const HChar* format, ... )
+{
+   va_list vargs;
+   Char buf[256];
+   Char* bufptr = buf;
+   Char* component;
+   Char* bugs_to;
+
+   static Bool entered = False;
+   if (entered) 
+     VG_(exit)(2);
+   entered = True;
+
+   va_start(vargs, format);
+   VG_(vsprintf) ( bufptr, format, vargs );
+   va_end(vargs);
+
+   if (isCore) {
+      component = "valgrind";
+      bugs_to   = VG_BUGS_TO;
+   } else { 
+      component = VG_(details).name;
+      bugs_to   = VG_(details).bug_reports_to;
+   }
+
+   // Treat vg_assert2(0, "foo") specially, as a panicky abort
+   if (VG_STREQ(expr, "0")) {
+      VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
+                  component, file, line, fn, expr );
+   } else {
+      VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
+                  component, file, line, fn, expr );
+   }
+   if (!VG_STREQ(buf, ""))
+      VG_(printf)("%s: %s\n", component, buf );
+
+   report_and_quit(bugs_to, 0,0,0);
+}
+
+__attribute__ ((noreturn))
+static void panic ( Char* name, Char* report, Char* str,
+                    Addr ip, Addr sp, Addr fp )
+{
+   VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
+   report_and_quit(report, ip, sp, fp);
+}
+
+void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp )
+{
+   panic("valgrind", VG_BUGS_TO, str, ip, sp, fp);
+}
+
+void VG_(core_panic) ( Char* str )
+{
+   VG_(core_panic_at)(str, 0,0,0);
+}
+
+void VG_(tool_panic) ( Char* str )
+{
+   panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0);
+}
+
+/* Print some helpful-ish text about unimplemented things, and give
+   up. */
+void VG_(unimplemented) ( Char* msg )
+{
+   VG_(message)(Vg_UserMsg, "");
+   VG_(message)(Vg_UserMsg, 
+      "Valgrind detected that your program requires");
+   VG_(message)(Vg_UserMsg, 
+      "the following unimplemented functionality:");
+   VG_(message)(Vg_UserMsg, "   %s", msg);
+   VG_(message)(Vg_UserMsg,
+      "This may be because the functionality is hard to implement,");
+   VG_(message)(Vg_UserMsg,
+      "or because no reasonable program would behave this way,");
+   VG_(message)(Vg_UserMsg,
+      "or because nobody has yet needed it.  In any case, let us know at");
+   VG_(message)(Vg_UserMsg,
+      "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
+   VG_(message)(Vg_UserMsg,
+      "");
+   VG_(message)(Vg_UserMsg,
+      "Valgrind has to exit now.  Sorry.  Bye!");
+   VG_(message)(Vg_UserMsg,
+      "");
+   VG_(pp_sched_status)();
+   VG_(exit)(1);
+}
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
+