Chromium Code Reviews| Index: mojo/devtools/common/debugger |
| diff --git a/mojo/devtools/common/debugger b/mojo/devtools/common/debugger |
| index b323f4ac6b2f1221cd9658f81716b46dc235dca1..04b347a664f143617d5b46d617cc2b86da5a0e39 100755 |
| --- a/mojo/devtools/common/debugger |
| +++ b/mojo/devtools/common/debugger |
| @@ -8,10 +8,25 @@ import os.path |
| import requests |
| import subprocess |
| import sys |
| +import tempfile |
| +import codecs |
| + |
| +from android_gdb.install_remote_file_reader import install_binary |
| _MOJO_DEBUGGER_PORT = 7777 |
| +# TODO(etiennej): Refactor with similar methods in subdirectories |
| +def _GetDirAbove(dirname): |
|
ppi
2015/07/09 13:12:40
_get_dir_above, let's make it not loop infinitely
etiennej
2015/07/15 07:13:21
Done.
|
| + """Returns the directory "above" this file containing |dirname|.""" |
| + path = os.path.abspath(__file__) |
| + while True: |
| + path, _ = os.path.split(path) |
| + assert path |
| + if dirname in os.listdir(path): |
| + return path |
| + |
| + |
| def _send_request(request, payload=None): |
| """Sends a request to mojo:debugger.""" |
| try: |
| @@ -132,25 +147,102 @@ 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: |
| + ndk_dir = os.path.join(_GetDirAbove('third_party'), 'third_party', |
| + 'android_tools', 'ndk') |
| + install_args = {} |
| + if args.gsutil_dir: |
| + install_args['gsutil'] = os.path.join(args.gsutil_dir, 'gsutil') |
| + else: |
| + install_args['gsutil'] = os.path.join( |
| + _GetDirAbove('depot_tools'), 'depot_tools', 'third_party', 'gsutil', |
| + 'gsutil') |
| + if args.adb_path: |
| + install_args['adb'] = args.adb_path |
| + install_binary(**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') |
| + # We need to pass some commands to GDB at startup. |
| + gdb_setup_commands = tempfile.NamedTemporaryFile() |
|
ppi
2015/07/09 13:12:40
maybe 'gdb_commands_file'?
etiennej
2015/07/15 07:13:21
Done.
|
| + gdb_setup_commands.write('source ' + python_gdb_script_path + '\n') |
| + debug_session_arguments = {} |
| + if args.build_dir: |
| + debug_session_arguments["build_directory"] = args.build_dir |
| + if args.package_name: |
| + debug_session_arguments["package_name"] = args.package_name |
| + if args.pyelftools_dir: |
| + debug_session_arguments["pyelftools_dir"] = args.pyelftools_dir |
| + debug_session_arguments = ', '.join( |
|
ppi
2015/07/09 13:12:40
Maybe compute this string before gdb command file
ppi
2015/07/09 13:12:40
Better to use a new variable / not to change the t
etiennej
2015/07/15 07:13:21
Done.
etiennej
2015/07/15 07:13:21
If one cannot redefine its variable types in Pytho
|
| + [k + '="' + codecs.encode(v, 'string_escape') + '"' |
| + for k, v in debug_session_arguments.items()]) |
| + gdb_setup_commands.write('py d = DebugSession(' + debug_session_arguments + |
| + ')\n') |
| + gdb_setup_commands.write('py d.start_debug()\n') |
| + gdb_setup_commands.flush() |
| + gdb_proc = subprocess.Popen([gdb_path, '-x', gdb_setup_commands.name], |
| + stdin=sys.stdin, |
| + stdout=sys.stdout, |
| + stderr=sys.stderr) |
| + gdb_proc.wait() |
| + |
| + |
| 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 +250,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) |