Index: tools/valgrind/asan/asan_symbolize.py |
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py |
index cd61daeb29ae867cf3dbffce876ba0a92b0aa6b6..dddfd127bffc40d4182555d7ff6a0fc5f12f4e23 100755 |
--- a/tools/valgrind/asan/asan_symbolize.py |
+++ b/tools/valgrind/asan/asan_symbolize.py |
@@ -10,6 +10,8 @@ import argparse |
import base64 |
import json |
import os |
+import re |
+import subprocess |
import sys |
class LineBuffered(object): |
@@ -48,6 +50,60 @@ def set_symbolizer_path(): |
os.environ['LLVM_SYMBOLIZER_PATH'] = os.path.abspath(symbolizer_path) |
+def is_hash_name(name): |
+ 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.
|
+ return bool(match) |
+ |
+ |
+def chrome_product_dir_path(exe_path): |
+ if exe_path is None: |
+ return None |
+ 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
|
+ 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.
|
+ path_parts = ['.'] + path_parts |
+ for index, part in enumerate(path_parts): |
+ if part.endswith('.app'): |
+ return os.path.sep.join(path_parts[:index]) |
+ return os.path.sep.join(path_parts[:-1]) |
+ |
+ |
+inode_path_cache = {} |
+ |
+ |
+def find_inode_at_path(inode, path): |
+ if inode in inode_path_cache: |
+ return inode_path_cache[inode] |
+ cmd = ['find', path, '-inum', str(inode)] |
+ find_line = subprocess.check_output(cmd).rstrip() |
+ lines = find_line.split('\n') |
+ ret = None |
+ if lines: |
+ # `find` may give us several paths (e.g. 'Chromium Framework' in the |
+ # product dir and 'Chromium Framework' inside 'Chromium.app', |
+ # chrome_dsym_hints() will produce correct .dSYM path for any of them. |
+ ret = lines[0] |
+ inode_path_cache[inode] = ret |
+ return ret |
+ |
+ |
+# Create a binary name filter that works around https://crbug.com/444835. |
+# When running tests on OSX swarming servers, ASan sometimes prints paths to |
+# files in cache (ending with SHA1 filenames) instead of paths to hardlinks to |
+# those files in the product dir. |
+# For a given |binary_path| chrome_osx_binary_name_filter() returns one of the |
+# hardlinks to the same inode in |product_dir_path|. |
+def make_chrome_osx_binary_name_filter(product_dir_path=''): |
+ def chrome_osx_binary_name_filter(binary_path): |
+ basename = os.path.basename(binary_path) |
+ if is_hash_name(basename) and product_dir_path: |
+ inode = os.stat(binary_path).st_ino |
+ new_binary_path = find_inode_at_path(inode, product_dir_path) |
+ if new_binary_path: |
+ 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.
|
+ return binary_path |
+ return chrome_osx_binary_name_filter |
+ |
+ |
# Construct a path to the .dSYM bundle for the given binary. |
# There are three possible cases for binary location in Chromium: |
# 1. The binary is a standalone executable or dynamic library in the product |
@@ -169,13 +225,22 @@ def main(): |
parser.add_argument('strip_path_prefix', nargs='*', |
help='When printing source file names, the longest prefix ending in one ' |
'of these substrings will be stripped. E.g.: "Release/../../".') |
+ parser.add_argument('--executable_path', |
earthdok
2015/01/23 15:41:50
dash, not underscore
Alexander Potapenko
2015/01/23 16:37:55
Done.
|
+ 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.
|
+ 'locate dSYM bundles for associated frameworks and bundles.') |
args = parser.parse_args() |
disable_buffering() |
set_symbolizer_path() |
asan_symbolize.demangle = True |
asan_symbolize.fix_filename_patterns = args.strip_path_prefix |
- loop = asan_symbolize.SymbolizationLoop(dsym_hint_producer=chrome_dsym_hints) |
+ 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.
|
+ if os.uname()[0] == 'Darwin': |
+ maybe_binary_name_filter = make_chrome_osx_binary_name_filter( |
+ chrome_product_dir_path(args.executable_path)) |
+ loop = asan_symbolize.SymbolizationLoop( |
+ binary_name_filter=maybe_binary_name_filter, |
+ dsym_hint_producer=chrome_dsym_hints) |
if args.test_summary_json_file: |
symbolize_snippets_in_json(args.test_summary_json_file, loop) |