Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(833)

Side by Side Diff: build/android/tombstones.py

Issue 18473004: Android: adds stack symbolization utilities. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « build/android/tests/symbolize/b.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6 #
7 # Find the most recent tombstone file(s) on all connected devices
8 # and prints their stacks.
9 #
10 # Assumes tombstone file was created with current symbols.
11
12 import datetime
13 import logging
14 import multiprocessing
15 import os
16 import subprocess
17 import sys
18 import optparse
19
20 from pylib import android_commands
21
22
23 def _ListTombstones(adb):
24 """List the tombstone files on the device.
25
26 Args:
27 adb: An instance of AndroidCommands.
28
29 Yields:
30 Tuples of (tombstone filename, date time of file on device).
31 """
32 lines = adb.RunShellCommand('TZ=UTC su -c ls -a -l /data/tombstones')
33 for line in lines:
34 if 'tombstone' in line and not 'No such file or directory' in line:
35 details = line.split()
36 t = datetime.datetime.strptime(details[-3] + ' ' + details[-2],
37 '%Y-%m-%d %H:%M')
38 yield details[-1], t
39
40
41 def _GetDeviceDateTime(adb):
42 """Determine the date time on the device.
43
44 Args:
45 adb: An instance of AndroidCommands.
46
47 Returns:
48 A datetime instance.
49 """
50 device_now_string = adb.RunShellCommand('TZ=UTC date')
51 return datetime.datetime.strptime(
52 device_now_string[0], '%a %b %d %H:%M:%S %Z %Y')
53
54
55 def _GetTombstoneData(adb, tombstone_file):
56 """Retrieve the tombstone data from the device
57
58 Args:
59 tombstone_file: the tombstone to retrieve
60
61 Returns:
62 A list of lines
63 """
64 return adb.GetProtectedFileContents('/data/tombstones/' + tombstone_file)
65
66
67 def _EraseTombstone(adb, tombstone_file):
68 """Deletes a tombstone from the device.
69
70 Args:
71 tombstone_file: the tombstone to delete.
72 """
73 return adb.RunShellCommand('su -c rm /data/tombstones/' + tombstone_file)
74
75
76 def _ResolveSymbols(tombstone_data, include_stack):
77 """Run the stack tool for given tombstone input.
78
79 Args:
80 tombstone_data: a list of strings of tombstone data.
81 include_stack: boolean whether to include stack data in output.
82
83 Yields:
84 A string for each line of resolved stack output.
85 """
86 stack_tool = os.path.join(os.path.dirname(__file__), '..', '..',
87 'third_party', 'android_platform', 'development',
88 'scripts', 'stack')
89 proc = subprocess.Popen(stack_tool, stdin=subprocess.PIPE,
90 stdout=subprocess.PIPE)
91 output = proc.communicate(input='\n'.join(tombstone_data))[0]
92 for line in output.split('\n'):
93 if not include_stack and 'Stack Data:' in line:
94 break
95 yield line
96
97
98 def _ResolveTombstone(tombstone):
99 lines = []
100 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) +
101 ', about this long ago: ' +
102 (str(tombstone['device_now'] - tombstone['time']) +
103 ' Device: ' + tombstone['serial'])]
104 print '\n'.join(lines)
105 print 'Resolving...'
106 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'])
107 return lines
108
109
110 def _ResolveTombstones(jobs, tombstones):
111 """Resolve a list of tombstones.
112
113 Args:
114 jobs: the number of jobs to use with multiprocess.
115 tombstones: a list of tombstones.
116 """
117 if not tombstones:
118 print 'No device attached? Or no tombstones?'
119 return
120 if len(tombstones) == 1:
121 data = _ResolveTombstone(tombstones[0])
122 else:
123 pool = multiprocessing.Pool(processes=jobs)
124 data = pool.map(_ResolveTombstone, tombstones)
125 data = ['\n'.join(d) for d in data]
126 print '\n'.join(data)
127
128
129 def _GetTombstonesForDevice(adb, options):
130 """Returns a list of tombstones on a given adb connection.
131
132 Args:
133 adb: An instance of Androidcommands.
134 options: command line arguments from OptParse
135 """
136 ret = []
137 all_tombstones = list(_ListTombstones(adb))
138 if not all_tombstones:
139 print 'No device attached? Or no tombstones?'
140 return ret
141
142 # Sort the tombstones in date order, descending
143 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1]))
144
145 # Only resolve the most recent unless --all-tombstones given.
146 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]]
147
148 device_now = _GetDeviceDateTime(adb)
149 for tombstone_file, tombstone_time in tombstones:
150 ret += [{'serial': adb.Adb().GetSerialNumber(),
151 'device_now': device_now,
152 'time': tombstone_time,
153 'file': tombstone_file,
154 'stack': options.stack,
155 'data': _GetTombstoneData(adb, tombstone_file)}]
156
157 # Erase all the tombstones if desired.
158 if options.wipe_tombstones:
159 for tombstone_file, _ in all_tombstones:
160 _EraseTombstone(adb, tombstone_file)
161
162 return ret
163
164 def main():
165 parser = optparse.OptionParser()
166 parser.add_option('-a', '--all-tombstones', action='store_true',
167 dest='all_tombstones', default=False,
168 help="""Resolve symbols for all tombstones, rather than just
169 the most recent""")
170 parser.add_option('-s', '--stack', action='store_true',
171 dest='stack', default=False,
172 help='Also include symbols for stack data')
173 parser.add_option('-w', '--wipe-tombstones', action='store_true',
174 dest='wipe_tombstones', default=False,
175 help='Erase all tombstones from device after processing')
176 parser.add_option('-j', '--jobs', type='int',
177 default=4,
178 help='Number of jobs to use when processing multiple '
179 'crash stacks.')
180 options, args = parser.parse_args()
181
182 devices = android_commands.GetAttachedDevices()
183 tombstones = []
184 for device in devices:
185 adb = android_commands.AndroidCommands(device)
186 tombstones += _GetTombstonesForDevice(adb, options)
187
188 _ResolveTombstones(options.jobs, tombstones)
189
190 if __name__ == '__main__':
191 sys.exit(main())
OLDNEW
« no previous file with comments | « build/android/tests/symbolize/b.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698