Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: tools/valgrind/asan/asan_symbolize.py

Issue 859293002: Fix report symbolization on swarming bots. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « testing/test_env.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
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 from third_party import asan_symbolize 7 from third_party import asan_symbolize
8 8
9 import argparse 9 import argparse
10 import base64 10 import base64
11 import json 11 import json
12 import os 12 import os
13 import re
14 import subprocess
13 import sys 15 import sys
14 16
15 class LineBuffered(object): 17 class LineBuffered(object):
16 """Disable buffering on a file object.""" 18 """Disable buffering on a file object."""
17 def __init__(self, stream): 19 def __init__(self, stream):
18 self.stream = stream 20 self.stream = stream
19 21
20 def write(self, data): 22 def write(self, data):
21 self.stream.write(data) 23 self.stream.write(data)
22 if '\n' in data: 24 if '\n' in data:
(...skipping 18 matching lines...) Expand all
41 script_dir = os.path.dirname(os.path.abspath(__file__)) 43 script_dir = os.path.dirname(os.path.abspath(__file__))
42 # Assume this script resides three levels below src/ (i.e. 44 # Assume this script resides three levels below src/ (i.e.
43 # src/tools/valgrind/asan/). 45 # src/tools/valgrind/asan/).
44 src_root = os.path.join(script_dir, "..", "..", "..") 46 src_root = os.path.join(script_dir, "..", "..", "..")
45 symbolizer_path = os.path.join(src_root, 'third_party', 47 symbolizer_path = os.path.join(src_root, 'third_party',
46 'llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer') 48 'llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer')
47 assert(os.path.isfile(symbolizer_path)) 49 assert(os.path.isfile(symbolizer_path))
48 os.environ['LLVM_SYMBOLIZER_PATH'] = os.path.abspath(symbolizer_path) 50 os.environ['LLVM_SYMBOLIZER_PATH'] = os.path.abspath(symbolizer_path)
49 51
50 52
53 def is_hash_name(name):
54 match = re.match('[0-9a-f]+', name)
earthdok 2015/01/23 15:41:50 Note that re.match() matches at the beginning of t
Alexander Potapenko 2015/01/23 16:37:55 Done.
55 return bool(match)
56
57
58 def chrome_product_dir_path(exe_path):
59 if exe_path is None:
60 return None
61 path_parts = exe_path.split(os.path.sep)
earthdok 2015/01/23 15:41:50 why not os.path.split()/os.path.join()?
Alexander Potapenko 2015/01/23 16:37:55 Done
62 if len(path_parts) == 1:
earthdok 2015/01/23 15:41:50 the logic is not entirely clear here. a comment wo
Alexander Potapenko 2015/01/23 16:37:55 Done.
63 path_parts = ['.'] + path_parts
64 for index, part in enumerate(path_parts):
65 if part.endswith('.app'):
66 return os.path.sep.join(path_parts[:index])
67 return os.path.sep.join(path_parts[:-1])
68
69
70 inode_path_cache = {}
71
72
73 def find_inode_at_path(inode, path):
74 if inode in inode_path_cache:
75 return inode_path_cache[inode]
76 cmd = ['find', path, '-inum', str(inode)]
77 find_line = subprocess.check_output(cmd).rstrip()
78 lines = find_line.split('\n')
79 ret = None
80 if lines:
81 # `find` may give us several paths (e.g. 'Chromium Framework' in the
82 # product dir and 'Chromium Framework' inside 'Chromium.app',
83 # chrome_dsym_hints() will produce correct .dSYM path for any of them.
84 ret = lines[0]
85 inode_path_cache[inode] = ret
86 return ret
87
88
89 # Create a binary name filter that works around https://crbug.com/444835.
90 # When running tests on OSX swarming servers, ASan sometimes prints paths to
91 # files in cache (ending with SHA1 filenames) instead of paths to hardlinks to
92 # those files in the product dir.
93 # For a given |binary_path| chrome_osx_binary_name_filter() returns one of the
94 # hardlinks to the same inode in |product_dir_path|.
95 def make_chrome_osx_binary_name_filter(product_dir_path=''):
96 def chrome_osx_binary_name_filter(binary_path):
97 basename = os.path.basename(binary_path)
98 if is_hash_name(basename) and product_dir_path:
99 inode = os.stat(binary_path).st_ino
100 new_binary_path = find_inode_at_path(inode, product_dir_path)
101 if new_binary_path:
102 binary_path = new_binary_path
earthdok 2015/01/23 15:41:50 return new_binary_path ?
Alexander Potapenko 2015/01/23 16:37:55 Done.
103 return binary_path
104 return chrome_osx_binary_name_filter
105
106
51 # Construct a path to the .dSYM bundle for the given binary. 107 # Construct a path to the .dSYM bundle for the given binary.
52 # There are three possible cases for binary location in Chromium: 108 # There are three possible cases for binary location in Chromium:
53 # 1. The binary is a standalone executable or dynamic library in the product 109 # 1. The binary is a standalone executable or dynamic library in the product
54 # dir, the debug info is in "binary.dSYM" in the product dir. 110 # dir, the debug info is in "binary.dSYM" in the product dir.
55 # 2. The binary is a standalone framework or .app bundle, the debug info is in 111 # 2. The binary is a standalone framework or .app bundle, the debug info is in
56 # "Framework.framework.dSYM" or "App.app.dSYM" in the product dir. 112 # "Framework.framework.dSYM" or "App.app.dSYM" in the product dir.
57 # 3. The binary is a framework or an .app bundle within another .app bundle 113 # 3. The binary is a framework or an .app bundle within another .app bundle
58 # (e.g. Outer.app/Contents/Versions/1.2.3.4/Inner.app), and the debug info 114 # (e.g. Outer.app/Contents/Versions/1.2.3.4/Inner.app), and the debug info
59 # is in Inner.app.dSYM in the product dir. 115 # is in Inner.app.dSYM in the product dir.
60 # The first case is handled by llvm-symbolizer, so we only need to construct 116 # The first case is handled by llvm-symbolizer, so we only need to construct
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 def main(): 218 def main():
163 parser = argparse.ArgumentParser(description='Symbolize sanitizer reports.') 219 parser = argparse.ArgumentParser(description='Symbolize sanitizer reports.')
164 parser.add_argument('--test-summary-json-file', 220 parser.add_argument('--test-summary-json-file',
165 help='Path to a JSON file produced by the test launcher. The script will ' 221 help='Path to a JSON file produced by the test launcher. The script will '
166 'ignore stdandard input and instead symbolize the output stnippets ' 222 'ignore stdandard input and instead symbolize the output stnippets '
167 'inside the JSON file. The result will be written back to the JSON ' 223 'inside the JSON file. The result will be written back to the JSON '
168 'file.') 224 'file.')
169 parser.add_argument('strip_path_prefix', nargs='*', 225 parser.add_argument('strip_path_prefix', nargs='*',
170 help='When printing source file names, the longest prefix ending in one ' 226 help='When printing source file names, the longest prefix ending in one '
171 'of these substrings will be stripped. E.g.: "Release/../../".') 227 'of these substrings will be stripped. E.g.: "Release/../../".')
228 parser.add_argument('--executable_path',
earthdok 2015/01/23 15:41:50 dash, not underscore
Alexander Potapenko 2015/01/23 16:37:55 Done.
229 help='Path to program executable. Will be used on OSX swarming bots to '
earthdok 2015/01/23 15:41:50 Please drop the future tense.
Alexander Potapenko 2015/01/23 16:37:55 Done.
230 'locate dSYM bundles for associated frameworks and bundles.')
172 args = parser.parse_args() 231 args = parser.parse_args()
173 232
174 disable_buffering() 233 disable_buffering()
175 set_symbolizer_path() 234 set_symbolizer_path()
176 asan_symbolize.demangle = True 235 asan_symbolize.demangle = True
177 asan_symbolize.fix_filename_patterns = args.strip_path_prefix 236 asan_symbolize.fix_filename_patterns = args.strip_path_prefix
178 loop = asan_symbolize.SymbolizationLoop(dsym_hint_producer=chrome_dsym_hints) 237 maybe_binary_name_filter = None
earthdok 2015/01/23 15:41:50 "maybe_" is kind of unnecessary
Alexander Potapenko 2015/01/23 16:37:55 Done.
238 if os.uname()[0] == 'Darwin':
239 maybe_binary_name_filter = make_chrome_osx_binary_name_filter(
240 chrome_product_dir_path(args.executable_path))
241 loop = asan_symbolize.SymbolizationLoop(
242 binary_name_filter=maybe_binary_name_filter,
243 dsym_hint_producer=chrome_dsym_hints)
179 244
180 if args.test_summary_json_file: 245 if args.test_summary_json_file:
181 symbolize_snippets_in_json(args.test_summary_json_file, loop) 246 symbolize_snippets_in_json(args.test_summary_json_file, loop)
182 else: 247 else:
183 # Process stdin. 248 # Process stdin.
184 asan_symbolize.logfile = sys.stdin 249 asan_symbolize.logfile = sys.stdin
185 loop.process_logfile() 250 loop.process_logfile()
186 251
187 if __name__ == '__main__': 252 if __name__ == '__main__':
188 main() 253 main()
OLDNEW
« no previous file with comments | « testing/test_env.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698