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 |