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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/android_platform/README.chromium ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/android_platform/development/scripts/symbol.py
diff --git a/third_party/android_platform/development/scripts/symbol.py b/third_party/android_platform/development/scripts/symbol.py
index df7f2c4b138ee1e6b2570d2f59eceb83e2c16855..b107787d6f2f64e44dbc4819ac0fb0092e3675fb 100755
--- a/third_party/android_platform/development/scripts/symbol.py
+++ b/third_party/android_platform/development/scripts/symbol.py
@@ -19,9 +19,12 @@
The information can include symbol names, offsets, and source locations.
"""
+import glob
+import itertools
import os
import re
import subprocess
+import zipfile
CHROME_SRC = os.path.join(os.path.realpath(os.path.dirname(__file__)),
os.pardir, os.pardir, os.pardir, os.pardir)
@@ -130,6 +133,117 @@ def FindToolchain():
raise Exception("Could not find tool chain")
+def GetAapt():
+ """Returns the path to aapt.
+
+ Args:
+ None
+
+ Returns:
+ the pathname of the 'aapt' executable.
+ """
+ sdk_home = os.path.join('third_party', 'android_tools', 'sdk')
+ sdk_home = os.environ.get('SDK_HOME', sdk_home)
+ aapt_exe = glob.glob(os.path.join(sdk_home, 'build-tools', '*', 'aapt'))
+ if not aapt_exe:
+ return None
+ return sorted(aapt_exe, key=os.path.getmtime, reverse=True)[0]
+
+def GetPackageName(aapt, apk_path):
+ """Returns the package name of the apk.
+
+ Args:
+ aapt: pathname for the 'aapt' executable.
+ apk_path: pathname of the APK file.
+
+ Returns:
+ the package name of the APK file.
+ """
+ if not aapt:
+ return None
+ aapt_output = subprocess.check_output(
+ [aapt, 'dump', 'badging', apk_path]).split('\n')
+ package_name_re = re.compile(r'package: .*name=\'(\S*)\'')
+ for line in aapt_output:
+ match = package_name_re.match(line)
+ if match:
+ return match.group(1)
+
+def GetCandidateApks():
+ """Returns a list of APKs which could contain the library.
+
+ Args:
+ None
+
+ Returns:
+ list of APK filename which could contain the library.
+ """
+ out_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out')
+ buildtype = os.environ.get('BUILDTYPE')
+ if buildtype:
+ candidate_dirs = [os.path.join(out_dir, buildtype, 'apks')]
+ else:
+ candidate_dirs = [os.path.join(out_dir, 'Debug', 'apks'),
+ os.path.join(out_dir, 'Release', 'apks'),
+ ]
+ candidate_apks = list(itertools.chain.from_iterable(
+ map(lambda d: glob.glob(os.path.join(d, '*.apk')), candidate_dirs)))
+ candidate_apks = sorted(candidate_apks, key=os.path.getmtime, reverse=True)
+ return candidate_apks
+
+def GetCrazyLib(apk_filename):
+ """Returns the name of the first crazy library from this APK.
+
+ Args:
+ apk_filename: name of an APK file.
+
+ Returns:
+ Name of the first library which would be crazy loaded from this APK.
+ """
+ zipf = zipfile.ZipFile(apk_filename, 'r')
rmcilroy 2014/07/22 14:22:31 nit - zip_file
anton1 2014/07/22 16:07:18 Done.
+ for filename in zipf.namelist():
+ match = re.match('lib/[^/]*/crazy.(lib.*[.]so)', filename)
+ if match:
+ return match.group(1)
+
+def GetMatchingApks(device_apk_name):
+ """Find any APKs which match the package indicated by the device_apk_name.
+
+ Args:
+ device_apk_name: name of the APK on the device.
+
+ Returns:
+ A list of APK filenames which could contain the desired library.
+ """
+ match = re.match('(.*)-[0-9]+[.]apk$', device_apk_name)
+ if not match:
+ return None
+ package_name = match.group(1)
+ aapt = GetAapt()
+ if not aapt:
+ # Allow false positives
+ return GetCandidateApks()
+ candidate_apks = GetCandidateApks()
+ return filter(
+ lambda candidate_apk :
+ package_name == GetPackageName(aapt, candidate_apk),
+ candidate_apks)
+
+def MapDeviceApkToLibrary(device_apk_name):
+ """Provide a library name which corresponds with device_apk_name.
+
+ Args:
+ device_apk_name: name of the APK on the device.
+
+ Returns:
+ Name of the library which corresponds to that APK.
+ """
+ matching_apks = GetMatchingApks(device_apk_name)
+ for matching_apk in matching_apks:
+ crazy_lib = GetCrazyLib(matching_apk)
+ if crazy_lib:
+ return crazy_lib
+
def TranslateLibPath(lib):
# SymbolInformation(lib, addr) receives lib as the path from symbols
# root to the symbols file. This needs to be translated to point to the
@@ -138,6 +252,19 @@ def TranslateLibPath(lib):
# If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it
# untranslated in case it is an Android symbol in SYMBOLS_DIR.
library_name = os.path.basename(lib)
+
+ # The filename in the stack trace maybe an APK name rather than a library
+ # name. This happens when the library was loaded directly from inside the
+ # APK. If this is the case we try to figure out the library name by looking
+ # for a matching APK file and finding the name of the library in contains.
+ # The name of the APK file on the device is of the form
+ # <package_name>-<number>.apk. The APK file on the host may have any name
+ # so we look at the APK badging to see if the package name matches.
+ if re.search('-[0-9]+[.]apk$', library_name):
+ mapping = MapDeviceApkToLibrary(library_name)
+ if mapping:
+ library_name = mapping
+
out_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out')
candidate_dirs = ['.',
os.path.join(out_dir, 'Debug', 'lib'),
« 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