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 |