From: Nicholas Nethercote Date: Fri, 8 Apr 2005 23:28:23 +0000 (+0000) Subject: Added new assert macros vg_assert2 and tl_assert2 which allow you to print a X-Git-Tag: svn/VALGRIND_3_0_0~790 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9aecfe0d1389a38baa3cd4a88fc4fec7104b6048;p=thirdparty%2Fvalgrind.git Added new assert macros vg_assert2 and tl_assert2 which allow you to print a string explaining more detail if the assertion fails (eg. the value of the bogus variable) using printf-style format arguments. One consequence of this is that you can do something like vg_assert2(0, "bad bad bad"); instead of calling VG_(core_panic). The advantage of the new approach is that it shows the file/function/line info for the failing code, whereas VG_(core_panic)() does not. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3528 --- diff --git a/coregrind/core.h b/coregrind/core.h index 0d4da658dc..40d65a4624 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -782,18 +782,25 @@ extern void VG_(wait_for_threadstate)(Bool (*pred)(void *), void *arg); // Useful for making failing stubs, when certain things haven't yet been // implemented. -#define I_die_here \ - VG_(core_assert_fail) ("Unimplemented functionality", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__) - -#define vg_assert(expr) \ - ((void) ((expr) ? 0 : \ - (VG_(core_assert_fail) (VG_STRINGIFY(expr), \ - __FILE__, __LINE__, \ - __PRETTY_FUNCTION__), 0))) -__attribute__ ((__noreturn__)) -extern void VG_(core_assert_fail) ( const Char* expr, const Char* file, - Int line, const Char* fn ); +#define I_die_here \ + VG_(assert_fail) ("Unimplemented functionality", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + "valgrind", VG_BUGS_TO, "") + +#define vg_assert(expr) \ + ((void) ((expr) ? 0 : \ + (VG_(assert_fail) (/*isCore*/True, VG_STRINGIFY(expr), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + ""), \ + 0))) + +#define vg_assert2(expr, format, args...) \ + ((void) ((expr) ? 0 : \ + (VG_(assert_fail) (/*isCore*/True, VG_STRINGIFY(expr), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + format, ##args), \ + 0))) + __attribute__ ((__noreturn__)) extern void VG_(core_panic) ( Char* str ); __attribute__ ((__noreturn__)) diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index 13d2844630..af2dac9746 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -1169,6 +1169,8 @@ static void report_and_quit ( const Char* report, StackTrace ips ) else VG_(pp_StackTrace)(ips, VG_(clo_backtrace_size)); + 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"); @@ -1181,35 +1183,51 @@ static void report_and_quit ( const Char* report, StackTrace ips ) VG_(exit)(1); } -__attribute__ ((noreturn)) -static void assert_fail ( const Char* expr, const Char* name, const Char* report, - const Char* file, Int line, const Char* fn ) +void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file, + Int line, const Char* fn, const Char* 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; - VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n", - name, file, line, fn, expr ); - report_and_quit(report, NULL); -} -void VG_(tool_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn ) -{ - assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to, - file, line, fn); -} + va_start(vargs,format); + VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs, &bufptr ); + add_to_vg_sprintf_buf('\0', &bufptr); + va_end(vargs); -void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn ) -{ - assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn); + 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, NULL); } __attribute__ ((noreturn)) static void panic ( Char* name, Char* report, Char* str, StackTrace ips ) { VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str); - VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) ); report_and_quit(report, ips); } diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 63ba06aa65..9898e32cb2 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -652,8 +652,8 @@ static void handle_tt_miss ( ThreadId tid ) /* Not found; we need to request a translation. */ if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/ )) { found = VG_(search_transtab)( NULL, ip, True ); - if (!found) - VG_(core_panic)("VG_TRC_INNER_FASTMISS: missing tt_fast entry"); + vg_assert2(found, "VG_TRC_INNER_FASTMISS: missing tt_fast entry"); + } else { // If VG_(translate)() fails, it's because it had to throw a // signal because the client jumped to a bad address. That @@ -840,9 +840,8 @@ VgSchedReturnCode VG_(scheduler) ( ThreadId tid ) break; default: - VG_(printf)("\ntrc = %d\n", trc); - VG_(core_panic)("VG_(scheduler), phase 3: " - "unexpected thread return code"); + vg_assert2(0, "VG_(scheduler), phase 3: " + "unexpected thread return code (%u)", trc); /* NOTREACHED */ break; diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c index 01e42c1368..bd4a28a66b 100644 --- a/coregrind/vg_signals.c +++ b/coregrind/vg_signals.c @@ -1718,8 +1718,8 @@ static void (*fault_catcher)(Int sig, Addr addr); void VG_(set_fault_catcher)(void (*catcher)(Int, Addr)) { - if (catcher != NULL && fault_catcher != NULL) - VG_(core_panic)("Fault catcher is already registered"); + vg_assert2(NULL == catcher || NULL == fault_catcher, + "Fault catcher is already registered"); fault_catcher = catcher; } diff --git a/include/tool.h.base b/include/tool.h.base index 69d187603e..7205b4d66e 100644 --- a/include/tool.h.base +++ b/include/tool.h.base @@ -453,16 +453,24 @@ extern Bool VG_(getcwd_alloc) ( Char** cwd ); #define VG_STRINGIFY_WRK(x) #x #define VG_STRINGIFY(x) VG_STRINGIFY_WRK(x) -#define tl_assert(expr) \ - ((void) ((expr) ? 0 : \ - (VG_(tool_assert_fail) (VG_STRINGIFY(expr), \ - __FILE__, __LINE__, \ - __PRETTY_FUNCTION__), 0))) +#define tl_assert(expr) \ + ((void) ((expr) ? 0 : \ + (VG_(assert_fail) (/*isCore?*/False, VG_STRINGIFY(expr), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + ""), \ + 0))) + +#define tl_assert2(expr, format, args...) \ + ((void) ((expr) ? 0 : \ + (VG_(assert_fail) (/*isCore?*/False, VG_STRINGIFY(expr), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + format, ##args), \ + 0))) __attribute__ ((__noreturn__)) -extern void VG_(tool_assert_fail) ( const Char* expr, const Char* file, - Int line, const Char* fn ); - +extern void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file, + Int line, const Char* fn, + const Char* format, ... ); /* ------------------------------------------------------------------ */ /* Get memory by anonymous mmap. */