From f1316f75dba50ce4079019a8ec2e91405a5f24ba Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Tue, 13 Jan 2015 12:16:30 -0800 Subject: [PATCH] Make --gdb work again by using gdbserver --gdb now starts gdbserver and I've added a new command gdb_attach which knows how to launch gdb and connect to the launched gdbserver This doesn't quite work on android yet, but it's very close. R=abarth@chromium.org, qsr@chromium.org BUG= Review URL: https://codereview.chromium.org/808053006 --- engine/src/flutter/tools/skydb | 63 ++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/engine/src/flutter/tools/skydb b/engine/src/flutter/tools/skydb index 191d6d1de9..6f063640ba 100755 --- a/engine/src/flutter/tools/skydb +++ b/engine/src/flutter/tools/skydb @@ -31,6 +31,7 @@ SUPPORTED_MIME_TYPES = [ ] DEFAULT_SKY_COMMAND_PORT = 7777 +GDB_PORT = 8888 SKY_SERVER_PORT = 9999 PID_FILE_PATH = "/tmp/skydb.pids" DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/examples/home.sky" @@ -132,12 +133,15 @@ class SkyDebugger(object): configuration, server_root) return sky_server - def start_command(self, args): + def _create_paths_for_build_dir(self, build_dir): # skypy.paths.Paths takes a root-relative build_dir argument. :( - build_dir = os.path.abspath(args.build_dir) - root_relative_build_dir = os.path.relpath(build_dir, SRC_ROOT) + abs_build_dir = os.path.abspath(build_dir) + root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT) + return skypy.paths.Paths(root_relative_build_dir) + + def start_command(self, args): # FIXME: Lame that we use self for a command-specific variable. - self.paths = skypy.paths.Paths(root_relative_build_dir) + self.paths = self._create_paths_for_build_dir(args.build_dir) self.stop_command(None) # Quit any existing process. self.pids = {} # Clear out our pid file. @@ -174,20 +178,32 @@ class SkyDebugger(object): self.pids['remote_sky_command_port'] = args.command_port shell_command = self._build_mojo_shell_command(args) + + # On android we can't launch inside gdb, but rather have to attach. + if args.gdb and not is_android: + shell_command = ['gdbserver', ':%s' % GDB_PORT] + shell_command + print ' '.join(map(pipes.quote, shell_command)) self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid - if args.gdb: - print "Sorry, I'm not sure how best to wire up --gdb to work" - print "with mojo_shell as a background process. For now use:" - print "gdb --pid %s" % self.pids['mojo_shell_pid'] - shell_command = ['gdb'] + shell_command + if args.gdb and is_android: + gdbserver_cmd = ['gdbserver', '--attach', ':%s' % GDB_PORT] + self.pids['remote_gdbserver_pid'] = subprocess.Popen(shell_command).pid - if not self._wait_for_sky_command_port(): - logging.error('Failed to start sky') - self.stop_command(None) + port_string = 'tcp:%s' % GDB_PORT + subprocess.check_call([ + 'adb', 'forward', port_string, port_string + ]) + self.pids['remote_gdbserver_port'] = GDB_PORT + + if not args.gdb: + if not self._wait_for_sky_command_port(): + logging.error('Failed to start sky') + self.stop_command(None) + else: + self.load_command(args) else: - self.load_command(args) + print 'No load issued, connect with gdb first and then run load.' def _kill_if_exists(self, key, name): pid = self.pids.pop(key, None) @@ -207,7 +223,7 @@ class SkyDebugger(object): self._kill_if_exists('sky_server_pid', 'sky_server') # We could be much more surgical here: - if 'remote_sky_command_port' in self.pids: + if 'remote_sky_server_port' in self.pids: device = android_commands.AndroidCommands( self.pids['device_serial']) forwarder.Forwarder.UnmapAllDevicePorts(device) @@ -217,6 +233,10 @@ class SkyDebugger(object): port_string = 'tcp:%s' % self.pids['sky_command_port'] subprocess.call(['adb', 'forward', '--remove', port_string]) + if 'remote_gdbserver_port' in self.pids: + port_string = 'tcp:%s' % self.pids['remote_gdbserver_port'] + subprocess.call(['adb', 'forward', '--remove', port_string]) + def load_command(self, args): if not urlparse.urlparse(args.url_or_path).scheme: # The load happens on the remote device, use the remote port. @@ -287,6 +307,17 @@ class SkyDebugger(object): ] subprocess.call(['adb', 'logcat', '-s'] + TAGS) + def gdb_attach_command(self, args): + self.paths = self._create_paths_for_build_dir(self.pids['build_dir']) + gdb_command = [ + '/usr/bin/gdb', self.paths.mojo_shell_path, + '--eval-command', 'target remote localhost:%s' % GDB_PORT + ] + print " ".join(gdb_command) + # We don't want python listenting for signals or anything, so exec + # gdb and let it take the entire process. + os.execv(gdb_command[0], gdb_command) + def main(self): logging.basicConfig(level=logging.INFO) logging.getLogger("requests").setLevel(logging.WARNING) @@ -318,6 +349,10 @@ class SkyDebugger(object): help=('dump sky-related logs from device')) logcat_parser.set_defaults(func=self.logcat_command) + gdb_attach_parser = subparsers.add_parser('gdb_attach', + help='launch gdb and attach to gdbserver launched from start --gdb') + gdb_attach_parser.set_defaults(func=self.gdb_attach_command) + self._add_basic_command(subparsers, 'trace', '/trace', 'toggle tracing') self._add_basic_command(subparsers, 'reload', '/reload',