mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This only barely works. We pull down system libraries once before we attach. The libraries we pull from the device do not have debug symbols, but have enough that we have decent callstacks. We launch a background process to repeatedly update a cache directory with symlinks into our build directory corresponding to the cache names used on the device, however gdb doesn't watch the solib-search-path directories to notice the links as we add them. Better solutions would be to add support for pulling down full android symboled system images and using those instead of pulling libraries off the device as well as figure out how to get android binaries to support build-id so that we can present a directory of build-id associated libraries to gdb on boot and have it to build-id based lookups of libraries instead of our current broken watch-logs-and-add-symlinks approach. If you know what you're doing with this you can actually make debugging work on the device. It's not particularly user friendly yet, but we'll work on it. I added a build_dir member to skypy.paths.Paths as a temporary measure before we move off of skypy's paths and onto mopy's paths. This helped eliminate problems with using a relative path in args.build_dir as is common. R=abarth@chromium.org, ojan@chromium.org, qsr@chromium.org BUG= Review URL: https://codereview.chromium.org/855663003
62 lines
2.2 KiB
Python
Executable File
62 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright 2015 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import argparse
|
|
import re
|
|
import sys
|
|
import os
|
|
import logging
|
|
import subprocess
|
|
|
|
|
|
# TODO(eseidel): This should be shared with adb_gdb
|
|
def main():
|
|
logging.basicConfig(level=logging.INFO)
|
|
parser = argparse.ArgumentParser(
|
|
description='Pull all libraries used by a pid on android into a cache.')
|
|
parser.add_argument('cache_root', type=str)
|
|
parser.add_argument('pid', type=int)
|
|
args = parser.parse_args()
|
|
|
|
if not os.path.exists(args.cache_root):
|
|
os.makedirs(args.cache_root)
|
|
|
|
subprocess.check_call(['adb', 'root'])
|
|
|
|
# TODO(eseidel): Check the build.props, or find some way to avoid
|
|
# re-pulling every library every time. adb_gdb has code to do this
|
|
# but doesn't seem to notice when the set of needed libraries changed.
|
|
|
|
library_regexp = re.compile(r'(?P<library_path>/system/.*\.so)')
|
|
cat_maps_cmd = ['adb', 'shell', 'cat', '/proc/%s/maps' % args.pid]
|
|
maps_lines = subprocess.check_output(cat_maps_cmd).strip().split('\n')
|
|
# adb shell doesn't return the return code from the shell?
|
|
if not maps_lines or 'No such file or directory' in maps_lines[0]:
|
|
print 'Failed to get maps for pid %s on device.' % args.pid
|
|
sys.exit(1)
|
|
|
|
def library_from_line(line):
|
|
result = library_regexp.search(line)
|
|
if not result:
|
|
return None
|
|
return result.group('library_path')
|
|
|
|
dev_null = open(os.devnull, 'w') # Leaking.
|
|
to_pull = set(filter(None, map(library_from_line, maps_lines)))
|
|
to_pull.add('/system/bin/linker') # Unclear why but adb_gdb pulls this too.
|
|
for library_path in sorted(to_pull):
|
|
# Not using os.path.join since library_path is absolute.
|
|
dest_file = os.path.normpath("%s/%s" % (args.cache_root, library_path))
|
|
dest_dir = os.path.dirname(dest_file)
|
|
if not os.path.exists(dest_dir):
|
|
os.makedirs(dest_dir)
|
|
print '%s -> %s' % (library_path, dest_file)
|
|
pull_cmd = ['adb', 'pull', library_path, dest_file]
|
|
subprocess.check_call(pull_cmd, stderr=dev_null)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|