| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import argparse | 6 import argparse |
| 7 import re | 7 import re |
| 8 import sys | 8 import sys |
| 9 import os | 9 import os |
| 10 import logging | 10 import logging |
| 11 import subprocess | 11 import subprocess |
| 12 | 12 |
| 13 SRC_ROOT = skypy.paths.Paths('ignored').src_root |
| 14 ADB_PATH = os.path.join(SRC_ROOT, |
| 15 'third_party/android_tools/sdk/platform-tools/adb') |
| 16 |
| 13 | 17 |
| 14 # TODO(eseidel): This should be shared with adb_gdb | 18 # TODO(eseidel): This should be shared with adb_gdb |
| 15 def main(): | 19 def main(): |
| 16 logging.basicConfig(level=logging.INFO) | 20 logging.basicConfig(level=logging.INFO) |
| 17 parser = argparse.ArgumentParser( | 21 parser = argparse.ArgumentParser( |
| 18 description='Pull all libraries used by a pid on android into a cache.') | 22 description='Pull all libraries used by a pid on android into a cache.') |
| 19 parser.add_argument('cache_root', type=str) | 23 parser.add_argument('cache_root', type=str) |
| 20 parser.add_argument('pid', type=int) | 24 parser.add_argument('pid', type=int) |
| 21 args = parser.parse_args() | 25 args = parser.parse_args() |
| 22 | 26 |
| 23 if not os.path.exists(args.cache_root): | 27 if not os.path.exists(args.cache_root): |
| 24 os.makedirs(args.cache_root) | 28 os.makedirs(args.cache_root) |
| 25 | 29 |
| 26 subprocess.check_call(['adb', 'root']) | 30 subprocess.check_call([ADB_PATH, 'root']) |
| 27 | 31 |
| 28 # TODO(eseidel): Check the build.props, or find some way to avoid | 32 # TODO(eseidel): Check the build.props, or find some way to avoid |
| 29 # re-pulling every library every time. adb_gdb has code to do this | 33 # re-pulling every library every time. adb_gdb has code to do this |
| 30 # but doesn't seem to notice when the set of needed libraries changed. | 34 # but doesn't seem to notice when the set of needed libraries changed. |
| 31 | 35 |
| 32 library_regexp = re.compile(r'(?P<library_path>/system/.*\.so)') | 36 library_regexp = re.compile(r'(?P<library_path>/system/.*\.so)') |
| 33 cat_maps_cmd = ['adb', 'shell', 'cat', '/proc/%s/maps' % args.pid] | 37 cat_maps_cmd = [ADB_PATH, 'shell', 'cat', '/proc/%s/maps' % args.pid] |
| 34 maps_lines = subprocess.check_output(cat_maps_cmd).strip().split('\n') | 38 maps_lines = subprocess.check_output(cat_maps_cmd).strip().split('\n') |
| 35 # adb shell doesn't return the return code from the shell? | 39 # adb shell doesn't return the return code from the shell? |
| 36 if not maps_lines or 'No such file or directory' in maps_lines[0]: | 40 if not maps_lines or 'No such file or directory' in maps_lines[0]: |
| 37 print 'Failed to get maps for pid %s on device.' % args.pid | 41 print 'Failed to get maps for pid %s on device.' % args.pid |
| 38 sys.exit(1) | 42 sys.exit(1) |
| 39 | 43 |
| 40 def library_from_line(line): | 44 def library_from_line(line): |
| 41 result = library_regexp.search(line) | 45 result = library_regexp.search(line) |
| 42 if not result: | 46 if not result: |
| 43 return None | 47 return None |
| 44 return result.group('library_path') | 48 return result.group('library_path') |
| 45 | 49 |
| 46 dev_null = open(os.devnull, 'w') # Leaking. | 50 dev_null = open(os.devnull, 'w') # Leaking. |
| 47 to_pull = set(filter(None, map(library_from_line, maps_lines))) | 51 to_pull = set(filter(None, map(library_from_line, maps_lines))) |
| 48 to_pull.add('/system/bin/linker') # Unclear why but adb_gdb pulls this too. | 52 to_pull.add('/system/bin/linker') # Unclear why but adb_gdb pulls this too. |
| 49 for library_path in sorted(to_pull): | 53 for library_path in sorted(to_pull): |
| 50 # Not using os.path.join since library_path is absolute. | 54 # Not using os.path.join since library_path is absolute. |
| 51 dest_file = os.path.normpath("%s/%s" % (args.cache_root, library_path)) | 55 dest_file = os.path.normpath("%s/%s" % (args.cache_root, library_path)) |
| 52 dest_dir = os.path.dirname(dest_file) | 56 dest_dir = os.path.dirname(dest_file) |
| 53 if not os.path.exists(dest_dir): | 57 if not os.path.exists(dest_dir): |
| 54 os.makedirs(dest_dir) | 58 os.makedirs(dest_dir) |
| 55 print '%s -> %s' % (library_path, dest_file) | 59 print '%s -> %s' % (library_path, dest_file) |
| 56 pull_cmd = ['adb', 'pull', library_path, dest_file] | 60 pull_cmd = [ADB_PATH, 'pull', library_path, dest_file] |
| 57 subprocess.check_call(pull_cmd, stderr=dev_null) | 61 subprocess.check_call(pull_cmd, stderr=dev_null) |
| 58 | 62 |
| 59 | 63 |
| 60 if __name__ == '__main__': | 64 if __name__ == '__main__': |
| 61 main() | 65 main() |
| OLD | NEW |