New command line option: --trace-children-skip-by-arg, which allows
chase/nochase decisions for child processes to be made on the basis
of their argv[] entries rather than on the name of their executables.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11483 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index e5871c4..d5e762d 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -124,6 +124,9 @@
" --trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]\n"
" --trace-children-skip=patt1,patt2,... specifies a list of executables\n"
" that --trace-children=yes should not trace into\n"
+" --trace-children-skip-by-arg=patt1,patt2,... same as --trace-children-skip=\n"
+" but check the argv[] entries for children, rather\n"
+" than the exe name, to make a follow/no-follow decision\n"
" --child-silent-after-fork=no|yes omit child output between fork & exec? [no]\n"
" --track-fds=no|yes track open file descriptors? [no]\n"
" --time-stamp=no|yes add timestamps to log messages? [no]\n"
@@ -503,7 +506,10 @@
else if VG_BOOL_CLO(arg, "--dsymutil", VG_(clo_dsymutil)) {}
- else if VG_STR_CLO (arg, "--trace-children-skip", VG_(clo_trace_children_skip)) {}
+ else if VG_STR_CLO (arg, "--trace-children-skip",
+ VG_(clo_trace_children_skip)) {}
+ else if VG_STR_CLO (arg, "--trace-children-skip-by-arg",
+ VG_(clo_trace_children_skip_by_arg)) {}
else if VG_BINT_CLO(arg, "--vex-iropt-verbosity",
VG_(clo_vex_control).iropt_verbosity, 0, 10) {}
diff --git a/coregrind/m_options.c b/coregrind/m_options.c
index a347c7d..888e2c7 100644
--- a/coregrind/m_options.c
+++ b/coregrind/m_options.c
@@ -57,6 +57,7 @@
Bool VG_(clo_demangle) = True;
Bool VG_(clo_trace_children) = False;
HChar* VG_(clo_trace_children_skip) = NULL;
+HChar* VG_(clo_trace_children_skip_by_arg) = NULL;
Bool VG_(clo_child_silent_after_fork) = False;
Char* VG_(clo_log_fname_expanded) = NULL;
Char* VG_(clo_xml_fname_expanded) = NULL;
@@ -255,9 +256,13 @@
}
/* Should we trace into this child executable (across execve etc) ?
- This involves considering --trace-children=, --trace-children-skip=
- and the name of the executable. */
-Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name )
+ This involves considering --trace-children=,
+ --trace-children-skip=, --trace-children-skip-by-arg=, and the name
+ of the executable. 'child_argv' must not include the name of the
+ executable itself; iow child_argv[0] must be the first arg, if any,
+ for the child. */
+Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name,
+ HChar** child_argv )
{
// child_exe_name is pulled out of the guest's space. We
// should be at least marginally cautious with it, lest it
@@ -265,13 +270,13 @@
if (child_exe_name == NULL || VG_(strlen)(child_exe_name) == 0)
return VG_(clo_trace_children); // we know narfink
- // the main logic
// If --trace-children=no, the answer is simply NO.
if (! VG_(clo_trace_children))
return False;
- // otherwise, return True, unless the exe name matches any of the
- // patterns specified by --trace-children-skip=.
+ // Otherwise, look for other reasons to say NO. First,
+ // see if the exe name matches any of the patterns specified
+ // by --trace-children-skip=.
if (VG_(clo_trace_children_skip)) {
HChar const* last = VG_(clo_trace_children_skip);
HChar const* name = (HChar const*)child_exe_name;
@@ -294,7 +299,36 @@
return False;
}
}
-
+
+ // Check if any of the args match any of the patterns specified
+ // by --trace-children-skip-by-arg=.
+ if (VG_(clo_trace_children_skip_by_arg) && child_argv != NULL) {
+ HChar const* last = VG_(clo_trace_children_skip_by_arg);
+ while (*last) {
+ Int i;
+ Bool matches;
+ HChar* patt;
+ HChar const* first = consume_commas(last);
+ last = consume_field(first);
+ if (first == last)
+ break;
+ vg_assert(last > first);
+ /* copy the candidate string into a temporary malloc'd block
+ so we can use VG_(string_match) on it. */
+ patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1);
+ VG_(memcpy)(patt, first, last - first);
+ vg_assert(patt[last-first] == 0);
+ for (i = 0; child_argv[i]; i++) {
+ matches = VG_(string_match)(patt, child_argv[i]);
+ if (matches) {
+ VG_(free)(patt);
+ return False;
+ }
+ }
+ VG_(free)(patt);
+ }
+ }
+
// --trace-children=yes, and this particular executable isn't
// excluded
return True;
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index 22eae28..2a58ea1 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -2550,8 +2550,29 @@
return;
}
+ // debug-only printing
+ if (0) {
+ VG_(printf)("ARG1 = %p(%s)\n", (void*)ARG1, (HChar*)ARG1);
+ if (ARG2) {
+ VG_(printf)("ARG2 = ");
+ Int q;
+ HChar** vec = (HChar**)ARG2;
+ for (q = 0; vec[q]; q++)
+ VG_(printf)("%p(%s) ", vec[q], vec[q]);
+ VG_(printf)("\n");
+ } else {
+ VG_(printf)("ARG2 = null\n");
+ }
+ }
+
// Decide whether or not we want to follow along
- trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1 );
+ { // Make 'child_argv' be a pointer to the child's arg vector
+ // (skipping the exe name)
+ HChar** child_argv = (HChar**)ARG2;
+ if (child_argv && child_argv[0] == NULL)
+ child_argv = NULL;
+ trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1, child_argv );
+ }
// Do the important checks: it is a file, is executable, permissions are
// ok, etc. We allow setuid executables to run only in the case when
diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h
index 06b5701..ecfbd9b 100644
--- a/coregrind/pub_core_options.h
+++ b/coregrind/pub_core_options.h
@@ -70,6 +70,10 @@
/* String containing comma-separated patterns for executable names
that should not be traced into even when --trace-children=yes */
extern HChar* VG_(clo_trace_children_skip);
+/* The same as VG_(clo_trace_children), except that these patterns are
+ tested against the arguments for child processes, rather than the
+ executable name. */
+extern HChar* VG_(clo_trace_children_skip_by_arg);
/* After a fork, the child's output can become confusingly
intermingled with the parent's output. This is especially
problematic when VG_(clo_xml) is True. Setting
@@ -220,9 +224,13 @@
extern Bool VG_(clo_dsymutil);
/* Should we trace into this child executable (across execve etc) ?
- This involves considering --trace-children=, --trace-children-skip=
- and the name of the executable. */
-extern Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name );
+ This involves considering --trace-children=,
+ --trace-children-skip=, --trace-children-skip-by-arg=, and the name
+ of the executable. 'child_argv' must not include the name of the
+ executable itself; iow child_argv[0] must be the first arg, if any,
+ for the child. */
+extern Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name,
+ HChar** child_argv );
#endif // __PUB_CORE_OPTIONS_H
diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml
index 59eb787..0fb6c9d 100644
--- a/docs/xml/manual-core.xml
+++ b/docs/xml/manual-core.xml
@@ -663,7 +663,7 @@
<varlistentry id="opt.trace-children-skip" xreflabel="--trace-children-skip">
<term>
- <option><![CDATA[--trace-children-skip=patt1,patt2 ]]></option>
+ <option><![CDATA[--trace-children-skip=patt1,patt2,... ]]></option>
</term>
<listitem>
<para>This option only has an effect when
@@ -687,6 +687,20 @@
</listitem>
</varlistentry>
+ <varlistentry id="opt.trace-children-skip-by-arg"
+ xreflabel="--trace-children-skip-by-arg">
+ <term>
+ <option><![CDATA[--trace-children-skip-by-arg=patt1,patt2,... ]]></option>
+ </term>
+ <listitem>
+ <para>This is the same as
+ <option>--trace-children-skip</option>, with one difference:
+ the decision as to whether to trace into a child process is
+ made by examining the arguments to the child process, rather
+ than the name of its executable.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="opt.child-silent-after-fork"
xreflabel="--child-silent-after-fork">
<term>
diff --git a/none/tests/cmdline1.stdout.exp b/none/tests/cmdline1.stdout.exp
index 9c6d5fe..fadaa59 100644
--- a/none/tests/cmdline1.stdout.exp
+++ b/none/tests/cmdline1.stdout.exp
@@ -12,6 +12,9 @@
--trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]
--trace-children-skip=patt1,patt2,... specifies a list of executables
that --trace-children=yes should not trace into
+ --trace-children-skip-by-arg=patt1,patt2,... same as --trace-children-skip=
+ but check the argv[] entries for children, rather
+ than the exe name, to make a follow/no-follow decision
--child-silent-after-fork=no|yes omit child output between fork & exec? [no]
--track-fds=no|yes track open file descriptors? [no]
--time-stamp=no|yes add timestamps to log messages? [no]
diff --git a/none/tests/cmdline2.stdout.exp b/none/tests/cmdline2.stdout.exp
index d27316f..6603e25 100644
--- a/none/tests/cmdline2.stdout.exp
+++ b/none/tests/cmdline2.stdout.exp
@@ -12,6 +12,9 @@
--trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]
--trace-children-skip=patt1,patt2,... specifies a list of executables
that --trace-children=yes should not trace into
+ --trace-children-skip-by-arg=patt1,patt2,... same as --trace-children-skip=
+ but check the argv[] entries for children, rather
+ than the exe name, to make a follow/no-follow decision
--child-silent-after-fork=no|yes omit child output between fork & exec? [no]
--track-fds=no|yes track open file descriptors? [no]
--time-stamp=no|yes add timestamps to log messages? [no]