From: Julian Seward Date: Sat, 15 Aug 2009 22:41:51 +0000 (+0000) Subject: When generating XML output for suppressions, print the suppression X-Git-Tag: svn/VALGRIND_3_5_0~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b1edb07f641a2cd9b9739667138744f6aca9615;p=thirdparty%2Fvalgrind.git When generating XML output for suppressions, print the suppression both wrapped up in XML tags (as before) but also in plain text in a sequence of CDATA blocks. Normally only one, but in the worst case the raw data will have ]]> in it, in which case it needs to be split across two CDATA blocks. This apparently simple change involved a lot of refactoring of the suppression printing machinery: * in the core-tool iface, change "print_extra_suppression_info" (which prints any auxiliary info) to "get_extra_suppression_info", which parks the text in a caller-supplied buffer. Adjust tools to match. * VG_(apply_StackTrace): accept a void* argument, which is passed to each invokation of the functional parameter (a poor man's closure implementation). * move PRINTF_CHECK into put_tool_basics.h, where it should have been all along * move private printf-into-an-XArray-of-character functions from m_debuginfo into m_xarray, and make them public * gen_suppression itself: use all the above changes. Basically we always generate the plaintext version into an XArray. In text mode that's just printed. In XML mode, we print the XMLery as before, but the plaintext version is dumped into a CDATA block too. * update the Protocol 4 specification to match all this. This still isn't 100% right in the sense that the CDATA block data needs to be split across multiple blocks if it should ever contain the CDATA end mark "]]>". The Protocol 4 spec has this right even though the implementation currently doesn't. Fixes #191189. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10822 --- diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index e280b93368..bb2016f14e 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -2269,28 +2269,18 @@ Bool VG_(use_FPO_info) ( /*MOD*/Addr* ipP, /*--- ---*/ /*--------------------------------------------------------------*/ -/* Implement a "p2XA" function ("printf-to-XA"), which printfs into an - XArray of HChar, adding stuff at the end. This is very convenient - for concocting result strings in format_message(). Note that the - resulting string is NOT zero-terminated. +/* Try to make p2XA(dst, fmt, args..) turn into + VG_(xaprintf_no_f_c)(dst, fmt, args) without having to resort to + vararg macros. As usual with everything to do with varargs, it's + an ugly hack. - Unfortunately no format check on p2XA, since we need to use %t - for XML escaped-string output, and gcc complains about that. + //#define p2XA(dstxa, format, args...) + // VG_(xaprintf_no_f_c)(dstxa, format, ##args) */ -static void add_char_to_XA ( HChar c, void* opaque ) -{ - XArray* dst = (XArray*)opaque; - (void) VG_(addBytesToXA)( dst, &c, 1 ); -} -static void p2XA ( XArray* dst, const HChar* format, ... ) -{ - va_list vargs; - va_start(vargs, format); - VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs ); - va_end(vargs); -} +#define p2XA VG_(xaprintf_no_f_c) -/* Add a zero-terminating byte to DST. */ +/* Add a zero-terminating byte to DST, which must be an XArray* of + HChar. */ static void zterm_XA ( XArray* dst ) { HChar zero = 0; diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index 4948c18e25..3891b5c0b5 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -46,6 +46,7 @@ #include "pub_core_stacktrace.h" #include "pub_core_tooliface.h" #include "pub_core_translate.h" // for VG_(translate)() +#include "pub_core_xarray.h" // VG_(xaprintf) et al /*------------------------------------------------------------*/ /*--- Globals ---*/ @@ -295,78 +296,133 @@ static Bool eq_Error ( VgRes res, Error* e1, Error* e2 ) } -/* Helper function for suppression generation: print a single line of - a suppression pseudo-stack-trace, either in XML or text mode. +/* Helper functions for suppression generation: print a single line of + a suppression pseudo-stack-trace, either in XML or text mode. It's + important that the behaviour of these two functions exactly + corresponds. */ #define ERRTXT_LEN 4096 -static void printSuppForIp(UInt n, Addr ip) +static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque) { static UChar buf[ERRTXT_LEN]; - if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) { - if (VG_(clo_xml)) - VG_(printf_xml_no_f_c)(" %t \n", buf); - else - VG_(printf)(" fun:%s\n", buf); - - } else if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) { - if (VG_(clo_xml)) - VG_(printf_xml_no_f_c)(" %t \n", buf); - else - VG_(printf)(" obj:%s\n", buf); - + VG_(printf_xml_no_f_c)(" %t \n", buf); + } else + if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) { + VG_(printf_xml_no_f_c)(" %t \n", buf); } else { - if (VG_(clo_xml)) - VG_(printf_xml_no_f_c)(" * \n"); - else - VG_(printf)(" obj:*\n"); + VG_(printf_xml_no_f_c)(" * \n"); } } +static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV) +{ + static UChar buf[ERRTXT_LEN]; + XArray* /* of HChar */ text = (XArray*)textV; + if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) { + VG_(xaprintf)(text, " fun:%s\n", buf); + } else + if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) { + VG_(xaprintf)(text, " obj:%s\n", buf); + } else { + VG_(xaprintf)(text, " obj:*\n"); + } +} /* Generate a suppression for an error, either in text or XML mode. */ static void gen_suppression(Error* err) { - ExeContext* ec = VG_(get_error_where)(err); + Char xtra[256]; /* assumed big enough (is overrun-safe) */ + Bool anyXtra; + Char* name; + ExeContext* ec; + XArray* /* HChar */ text; + + const HChar* dummy_name = "insert_a_suppression_name_here"; + + vg_assert(err); + + /* In XML mode, we also need to print the plain text version of the + suppresion in a CDATA section. What that really means is, we + need to generate the plaintext version both in XML and text + mode. So generate it into TEXT. */ + text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1", + VG_(free), sizeof(HChar) ); + vg_assert(text); + + ec = VG_(get_error_where)(err); + vg_assert(ec); + + name = VG_TDICT_CALL(tool_get_error_name, err); + if (NULL == name) { + VG_(umsg)("(%s does not allow error to be suppressed)\n", + VG_(details).name); + return; + } - //(example code, see comment on CoreSuppKind above) - if (0) { - //if (0) ThreadErr == err->ekind) { - // VG_(printf)("{\n"); - // VG_(printf)(" \n"); - // VG_(printf)(" core:Thread\n"); + /* Ok. Generate the plain text version into TEXT. */ + VG_(xaprintf)(text, "{\n"); + VG_(xaprintf)(text, " <%s>\n", dummy_name); + VG_(xaprintf)(text, " %s:%s\n", VG_(details).name, name); - } else { - Char* name = VG_TDICT_CALL(tool_get_error_name, err); - if (NULL == name) { - VG_(umsg)("(%s does not allow error to be suppressed)\n", - VG_(details).name); - return; - } - if (VG_(clo_xml)) { - VG_(printf_xml)(" \n"); - VG_(printf_xml)(" insert_a_suppression_name_here\n"); - VG_(printf_xml)(" %s:%s\n", VG_(details).name, name); - } else { - VG_(printf)("{\n"); - VG_(printf)(" \n"); - VG_(printf)(" %s:%s\n", VG_(details).name, name); - } - VG_TDICT_CALL(tool_print_extra_suppression_info, err); - } + VG_(memset)(xtra, 0, sizeof(xtra)); + anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info, + err, xtra, sizeof(xtra)); + vg_assert(xtra[sizeof(xtra)-1] == 0); + + if (anyXtra) + VG_(xaprintf)(text, " %s\n", xtra); // Print stack trace elements - VG_(apply_StackTrace)(printSuppForIp, + VG_(apply_StackTrace)(printSuppForIp_nonXML, + text, VG_(get_ExeContext_StackTrace)(ec), VG_(get_ExeContext_n_ips)(ec)); - if (VG_(clo_xml)) { - VG_(printf_xml)(" \n"); + VG_(xaprintf)(text, "}\n"); + // zero terminate + VG_(xaprintf)(text, "%c", (HChar)0 ); + // VG_(printf) of text + + /* And now display it. */ + if (! VG_(clo_xml) ) { + + // the simple case + VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) ); + } else { - VG_(printf)("}\n"); + + /* Now we have to print the XML directly. No need to go to the + effort of stuffing it in an XArray, since we won't need it + again. */ + VG_(printf_xml)(" \n"); + VG_(printf_xml)(" %s\n", dummy_name); + VG_(printf_xml_no_f_c)( + " %t:%t\n", VG_(details).name, name); + if (anyXtra) + VG_(printf_xml_no_f_c)(" %t\n", xtra); + + // Print stack trace elements + VG_(apply_StackTrace)(printSuppForIp_XML, + NULL, + VG_(get_ExeContext_StackTrace)(ec), + VG_(get_ExeContext_n_ips)(ec)); + + // And now the cdata bit + // XXX FIXME! properly handle the case where the raw text + // itself contains "]]>", as specified in Protocol 4. + VG_(printf_xml)(" \n"); + VG_(printf_xml)("\n"); + VG_(printf_xml)(" \n"); + VG_(printf_xml)(" \n"); + } + + VG_(deleteXA)(text); } diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 130107afa4..42e0b978d8 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -514,7 +514,7 @@ UInt VG_(get_StackTrace) ( ThreadId tid, stack_highest_word); } -static void printIpDesc(UInt n, Addr ip) +static void printIpDesc(UInt n, Addr ip, void* uu_opaque) { #define BUF_LEN 4096 @@ -537,7 +537,7 @@ void VG_(pp_StackTrace) ( StackTrace ips, UInt n_ips ) if (VG_(clo_xml)) VG_(printf_xml)(" \n"); - VG_(apply_StackTrace)( printIpDesc, ips, n_ips ); + VG_(apply_StackTrace)( printIpDesc, NULL, ips, n_ips ); if (VG_(clo_xml)) VG_(printf_xml)(" \n"); @@ -555,8 +555,11 @@ void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt max_n_ips ) VG_(pp_StackTrace)(ips, n_ips); } -void VG_(apply_StackTrace)( void(*action)(UInt n, Addr ip), - StackTrace ips, UInt n_ips ) +void VG_(apply_StackTrace)( + void(*action)(UInt n, Addr ip, void* opaque), + void* opaque, + StackTrace ips, UInt n_ips + ) { Bool main_done = False; Int i = 0; @@ -576,7 +579,7 @@ void VG_(apply_StackTrace)( void(*action)(UInt n, Addr ip), } // Act on the ip - action(i, ip); + action(i, ip, opaque); i++; } while (i < n_ips && !main_done); diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c index 6f76d59788..c59e59b73f 100644 --- a/coregrind/m_tooliface.c +++ b/coregrind/m_tooliface.c @@ -233,7 +233,7 @@ void VG_(needs_tool_errors)( Bool (*read_extra) (Int, Char**, SizeT*, Supp*), Bool (*matches) (Error*, Supp*), Char* (*name) (Error*), - void (*print_extra)(Error*) + Bool (*get_xtra_si)(Error*,/*OUT*/Char*,Int) ) { VG_(needs).tool_errors = True; @@ -246,7 +246,7 @@ void VG_(needs_tool_errors)( VG_(tdict).tool_read_extra_suppression_info = read_extra; VG_(tdict).tool_error_matches_suppression = matches; VG_(tdict).tool_get_error_name = name; - VG_(tdict).tool_print_extra_suppression_info = print_extra; + VG_(tdict).tool_get_extra_suppression_info = get_xtra_si; } void VG_(needs_command_line_options)( diff --git a/coregrind/m_xarray.c b/coregrind/m_xarray.c index c00391b010..eef668b8c1 100644 --- a/coregrind/m_xarray.c +++ b/coregrind/m_xarray.c @@ -306,6 +306,31 @@ void VG_(dropHeadXA) ( XArray* xao, Word n ) xa->usedsizeE -= n; } +/* --------- Printeffery --------- */ + +static void add_char_to_XA ( HChar c, void* opaque ) +{ + XArray* dst = (XArray*)opaque; + (void) VG_(addBytesToXA)( dst, &c, 1 ); +} + +void VG_(xaprintf)( XArray* dst, const HChar* format, ... ) +{ + va_list vargs; + va_start(vargs, format); + VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs ); + va_end(vargs); +} + +/* and again .. */ +void VG_(xaprintf_no_f_c)( XArray* dst, const HChar* format, ... ) +{ + va_list vargs; + va_start(vargs, format); + VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs ); + va_end(vargs); +} + /*--------------------------------------------------------------------*/ /*--- end m_xarray.c ---*/ diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h index 9e928cb491..e5785054e0 100644 --- a/coregrind/pub_core_tooliface.h +++ b/coregrind/pub_core_tooliface.h @@ -125,7 +125,7 @@ typedef struct { Bool (*tool_read_extra_suppression_info) (Int, Char**, SizeT*, Supp*); Bool (*tool_error_matches_suppression) (Error*, Supp*); Char* (*tool_get_error_name) (Error*); - void (*tool_print_extra_suppression_info)(Error*); + Bool (*tool_get_extra_suppression_info) (Error*,/*OUT*/Char*,Int); // VG_(needs).superblock_discards void (*tool_discard_superblock_info)(Addr64, VexGuestExtents); diff --git a/docs/internals/xml-output-protocol4.txt b/docs/internals/xml-output-protocol4.txt index 98bce27ec7..7da70a99a0 100644 --- a/docs/internals/xml-output-protocol4.txt +++ b/docs/internals/xml-output-protocol4.txt @@ -298,14 +298,26 @@ SUPPRESSION ----------- These are optionally emitted as part of ERRORs, and specify the suppression that would be needed to suppress the containing error. +For convenience, the suppression is presented twice, once in +a structured nicely wrapped up in tags, and once as raw text +suitable for direct copying and pasting into a suppressions file. TEXT name of the suppression TEXT kind, eg "Memcheck:Param" TEXT (optional) aux kind, eg "write(buf)" SFRAME (one or more) frames + CDATAS +where CDATAS is a sequence of one or more blocks +holding the raw text. Unfortunately, CDATA provides no way to escape +the ending marker "]]>", which means that if the raw data contains +such a sequence, it has to be split between two CDATA blocks, one +ending with data "]]" and the other beginning with data "<". This is +why the spec calls for one or more CDATA blocks rather than exactly +one. + SFRAME ------ diff --git a/drd/drd_error.c b/drd/drd_error.c index 4b1c2fad9d..7b1b8a52ca 100644 --- a/drd/drd_error.c +++ b/drd/drd_error.c @@ -528,14 +528,18 @@ static Char* drd_get_error_name(Error* e) } /** - * Print extra suppression information. + * Return extra suppression information. * * Invoked while printing a suppression pattern because the user * specified --gen-suppressions=yes or all on the command line. DRD does not * define any 'extra' suppression information. */ -static void drd_print_extra_suppression_info(Error* e) -{ } +static +Bool drd_get_extra_suppression_info(Error* e, + /*OUT*/Char* buf, Int nBuf) +{ + return False; +} /** Tell the Valgrind core about DRD's error handlers. */ void DRD_(register_error_handlers)(void) @@ -549,5 +553,5 @@ void DRD_(register_error_handlers)(void) drd_read_extra_suppression_info, drd_error_matches_suppression, drd_get_error_name, - drd_print_extra_suppression_info); + drd_get_extra_suppression_info); } diff --git a/exp-ptrcheck/pc_common.c b/exp-ptrcheck/pc_common.c index 0421e6ba46..a45c416327 100644 --- a/exp-ptrcheck/pc_common.c +++ b/exp-ptrcheck/pc_common.c @@ -775,16 +775,23 @@ Char* pc_get_error_name ( Error* err ) } } -void pc_print_extra_suppression_info ( Error* err ) +Bool pc_get_extra_suppression_info ( Error* err, + /*OUT*/Char* buf, Int nBuf ) { - if (XE_SysParam == VG_(get_error_kind)(err)) { - VG_(printf)(" %s\n", VG_(get_error_string)(err)); + ErrorKind ekind = VG_(get_error_kind )(err); + tl_assert(buf); + tl_assert(nBuf >= 16); // stay sane + if (XE_SysParam == ekind) { + Char* errstr = VG_(get_error_string)(err); + tl_assert(errstr); + VG_(snprintf)(buf, nBuf-1, "%s", errstr); + return True; + } else { + return False; } } - - /*--------------------------------------------------------------------*/ /*--- end pc_common.c ---*/ /*--------------------------------------------------------------------*/ diff --git a/exp-ptrcheck/pc_common.h b/exp-ptrcheck/pc_common.h index 1e2549af4c..4772008dca 100644 --- a/exp-ptrcheck/pc_common.h +++ b/exp-ptrcheck/pc_common.h @@ -56,7 +56,8 @@ Bool pc_read_extra_suppression_info ( Int fd, Char** bufpp, SizeT* nBufp, Supp* su ); Bool pc_error_matches_suppression (Error* err, Supp* su); Char* pc_get_error_name ( Error* err ); -void pc_print_extra_suppression_info ( Error* err ); +Bool pc_get_extra_suppression_info ( Error* err, + /*OUT*/Char* buf, Int nBuf ); extern Bool h_clo_partial_loads_ok; /* extern Bool h_clo_lossage_check; */ diff --git a/exp-ptrcheck/pc_main.c b/exp-ptrcheck/pc_main.c index 436dba0136..64bee72572 100644 --- a/exp-ptrcheck/pc_main.c +++ b/exp-ptrcheck/pc_main.c @@ -190,7 +190,7 @@ static void pc_pre_clo_init(void) pc_read_extra_suppression_info, pc_error_matches_suppression, pc_get_error_name, - pc_print_extra_suppression_info); + pc_get_extra_suppression_info); VG_(needs_xml_output) (); diff --git a/helgrind/hg_errors.c b/helgrind/hg_errors.c index 6897e317e5..f5649bc245 100644 --- a/helgrind/hg_errors.c +++ b/helgrind/hg_errors.c @@ -1068,9 +1068,11 @@ Bool HG_(error_matches_suppression) ( Error* err, Supp* su ) } } -void HG_(print_extra_suppression_info) ( Error* err ) +Bool HG_(get_extra_suppression_info) ( Error* err, + /*OUT*/Char* buf, Int nBuf ) { /* Do nothing */ + return False; } diff --git a/helgrind/hg_errors.h b/helgrind/hg_errors.h index 6b97f488c2..ee49491853 100644 --- a/helgrind/hg_errors.h +++ b/helgrind/hg_errors.h @@ -44,7 +44,8 @@ Bool HG_(read_extra_suppression_info) ( Int fd, Char** bufpp, SizeT* nBufp, Supp* su ); Bool HG_(error_matches_suppression) ( Error* err, Supp* su ); Char* HG_(get_error_name) ( Error* err ); -void HG_(print_extra_suppression_info) ( Error* err ); +Bool HG_(get_extra_suppression_info) ( Error* err, + /*OUT*/Char* buf, Int nBuf ); /* Functions for recording various kinds of errors. */ void HG_(record_error_Race) ( Thread* thr, diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index 3a53f7129e..2e4ff1d8d3 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -4601,7 +4601,7 @@ static void hg_pre_clo_init ( void ) HG_(read_extra_suppression_info), HG_(error_matches_suppression), HG_(get_error_name), - HG_(print_extra_suppression_info)); + HG_(get_extra_suppression_info)); VG_(needs_xml_output) (); diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h index 734391c1d9..e66456136d 100644 --- a/include/pub_tool_basics.h +++ b/include/pub_tool_basics.h @@ -323,6 +323,16 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { # define UNLIKELY(x) (x) #endif +// printf format string checking for gcc. +// This feature has been supported since at least gcc version 2.95. +// For more information about the format attribute, see +// http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html. +#if defined(__GNUC__) +#define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y))) +#else +#define PRINTF_CHECK(x, y) +#endif + #endif /* __PUB_TOOL_BASICS_H */ diff --git a/include/pub_tool_libcprint.h b/include/pub_tool_libcprint.h index dd92feebcb..0e057cbba0 100644 --- a/include/pub_tool_libcprint.h +++ b/include/pub_tool_libcprint.h @@ -31,20 +31,6 @@ #ifndef __PUB_TOOL_LIBCPRINT_H #define __PUB_TOOL_LIBCPRINT_H - -/* Enable compile-time format string checking by gcc. - This feature is supported since at least gcc version 2.95. - For more information about the format attribute, see also - http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html. - */ - -#if defined(__GNUC__) -#define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y))) -#else -#define PRINTF_CHECK(x, y) -#endif - - /* --------------------------------------------------------------------- Basic printing ------------------------------------------------------------------ */ diff --git a/include/pub_tool_stacktrace.h b/include/pub_tool_stacktrace.h index f17758bb27..6792c69c69 100644 --- a/include/pub_tool_stacktrace.h +++ b/include/pub_tool_stacktrace.h @@ -62,11 +62,16 @@ extern UInt VG_(get_StackTrace) ( ThreadId tid, /*OUT*/StackTrace fps, Word first_ip_delta ); -// Apply a function to every element in the StackTrace. The parameter 'n' -// gives the index of the passed ip. Doesn't go below main() unless -// --show-below-main=yes is set. -extern void VG_(apply_StackTrace)( void(*action)(UInt n, Addr ip), - StackTrace ips, UInt n_ips ); +// Apply a function to every element in the StackTrace. The parameter +// 'n' gives the index of the passed ip. 'opaque' is an arbitrary +// pointer provided to each invokation of 'action' (a poor man's +// closure). Doesn't go below main() unless --show-below-main=yes is +// set. +extern void VG_(apply_StackTrace)( + void(*action)(UInt n, Addr ip, void* opaque), + void* opaque, + StackTrace ips, UInt n_ips + ); // Print a StackTrace. extern void VG_(pp_StackTrace) ( StackTrace ips, UInt n_ips ); diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h index 19f2c4c419..fa8d10410c 100644 --- a/include/pub_tool_tooliface.h +++ b/include/pub_tool_tooliface.h @@ -332,10 +332,17 @@ extern void VG_(needs_tool_errors) ( // VG_(tdict).tool_recognised_suppression(). Char* (*get_error_name)(Error* err), - // This should print any extra info for the error, for --gen-suppressions, - // including the newline. This is the inverse of + // This should print into buf[0..nBuf-1] any extra info for the + // error, for --gen-suppressions, but not including any leading + // spaces nor a trailing newline. When called, buf[0 .. nBuf-1] + // will be zero filled, and it is expected and checked that the + // last element is still zero after the call. In other words the + // tool may not overrun the buffer, and this is checked for. If + // there is any info printed in the buffer, return True, otherwise + // do nothing, and return False. This function is the inverse of // VG_(tdict).tool_read_extra_suppression_info(). - void (*print_extra_suppression_info)(Error* err) + Bool (*print_extra_suppression_info)(Error* err, + /*OUT*/Char* buf, Int nBuf) ); /* Is information kept by the tool about specific instructions or diff --git a/include/pub_tool_xarray.h b/include/pub_tool_xarray.h index 8e6cdcf191..d9147f85da 100644 --- a/include/pub_tool_xarray.h +++ b/include/pub_tool_xarray.h @@ -125,6 +125,18 @@ extern void VG_(dropHeadXA) ( XArray*, Word ); is NULL, in which case the parent's cost-center is used. */ extern XArray* VG_(cloneXA)( HChar* cc, XArray* xa ); +/* Convenience function: printf into an XArray of HChar, adding stuff + at the end. This is very convenient for concocting arbitrary + length printf output in an XArray. Note that the resulting string + is NOT zero-terminated. Versions are provided with and without a + format check, the latter so the unknown (to gcc) "%t" can be used + without gcc complaining. */ +extern void VG_(xaprintf)( XArray* dst, const HChar* format, ... ) + PRINTF_CHECK(2, 3); + +extern void VG_(xaprintf_no_f_c) + ( XArray* dst, const HChar* format, ... ); + #endif // __PUB_TOOL_XARRAY_H /*--------------------------------------------------------------------*/ diff --git a/memcheck/mc_errors.c b/memcheck/mc_errors.c index 441c991d9c..5ee1055066 100644 --- a/memcheck/mc_errors.c +++ b/memcheck/mc_errors.c @@ -1499,11 +1499,19 @@ Char* MC_(get_error_name) ( Error* err ) } } -void MC_(print_extra_suppression_info) ( Error* err ) +Bool MC_(get_extra_suppression_info) ( Error* err, + /*OUT*/Char* buf, Int nBuf ) { ErrorKind ekind = VG_(get_error_kind )(err); + tl_assert(buf); + tl_assert(nBuf >= 16); // stay sane if (Err_RegParam == ekind || Err_MemParam == ekind) { - VG_(printf)(" %s\n", VG_(get_error_string)(err)); + Char* errstr = VG_(get_error_string)(err); + tl_assert(errstr); + VG_(snprintf)(buf, nBuf-1, "%s", errstr); + return True; + } else { + return False; } } diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h index 920378362a..1032cf5ea5 100644 --- a/memcheck/mc_include.h +++ b/memcheck/mc_include.h @@ -320,7 +320,8 @@ Bool MC_(read_extra_suppression_info) ( Int fd, Char** buf, Bool MC_(error_matches_suppression) ( Error* err, Supp* su ); -void MC_(print_extra_suppression_info) ( Error* err ); +Bool MC_(get_extra_suppression_info) ( Error* err, + /*OUT*/Char* buf, Int nBuf ); Char* MC_(get_error_name) ( Error* err ); diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index ffe75917f2..c262d69d76 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -5715,7 +5715,7 @@ static void mc_pre_clo_init(void) MC_(read_extra_suppression_info), MC_(error_matches_suppression), MC_(get_error_name), - MC_(print_extra_suppression_info)); + MC_(get_extra_suppression_info)); VG_(needs_libc_freeres) (); VG_(needs_command_line_options)(mc_process_cmd_line_options, mc_print_usage,