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

Side by Side Diff: third_party/android_platform/development/scripts/symbol.py

Issue 401003003: Stack trace support for libraries loaded directly from APKs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove incidental whitespace change. Created 6 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 | « third_party/android_platform/README.chromium ('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
1 #!/usr/bin/python 1 #!/usr/bin/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 """Module for looking up symbolic debugging information. 17 """Module for looking up symbolic debugging information.
18 18
19 The information can include symbol names, offsets, and source locations. 19 The information can include symbol names, offsets, and source locations.
20 """ 20 """
21 21
22 import glob
23 import itertools
22 import os 24 import os
23 import re 25 import re
24 import subprocess 26 import subprocess
27 import zipfile
25 28
26 CHROME_SRC = os.path.join(os.path.realpath(os.path.dirname(__file__)), 29 CHROME_SRC = os.path.join(os.path.realpath(os.path.dirname(__file__)),
27 os.pardir, os.pardir, os.pardir, os.pardir) 30 os.pardir, os.pardir, os.pardir, os.pardir)
28 ANDROID_BUILD_TOP = CHROME_SRC 31 ANDROID_BUILD_TOP = CHROME_SRC
29 SYMBOLS_DIR = CHROME_SRC 32 SYMBOLS_DIR = CHROME_SRC
30 CHROME_SYMBOLS_DIR = CHROME_SRC 33 CHROME_SYMBOLS_DIR = CHROME_SRC
31 34
32 ARCH = "arm" 35 ARCH = "arm"
33 36
34 TOOLCHAIN_INFO = None 37 TOOLCHAIN_INFO = None
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 # Look for addr2line to check for valid toolchain path. 126 # Look for addr2line to check for valid toolchain path.
124 for (label, platform, target) in known_toolchains: 127 for (label, platform, target) in known_toolchains:
125 toolchain_info = (label, platform, target); 128 toolchain_info = (label, platform, target);
126 if os.path.exists(ToolPath("addr2line", toolchain_info)): 129 if os.path.exists(ToolPath("addr2line", toolchain_info)):
127 TOOLCHAIN_INFO = toolchain_info 130 TOOLCHAIN_INFO = toolchain_info
128 print "Using toolchain from :" + ToolPath("", TOOLCHAIN_INFO) 131 print "Using toolchain from :" + ToolPath("", TOOLCHAIN_INFO)
129 return toolchain_info 132 return toolchain_info
130 133
131 raise Exception("Could not find tool chain") 134 raise Exception("Could not find tool chain")
132 135
136 def GetAapt():
137 """Returns the path to aapt.
138
139 Args:
140 None
141
142 Returns:
143 the pathname of the 'aapt' executable.
144 """
145 sdk_home = os.path.join('third_party', 'android_tools', 'sdk')
146 sdk_home = os.environ.get('SDK_HOME', sdk_home)
147 aapt_exe = glob.glob(os.path.join(sdk_home, 'build-tools', '*', 'aapt'))
148 if not aapt_exe:
149 return None
150 return sorted(aapt_exe, key=os.path.getmtime, reverse=True)[0]
151
152 def GetPackageName(aapt, apk_path):
153 """Returns the package name of the apk.
154
155 Args:
156 aapt: pathname for the 'aapt' executable.
157 apk_path: pathname of the APK file.
158
159 Returns:
160 the package name of the APK file.
161 """
162 if not aapt:
163 return None
164 aapt_output = subprocess.check_output(
165 [aapt, 'dump', 'badging', apk_path]).split('\n')
166 package_name_re = re.compile(r'package: .*name=\'(\S*)\'')
167 for line in aapt_output:
168 match = package_name_re.match(line)
169 if match:
170 return match.group(1)
171
172 def GetCandidateApks():
173 """Returns a list of APKs which could contain the library.
174
175 Args:
176 None
177
178 Returns:
179 list of APK filename which could contain the library.
180 """
181 out_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out')
182 buildtype = os.environ.get('BUILDTYPE')
183 if buildtype:
184 candidate_dirs = [os.path.join(out_dir, buildtype, 'apks')]
185 else:
186 candidate_dirs = [os.path.join(out_dir, 'Debug', 'apks'),
187 os.path.join(out_dir, 'Release', 'apks'),
188 ]
189 candidate_apks = list(itertools.chain.from_iterable(
190 map(lambda d: glob.glob(os.path.join(d, '*.apk')), candidate_dirs)))
191 candidate_apks = sorted(candidate_apks, key=os.path.getmtime, reverse=True)
192 return candidate_apks
193
194 def GetCrazyLib(apk_filename):
195 """Returns the name of the first crazy library from this APK.
196
197 Args:
198 apk_filename: name of an APK file.
199
200 Returns:
201 Name of the first library which would be crazy loaded from this APK.
202 """
203 zipf = zipfile.ZipFile(apk_filename, 'r')
rmcilroy 2014/07/22 14:22:31 nit - zip_file
anton1 2014/07/22 16:07:18 Done.
204 for filename in zipf.namelist():
205 match = re.match('lib/[^/]*/crazy.(lib.*[.]so)', filename)
206 if match:
207 return match.group(1)
208
209 def GetMatchingApks(device_apk_name):
210 """Find any APKs which match the package indicated by the device_apk_name.
211
212 Args:
213 device_apk_name: name of the APK on the device.
214
215 Returns:
216 A list of APK filenames which could contain the desired library.
217 """
218 match = re.match('(.*)-[0-9]+[.]apk$', device_apk_name)
219 if not match:
220 return None
221 package_name = match.group(1)
222 aapt = GetAapt()
223 if not aapt:
224 # Allow false positives
225 return GetCandidateApks()
226 candidate_apks = GetCandidateApks()
227 return filter(
228 lambda candidate_apk :
229 package_name == GetPackageName(aapt, candidate_apk),
230 candidate_apks)
231
232 def MapDeviceApkToLibrary(device_apk_name):
233 """Provide a library name which corresponds with device_apk_name.
234
235 Args:
236 device_apk_name: name of the APK on the device.
237
238 Returns:
239 Name of the library which corresponds to that APK.
240 """
241 matching_apks = GetMatchingApks(device_apk_name)
242 for matching_apk in matching_apks:
243 crazy_lib = GetCrazyLib(matching_apk)
244 if crazy_lib:
245 return crazy_lib
246
133 def TranslateLibPath(lib): 247 def TranslateLibPath(lib):
134 # SymbolInformation(lib, addr) receives lib as the path from symbols 248 # SymbolInformation(lib, addr) receives lib as the path from symbols
135 # root to the symbols file. This needs to be translated to point to the 249 # root to the symbols file. This needs to be translated to point to the
136 # correct .so path. If the user doesn't explicitly specify which directory to 250 # correct .so path. If the user doesn't explicitly specify which directory to
137 # use, then use the most recently updated one in one of the known directories. 251 # use, then use the most recently updated one in one of the known directories.
138 # If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it 252 # If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it
139 # untranslated in case it is an Android symbol in SYMBOLS_DIR. 253 # untranslated in case it is an Android symbol in SYMBOLS_DIR.
140 library_name = os.path.basename(lib) 254 library_name = os.path.basename(lib)
255
256 # The filename in the stack trace maybe an APK name rather than a library
257 # name. This happens when the library was loaded directly from inside the
258 # APK. If this is the case we try to figure out the library name by looking
259 # for a matching APK file and finding the name of the library in contains.
260 # The name of the APK file on the device is of the form
261 # <package_name>-<number>.apk. The APK file on the host may have any name
262 # so we look at the APK badging to see if the package name matches.
263 if re.search('-[0-9]+[.]apk$', library_name):
264 mapping = MapDeviceApkToLibrary(library_name)
265 if mapping:
266 library_name = mapping
267
141 out_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out') 268 out_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out')
142 candidate_dirs = ['.', 269 candidate_dirs = ['.',
143 os.path.join(out_dir, 'Debug', 'lib'), 270 os.path.join(out_dir, 'Debug', 'lib'),
144 os.path.join(out_dir, 'Debug', 'lib.target'), 271 os.path.join(out_dir, 'Debug', 'lib.target'),
145 os.path.join(out_dir, 'Release', 'lib'), 272 os.path.join(out_dir, 'Release', 'lib'),
146 os.path.join(out_dir, 'Release', 'lib.target'), 273 os.path.join(out_dir, 'Release', 'lib.target'),
147 ] 274 ]
148 275
149 candidate_libraries = map( 276 candidate_libraries = map(
150 lambda d: ('%s/%s/%s' % (CHROME_SYMBOLS_DIR, d, library_name)), 277 lambda d: ('%s/%s/%s' % (CHROME_SYMBOLS_DIR, d, library_name)),
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 process.stdin.write("\n") 541 process.stdin.write("\n")
415 process.stdin.close() 542 process.stdin.close()
416 demangled_symbol = process.stdout.readline().strip() 543 demangled_symbol = process.stdout.readline().strip()
417 process.stdout.close() 544 process.stdout.close()
418 return demangled_symbol 545 return demangled_symbol
419 546
420 def FormatSymbolWithOffset(symbol, offset): 547 def FormatSymbolWithOffset(symbol, offset):
421 if offset == 0: 548 if offset == 0:
422 return symbol 549 return symbol
423 return "%s+%d" % (symbol, offset) 550 return "%s+%d" % (symbol, offset)
OLDNEW
« no previous file with comments | « third_party/android_platform/README.chromium ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698