First pass at adding ability for Memcheck to print all output in XML
form. The relevant flag is --xml=yes. Currently this only works with
Memcheck.
Specifying this flag fixes various other options relating to verbosity
and behaviour of the leak checker, so that the resulting output is in
a relatively fixed form suitable for parsing by GUIs.
Still to do:
* Add mechanism to show error counts
* Add regression test
* Document the resulting format
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3773 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index 23450d8..4120180 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -1392,6 +1392,12 @@
vg_assert(0 == res);
}
+/*====================================================================*/
+/*=== Command-line: variables, processing, etc ===*/
+/*====================================================================*/
+
+// See pub_{core,tool}_options.h for explanations of all these.
+
static void usage ( Bool debug_help )
{
Char* usage1 =
@@ -1404,6 +1410,7 @@
" --version show version\n"
" -q --quiet run silently; only print error msgs\n"
" -v --verbose be more verbose, incl counts of errors\n"
+" --xml=yes show errors as XML\n"
" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
" --track-fds=no|yes track open file descriptors? [no]\n"
" --time-stamp=no|yes add timestamps to log messages? [no]\n"
@@ -1627,6 +1634,7 @@
/* do nothing */
}
+ else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
@@ -1798,6 +1806,29 @@
VG_(bad_option)("--gen-suppressions=");
}
+ /* If we've been asked to emit XML, mash around various other
+ options so as to constrain the output somewhat, and to remove
+ any need for user input during the run. */
+ if (VG_(clo_xml)) {
+ /* Disable suppression generation (requires user input) */
+ VG_(clo_gen_suppressions) = 0;
+ /* Disable attaching to GDB (requires user input) */
+ VG_(clo_db_attach) = False;
+ /* Set a known verbosity level */
+ VG_(clo_verbosity) = 1;
+ /* Disable error limits (this might be a bad idea!) */
+ VG_(clo_error_limit) = False;
+ /* Disable emulation warnings */
+ VG_(clo_show_emwarns) = False;
+ /* Disable waiting for GDB to debug Valgrind */
+ VG_(clo_wait_for_gdb) = False;
+ /* No file-descriptor leak checking yet */
+ VG_(clo_track_fds) = False;
+ /* Also, we want to set options for the leak checker, but that
+ will have to be done in Memcheck's flag-handling code, not
+ here. */
+ }
+
/* All non-logging-related options have been checked. If the logging
option specified is ok, we can switch to it, as we know we won't
have to generate any other command-line-related error messages.
@@ -1914,6 +1945,16 @@
}
}
+
+ /* Check that the requested tool actually supports XML output. */
+ if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
+ VG_(clo_xml) = False;
+ VG_(message)(Vg_UserMsg,
+ "Currently only Memcheck supports XML output.");
+ VG_(bad_option)("--xml=yes");
+ /*NOTREACHED*/
+ }
+
// Move log_fd into the safe range, so it doesn't conflict with any app fds.
// XXX: this is more or less duplicating the behaviour of the calls to
// VG_(safe_fd)() above, although this does not close the original fd.
@@ -1932,27 +1973,43 @@
command line args, to help people trying to interpret the
results of a run which encompasses multiple processes. */
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "<valgrindoutput>");
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
+ VG_(message)(Vg_UserMsg, "");
+ }
+
+ HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
+ HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
+
if (VG_(clo_verbosity > 0)) {
/* Tool details */
- VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
+ VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
+ xpre,
VG_(details).name,
NULL == VG_(details).version ? "" : "-",
NULL == VG_(details).version
? (Char*)"" : VG_(details).version,
- VG_(details).description);
- VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
+ VG_(details).description,
+ xpost);
+ VG_(message)(Vg_UserMsg, "%s%s%s",
+ xpre, VG_(details).copyright_author, xpost);
/* Core details */
VG_(message)(Vg_UserMsg,
- "Using LibVEX rev %s, a library for dynamic binary translation.",
- LibVEX_Version() );
+ "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
+ xpre, LibVEX_Version(), xpost );
VG_(message)(Vg_UserMsg,
- "Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.");
+ "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
+ xpre, xpost );
VG_(message)(Vg_UserMsg,
- "Using valgrind-%s, a dynamic binary instrumentation framework.",
- VERSION);
+ "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
+ xpre, VERSION, xpost);
VG_(message)(Vg_UserMsg,
- "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
+ "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
+ xpre, xpost );
}
if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
@@ -1963,6 +2020,17 @@
for (i = 0; i < VG_(client_argc); i++)
VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
}
+ else
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
+ VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "<argv>");
+ for (i = 0; i < VG_(client_argc); i++)
+ VG_(message)(Vg_UserMsg, " <arg>%s</arg>", VG_(client_argv)[i]);
+ VG_(message)(Vg_UserMsg, "</argv>");
+ }
if (VG_(clo_verbosity) > 1) {
Int fd;
@@ -1983,7 +2051,7 @@
if (fd < 0) {
VG_(message)(Vg_DebugMsg, " can't open /proc/version");
} else {
- #define BUF_LEN 256
+# define BUF_LEN 256
Char version_buf[BUF_LEN];
Int n = VG_(read) ( fd, version_buf, BUF_LEN );
vg_assert(n <= BUF_LEN);
@@ -1994,7 +2062,7 @@
VG_(message)(Vg_DebugMsg, " (empty?)");
}
VG_(close)(fd);
- #undef BUF_LEN
+# undef BUF_LEN
}
}
@@ -2291,8 +2359,10 @@
remains = VGA_(stack_unused)(tid);
if (remains < VKI_PAGE_SIZE)
- VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
- tid, remains);
+ VG_(message)(Vg_DebugMsg,
+ "WARNING: Thread %d is within %d bytes "
+ "of running out of stack!",
+ tid, remains);
}
/*
@@ -2726,7 +2796,7 @@
// Verbosity message
// p: end_rdtsc_calibration [so startup message is printed first]
//--------------------------------------------------------------
- if (VG_(clo_verbosity) == 1)
+ if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
if (VG_(clo_verbosity) > 0)
VG_(message)(Vg_UserMsg, "");
@@ -2745,6 +2815,11 @@
vg_assert(VG_(master_tid) == 1);
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
+ VG_(message)(Vg_UserMsg, "");
+ }
+
VG_(debugLog)(1, "main", "Running thread 1\n");
VGA_(main_thread_wrapper)(1);
@@ -2780,6 +2855,11 @@
if (VG_(clo_verbosity) > 0)
VG_(message)(Vg_UserMsg, "");
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
+ VG_(message)(Vg_UserMsg, "");
+ }
+
/* Print out file descriptor summary and stats. */
if (VG_(clo_track_fds))
VG_(show_open_fds)();
@@ -2789,6 +2869,12 @@
VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "</valgrindoutput>");
+ VG_(message)(Vg_UserMsg, "");
+ }
+
VG_(sanity_check_general)( True /*include expensive checks*/ );
if (VG_(clo_verbosity) > 1)