OLD | NEW |
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 # |
(...skipping 11 matching lines...) Expand all Loading... |
22 import glob | 22 import glob |
23 import itertools | 23 import itertools |
24 import logging | 24 import logging |
25 import os | 25 import os |
26 import re | 26 import re |
27 import struct | 27 import struct |
28 import subprocess | 28 import subprocess |
29 import sys | 29 import sys |
30 import zipfile | 30 import zipfile |
31 | 31 |
32 CHROME_SRC = os.path.join(os.path.realpath(os.path.dirname(__file__)), | 32 sys.path.insert(0, os.path.join(os.path.dirname(__file__), |
33 os.pardir, os.pardir, os.pardir, os.pardir) | 33 os.pardir, os.pardir, os.pardir, os.pardir, |
| 34 'build', 'android')) |
| 35 from pylib import constants |
| 36 from pylib.symbols import elf_symbolizer |
| 37 |
| 38 |
| 39 CHROME_SRC = constants.DIR_SOURCE_ROOT |
34 ANDROID_BUILD_TOP = CHROME_SRC | 40 ANDROID_BUILD_TOP = CHROME_SRC |
35 SYMBOLS_DIR = CHROME_SRC | 41 SYMBOLS_DIR = CHROME_SRC |
36 CHROME_SYMBOLS_DIR = CHROME_SRC | 42 CHROME_SYMBOLS_DIR = None |
37 | |
38 ARCH = "arm" | 43 ARCH = "arm" |
39 | |
40 TOOLCHAIN_INFO = None | 44 TOOLCHAIN_INFO = None |
41 | 45 |
42 sys.path.insert(0, os.path.join(CHROME_SRC, 'build', 'android')) | |
43 from pylib.symbols import elf_symbolizer | |
44 | 46 |
45 # See: | 47 # See: |
46 # http://bugs.python.org/issue14315 | 48 # http://bugs.python.org/issue14315 |
47 # https://hg.python.org/cpython/rev/6dd5e9556a60#l2.8 | 49 # https://hg.python.org/cpython/rev/6dd5e9556a60#l2.8 |
48 def PatchZipFile(): | 50 def PatchZipFile(): |
49 oldDecodeExtra = zipfile.ZipInfo._decodeExtra | 51 oldDecodeExtra = zipfile.ZipInfo._decodeExtra |
50 def decodeExtra(self): | 52 def decodeExtra(self): |
51 try: | 53 try: |
52 oldDecodeExtra(self) | 54 oldDecodeExtra(self) |
53 except struct.error: | 55 except struct.error: |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 197 |
196 Args: | 198 Args: |
197 prefix_list: list of path prefixes. | 199 prefix_list: list of path prefixes. |
198 suffix_list: list of path suffixes. | 200 suffix_list: list of path suffixes. |
199 | 201 |
200 Returns: | 202 Returns: |
201 List of paths each of which joins a prefix with a suffix. | 203 List of paths each of which joins a prefix with a suffix. |
202 """ | 204 """ |
203 return [ | 205 return [ |
204 os.path.join(prefix, suffix) | 206 os.path.join(prefix, suffix) |
205 for prefix in prefix_list for suffix in suffix_list ] | 207 for suffix in suffix_list for prefix in prefix_list ] |
| 208 |
| 209 |
| 210 def _GetChromeOutputDirCandidates(): |
| 211 """Returns a list of output directories to look in.""" |
| 212 if os.environ.get('CHROMIUM_OUTPUT_DIR') or os.environ.get('BUILDTYPE'): |
| 213 return [constants.GetOutDirectory()] |
| 214 return [constants.GetOutDirectory(build_type='Debug'), |
| 215 constants.GetOutDirectory(build_type='Release')] |
| 216 |
206 | 217 |
207 def GetCandidates(dirs, filepart, candidate_fun): | 218 def GetCandidates(dirs, filepart, candidate_fun): |
208 """Returns a list of candidate filenames. | 219 """Returns a list of candidate filenames, sorted by modification time. |
209 | 220 |
210 Args: | 221 Args: |
211 dirs: a list of the directory part of the pathname. | 222 dirs: a list of the directory part of the pathname. |
212 filepart: the file part of the pathname. | 223 filepart: the file part of the pathname. |
213 candidate_fun: a function to apply to each candidate, returns a list. | 224 candidate_fun: a function to apply to each candidate, returns a list. |
214 | 225 |
215 Returns: | 226 Returns: |
216 A list of candidate files ordered by modification time, newest first. | 227 A list of candidate files ordered by modification time, newest first. |
217 """ | 228 """ |
218 out_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out') | 229 candidates = PathListJoin(dirs, [filepart]) |
219 out_dir = os.path.join(CHROME_SYMBOLS_DIR, out_dir) | |
220 buildtype = os.environ.get('BUILDTYPE') | |
221 if buildtype: | |
222 buildtype_list = [ buildtype ] | |
223 else: | |
224 buildtype_list = [ 'Debug', 'Release' ] | |
225 | |
226 candidates = PathListJoin([out_dir], buildtype_list) + [CHROME_SYMBOLS_DIR] | |
227 candidates = PathListJoin(candidates, dirs) | |
228 candidates = PathListJoin(candidates, [filepart]) | |
229 logging.debug('GetCandidates: prefiltered candidates = %s' % candidates) | 230 logging.debug('GetCandidates: prefiltered candidates = %s' % candidates) |
230 candidates = list( | 231 candidates = list( |
231 itertools.chain.from_iterable(map(candidate_fun, candidates))) | 232 itertools.chain.from_iterable(map(candidate_fun, candidates))) |
232 candidates = sorted(candidates, key=os.path.getmtime, reverse=True) | 233 candidates.sort(key=os.path.getmtime, reverse=True) |
233 return candidates | 234 return candidates |
234 | 235 |
235 def GetCandidateApks(): | 236 def GetCandidateApks(): |
236 """Returns a list of APKs which could contain the library. | 237 """Returns a list of APKs which could contain the library. |
237 | 238 |
238 Args: | 239 Args: |
239 None | 240 None |
240 | 241 |
241 Returns: | 242 Returns: |
242 list of APK filename which could contain the library. | 243 list of APK filename which could contain the library. |
243 """ | 244 """ |
244 return GetCandidates(['apks'], '*.apk', glob.glob) | 245 dirs = PathListJoin(_GetChromeOutputDirCandidates(), ['apks']) |
| 246 return GetCandidates(dirs, '*.apk', glob.glob) |
245 | 247 |
246 def GetCrazyLib(apk_filename): | 248 def GetCrazyLib(apk_filename): |
247 """Returns the name of the first crazy library from this APK. | 249 """Returns the name of the first crazy library from this APK. |
248 | 250 |
249 Args: | 251 Args: |
250 apk_filename: name of an APK file. | 252 apk_filename: name of an APK file. |
251 | 253 |
252 Returns: | 254 Returns: |
253 Name of the first library which would be crazy loaded from this APK. | 255 Name of the first library which would be crazy loaded from this APK. |
254 """ | 256 """ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 Returns: | 289 Returns: |
288 Name of the library which corresponds to that APK. | 290 Name of the library which corresponds to that APK. |
289 """ | 291 """ |
290 matching_apks = GetMatchingApks(device_apk_name) | 292 matching_apks = GetMatchingApks(device_apk_name) |
291 logging.debug('MapDeviceApkToLibrary: matching_apks=%s' % matching_apks) | 293 logging.debug('MapDeviceApkToLibrary: matching_apks=%s' % matching_apks) |
292 for matching_apk in matching_apks: | 294 for matching_apk in matching_apks: |
293 crazy_lib = GetCrazyLib(matching_apk) | 295 crazy_lib = GetCrazyLib(matching_apk) |
294 if crazy_lib: | 296 if crazy_lib: |
295 return crazy_lib | 297 return crazy_lib |
296 | 298 |
| 299 def GetLibrarySearchPaths(): |
| 300 if CHROME_SYMBOLS_DIR: |
| 301 return [CHROME_SYMBOLS_DIR] |
| 302 dirs = _GetChromeOutputDirCandidates() |
| 303 return PathListJoin(dirs, ['lib.unstripped', 'lib', 'lib.target', '.']) |
| 304 |
297 def GetCandidateLibraries(library_name): | 305 def GetCandidateLibraries(library_name): |
298 """Returns a list of candidate library filenames. | 306 """Returns a list of candidate library filenames. |
299 | 307 |
300 Args: | 308 Args: |
301 library_name: basename of the library to match. | 309 library_name: basename of the library to match. |
302 | 310 |
303 Returns: | 311 Returns: |
304 A list of matching library filenames for library_name. | 312 A list of matching library filenames for library_name. |
305 """ | 313 """ |
306 return GetCandidates( | 314 candidates = GetCandidates( |
307 ['lib', 'lib.target', '.'], library_name, | 315 GetLibrarySearchPaths(), library_name, |
308 lambda filename: filter(os.path.exists, [filename])) | 316 lambda filename: filter(os.path.exists, [filename])) |
| 317 # For GN, candidates includes both stripped an unstripped libraries. Stripped |
| 318 # libraries are always newer. Explicitly look for .unstripped and sort them |
| 319 # ahead. |
| 320 candidates.sort(key=lambda c: int('unstripped' not in c)) |
| 321 return candidates |
| 322 |
309 | 323 |
310 def TranslateLibPath(lib): | 324 def TranslateLibPath(lib): |
311 # The filename in the stack trace maybe an APK name rather than a library | 325 # The filename in the stack trace maybe an APK name rather than a library |
312 # name. This happens when the library was loaded directly from inside the | 326 # name. This happens when the library was loaded directly from inside the |
313 # APK. If this is the case we try to figure out the library name by looking | 327 # APK. If this is the case we try to figure out the library name by looking |
314 # for a matching APK file and finding the name of the library in contains. | 328 # for a matching APK file and finding the name of the library in contains. |
315 # The name of the APK file on the device is of the form | 329 # The name of the APK file on the device is of the form |
316 # <package_name>-<number>.apk. The APK file on the host may have any name | 330 # <package_name>-<number>.apk. The APK file on the host may have any name |
317 # so we look at the APK badging to see if the package name matches. | 331 # so we look at the APK badging to see if the package name matches. |
318 apk = GetApkFromLibrary(lib) | 332 apk = GetApkFromLibrary(lib) |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 process.stdin.write("\n") | 605 process.stdin.write("\n") |
592 process.stdin.close() | 606 process.stdin.close() |
593 demangled_symbol = process.stdout.readline().strip() | 607 demangled_symbol = process.stdout.readline().strip() |
594 process.stdout.close() | 608 process.stdout.close() |
595 return demangled_symbol | 609 return demangled_symbol |
596 | 610 |
597 def FormatSymbolWithOffset(symbol, offset): | 611 def FormatSymbolWithOffset(symbol, offset): |
598 if offset == 0: | 612 if offset == 0: |
599 return symbol | 613 return symbol |
600 return "%s+%d" % (symbol, offset) | 614 return "%s+%d" % (symbol, offset) |
OLD | NEW |