Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 # | 6 # |
| 7 # Find the most recent tombstone file(s) on all connected devices | 7 # Find the most recent tombstone file(s) on all connected devices |
| 8 # and prints their stacks. | 8 # and prints their stacks. |
| 9 # | 9 # |
| 10 # Assumes tombstone file was created with current symbols. | 10 # Assumes tombstone file was created with current symbols. |
| 11 | 11 |
| 12 import datetime | 12 import datetime |
| 13 import multiprocessing | 13 import multiprocessing |
| 14 import os | 14 import os |
| 15 import re | |
| 15 import subprocess | 16 import subprocess |
| 16 import sys | 17 import sys |
| 17 import optparse | 18 import optparse |
| 18 | 19 |
| 19 from pylib import android_commands | 20 from pylib import android_commands |
| 20 from pylib.device import device_utils | 21 from pylib.device import device_utils |
| 21 | 22 |
| 22 | 23 |
| 23 def _ListTombstones(device): | 24 def _ListTombstones(device): |
| 24 """List the tombstone files on the device. | 25 """List the tombstone files on the device. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 """Deletes a tombstone from the device. | 70 """Deletes a tombstone from the device. |
| 70 | 71 |
| 71 Args: | 72 Args: |
| 72 device: An instance of DeviceUtils. | 73 device: An instance of DeviceUtils. |
| 73 tombstone_file: the tombstone to delete. | 74 tombstone_file: the tombstone to delete. |
| 74 """ | 75 """ |
| 75 return device.RunShellCommand( | 76 return device.RunShellCommand( |
| 76 'rm /data/tombstones/' + tombstone_file, as_root=True) | 77 'rm /data/tombstones/' + tombstone_file, as_root=True) |
| 77 | 78 |
| 78 | 79 |
| 79 def _ResolveSymbols(tombstone_data, include_stack, arch): | 80 def _DeviceAbiToArch(device_abi): |
| 81 # The order of this list is significant to find the more specific match (e.g., | |
| 82 # arm64) before the less specific (e.g., arm). | |
| 83 arches = ['arm64', 'arm', 'x86_64', 'x86_64', 'x86', 'mips'] | |
| 84 for arch in arches: | |
| 85 if arch in device_abi: | |
| 86 return arch | |
| 87 | |
| 88 print 'Error: Unknown device ABI' | |
|
Sami
2014/08/07 12:00:17
How about a more noisy and informative "raise Runt
rmcilroy
2014/08/07 12:43:37
Done.
| |
| 89 return None | |
| 90 | |
| 91 def _ResolveSymbols(tombstone_data, include_stack, device_abi): | |
| 80 """Run the stack tool for given tombstone input. | 92 """Run the stack tool for given tombstone input. |
| 81 | 93 |
| 82 Args: | 94 Args: |
| 83 tombstone_data: a list of strings of tombstone data. | 95 tombstone_data: a list of strings of tombstone data. |
| 84 include_stack: boolean whether to include stack data in output. | 96 include_stack: boolean whether to include stack data in output. |
| 85 arch: the device architecture of tombstone data. | 97 arch: the device architecture of tombstone data. |
|
Sami
2014/08/07 12:00:17
Can you document the new parameter here?
rmcilroy
2014/08/07 12:43:37
Done.
| |
| 86 | 98 |
| 87 Yields: | 99 Yields: |
| 88 A string for each line of resolved stack output. | 100 A string for each line of resolved stack output. |
| 89 """ | 101 """ |
| 102 # Check if the tombstone data has am ABI listed, if so use this in preference | |
|
Sami
2014/08/07 12:00:17
s/am/an/
rmcilroy
2014/08/07 12:43:37
Done.
| |
| 103 # to the devices default ABI. | |
|
Sami
2014/08/07 12:00:17
s/devices/device's/
rmcilroy
2014/08/07 12:43:37
Done.
| |
| 104 for line in tombstone_data: | |
| 105 found_abi = re.search('ABI: \'(.+?)\'', line) | |
| 106 if found_abi: | |
| 107 device_abi = found_abi.group(1) | |
| 108 arch = _DeviceAbiToArch(device_abi) | |
| 109 if not arch: | |
| 110 return | |
| 111 | |
| 90 stack_tool = os.path.join(os.path.dirname(__file__), '..', '..', | 112 stack_tool = os.path.join(os.path.dirname(__file__), '..', '..', |
| 91 'third_party', 'android_platform', 'development', | 113 'third_party', 'android_platform', 'development', |
| 92 'scripts', 'stack') | 114 'scripts', 'stack') |
| 93 proc = subprocess.Popen([stack_tool, '--arch', arch], stdin=subprocess.PIPE, | 115 proc = subprocess.Popen([stack_tool, '--arch', arch], stdin=subprocess.PIPE, |
| 94 stdout=subprocess.PIPE) | 116 stdout=subprocess.PIPE) |
| 95 output = proc.communicate(input='\n'.join(tombstone_data))[0] | 117 output = proc.communicate(input='\n'.join(tombstone_data))[0] |
| 96 for line in output.split('\n'): | 118 for line in output.split('\n'): |
| 97 if not include_stack and 'Stack Data:' in line: | 119 if not include_stack and 'Stack Data:' in line: |
| 98 break | 120 break |
| 99 yield line | 121 yield line |
| 100 | 122 |
| 101 | 123 |
| 102 def _ResolveTombstone(tombstone): | 124 def _ResolveTombstone(tombstone): |
| 103 lines = [] | 125 lines = [] |
| 104 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) + | 126 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) + |
| 105 ', about this long ago: ' + | 127 ', about this long ago: ' + |
| 106 (str(tombstone['device_now'] - tombstone['time']) + | 128 (str(tombstone['device_now'] - tombstone['time']) + |
| 107 ' Device: ' + tombstone['serial'])] | 129 ' Device: ' + tombstone['serial'])] |
| 108 print '\n'.join(lines) | 130 print '\n'.join(lines) |
| 109 print 'Resolving...' | 131 print 'Resolving...' |
| 110 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'], | 132 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'], |
| 111 tombstone['arch']) | 133 tombstone['device_abi']) |
| 112 return lines | 134 return lines |
| 113 | 135 |
| 114 | 136 |
| 115 def _ResolveTombstones(jobs, tombstones): | 137 def _ResolveTombstones(jobs, tombstones): |
| 116 """Resolve a list of tombstones. | 138 """Resolve a list of tombstones. |
| 117 | 139 |
| 118 Args: | 140 Args: |
| 119 jobs: the number of jobs to use with multiprocess. | 141 jobs: the number of jobs to use with multiprocess. |
| 120 tombstones: a list of tombstones. | 142 tombstones: a list of tombstones. |
| 121 """ | 143 """ |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 146 | 168 |
| 147 # Sort the tombstones in date order, descending | 169 # Sort the tombstones in date order, descending |
| 148 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1])) | 170 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1])) |
| 149 | 171 |
| 150 # Only resolve the most recent unless --all-tombstones given. | 172 # Only resolve the most recent unless --all-tombstones given. |
| 151 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]] | 173 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]] |
| 152 | 174 |
| 153 device_now = _GetDeviceDateTime(device) | 175 device_now = _GetDeviceDateTime(device) |
| 154 for tombstone_file, tombstone_time in tombstones: | 176 for tombstone_file, tombstone_time in tombstones: |
| 155 ret += [{'serial': str(device), | 177 ret += [{'serial': str(device), |
| 156 'arch': device.GetProp('ro.product.cpu.abi'), | 178 'device_abi': device.GetProp('ro.product.cpu.abi'), |
| 157 'device_now': device_now, | 179 'device_now': device_now, |
| 158 'time': tombstone_time, | 180 'time': tombstone_time, |
| 159 'file': tombstone_file, | 181 'file': tombstone_file, |
| 160 'stack': options.stack, | 182 'stack': options.stack, |
| 161 'data': _GetTombstoneData(device, tombstone_file)}] | 183 'data': _GetTombstoneData(device, tombstone_file)}] |
| 162 | 184 |
| 163 # Erase all the tombstones if desired. | 185 # Erase all the tombstones if desired. |
| 164 if options.wipe_tombstones: | 186 if options.wipe_tombstones: |
| 165 for tombstone_file, _ in all_tombstones: | 187 for tombstone_file, _ in all_tombstones: |
| 166 _EraseTombstone(device, tombstone_file) | 188 _EraseTombstone(device, tombstone_file) |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 193 | 215 |
| 194 tombstones = [] | 216 tombstones = [] |
| 195 for device_serial in devices: | 217 for device_serial in devices: |
| 196 device = device_utils.DeviceUtils(device_serial) | 218 device = device_utils.DeviceUtils(device_serial) |
| 197 tombstones += _GetTombstonesForDevice(device, options) | 219 tombstones += _GetTombstonesForDevice(device, options) |
| 198 | 220 |
| 199 _ResolveTombstones(options.jobs, tombstones) | 221 _ResolveTombstones(options.jobs, tombstones) |
| 200 | 222 |
| 201 if __name__ == '__main__': | 223 if __name__ == '__main__': |
| 202 sys.exit(main()) | 224 sys.exit(main()) |
| OLD | NEW |