diff options
-rw-r--r-- | base/base_unittests.isolate | 7 | ||||
-rw-r--r-- | chrome/browser_tests.isolate | 7 | ||||
-rw-r--r-- | chrome/chrome.isolate | 11 | ||||
-rw-r--r-- | chrome/interactive_ui_tests.isolate | 7 | ||||
-rw-r--r-- | chrome/unit_tests.isolate | 7 | ||||
-rw-r--r-- | content/content_browsertests.isolate | 12 | ||||
-rw-r--r-- | content/content_unittests.isolate | 7 | ||||
-rw-r--r-- | net/net_unittests.isolate | 7 | ||||
-rwxr-xr-x | testing/test_env.py | 12 | ||||
-rwxr-xr-x | tools/valgrind/asan/asan_symbolize.py | 84 |
10 files changed, 154 insertions, 7 deletions
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate index fca76d5..0822b24 100644 --- a/base/base_unittests.isolate +++ b/base/base_unittests.isolate @@ -58,6 +58,13 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/base_unittests.dSYM/', + ], + }, + }], ['OS=="win" and (fastbuild==0 or fastbuild==1)', { 'variables': { 'files': [ diff --git a/chrome/browser_tests.isolate b/chrome/browser_tests.isolate index 912fbca..2624378c 100644 --- a/chrome/browser_tests.isolate +++ b/chrome/browser_tests.isolate @@ -208,6 +208,13 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/browser_tests.dSYM/', + ], + }, + }], ['OS=="win" and libpeer_target_type=="loadable_module"', { 'variables': { 'files': [ diff --git a/chrome/chrome.isolate b/chrome/chrome.isolate index 64ae230..061cc23 100644 --- a/chrome/chrome.isolate +++ b/chrome/chrome.isolate @@ -77,6 +77,17 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/<(mac_product_name) Framework.framework.dSYM/', + '<(PRODUCT_DIR)/<(mac_product_name) Helper.app.dSYM/', + '<(PRODUCT_DIR)/<(mac_product_name).app.dSYM/', + '<(PRODUCT_DIR)/exif.so.dSYM/', + '<(PRODUCT_DIR)/ffmpegsumo.so.dSYM/', + ], + }, + }], ['OS=="win"', { 'variables': { 'files': [ diff --git a/chrome/interactive_ui_tests.isolate b/chrome/interactive_ui_tests.isolate index d968a7d..1d78389 100644 --- a/chrome/interactive_ui_tests.isolate +++ b/chrome/interactive_ui_tests.isolate @@ -70,6 +70,13 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/interactive_ui_tests.dSYM/', + ], + }, + }], ['OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/chrome/unit_tests.isolate b/chrome/unit_tests.isolate index a03f8a5..3c12a33 100644 --- a/chrome/unit_tests.isolate +++ b/chrome/unit_tests.isolate @@ -80,6 +80,13 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/unit_tests.dSYM/', + ], + }, + }], ['OS=="linux" or OS=="mac"', { 'variables': { 'read_only': 1, diff --git a/content/content_browsertests.isolate b/content/content_browsertests.isolate index 9701675..9de603a 100644 --- a/content/content_browsertests.isolate +++ b/content/content_browsertests.isolate @@ -86,6 +86,18 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/content_browsertests.dSYM/', + '<(PRODUCT_DIR)/Content Shell.app.dSYM/', + '<(PRODUCT_DIR)/ffmpegsumo.so.dSYM/', + '<(PRODUCT_DIR)/npapi_test_plugin.plugin.dSYM/', + '<(PRODUCT_DIR)/test_netscape_plugin.plugin.dSYM/', + '<(PRODUCT_DIR)/ppapi_tests.plugin.dSYM/', + ], + }, + }], ['OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/content/content_unittests.isolate b/content/content_unittests.isolate index b72dcee..ba15585 100644 --- a/content/content_unittests.isolate +++ b/content/content_unittests.isolate @@ -97,6 +97,13 @@ ], }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/content_unittests.dSYM/', + ], + }, + }], ['OS=="win" and (fastbuild==0 or fastbuild==1)', { 'variables': { 'files': [ diff --git a/net/net_unittests.isolate b/net/net_unittests.isolate index ec515fb..877c21e 100644 --- a/net/net_unittests.isolate +++ b/net/net_unittests.isolate @@ -34,6 +34,13 @@ 'read_only': 1, }, }], + ['OS=="mac" and asan==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/net_unittests.dSYM/', + ], + }, + }], ['OS=="win" and (fastbuild==0 or fastbuild==1)', { 'variables': { 'files': [ diff --git a/testing/test_env.py b/testing/test_env.py index 597ca2a..66a3721 100755 --- a/testing/test_env.py +++ b/testing/test_env.py @@ -124,12 +124,14 @@ def get_sanitizer_env(cmd, asan, lsan, msan, tsan): return extra_env -def get_sanitizer_symbolize_command(json_path=None): +def get_sanitizer_symbolize_command(json_path=None, executable_path=None): """Construct the command to invoke offline symbolization script.""" script_path = '../tools/valgrind/asan/asan_symbolize.py' cmd = [sys.executable, script_path] if json_path is not None: cmd.append('--test-summary-json-file=%s' % json_path) + if executable_path is not None: + cmd.append('--executable-path=%s' % executable_path) return cmd @@ -149,7 +151,8 @@ def symbolize_snippets_in_json(cmd, env): return try: - symbolize_command = get_sanitizer_symbolize_command(json_path=json_path) + symbolize_command = get_sanitizer_symbolize_command( + json_path=json_path, executable_path=cmd[0]) p = subprocess.Popen(symbolize_command, stderr=subprocess.PIPE, env=env) (_, stderr) = p.communicate() except OSError as e: @@ -207,8 +210,9 @@ def run_executable(cmd, env): # Need to pipe to the symbolizer script. p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE, stderr=sys.stdout) - p2 = subprocess.Popen(get_sanitizer_symbolize_command(), - env=env, stdin=p1.stdout) + p2 = subprocess.Popen( + get_sanitizer_symbolize_command(executable_path=cmd[0]), + env=env, stdin=p1.stdout) p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. p1.wait() p2.wait() diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py index cd61dae..9280d7a 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': + 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) |