Chromium Code Reviews| Index: sky/tools/skydb |
| diff --git a/sky/tools/skydb b/sky/tools/skydb |
| index 191d6d1de938973bcf690b0a7aec3384d28a9ba1..6f063640bafc146dec0915e0a991a121caac84c3 100755 |
| --- a/sky/tools/skydb |
| +++ b/sky/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: |
|
eseidel
2015/01/13 20:11:32
This was just checking for the wrong key. They bo
|
| 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', |