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

Unified Diff: mojo/devtools/common/debugger

Issue 1209593002: GDB support for Android in devtools' debugger. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 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 | « mojo/devtools/common/android_gdb/session.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/devtools/common/debugger
diff --git a/mojo/devtools/common/debugger b/mojo/devtools/common/debugger
index b323f4ac6b2f1221cd9658f81716b46dc235dca1..23898eb328f7a4bace7d60ad7213761469b7c21e 100755
--- a/mojo/devtools/common/debugger
+++ b/mojo/devtools/common/debugger
@@ -4,12 +4,65 @@
# found in the LICENSE file.
import argparse
+import codecs
+import logging
import os.path
import requests
+import signal
import subprocess
import sys
+import tempfile
+
+
+from android_gdb.install_remote_file_reader import install
+
_MOJO_DEBUGGER_PORT = 7777
+_DEFAULT_PACKAGE_NAME = 'org.chromium.mojo.shell'
+
+
+# TODO(etiennej): Refactor with similar methods in subdirectories
+class DirectoryNotFoundException(Exception):
+ """Directory has not been found."""
+ pass
+
+
+def _get_dir_above(dirname):
+ """Returns the directory "above" this file containing |dirname|."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ if not tail:
+ raise DirectoryNotFoundException(dirname)
+ if dirname in os.listdir(path):
+ return path
+
+
+# The two methods below are taken from //tools/find_depot_tools.py.
+def _is_real_depot_tools(path):
+ return os.path.isfile(os.path.join(path, 'gclient.py'))
+
+
+def _get_depot_tools_path():
+ """Searches for depot_tools."""
+ # First look if depot_tools is already in PYTHONPATH.
+ for i in sys.path:
+ if i.rstrip(os.sep).endswith('depot_tools') and _is_real_depot_tools(i):
+ return i
+ # Then look if depot_tools is in PATH, common case.
+ for i in os.environ['PATH'].split(os.pathsep):
+ if _is_real_depot_tools(i):
+ return i
+ # Rare case, it's not even in PATH, look upward up to root.
+ root_dir = os.path.dirname(os.path.abspath(__file__))
+ previous_dir = os.path.abspath(__file__)
+ while root_dir and root_dir != previous_dir:
+ i = os.path.join(root_dir, 'depot_tools')
+ if _is_real_depot_tools(i):
+ return i
+ previous_dir = root_dir
+ root_dir = os.path.dirname(root_dir)
+ return None
def _send_request(request, payload=None):
@@ -132,25 +185,141 @@ def _device_stack(args):
return 0
+def _gdb_attach(args):
+ """Run GDB on an instance of Mojo Shell on an android device."""
+ if args.ndk_dir:
+ ndk_dir = args.ndk_dir
+ else:
+ try:
+ ndk_dir = os.path.join(_get_dir_above('third_party'), 'third_party',
+ 'android_tools', 'ndk')
+ if not os.path.exists(ndk_dir):
+ raise DirectoryNotFoundException()
+ except DirectoryNotFoundException:
+ logging.fatal("Unable to find the Android NDK, please specify its path "
+ "with --ndk-dir.")
+ return
+
+ install_args = {}
+ if args.gsutil_dir:
+ install_args['gsutil'] = os.path.join(args.gsutil_dir, 'gsutil')
+ else:
+ try:
+ install_args['gsutil'] = os.path.join(
+ _get_depot_tools_path(), 'third_party', 'gsutil',
+ 'gsutil')
+ if not os.path.exists(install_args['gsutil']):
+ raise DirectoryNotFoundException()
+ except DirectoryNotFoundException:
+ logging.fatal("Unable to find gsutil, please specify its path with " "--gsutil-dir.")
+ return
+
+ if args.adb_path:
+ install_args['adb'] = args.adb_path
+ install(**install_args)
+
+ gdb_path = os.path.join(
+ ndk_dir,
+ 'toolchains',
+ # TODO(etiennej): Always select the most recent toolchain?
+ 'arm-linux-androideabi-4.9',
+ 'prebuilt',
+ # TODO(etiennej): DEPS mac NDK and use it on macs.
+ 'linux-x86_64',
+ 'bin',
+ 'arm-linux-androideabi-gdb')
+ python_gdb_script_path = os.path.join(os.path.dirname(__file__),
+ 'android_gdb', 'session.py')
+ debug_session_arguments = {}
+ if args.build_dir:
+ debug_session_arguments["build_directory"] = args.build_dir
+ else:
+ try:
+ debug_session_arguments["build_directory"] = os.path.join(
+ _get_dir_above('out'), 'out', 'android_Debug')
+ if not os.path.exists(debug_session_arguments["build_directory"]):
+ raise DirectoryNotFoundException()
+ except DirectoryNotFoundException:
+ logging.fatal("Unable to find the build directory, please specify it "
+ "using --build-dir.")
+ return
+
+ if args.package_name:
+ debug_session_arguments["package_name"] = args.package_name
+ else:
+ debug_session_arguments["package_name"] = _DEFAULT_PACKAGE_NAME
+ if args.pyelftools_dir:
+ debug_session_arguments["pyelftools_dir"] = args.pyelftools_dir
+ else:
+ debug_session_arguments["pyelftools_dir"] = os.path.join(
+ _get_dir_above('third_party'), 'third_party', 'pyelftools')
+
+ debug_session_arguments_str = ', '.join(
+ [k + '="' + codecs.encode(v, 'string_escape') + '"'
+ for k, v in debug_session_arguments.items()])
+
+ # We need to pass some commands to GDB at startup.
+ gdb_commands_file = tempfile.NamedTemporaryFile()
+ gdb_commands_file.write('source ' + python_gdb_script_path + '\n')
+ gdb_commands_file.write('py d = DebugSession(' + debug_session_arguments_str
+ + ')\n')
+ gdb_commands_file.write('py d.start()\n')
+ gdb_commands_file.flush()
+
+ gdb_proc = subprocess.Popen([gdb_path, '-x', gdb_commands_file.name],
+ stdin=sys.stdin,
+ stdout=sys.stdout,
+ stderr=sys.stderr)
+
+ # We don't want SIGINT to stop this program. It is automatically propagated by
+ # the system to gdb.
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ gdb_proc.wait()
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+
def _add_device_command(subparsers):
"""Sets up the parser for the 'device' command."""
device_parser = subparsers.add_parser('device',
help='interact with the Android device (requires adb in PATH or passing '
'--adb-path)')
device_parser.add_argument('--adb-path', type=str,
- help='path to the adb tool from the Android SDK')
+ help='path to the adb tool from the Android SDK (optional)')
device_subparser = device_parser.add_subparsers(
help='the command to run')
device_stack_parser = device_subparser.add_parser('stack',
help='symbolize the crash stacktraces from the device log')
- device_stack_parser.add_argument('--build-dir', type=str,
- help='path to the build directory')
device_stack_parser.add_argument('--ndk-dir', type=str,
help='path to the directory containing the Android NDK')
+ device_stack_parser.add_argument('--build-dir', type=str,
+ help='path to the build directory')
device_stack_parser.set_defaults(func=_device_stack)
+def _add_gdb_command(subparsers):
+ gdb_parser = subparsers.add_parser(
+ 'gdb', help='Debug Mojo Shell and its apps using GDB')
+ gdb_subparser = gdb_parser.add_subparsers(
+ help='Commands to GDB')
+
+ gdb_attach_parser = gdb_subparser.add_parser(
+ 'attach', help='Attach GDB to a running Mojo Shell process')
+ gdb_attach_parser.add_argument('--adb-path', type=str,
+ help='path to the adb tool from the Android SDK (optional)')
+ gdb_attach_parser.add_argument('--ndk-dir', type=str,
+ help='path to the directory containing the Android NDK')
+ gdb_attach_parser.add_argument('--build-dir', type=str,
+ help='path to the build directory')
+ gdb_attach_parser.add_argument('--pyelftools-dir', type=str,
+ help='Path to a directory containing third party libraries')
+ gdb_attach_parser.add_argument('--gsutil-dir', type=str,
+ help='Path to a directory containing gsutil')
+ gdb_attach_parser.add_argument('--package-name', type=str,
+ help='Name of the Mojo Shell android package to debug')
+ gdb_attach_parser.set_defaults(func=_gdb_attach)
+
+
def main():
parser = argparse.ArgumentParser(description='Command-line interface for '
'mojo:debugger')
@@ -158,6 +327,7 @@ def main():
_add_device_command(subparsers)
_add_tracing_command(subparsers)
_add_wm_command(subparsers)
+ _add_gdb_command(subparsers)
args = parser.parse_args()
return args.func(args)
« no previous file with comments | « mojo/devtools/common/android_gdb/session.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698