| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # coding=utf-8 | 2 # coding=utf-8 |
| 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Traces an executable and its child processes and extract the files accessed | 7 """Traces an executable and its child processes and extract the files accessed |
| 8 by them. | 8 by them. |
| 9 | 9 |
| 10 The implementation uses OS-specific API. The native Kernel logger and the ETL | 10 The implementation uses OS-specific API. The native Kernel logger and the ETL |
| (...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 # This is the most common format. function(args) = result | 1025 # This is the most common format. function(args) = result |
| 1026 RE_HEADER = re.compile(r'^([a-z_0-9]+)\((.+?)\)\s+= (.+)$') | 1026 RE_HEADER = re.compile(r'^([a-z_0-9]+)\((.+?)\)\s+= (.+)$') |
| 1027 # An interrupted function call, only grab the minimal header. | 1027 # An interrupted function call, only grab the minimal header. |
| 1028 RE_UNFINISHED = re.compile(r'^([^\(]+)(.*) \<unfinished \.\.\.\>$') | 1028 RE_UNFINISHED = re.compile(r'^([^\(]+)(.*) \<unfinished \.\.\.\>$') |
| 1029 # A resumed function call. | 1029 # A resumed function call. |
| 1030 RE_RESUMED = re.compile(r'^<\.\.\. ([^ ]+) resumed> (.+)$') | 1030 RE_RESUMED = re.compile(r'^<\.\.\. ([^ ]+) resumed> (.+)$') |
| 1031 # A process received a signal. | 1031 # A process received a signal. |
| 1032 RE_SIGNAL = re.compile(r'^--- SIG[A-Z]+ .+ ---') | 1032 RE_SIGNAL = re.compile(r'^--- SIG[A-Z]+ .+ ---') |
| 1033 # A process didn't handle a signal. Ignore any junk appearing before, | 1033 # A process didn't handle a signal. Ignore any junk appearing before, |
| 1034 # because the process was forcibly killed so it won't open any new file. | 1034 # because the process was forcibly killed so it won't open any new file. |
| 1035 RE_KILLED = re.compile(r'^.*\+\+\+ killed by ([A-Z]+) \+\+\+$') | 1035 RE_KILLED = re.compile( |
| 1036 r'^.*\+\+\+ killed by ([A-Z]+)( \(core dumped\))? \+\+\+$') |
| 1036 # A call was canceled. Ignore any prefix. | 1037 # A call was canceled. Ignore any prefix. |
| 1037 RE_UNAVAILABLE = re.compile(r'^.*\)\s*= \? <unavailable>$') | 1038 RE_UNAVAILABLE = re.compile(r'^.*\)\s*= \? <unavailable>$') |
| 1038 # Happens when strace fails to even get the function name. | 1039 # Happens when strace fails to even get the function name. |
| 1039 UNNAMED_FUNCTION = '????' | 1040 UNNAMED_FUNCTION = '????' |
| 1040 | 1041 |
| 1041 # Corner-case in python, a class member function decorator must not be | 1042 # Corner-case in python, a class member function decorator must not be |
| 1042 # @staticmethod. | 1043 # @staticmethod. |
| 1043 def parse_args(regexp, expect_zero): # pylint: disable=E0213 | 1044 def parse_args(regexp, expect_zero): # pylint: disable=E0213 |
| 1044 """Automatically convert the str 'args' into a list of processed | 1045 """Automatically convert the str 'args' into a list of processed |
| 1045 arguments. | 1046 arguments. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 | 1135 |
| 1135 def on_line(self, line): | 1136 def on_line(self, line): |
| 1136 self._line_number += 1 | 1137 self._line_number += 1 |
| 1137 if self.RE_SIGNAL.match(line): | 1138 if self.RE_SIGNAL.match(line): |
| 1138 # Ignore signals. | 1139 # Ignore signals. |
| 1139 return | 1140 return |
| 1140 | 1141 |
| 1141 try: | 1142 try: |
| 1142 match = self.RE_KILLED.match(line) | 1143 match = self.RE_KILLED.match(line) |
| 1143 if match: | 1144 if match: |
| 1144 # Converts a '+++ killied by Foo +++' trace into an exit_group(). | 1145 # Converts a '+++ killed by Foo +++' trace into an exit_group(). |
| 1145 self.handle_exit_group(match.group(1), None) | 1146 self.handle_exit_group(match.group(1), None) |
| 1146 return | 1147 return |
| 1147 | 1148 |
| 1148 match = self.RE_UNFINISHED.match(line) | 1149 match = self.RE_UNFINISHED.match(line) |
| 1149 if match: | 1150 if match: |
| 1150 if match.group(1) in self._pending_calls: | 1151 if match.group(1) in self._pending_calls: |
| 1151 raise TracingFailure( | 1152 raise TracingFailure( |
| 1152 'Found two unfinished calls for the same function', | 1153 'Found two unfinished calls for the same function', |
| 1153 None, None, None, | 1154 None, None, None, |
| 1154 self._pending_calls) | 1155 self._pending_calls) |
| (...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3200 return command(argv[1:]) | 3201 return command(argv[1:]) |
| 3201 except TracingFailure, e: | 3202 except TracingFailure, e: |
| 3202 sys.stderr.write('\nError: ') | 3203 sys.stderr.write('\nError: ') |
| 3203 sys.stderr.write(str(e)) | 3204 sys.stderr.write(str(e)) |
| 3204 sys.stderr.write('\n') | 3205 sys.stderr.write('\n') |
| 3205 return 1 | 3206 return 1 |
| 3206 | 3207 |
| 3207 | 3208 |
| 3208 if __name__ == '__main__': | 3209 if __name__ == '__main__': |
| 3209 sys.exit(main(sys.argv[1:])) | 3210 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |