| Index: tools/valgrind/asan/asan_symbolize.py
|
| diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py
|
| index 9e7d50419348548665bc2f34b8671581b2669b4f..cd61daeb29ae867cf3dbffce876ba0a92b0aa6b6 100755
|
| --- a/tools/valgrind/asan/asan_symbolize.py
|
| +++ b/tools/valgrind/asan/asan_symbolize.py
|
| @@ -6,6 +6,9 @@
|
|
|
| from third_party import asan_symbolize
|
|
|
| +import argparse
|
| +import base64
|
| +import json
|
| import os
|
| import sys
|
|
|
| @@ -90,14 +93,96 @@ def chrome_dsym_hints(binary):
|
| return [result]
|
|
|
|
|
| +# We want our output to match base::EscapeJSONString(), which produces
|
| +# doubly-escaped strings. The first escaping pass is handled by this class. The
|
| +# second pass happens when JSON data is dumped to file.
|
| +class StringEncoder(json.JSONEncoder):
|
| + def __init__(self):
|
| + json.JSONEncoder.__init__(self)
|
| +
|
| + def encode(self, s):
|
| + assert(isinstance(s, basestring))
|
| + encoded = json.JSONEncoder.encode(self, s)
|
| + assert(len(encoded) >= 2)
|
| + assert(encoded[0] == '"')
|
| + assert(encoded[-1] == '"')
|
| + encoded = encoded[1:-1]
|
| + # Special case from base::EscapeJSONString().
|
| + encoded = encoded.replace('<', '\u003C')
|
| + return encoded
|
| +
|
| +
|
| +class JSONTestRunSymbolizer(object):
|
| + def __init__(self, symbolization_loop):
|
| + self.string_encoder = StringEncoder()
|
| + self.symbolization_loop = symbolization_loop
|
| +
|
| + def symbolize_snippet(self, snippet):
|
| + symbolized_lines = []
|
| + for line in snippet.split('\n'):
|
| + symbolized_lines += self.symbolization_loop.process_line(line)
|
| + return '\n'.join(symbolized_lines)
|
| +
|
| + def symbolize(self, test_run):
|
| + original_snippet = base64.b64decode(test_run['output_snippet_base64'])
|
| + symbolized_snippet = self.symbolize_snippet(original_snippet)
|
| + if symbolized_snippet == original_snippet:
|
| + # No sanitizer reports in snippet.
|
| + return
|
| +
|
| + test_run['original_output_snippet'] = test_run['output_snippet']
|
| + test_run['original_output_snippet_base64'] = \
|
| + test_run['output_snippet_base64']
|
| +
|
| + escaped_snippet = StringEncoder().encode(symbolized_snippet)
|
| + test_run['output_snippet'] = escaped_snippet
|
| + test_run['output_snippet_base64'] = \
|
| + base64.b64encode(symbolized_snippet)
|
| + test_run['snippet_processed_by'] = 'asan_symbolize.py'
|
| + # Originally, "lossless" refers to "no Unicode data lost while encoding the
|
| + # string". However, since we're applying another kind of transformation
|
| + # (symbolization), it doesn't seem right to consider the snippet lossless.
|
| + test_run['losless_snippet'] = False
|
| +
|
| +
|
| +def symbolize_snippets_in_json(filename, symbolization_loop):
|
| + with open(filename, 'r') as f:
|
| + json_data = json.load(f)
|
| +
|
| + test_run_symbolizer = JSONTestRunSymbolizer(symbolization_loop)
|
| + for iteration_data in json_data['per_iteration_data']:
|
| + for test_name, test_runs in iteration_data.iteritems():
|
| + for test_run in test_runs:
|
| + test_run_symbolizer.symbolize(test_run)
|
| +
|
| + with open(filename, 'w') as f:
|
| + json.dump(json_data, f, indent=3, sort_keys=True)
|
| +
|
| +
|
| def main():
|
| + parser = argparse.ArgumentParser(description='Symbolize sanitizer reports.')
|
| + parser.add_argument('--test-summary-json-file',
|
| + help='Path to a JSON file produced by the test launcher. The script will '
|
| + 'ignore stdandard input and instead symbolize the output stnippets '
|
| + 'inside the JSON file. The result will be written back to the JSON '
|
| + 'file.')
|
| + 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/../../".')
|
| + args = parser.parse_args()
|
| +
|
| disable_buffering()
|
| set_symbolizer_path()
|
| asan_symbolize.demangle = True
|
| - asan_symbolize.fix_filename_patterns = sys.argv[1:]
|
| - asan_symbolize.logfile = sys.stdin
|
| + asan_symbolize.fix_filename_patterns = args.strip_path_prefix
|
| loop = asan_symbolize.SymbolizationLoop(dsym_hint_producer=chrome_dsym_hints)
|
| - loop.process_logfile()
|
| +
|
| + if args.test_summary_json_file:
|
| + symbolize_snippets_in_json(args.test_summary_json_file, loop)
|
| + else:
|
| + # Process stdin.
|
| + asan_symbolize.logfile = sys.stdin
|
| + loop.process_logfile()
|
|
|
| if __name__ == '__main__':
|
| main()
|
|
|