blob: 952486285e4ba3f2d504478b462f382659d2f4cc [file] [log] [blame]
Index: coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- coregrind/m_syswrap/syswrap-generic.c (revision 11243)
+++ coregrind/m_syswrap/syswrap-generic.c (working copy)
@@ -2575,6 +2575,11 @@
} else {
path = (Char*)ARG1;
+ if (VG_(clo_xml)) {
+ VG_(printf_xml)("\n<execv/>\n\n</valgrindoutput>\n\n");
+ } else {
+ VG_(umsg)("execv called - the tool will now quit\n");
+ }
}
// Set up the child's environment.
Index: coregrind/pub_core_libcfile.h
===================================================================
--- coregrind/pub_core_libcfile.h (revision 11243)
+++ coregrind/pub_core_libcfile.h (working copy)
@@ -41,6 +41,7 @@
/* Move an fd into the Valgrind-safe range */
extern Int VG_(safe_fd) ( Int oldfd );
+extern Int reopen_output_fd(Bool xml);
extern Int VG_(fcntl) ( Int fd, Int cmd, Addr arg );
/* Convert an fd into a filename */
Index: coregrind/m_main.c
===================================================================
--- coregrind/m_main.c (revision 11243)
+++ coregrind/m_main.c (working copy)
@@ -320,6 +320,64 @@
}
}
+Int reopen_output_fd(Bool xml) {
+ // Returns FD
+ Char *filename = NULL;
+ Char *fsname_unexpanded = xml ? VG_(clo_xml_fname_unexpanded) :
+ VG_(clo_log_fname_unexpanded);
+ const Char *output_type = xml ? "xml" : "log";
+ Int ret = -1;
+ SysRes sres;
+
+ vg_assert(fsname_unexpanded != NULL);
+ vg_assert(VG_(strlen)(fsname_unexpanded) <= 900); /* paranoia */
+
+ // Nb: we overwrite an existing file of this name without asking
+ // any questions.
+ filename = VG_(expand_file_name)(xml ? "--xml-file" : "--log-file",
+ fsname_unexpanded);
+ sres = VG_(open)(filename,
+ VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
+ VKI_S_IRUSR|VKI_S_IWUSR);
+ if (!sr_isError(sres)) {
+ ret = sr_Res(sres);
+ if (xml)
+ VG_(clo_xml_fname_expanded) = filename;
+ else
+ VG_(clo_log_fname_expanded) = filename;
+
+ /* strdup here is probably paranoid overkill, but ... */
+ // TODO: do we need to do anything with it?
+ /* *fsname_unexpanded = VG_(strdup)( "main.mpclo.2",
+ xml_fsname_unexpanded ); */
+ } else {
+ VG_(message)(Vg_UserMsg,
+ "Can't create %s file '%s' (%s); giving up!\n",
+ output_type, filename, VG_(strerror)(sr_Err(sres)));
+ VG_(fmsg_bad_option)("--[xml|log]-file=<file>",
+ "--[xml|log]-file=<file> (didn't work out for some reason.)");
+ /*NOTREACHED*/
+ }
+
+ return ret;
+}
+
+static Int move_fd_into_safe_range(Int fd, Bool xml) {
+ OutputSink *sink = xml ? &(VG_(xml_output_sink)) : &(VG_(log_output_sink));
+ // Move fd into the safe range, so it doesn't conflict with any app fds.
+ fd = VG_(fcntl)(fd, VKI_F_DUPFD, VG_(fd_hard_limit));
+ if (fd < 0) {
+ VG_(printf)("valgrind: failed to move %s file fd "
+ "into safe range, using stderr\n", xml ? "XML" : "log");
+ sink->fd = 2; // stderr
+ sink->is_socket = False;
+ } else {
+ sink->fd = fd;
+ VG_(fcntl)(fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
+ }
+ return fd;
+}
+
/* The main processing for command line options. See comments above
on early_process_cmd_line_options.
@@ -346,13 +404,11 @@
*/
static
void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd,
- /*OUT*/Char** xml_fname_unexpanded,
const HChar* toolname )
{
// VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
// and we cannot change it until we know what we are changing it to is
// ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
- SysRes sres;
Int i, tmp_log_fd, tmp_xml_fd;
Int toolname_len = VG_(strlen)(toolname);
Char* tmp_str; // Used in a couple of places.
@@ -525,9 +581,13 @@
else if VG_STR_CLO(arg, "--log-file", log_fsname_unexpanded) {
log_to = VgLogTo_File;
+ VG_(clo_log_fname_unexpanded) =
+ VG_(strdup)("", log_fsname_unexpanded);
}
else if VG_STR_CLO(arg, "--xml-file", xml_fsname_unexpanded) {
xml_to = VgLogTo_File;
+ VG_(clo_xml_fname_unexpanded) =
+ VG_(strdup)("", xml_fsname_unexpanded);
}
else if VG_STR_CLO(arg, "--log-socket", log_fsname_unexpanded) {
@@ -650,17 +710,20 @@
if (VG_(clo_gen_suppressions) > 0 &&
!VG_(needs).core_errors && !VG_(needs).tool_errors) {
- VG_(fmsg_bad_option)("--gen-suppressions=yes",
- "Can't use --gen-suppressions= with %s\n"
- "because it doesn't generate errors.\n", VG_(details).name);
+ VG_(message)(Vg_UserMsg,
+ "Can't use --gen-suppressions= with this tool,\n");
+ VG_(message)(Vg_UserMsg,
+ "as it doesn't generate errors.\n");
+ VG_(fmsg_bad_option)("--gen-suppressions=", "\n");
}
/* If XML output is requested, check that the tool actually
supports it. */
if (VG_(clo_xml) && !VG_(needs).xml_output) {
VG_(clo_xml) = False;
- VG_(fmsg_bad_option)("--xml=yes",
+ VG_(message)(Vg_UserMsg,
"%s does not support XML output.\n", VG_(details).name);
+ VG_(fmsg_bad_option)("--xml=yes", "\n");
/*NOTREACHED*/
}
@@ -744,27 +807,7 @@
break;
case VgLogTo_File: {
- Char* logfilename;
-
- vg_assert(log_fsname_unexpanded != NULL);
- vg_assert(VG_(strlen)(log_fsname_unexpanded) <= 900); /* paranoia */
-
- // Nb: we overwrite an existing file of this name without asking
- // any questions.
- logfilename = VG_(expand_file_name)("--log-file",
- log_fsname_unexpanded);
- sres = VG_(open)(logfilename,
- VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
- VKI_S_IRUSR|VKI_S_IWUSR);
- if (!sr_isError(sres)) {
- tmp_log_fd = sr_Res(sres);
- VG_(clo_log_fname_expanded) = logfilename;
- } else {
- VG_(fmsg)("can't create log file '%s': %s\n",
- logfilename, VG_(strerror)(sr_Err(sres)));
- VG_(exit)(1);
- /*NOTREACHED*/
- }
+ tmp_log_fd = reopen_output_fd(False);
break;
}
@@ -803,30 +846,7 @@
break;
case VgLogTo_File: {
- Char* xmlfilename;
-
- vg_assert(xml_fsname_unexpanded != NULL);
- vg_assert(VG_(strlen)(xml_fsname_unexpanded) <= 900); /* paranoia */
-
- // Nb: we overwrite an existing file of this name without asking
- // any questions.
- xmlfilename = VG_(expand_file_name)("--xml-file",
- xml_fsname_unexpanded);
- sres = VG_(open)(xmlfilename,
- VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
- VKI_S_IRUSR|VKI_S_IWUSR);
- if (!sr_isError(sres)) {
- tmp_xml_fd = sr_Res(sres);
- VG_(clo_xml_fname_expanded) = xmlfilename;
- /* strdup here is probably paranoid overkill, but ... */
- *xml_fname_unexpanded = VG_(strdup)( "main.mpclo.2",
- xml_fsname_unexpanded );
- } else {
- VG_(fmsg)("can't create XML file '%s': %s\n",
- xmlfilename, VG_(strerror)(sr_Err(sres)));
- VG_(exit)(1);
- /*NOTREACHED*/
- }
+ tmp_xml_fd = reopen_output_fd(True);
break;
}
@@ -872,18 +892,7 @@
// Finalise the output fds: the log fd ..
if (tmp_log_fd >= 0) {
- // Move log_fd into the safe range, so it doesn't conflict with
- // any app fds.
- tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
- if (tmp_log_fd < 0) {
- VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd "
- "into safe range, using stderr\n");
- VG_(log_output_sink).fd = 2; // stderr
- VG_(log_output_sink).is_socket = False;
- } else {
- VG_(log_output_sink).fd = tmp_log_fd;
- VG_(fcntl)(VG_(log_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
- }
+ tmp_log_fd = move_fd_into_safe_range(tmp_log_fd, False);
} else {
// If they said --log-fd=-1, don't print anything. Plausible for use in
// regression testing suites that use client requests to count errors.
@@ -894,18 +903,7 @@
// Finalise the output fds: and the XML fd ..
if (tmp_xml_fd >= 0) {
- // Move xml_fd into the safe range, so it doesn't conflict with
- // any app fds.
- tmp_xml_fd = VG_(fcntl)(tmp_xml_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
- if (tmp_xml_fd < 0) {
- VG_(message)(Vg_UserMsg, "valgrind: failed to move XML file fd "
- "into safe range, using stderr\n");
- VG_(xml_output_sink).fd = 2; // stderr
- VG_(xml_output_sink).is_socket = False;
- } else {
- VG_(xml_output_sink).fd = tmp_xml_fd;
- VG_(fcntl)(VG_(xml_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
- }
+ tmp_xml_fd = move_fd_into_safe_range(tmp_xml_fd, True);
} else {
// If they said --xml-fd=-1, don't print anything. Plausible for use in
// regression testing suites that use client requests to count errors.
@@ -997,9 +995,12 @@
If logging to file or a socket, write details of parent PID and
command line args, to help people trying to interpret the
results of a run which encompasses multiple processes. */
-static void print_preamble ( Bool logging_to_fd,
- Char* xml_fname_unexpanded,
- const HChar* toolname )
+// TODO(timurrrr): we add a non-static declaration of this function since
+// we need it in coregrind/m_libcproc.c
+// Should we move it to some header file?
+void print_preamble ( Bool logging_to_fd, const HChar* toolname );
+
+void print_preamble ( Bool logging_to_fd, const HChar* toolname )
{
Int i;
HChar* xpre = VG_(clo_xml) ? " <line>" : "";
@@ -1007,9 +1008,15 @@
UInt (*umsg_or_xml)( const HChar*, ... )
= VG_(clo_xml) ? VG_(printf_xml) : VG_(umsg);
+ static const char* last_toolname = NULL;
vg_assert( VG_(args_for_client) );
vg_assert( VG_(args_for_valgrind) );
+
+ // This way you may pass toolname == NULL provided the first invocation
+ // with toolname != NULL takes place in valgrind_main().
+ toolname = (toolname == NULL ? last_toolname : toolname);
vg_assert( toolname );
+ last_toolname = toolname;
if (VG_(clo_xml)) {
VG_(printf_xml)("<?xml version=\"1.0\"?>\n");
@@ -1021,13 +1028,13 @@
VG_(printf_xml)("\n");
}
- if (VG_(clo_xml) || VG_(clo_verbosity > 0)) {
+ if (VG_(clo_xml) || VG_(clo_verbosity) > 0) {
if (VG_(clo_xml))
VG_(printf_xml)("<preamble>\n");
/* Tool details */
- umsg_or_xml( VG_(clo_xml) ? "%s%t%t%t, %t%s\n" : "%s%s%s%s, %s%s\n",
+ umsg_or_xml( "%s%s%s%s, %s%s\n",
xpre,
VG_(details).name,
NULL == VG_(details).version ? "" : "-",
@@ -1043,8 +1050,7 @@
);
}
- umsg_or_xml( VG_(clo_xml) ? "%s%t%s\n" : "%s%s%s\n",
- xpre, VG_(details).copyright_author, xpost );
+ umsg_or_xml("%s%s%s\n", xpre, VG_(details).copyright_author, xpost);
/* Core details */
umsg_or_xml(
@@ -1076,6 +1082,7 @@
}
else
if (VG_(clo_xml)) {
+ Char *xml_fname_unexpanded = VG_(clo_xml_fname_unexpanded);
VG_(printf_xml)("\n");
VG_(printf_xml)("<pid>%d</pid>\n", VG_(getpid)());
VG_(printf_xml)("<ppid>%d</ppid>\n", VG_(getppid)());
@@ -1383,7 +1390,6 @@
Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
ThreadId tid_main = VG_INVALID_THREADID;
Bool logging_to_fd = False;
- Char* xml_fname_unexpanded = NULL;
Int loglevel, i;
struct vki_rlimit zero = { 0, 0 };
XArray* addr2dihandle = NULL;
@@ -1838,8 +1844,7 @@
VG_(debugLog)(1, "main",
"(main_) Process Valgrind's command line options, "
"setup logging\n");
- main_process_cmd_line_options ( &logging_to_fd, &xml_fname_unexpanded,
- toolname );
+ main_process_cmd_line_options ( &logging_to_fd, toolname );
//--------------------------------------------------------------
// Zeroise the millisecond counter by doing a first read of it.
@@ -1852,10 +1857,10 @@
// p: tl_pre_clo_init [for 'VG_(details).name' and friends]
// p: main_process_cmd_line_options()
// [for VG_(clo_verbosity), VG_(clo_xml),
- // logging_to_fd, xml_fname_unexpanded]
+ // logging_to_fd]
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Print the preamble...\n");
- print_preamble(logging_to_fd, xml_fname_unexpanded, toolname);
+ print_preamble(logging_to_fd, toolname);
VG_(debugLog)(1, "main", "...finished the preamble\n");
//--------------------------------------------------------------
Index: coregrind/m_libcproc.c
===================================================================
--- coregrind/m_libcproc.c (revision 11243)
+++ coregrind/m_libcproc.c (working copy)
@@ -33,9 +33,12 @@
#include "pub_core_vkiscnums.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_libcproc.h"
#include "pub_core_libcsignal.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_options.h"
#include "pub_core_seqmatch.h"
#include "pub_core_mallocfree.h"
#include "pub_core_syscall.h"
@@ -722,10 +725,39 @@
(*atforks[i].parent)(tid);
}
+// Defined in m_main.c
+void print_preamble(Bool logging_to_fd, const char* toolname);
+
+Char* VG_(clo_log_fname_unexpanded) = NULL;
+Char* VG_(clo_xml_fname_unexpanded) = NULL;
+
+// If --log-file=ABC%pXYZ is specified, we'd like to have separate log files
+// for each forked child.
+// If %p is present in the --log-file option, this function creates
+// a new log file and redirects the child's output to it.
+static void open_new_logfile_for_forked_child(void)
+{
+ Int tmp_fd = -1;
+
+ if (VG_(log_output_sink).is_socket == False && VG_(clo_log_fname_unexpanded) != NULL) {
+ tmp_fd = reopen_output_fd(False);
+ VG_(log_output_sink).fd = VG_(safe_fd)(tmp_fd);
+ }
+
+ if (VG_(xml_output_sink).is_socket == False && VG_(clo_xml_fname_unexpanded) != NULL) {
+ tmp_fd = reopen_output_fd(True);
+ VG_(xml_output_sink).fd = VG_(safe_fd)(tmp_fd);
+ }
+
+ print_preamble(False, NULL);
+}
+
void VG_(do_atfork_child)(ThreadId tid)
{
Int i;
+ open_new_logfile_for_forked_child();
+
for (i = 0; i < n_atfork; i++)
if (atforks[i].child != NULL)
(*atforks[i].child)(tid);
Index: coregrind/pub_core_options.h
===================================================================
--- coregrind/pub_core_options.h (revision 11243)
+++ coregrind/pub_core_options.h (working copy)
@@ -80,6 +80,9 @@
extern Char* VG_(clo_log_fname_expanded);
extern Char* VG_(clo_xml_fname_expanded);
+extern Char* VG_(clo_log_fname_unexpanded);
+extern Char* VG_(clo_xml_fname_unexpanded);
+
/* Add timestamps to log messages? default: NO */
extern Bool VG_(clo_time_stamp);