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