xref: /aosp_15_r20/external/angle/build/android/stacktrace/stackwalker.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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