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..9280d7a893ecf3bf3f07275a14cca3efe506fa76 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,73 @@ 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) |
+ return bool(match) |
+ |
+ |
+def split_path(path): |
+ ret = [] |
+ while True: |
+ head, tail = os.path.split(path) |
+ if head == path: |
+ return [head] + ret |
+ ret, path = [tail] + ret, head |
+ |
+ |
+def chrome_product_dir_path(exe_path): |
+ if exe_path is None: |
+ return None |
+ path_parts = split_path(exe_path) |
+ # Make sure the product dir path isn't empty if |exe_path| consists of |
+ # a single component. |
+ if len(path_parts) == 1: |
+ path_parts = ['.'] + path_parts |
+ for index, part in enumerate(path_parts): |
+ if part.endswith('.app'): |
+ return os.path.join(*path_parts[:index]) |
+ # If the executable isn't an .app bundle, it's a commandline binary that |
+ # resides right in the product dir. |
+ return os.path.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: |
+ return new_binary_path |
+ 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 |
@@ -63,7 +132,7 @@ def set_symbolizer_path(): |
# path. Only one of these bundles may be a framework and frameworks cannot |
# contain other bundles. |
def chrome_dsym_hints(binary): |
- path_parts = binary.split(os.path.sep) |
+ path_parts = split_path(binary) |
app_positions = [] |
framework_positions = [] |
for index, part in enumerate(path_parts): |
@@ -89,7 +158,7 @@ def chrome_dsym_hints(binary): |
# In case 2 this is the same as |outermost_bundle|. |
innermost_bundle = bundle_positions[-1] |
dsym_path = product_dir + [path_parts[innermost_bundle]] |
- result = '%s.dSYM' % os.path.sep.join(dsym_path) |
+ result = '%s.dSYM' % os.path.join(*dsym_path) |
return [result] |
@@ -169,13 +238,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', |
+ help='Path to program executable. Used on OSX swarming bots to 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) |
+ binary_name_filter = None |
+ if os.uname()[0] == 'Darwin': |
Timur Iskhodzhanov
2015/02/11 21:36:16
this asserts on Windows, again.
|
+ binary_name_filter = make_chrome_osx_binary_name_filter( |
+ chrome_product_dir_path(args.executable_path)) |
+ loop = asan_symbolize.SymbolizationLoop( |
+ binary_name_filter=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) |