1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2016 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Worker 8*8975f5c5SAndroid Build Coastguard Workerimport argparse 9*8975f5c5SAndroid Build Coastguard Workerimport os 10*8975f5c5SAndroid Build Coastguard Workerimport re 11*8975f5c5SAndroid Build Coastguard Workerimport sys 12*8975f5c5SAndroid Build Coastguard Workerimport tempfile 13*8975f5c5SAndroid Build Coastguard Worker 14*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 15*8975f5c5SAndroid Build Coastguard Worker sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 16*8975f5c5SAndroid Build Coastguard Workerfrom pylib.constants import host_paths 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Workerif host_paths.DEVIL_PATH not in sys.path: 19*8975f5c5SAndroid Build Coastguard Worker sys.path.append(host_paths.DEVIL_PATH) 20*8975f5c5SAndroid Build Coastguard Workerfrom devil.utils import cmd_helper 21*8975f5c5SAndroid Build Coastguard Worker 22*8975f5c5SAndroid Build Coastguard Worker 23*8975f5c5SAndroid Build Coastguard Worker_MICRODUMP_BEGIN = re.compile( 24*8975f5c5SAndroid Build Coastguard Worker '.*google-breakpad: -----BEGIN BREAKPAD MICRODUMP-----') 25*8975f5c5SAndroid Build Coastguard Worker_MICRODUMP_END = re.compile( 26*8975f5c5SAndroid Build Coastguard Worker '.*google-breakpad: -----END BREAKPAD MICRODUMP-----') 27*8975f5c5SAndroid Build Coastguard Worker 28*8975f5c5SAndroid Build Coastguard Worker""" Example Microdump 29*8975f5c5SAndroid Build Coastguard Worker<timestamp> 6270 6131 F google-breakpad: -----BEGIN BREAKPAD MICRODUMP----- 30*8975f5c5SAndroid Build Coastguard Worker<timestamp> 6270 6131 F google-breakpad: V Chrome_Android:54.0.2790.0 31*8975f5c5SAndroid Build Coastguard Worker... 32*8975f5c5SAndroid Build Coastguard Worker<timestamp> 6270 6131 F google-breakpad: -----END BREAKPAD MICRODUMP----- 33*8975f5c5SAndroid Build Coastguard Worker 34*8975f5c5SAndroid Build Coastguard Worker""" 35*8975f5c5SAndroid Build Coastguard Worker 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Workerdef GetMicroDumps(dump_path): 38*8975f5c5SAndroid Build Coastguard Worker """Returns all microdumps found in given log file 39*8975f5c5SAndroid Build Coastguard Worker 40*8975f5c5SAndroid Build Coastguard Worker Args: 41*8975f5c5SAndroid Build Coastguard Worker dump_path: Path to the log file. 42*8975f5c5SAndroid Build Coastguard Worker 43*8975f5c5SAndroid Build Coastguard Worker Returns: 44*8975f5c5SAndroid Build Coastguard Worker List of all microdumps as lists of lines. 45*8975f5c5SAndroid Build Coastguard Worker """ 46*8975f5c5SAndroid Build Coastguard Worker with open(dump_path, 'r') as d: 47*8975f5c5SAndroid Build Coastguard Worker data = d.read() 48*8975f5c5SAndroid Build Coastguard Worker all_dumps = [] 49*8975f5c5SAndroid Build Coastguard Worker current_dump = None 50*8975f5c5SAndroid Build Coastguard Worker for line in data.splitlines(): 51*8975f5c5SAndroid Build Coastguard Worker if current_dump is not None: 52*8975f5c5SAndroid Build Coastguard Worker if _MICRODUMP_END.match(line): 53*8975f5c5SAndroid Build Coastguard Worker current_dump.append(line) 54*8975f5c5SAndroid Build Coastguard Worker all_dumps.append(current_dump) 55*8975f5c5SAndroid Build Coastguard Worker current_dump = None 56*8975f5c5SAndroid Build Coastguard Worker else: 57*8975f5c5SAndroid Build Coastguard Worker current_dump.append(line) 58*8975f5c5SAndroid Build Coastguard Worker elif _MICRODUMP_BEGIN.match(line): 59*8975f5c5SAndroid Build Coastguard Worker current_dump = [] 60*8975f5c5SAndroid Build Coastguard Worker current_dump.append(line) 61*8975f5c5SAndroid Build Coastguard Worker return all_dumps 62*8975f5c5SAndroid Build Coastguard Worker 63*8975f5c5SAndroid Build Coastguard Worker 64*8975f5c5SAndroid Build Coastguard Workerdef SymbolizeMicroDump(stackwalker_binary_path, dump, symbols_path): 65*8975f5c5SAndroid Build Coastguard Worker """Runs stackwalker on microdump. 66*8975f5c5SAndroid Build Coastguard Worker 67*8975f5c5SAndroid Build Coastguard Worker Runs the stackwalker binary at stackwalker_binary_path on a given microdump 68*8975f5c5SAndroid Build Coastguard Worker using the symbols at symbols_path. 69*8975f5c5SAndroid Build Coastguard Worker 70*8975f5c5SAndroid Build Coastguard Worker Args: 71*8975f5c5SAndroid Build Coastguard Worker stackwalker_binary_path: Path to the stackwalker binary. 72*8975f5c5SAndroid Build Coastguard Worker dump: The microdump to run the stackwalker on. 73*8975f5c5SAndroid Build Coastguard Worker symbols_path: Path the the symbols file to use. 74*8975f5c5SAndroid Build Coastguard Worker 75*8975f5c5SAndroid Build Coastguard Worker Returns: 76*8975f5c5SAndroid Build Coastguard Worker Output from stackwalker tool. 77*8975f5c5SAndroid Build Coastguard Worker """ 78*8975f5c5SAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as tf: 79*8975f5c5SAndroid Build Coastguard Worker for l in dump: 80*8975f5c5SAndroid Build Coastguard Worker tf.write('%s\n' % l) 81*8975f5c5SAndroid Build Coastguard Worker cmd = [stackwalker_binary_path, tf.name, symbols_path] 82*8975f5c5SAndroid Build Coastguard Worker return cmd_helper.GetCmdOutput(cmd) 83*8975f5c5SAndroid Build Coastguard Worker 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Workerdef AddArguments(parser): 86*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--stackwalker-binary-path', required=True, 87*8975f5c5SAndroid Build Coastguard Worker help='Path to stackwalker binary.') 88*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--stack-trace-path', required=True, 89*8975f5c5SAndroid Build Coastguard Worker help='Path to stacktrace containing microdump.') 90*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--symbols-path', required=True, 91*8975f5c5SAndroid Build Coastguard Worker help='Path to symbols file.') 92*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--output-file', 93*8975f5c5SAndroid Build Coastguard Worker help='Path to dump stacktrace output to') 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Workerdef _PrintAndLog(line, fp): 97*8975f5c5SAndroid Build Coastguard Worker if fp: 98*8975f5c5SAndroid Build Coastguard Worker fp.write('%s\n' % line) 99*8975f5c5SAndroid Build Coastguard Worker print(line) 100*8975f5c5SAndroid Build Coastguard Worker 101*8975f5c5SAndroid Build Coastguard Worker 102*8975f5c5SAndroid Build Coastguard Workerdef main(): 103*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 104*8975f5c5SAndroid Build Coastguard Worker AddArguments(parser) 105*8975f5c5SAndroid Build Coastguard Worker args = parser.parse_args() 106*8975f5c5SAndroid Build Coastguard Worker 107*8975f5c5SAndroid Build Coastguard Worker micro_dumps = GetMicroDumps(args.stack_trace_path) 108*8975f5c5SAndroid Build Coastguard Worker if not micro_dumps: 109*8975f5c5SAndroid Build Coastguard Worker print('No microdump found. Exiting.') 110*8975f5c5SAndroid Build Coastguard Worker return 0 111*8975f5c5SAndroid Build Coastguard Worker 112*8975f5c5SAndroid Build Coastguard Worker symbolized_dumps = [] 113*8975f5c5SAndroid Build Coastguard Worker for micro_dump in micro_dumps: 114*8975f5c5SAndroid Build Coastguard Worker symbolized_dumps.append(SymbolizeMicroDump( 115*8975f5c5SAndroid Build Coastguard Worker args.stackwalker_binary_path, micro_dump, args.symbols_path)) 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Worker try: 118*8975f5c5SAndroid Build Coastguard Worker fp = open(args.output_file, 'w') if args.output_file else None 119*8975f5c5SAndroid Build Coastguard Worker _PrintAndLog('%d microdumps found.' % len(micro_dumps), fp) 120*8975f5c5SAndroid Build Coastguard Worker _PrintAndLog('---------- Start output from stackwalker ----------', fp) 121*8975f5c5SAndroid Build Coastguard Worker for index, symbolized_dump in list(enumerate(symbolized_dumps)): 122*8975f5c5SAndroid Build Coastguard Worker _PrintAndLog( 123*8975f5c5SAndroid Build Coastguard Worker '------------------ Start dump %d ------------------' % index, fp) 124*8975f5c5SAndroid Build Coastguard Worker _PrintAndLog(symbolized_dump, fp) 125*8975f5c5SAndroid Build Coastguard Worker _PrintAndLog( 126*8975f5c5SAndroid Build Coastguard Worker '------------------- End dump %d -------------------' % index, fp) 127*8975f5c5SAndroid Build Coastguard Worker _PrintAndLog('----------- End output from stackwalker -----------', fp) 128*8975f5c5SAndroid Build Coastguard Worker except Exception: 129*8975f5c5SAndroid Build Coastguard Worker if fp: 130*8975f5c5SAndroid Build Coastguard Worker fp.close() 131*8975f5c5SAndroid Build Coastguard Worker raise 132*8975f5c5SAndroid Build Coastguard Worker return 0 133*8975f5c5SAndroid Build Coastguard Worker 134*8975f5c5SAndroid Build Coastguard Worker 135*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 136*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 137