Commit 9d919340 authored by glider's avatar glider Committed by Commit bot

Fix report symbolization on swarming bots.

According to issue 444835 there were at least two problems with debug info on
the swarming bots:
 - the .dSYM bundles for the test binaries and other applications weren't
uploaded to swarming servers;
 - for some binaries (e.g. Chromium Framework) their names were replaced with
SHA-1 hashes that confused llvm-symbolizer and made finding the .dSYM bundles
impossible.

This CL adds the necessary .dSYM paths to .isolate files for the tests
currently being ran on swarming bots (for other tests their .dSYM paths will be
added as needed).
It also extends tools/valgrind/asan/asan_symbolize.py with a binary name filter
that replaces the hashes with the corresponding file names in the product
directory.

BUG=444835
R=earthdok@chromium.org,maruel@chromium.org,csharp@chromium.org

Review URL: https://codereview.chromium.org/859293002

Cr-Commit-Position: refs/heads/master@{#315059}
parent 14902170
......@@ -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': [
......
......@@ -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': [
......
......@@ -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': [
......
......@@ -70,6 +70,13 @@
],
},
}],
['OS=="mac" and asan==1', {
'variables': {
'files': [
'<(PRODUCT_DIR)/interactive_ui_tests.dSYM/',
],
},
}],
['OS=="mac" or OS=="win"', {
'variables': {
'command': [
......
......@@ -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,
......
......@@ -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': [
......
......@@ -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': [
......
......@@ -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': [
......
......@@ -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()
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment