diff options
author | maruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-04 19:03:24 +0000 |
---|---|---|
committer | maruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-04 19:03:24 +0000 |
commit | 733dfd0a6f394be71d448d6446b10ae277c57696 (patch) | |
tree | 4c03f021a7606ce979dcc6f950d72c2e504794b5 /tools/isolate/trace_inputs.py | |
parent | 58373dc0c5717b260e6bea465cdc0325336cbb59 (diff) | |
download | chromium_src-733dfd0a6f394be71d448d6446b10ae277c57696.zip chromium_src-733dfd0a6f394be71d448d6446b10ae277c57696.tar.gz chromium_src-733dfd0a6f394be71d448d6446b10ae277c57696.tar.bz2 |
Improve dtrace execve() parsing to support quotes and reenable execve tracing.
Since sprintf() is not available in dtrace, use custom quoting using char '\1'.
TBR=cmp@chromium.org
NOTRY=true
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com/10694084
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145479 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/isolate/trace_inputs.py')
-rwxr-xr-x | tools/isolate/trace_inputs.py | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/tools/isolate/trace_inputs.py b/tools/isolate/trace_inputs.py index c5c6dff..089a45b 100755 --- a/tools/isolate/trace_inputs.py +++ b/tools/isolate/trace_inputs.py @@ -1325,11 +1325,11 @@ class Dtrace(ApiBase): match = self.RE_EXECVE.match(args) if not match: raise TracingFailure( - 'Failed to parse arguments: %s' % args, + 'Failed to parse arguments: %r' % args, None, None, None) proc = self.processes[pid] proc.executable = match.group(1) - proc.command = process_quoted_arguments(match.group(3)) + proc.command = self.process_escaped_arguments(match.group(3)) if int(match.group(2)) != len(proc.command): raise TracingFailure( 'Failed to parse execve() arguments: %s' % args, @@ -1400,6 +1400,38 @@ class Dtrace(ApiBase): """Is called for all the event traces that are not handled.""" raise NotImplementedError('Please implement me') + @staticmethod + def process_escaped_arguments(text): + """Extracts escaped arguments on a string and return the arguments as a + list. + + Implemented as an automaton. + + Example: + With text = '\\001python2.7\\001-c\\001print(\\"hi\\")\\0', the + function will return ['python2.7', '-c', 'print("hi")] + """ + if not text.endswith('\\0'): + raise ValueError('String is not null terminated: %r' % text, text) + text = text[:-2] + + def unescape(x): + """Replaces '\\' with '\' and '\?' (where ? is anything) with ?. + + Implemented as an automaton. + """ + out = [] + escaped = False + for i in x: + if i == '\\' and not escaped: + escaped = True + continue + escaped = False + out.append(i) + return ''.join(out) + + return [unescape(i) for i in text.split('\\001')] + class Tracer(ApiBase.Tracer): # pylint: disable=C0301 # @@ -1617,39 +1649,38 @@ class Dtrace(ApiBase): } syscall::exec*:return /trackedpid[pid] && errno == 0/ { /* We need to join strings here, as using multiple printf() would - * cause tearing when multiple threads/processes are traced. */ + * cause tearing when multiple threads/processes are traced. + * Since it is impossible to escape a string and join it to another one, + * like sprintf("%s%S", previous, more), use hackery. + * Each of the elements are split with a \\1. \\0 cannot be used because + * it is simply ignored. This will conflict with any program putting a + * \\1 in their execve() string but this should be "rare enough" */ this->args = ""; /* Process exec_argv[0] */ this->args = strjoin( - this->args, (self->exec_argc > 0) ? ", \\"" : ""); - this->args = strjoin( this->args, (self->exec_argc > 0) ? self->exec_argv0 : ""); - this->args = strjoin(this->args, (self->exec_argc > 0) ? "\\"" : ""); /* Process exec_argv[1] */ this->args = strjoin( - this->args, (self->exec_argc > 1) ? ", \\"" : ""); + this->args, (self->exec_argc > 1) ? "\\1" : ""); this->args = strjoin( this->args, (self->exec_argc > 1) ? self->exec_argv1 : ""); - this->args = strjoin(this->args, (self->exec_argc > 1) ? "\\"" : ""); /* Process exec_argv[2] */ this->args = strjoin( - this->args, (self->exec_argc > 2) ? ", \\"" : ""); + this->args, (self->exec_argc > 2) ? "\\1" : ""); this->args = strjoin( this->args, (self->exec_argc > 2) ? self->exec_argv2 : ""); - this->args = strjoin(this->args, (self->exec_argc > 2) ? "\\"" : ""); /* Process exec_argv[3] */ this->args = strjoin( - this->args, (self->exec_argc > 3) ? ", \\"" : ""); + this->args, (self->exec_argc > 3) ? "\\1" : ""); this->args = strjoin( this->args, (self->exec_argc > 3) ? self->exec_argv3 : ""); - this->args = strjoin(this->args, (self->exec_argc > 3) ? "\\"" : ""); /* Prints self->exec_argc to permits verifying the internal * consistency since this code is quite fishy. */ - printf("%d %d %s(\\"%s\\", [%d%s])\\n", + printf("%d %d %s(\\"%s\\", [%d, %S])\\n", logindex, pid, probefunc, self->exec_arg0, self->exec_argc, @@ -1786,7 +1817,7 @@ class Dtrace(ApiBase): os.getpid(), self._script, self._dummy_file_id, - self.D_CODE) + self.D_CODE) + self.D_CODE_EXECVE def trace(self, cmd, cwd, tracename, output): """Runs dtrace on an executable. |