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

Side by Side Diff: mojo/devtools/common/android_stack_parser/stack

Issue 1306603002: Improve android stack parser (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « no previous file | mojo/devtools/common/android_stack_parser/stack_utils.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright (C) 2013 The Android Open Source Project 3 # Copyright (C) 2013 The Android Open Source Project
4 # 4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License. 6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at 7 # You may obtain a copy of the License at
8 # 8 #
9 # http://www.apache.org/licenses/LICENSE-2.0 9 # http://www.apache.org/licenses/LICENSE-2.0
10 # 10 #
11 # Unless required by applicable law or agreed to in writing, software 11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, 12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and 14 # See the License for the specific language governing permissions and
15 # limitations under the License. 15 # limitations under the License.
16 16
17 """stack symbolizes native crash dumps.""" 17 """stack symbolizes native crash dumps."""
18 18
19 import getopt 19 import getopt
20 import glob
21 import os 20 import os
22 import re 21 import os.path
23 import sys 22 import sys
24 23
24 import stack_utils
25 import stack_core 25 import stack_core
26 import subprocess 26 import subprocess
27 import symbol 27 import symbol
28 28
29 _DEFAULT_SYMROOT = '/tmp/symbols' 29 _DEFAULT_SYMROOT = '/tmp/symbols'
30 _DEFAULT_BUILD_DIR = 'out/android_Debug' 30 _DEFAULT_BUILD_DIR = 'out/android_Debug'
31 _DEFAULT_NDK_DIR = 'third_party/android_tools/ndk' 31 _DEFAULT_NDK_DIR = 'third_party/android_tools/ndk'
32 32
33 33
34 def PrintUsage(): 34 def PrintUsage():
(...skipping 29 matching lines...) Expand all
64 print 64 print
65 print " FILE should contain a stack trace in it somewhere" 65 print " FILE should contain a stack trace in it somewhere"
66 print " the tool will find that and re-print it with" 66 print " the tool will find that and re-print it with"
67 print " source files and line numbers. If you don't" 67 print " source files and line numbers. If you don't"
68 print " pass FILE, or if file is -, it reads from" 68 print " pass FILE, or if file is -, it reads from"
69 print " stdin." 69 print " stdin."
70 print 70 print
71 # pylint: enable-msg=C6310 71 # pylint: enable-msg=C6310
72 sys.exit(1) 72 sys.exit(1)
73 73
74 def UnzipSymbols(symbolfile, symdir=None):
75 """Unzips a file to _DEFAULT_SYMROOT and returns the unzipped location.
76
77 Args:
78 symbolfile: The .zip file to unzip
79 symdir: Optional temporary directory to use for extraction
80
81 Returns:
82 A tuple containing (the directory into which the zip file was unzipped,
83 the path to the "symbols" directory in the unzipped file). To clean
84 up, the caller can delete the first element of the tuple.
85
86 Raises:
87 SymbolDownloadException: When the unzip fails.
88 """
89 if not symdir:
90 symdir = "%s/%s" % (_DEFAULT_SYMROOT, hash(symbolfile))
91 if not os.path.exists(symdir):
92 os.makedirs(symdir)
93
94 print "extracting %s..." % symbolfile
95 saveddir = os.getcwd()
96 os.chdir(symdir)
97 try:
98 unzipcode = subprocess.call(["unzip", "-qq", "-o", symbolfile])
99 if unzipcode > 0:
100 os.remove(symbolfile)
101 raise SymbolDownloadException("failed to extract symbol files (%s)."
102 % symbolfile)
103 finally:
104 os.chdir(saveddir)
105
106 android_symbols = glob.glob("%s/out/target/product/*/symbols" % symdir)
107 if android_symbols:
108 return (symdir, android_symbols[0])
109 else:
110 # This is a zip of Chrome symbols, so symbol.CHROME_SYMBOLS_DIR needs to be
111 # updated to point here.
112 symbol.CHROME_SYMBOLS_DIR = symdir
113 return (symdir, symdir)
114
115
116 def GetBasenameFromMojoApp(url):
117 """Used by GetSymbolMapping() to extract the basename from the location the
118 mojo app was downloaded from. The location is a URL, e.g.
119 http://foo/bar/x.so."""
120 index = url.rfind('/')
121 return url[(index + 1):] if index != -1 else url
122
123
124 def GetSymboledNameForMojoApp(path):
125 """Used by GetSymbolMapping to get the non-stripped library name for an
126 installed mojo app."""
127 # e.g. tracing.mojo -> libtracing_library.so
128 name, ext = os.path.splitext(path)
129 if ext != '.mojo':
130 return path
131 return 'lib%s_library.so' % name
132
133
134 def GetSymbolMapping(lines):
135 """Returns a mapping (dictionary) from download file to .so."""
136 regex = re.compile('Caching mojo app (\S+) at (\S+)')
137 mappings = {}
138 for line in lines:
139 result = regex.search(line)
140 if result:
141 url = GetBasenameFromMojoApp(result.group(1))
142 mappings[result.group(2)] = GetSymboledNameForMojoApp(url)
143 return mappings
144
145
146 def _LowestAncestorContainingRelpath(dir_path, relpath):
147 """Returns the lowest ancestor dir of |dir_path| that contains |relpath|.
148 """
149 cur_dir_path = os.path.abspath(dir_path)
150 while True:
151 if os.path.exists(os.path.join(cur_dir_path, relpath)):
152 return cur_dir_path
153
154 next_dir_path = os.path.dirname(cur_dir_path)
155 if next_dir_path != cur_dir_path:
156 cur_dir_path = next_dir_path
157 else:
158 return None
159
160
161 def _GuessDir(relpath):
162 """Returns absolute path to location |relpath| in the lowest ancestor of this
163 file that contains it."""
164 lowest_ancestor = _LowestAncestorContainingRelpath(
165 os.path.dirname(__file__), relpath)
166 if not lowest_ancestor:
167 return None
168 return os.path.join(lowest_ancestor, relpath)
169
170 74
171 75
172 def main(): 76 def main():
173 try: 77 try:
174 options, arguments = getopt.getopt(sys.argv[1:], "", 78 options, arguments = getopt.getopt(sys.argv[1:], "",
175 ["more-info", 79 ["more-info",
176 "less-info", 80 "less-info",
177 "build-dir=", 81 "build-dir=",
178 "ndk-dir=", 82 "ndk-dir=",
179 "symbols-dir=", 83 "symbols-dir=",
(...skipping 17 matching lines...) Expand all
197 elif option == "--build-dir": 101 elif option == "--build-dir":
198 symbol.BUILD_DIR = value 102 symbol.BUILD_DIR = value
199 elif option == "--ndk-dir": 103 elif option == "--ndk-dir":
200 symbol.NDK_DIR = value 104 symbol.NDK_DIR = value
201 elif option == "--more-info": 105 elif option == "--more-info":
202 more_info = True 106 more_info = True
203 elif option == "--less-info": 107 elif option == "--less-info":
204 more_info = False 108 more_info = False
205 109
206 if not symbol.BUILD_DIR: 110 if not symbol.BUILD_DIR:
207 guess = _GuessDir(_DEFAULT_BUILD_DIR) 111 guess = stack_utils.GuessDir(_DEFAULT_BUILD_DIR)
208 if not guess: 112 if not guess:
209 print "Couldn't find the build directory, please pass --build-dir." 113 print "Couldn't find the build directory, please pass --build-dir."
210 return 1 114 return 1
211 print "Inferring the build directory path as " + guess 115 print "Inferring the build directory path as " + guess
212 symbol.BUILD_DIR = guess 116 symbol.BUILD_DIR = guess
213 117
214 if not symbol.NDK_DIR: 118 if not symbol.NDK_DIR:
215 guess = _GuessDir(_DEFAULT_NDK_DIR) 119 guess = stack_utils.GuessDir(_DEFAULT_NDK_DIR)
216 if not guess: 120 if not guess:
217 print "Couldn't find the Android NDK, please pass --ndk-dir." 121 print "Couldn't find the Android NDK, please pass --ndk-dir."
218 return 1 122 return 1
219 print "Inferring the Android NDK path as " + guess 123 print "Inferring the Android NDK path as " + guess
220 symbol.NDK_DIR = guess 124 symbol.NDK_DIR = guess
221 125
222 126
223 if len(arguments) > 1: 127 if len(arguments) > 1:
224 PrintUsage() 128 PrintUsage()
225 129
226 if not arguments or arguments[0] == "-": 130 if not arguments or arguments[0] == "-":
227 print "Reading native crash info from stdin" 131 print "Reading native crash info from stdin"
228 f = sys.stdin 132 f = sys.stdin
229 else: 133 else:
230 print "Searching for native crashes in %s" % arguments[0] 134 print "Searching for native crashes in %s" % arguments[0]
231 f = open(arguments[0], "r") 135 f = open(arguments[0], "r")
232 136
233 lines = f.readlines() 137 lines = f.readlines()
234 f.close() 138 f.close()
235 139
236 rootdir = None 140 rootdir = None
237 if zip_arg: 141 if zip_arg:
238 rootdir, symbol.SYMBOLS_DIR = UnzipSymbols(zip_arg) 142 rootdir, symbol.SYMBOLS_DIR = stack_utils.UnzipSymbols(zip_arg)
239 143
240 if symbol.SYMBOLS_DIR: 144 if symbol.SYMBOLS_DIR:
241 print "Reading Android symbols from", symbol.SYMBOLS_DIR 145 print "Reading Android symbols from", symbol.SYMBOLS_DIR
242 146
243 print "Reading Mojo symbols from", symbol.BUILD_DIR 147 print "Reading Mojo symbols from", symbol.BUILD_DIR
244 stack_core.ConvertTrace(lines, more_info, GetSymbolMapping(lines)) 148 stack_core.ConvertTrace(lines, more_info, stack_utils.GetSymbolMapping(lines))
245 149
246 if rootdir: 150 if rootdir:
247 # be a good citizen and clean up...os.rmdir and os.removedirs() don't work 151 # be a good citizen and clean up...os.rmdir and os.removedirs() don't work
248 cmd = "rm -rf \"%s\"" % rootdir 152 cmd = "rm -rf \"%s\"" % rootdir
249 print "\ncleaning up (%s)" % cmd 153 print "\ncleaning up (%s)" % cmd
250 os.system(cmd) 154 os.system(cmd)
251 155
252 if __name__ == "__main__": 156 if __name__ == "__main__":
253 main() 157 main()
254 158
255 # vi: ts=2 sw=2 159 # vi: ts=2 sw=2
OLDNEW
« no previous file with comments | « no previous file | mojo/devtools/common/android_stack_parser/stack_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698