OLD | NEW |
1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 19 matching lines...) Expand all Loading... |
30 import logging | 30 import logging |
31 | 31 |
32 from webkitpy.common.webkit_finder import WebKitFinder | 32 from webkitpy.common.webkit_finder import WebKitFinder |
33 from webkitpy.layout_tests.breakpad.dump_reader import DumpReader | 33 from webkitpy.layout_tests.breakpad.dump_reader import DumpReader |
34 | 34 |
35 | 35 |
36 _log = logging.getLogger(__name__) | 36 _log = logging.getLogger(__name__) |
37 | 37 |
38 | 38 |
39 class DumpReaderMultipart(DumpReader): | 39 class DumpReaderMultipart(DumpReader): |
| 40 |
40 """Base class for Linux and Android breakpad dump reader.""" | 41 """Base class for Linux and Android breakpad dump reader.""" |
41 | 42 |
42 def __init__(self, host, build_dir): | 43 def __init__(self, host, build_dir): |
43 super(DumpReaderMultipart, self).__init__(host, build_dir) | 44 super(DumpReaderMultipart, self).__init__(host, build_dir) |
44 self._webkit_finder = WebKitFinder(host.filesystem) | 45 self._webkit_finder = WebKitFinder(host.filesystem) |
45 self._breakpad_tools_available = None | 46 self._breakpad_tools_available = None |
46 self._generated_symbols = False | 47 self._generated_symbols = False |
47 | 48 |
48 def check_is_functional(self): | 49 def check_is_functional(self): |
49 return self._check_breakpad_tools_available() | 50 return self._check_breakpad_tools_available() |
50 | 51 |
51 def _get_pid_from_dump(self, dump_file): | 52 def _get_pid_from_dump(self, dump_file): |
52 dump = self._read_dump(dump_file) | 53 dump = self._read_dump(dump_file) |
53 if not dump: | 54 if not dump: |
54 return None | 55 return None |
55 if 'pid' in dump: | 56 if 'pid' in dump: |
56 return dump['pid'][0] | 57 return dump['pid'][0] |
57 return None | 58 return None |
58 | 59 |
59 def _get_stack_from_dump(self, dump_file): | 60 def _get_stack_from_dump(self, dump_file): |
60 dump = self._read_dump(dump_file) | 61 dump = self._read_dump(dump_file) |
61 if not dump: | 62 if not dump: |
62 return None | 63 return None |
63 if not 'upload_file_minidump' in dump: | 64 if not 'upload_file_minidump' in dump: |
64 return None | 65 return None |
65 | 66 |
66 self._generate_breakpad_symbols_if_necessary() | 67 self._generate_breakpad_symbols_if_necessary() |
67 f, temp_name = self._host.filesystem.open_binary_tempfile('dmp') | 68 f, temp_name = self._host.filesystem.open_binary_tempfile('dmp') |
68 f.write("\r\n".join(dump['upload_file_minidump'])) | 69 f.write('\r\n'.join(dump['upload_file_minidump'])) |
69 f.close() | 70 f.close() |
70 | 71 |
71 cmd = [self._path_to_minidump_stackwalk(), temp_name, self._symbols_dir(
)] | 72 cmd = [self._path_to_minidump_stackwalk(), temp_name, self._symbols_dir(
)] |
72 try: | 73 try: |
73 stack = self._host.executive.run_command(cmd, return_stderr=False) | 74 stack = self._host.executive.run_command(cmd, return_stderr=False) |
74 except: | 75 except: |
75 _log.warning('Failed to execute "%s"' % ' '.join(cmd)) | 76 _log.warning('Failed to execute "%s"' % ' '.join(cmd)) |
76 stack = None | 77 stack = None |
77 finally: | 78 finally: |
78 self._host.filesystem.remove(temp_name) | 79 self._host.filesystem.remove(temp_name) |
79 return stack | 80 return stack |
80 | 81 |
81 def _read_dump(self, dump_file): | 82 def _read_dump(self, dump_file): |
82 with self._host.filesystem.open_binary_file_for_reading(dump_file) as f: | 83 with self._host.filesystem.open_binary_file_for_reading(dump_file) as f: |
83 boundary = f.readline().strip()[2:] | 84 boundary = f.readline().strip()[2:] |
84 f.seek(0) | 85 f.seek(0) |
85 try: | 86 try: |
86 data = cgi.parse_multipart(f, {'boundary': boundary}) | 87 data = cgi.parse_multipart(f, {'boundary': boundary}) |
87 return data | 88 return data |
88 except: | 89 except: |
89 pass | 90 pass |
90 return None | 91 return None |
91 | 92 |
92 def _check_breakpad_tools_available(self): | 93 def _check_breakpad_tools_available(self): |
93 if self._breakpad_tools_available != None: | 94 if self._breakpad_tools_available is not None: |
94 return self._breakpad_tools_available | 95 return self._breakpad_tools_available |
95 | 96 |
96 REQUIRED_BREAKPAD_TOOLS = [ | 97 REQUIRED_BREAKPAD_TOOLS = [ |
97 'dump_syms', | 98 'dump_syms', |
98 'minidump_stackwalk', | 99 'minidump_stackwalk', |
99 ] | 100 ] |
100 result = True | 101 result = True |
101 for binary in REQUIRED_BREAKPAD_TOOLS: | 102 for binary in REQUIRED_BREAKPAD_TOOLS: |
102 full_path = self._host.filesystem.join(self._build_dir, binary) | 103 full_path = self._host.filesystem.join(self._build_dir, binary) |
103 if not self._host.filesystem.exists(full_path): | 104 if not self._host.filesystem.exists(full_path): |
104 result = False | 105 result = False |
105 _log.error('Unable to find %s' % binary) | 106 _log.error('Unable to find %s' % binary) |
106 _log.error(' at %s' % full_path) | 107 _log.error(' at %s' % full_path) |
107 | 108 |
108 if not result: | 109 if not result: |
109 _log.error(" Could not find breakpad tools, unexpected crashes wo
n't be symbolized") | 110 _log.error(" Could not find breakpad tools, unexpected crashes wo
n't be symbolized") |
110 _log.error(' Did you build the target blink_tests?') | 111 _log.error(' Did you build the target blink_tests?') |
111 _log.error('') | 112 _log.error('') |
112 | 113 |
113 self._breakpad_tools_available = result | 114 self._breakpad_tools_available = result |
114 return self._breakpad_tools_available | 115 return self._breakpad_tools_available |
115 | 116 |
116 def _path_to_minidump_stackwalk(self): | 117 def _path_to_minidump_stackwalk(self): |
117 return self._host.filesystem.join(self._build_dir, "minidump_stackwalk") | 118 return self._host.filesystem.join(self._build_dir, 'minidump_stackwalk') |
118 | 119 |
119 def _path_to_generate_breakpad_symbols(self): | 120 def _path_to_generate_breakpad_symbols(self): |
120 return self._webkit_finder.path_from_chromium_base("components", "crash"
, "tools", "generate_breakpad_symbols.py") | 121 return self._webkit_finder.path_from_chromium_base('components', 'crash'
, 'tools', 'generate_breakpad_symbols.py') |
121 | 122 |
122 def _symbols_dir(self): | 123 def _symbols_dir(self): |
123 return self._host.filesystem.join(self._build_dir, 'content_shell.syms') | 124 return self._host.filesystem.join(self._build_dir, 'content_shell.syms') |
124 | 125 |
125 def _generate_breakpad_symbols_if_necessary(self): | 126 def _generate_breakpad_symbols_if_necessary(self): |
126 if self._generated_symbols: | 127 if self._generated_symbols: |
127 return | 128 return |
128 self._generated_symbols = True | 129 self._generated_symbols = True |
129 | 130 |
130 _log.debug("Generating breakpad symbols") | 131 _log.debug('Generating breakpad symbols') |
131 for binary in self._binaries_to_symbolize(): | 132 for binary in self._binaries_to_symbolize(): |
132 full_path = self._host.filesystem.join(self._build_dir, binary) | 133 full_path = self._host.filesystem.join(self._build_dir, binary) |
133 cmd = [ | 134 cmd = [ |
134 self._path_to_generate_breakpad_symbols(), | 135 self._path_to_generate_breakpad_symbols(), |
135 '--binary=%s' % full_path, | 136 '--binary=%s' % full_path, |
136 '--symbols-dir=%s' % self._symbols_dir(), | 137 '--symbols-dir=%s' % self._symbols_dir(), |
137 '--build-dir=%s' % self._build_dir, | 138 '--build-dir=%s' % self._build_dir, |
138 ] | 139 ] |
139 try: | 140 try: |
140 self._host.executive.run_command(cmd) | 141 self._host.executive.run_command(cmd) |
141 except: | 142 except: |
142 _log.error('Failed to execute "%s"' % ' '.join(cmd)) | 143 _log.error('Failed to execute "%s"' % ' '.join(cmd)) |
143 | 144 |
144 def _binaries_to_symbolize(self): | 145 def _binaries_to_symbolize(self): |
145 """This routine must be implemented by subclasses. | 146 """This routine must be implemented by subclasses. |
146 | 147 |
147 Returns an array of binaries that need to be symbolized.""" | 148 Returns an array of binaries that need to be symbolized.""" |
148 raise NotImplementedError() | 149 raise NotImplementedError() |
149 | 150 |
150 | 151 |
151 class DumpReaderLinux(DumpReaderMultipart): | 152 class DumpReaderLinux(DumpReaderMultipart): |
| 153 |
152 """Linux breakpad dump reader.""" | 154 """Linux breakpad dump reader.""" |
153 | 155 |
154 def _binaries_to_symbolize(self): | 156 def _binaries_to_symbolize(self): |
155 return ['content_shell', 'libtest_netscape_plugin.so', 'libffmpegsumo.so
', 'libosmesa.so'] | 157 return ['content_shell', 'libtest_netscape_plugin.so', 'libffmpegsumo.so
', 'libosmesa.so'] |
156 | 158 |
157 def _file_extension(self): | 159 def _file_extension(self): |
158 return 'dmp' | 160 return 'dmp' |
159 | 161 |
160 | 162 |
161 class DumpReaderAndroid(DumpReaderMultipart): | 163 class DumpReaderAndroid(DumpReaderMultipart): |
| 164 |
162 """Android breakpad dump reader.""" | 165 """Android breakpad dump reader.""" |
163 | 166 |
164 def _binaries_to_symbolize(self): | 167 def _binaries_to_symbolize(self): |
165 return ['lib/libcontent_shell_content_view.so'] | 168 return ['lib/libcontent_shell_content_view.so'] |
166 | 169 |
167 def _file_extension(self): | 170 def _file_extension(self): |
168 return 'dmp' | 171 return 'dmp' |
OLD | NEW |