OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 json | 6 import json |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import re | 9 import re |
10 import shutil | 10 import shutil |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 return None | 48 return None |
49 | 49 |
50 if not os.path.exists(filename_out): | 50 if not os.path.exists(filename_out): |
51 return None | 51 return None |
52 | 52 |
53 return filename_out | 53 return filename_out |
54 | 54 |
55 | 55 |
56 def prepare_symbol_info(maps_path, | 56 def prepare_symbol_info(maps_path, |
57 output_dir_path=None, | 57 output_dir_path=None, |
58 fake_directories=None, | 58 alternative_dirs=None, |
59 use_tempdir=False, | 59 use_tempdir=False, |
60 use_source_file_name=False): | 60 use_source_file_name=False): |
61 """Prepares (collects) symbol information files for find_runtime_symbols. | 61 """Prepares (collects) symbol information files for find_runtime_symbols. |
62 | 62 |
63 1) If |output_dir_path| is specified, it tries collecting symbol information | 63 1) If |output_dir_path| is specified, it tries collecting symbol information |
64 files in the given directory |output_dir_path|. | 64 files in the given directory |output_dir_path|. |
65 1-a) If |output_dir_path| doesn't exist, create the directory and use it. | 65 1-a) If |output_dir_path| doesn't exist, create the directory and use it. |
66 1-b) If |output_dir_path| is an empty directory, use it. | 66 1-b) If |output_dir_path| is an empty directory, use it. |
67 1-c) If |output_dir_path| is a directory which has 'files.json', assumes that | 67 1-c) If |output_dir_path| is a directory which has 'files.json', assumes that |
68 files are already collected and just ignores it. | 68 files are already collected and just ignores it. |
69 1-d) Otherwise, depends on |use_tempdir|. | 69 1-d) Otherwise, depends on |use_tempdir|. |
70 | 70 |
71 2) If |output_dir_path| is not specified, it tries to create a new directory | 71 2) If |output_dir_path| is not specified, it tries to create a new directory |
72 depending on 'maps_path'. | 72 depending on 'maps_path'. |
73 | 73 |
74 If it cannot create a new directory, creates a temporary directory depending | 74 If it cannot create a new directory, creates a temporary directory depending |
75 on |use_tempdir|. If |use_tempdir| is False, returns None. | 75 on |use_tempdir|. If |use_tempdir| is False, returns None. |
76 | 76 |
77 Args: | 77 Args: |
78 maps_path: A path to a file which contains '/proc/<pid>/maps'. | 78 maps_path: A path to a file which contains '/proc/<pid>/maps'. |
79 fake_directories: A mapping from a directory '/path/on/target' where the | 79 alternative_dirs: A mapping from a directory '/path/on/target' where the |
80 target process runs to a directory '/path/on/host' where the script | 80 target process runs to a directory '/path/on/host' where the script |
81 reads the binary. Considered to be used for Android binaries. | 81 reads the binary. Considered to be used for Android binaries. |
82 output_dir_path: A path to a directory where files are prepared. | 82 output_dir_path: A path to a directory where files are prepared. |
83 use_tempdir: If True, it creates a temporary directory when it cannot | 83 use_tempdir: If True, it creates a temporary directory when it cannot |
84 create a new directory. | 84 create a new directory. |
85 use_source_file_name: If True, it adds reduced result of 'readelf -wL' | 85 use_source_file_name: If True, it adds reduced result of 'readelf -wL' |
86 to find source file names. | 86 to find source file names. |
87 | 87 |
88 Returns: | 88 Returns: |
89 A pair of a path to the prepared directory and a boolean representing | 89 A pair of a path to the prepared directory and a boolean representing |
90 if it created a temporary directory or not. | 90 if it created a temporary directory or not. |
91 """ | 91 """ |
92 fake_directories = fake_directories or {} | 92 alternative_dirs = alternative_dirs or {} |
93 if not output_dir_path: | 93 if not output_dir_path: |
94 matched = re.match('^(.*)\.maps$', os.path.basename(maps_path)) | 94 matched = re.match('^(.*)\.maps$', os.path.basename(maps_path)) |
95 if matched: | 95 if matched: |
96 output_dir_path = matched.group(1) + '.pre' | 96 output_dir_path = matched.group(1) + '.pre' |
97 if not output_dir_path: | 97 if not output_dir_path: |
98 matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path)) | 98 matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path)) |
99 if matched: | 99 if matched: |
100 output_dir_path = matched.group(1) + '.pre' | 100 output_dir_path = matched.group(1) + '.pre' |
101 if not output_dir_path: | 101 if not output_dir_path: |
102 output_dir_path = os.path.basename(maps_path) + '.pre' | 102 output_dir_path = os.path.basename(maps_path) + '.pre' |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 | 138 |
139 with open(maps_path, mode='r') as f: | 139 with open(maps_path, mode='r') as f: |
140 maps = ProcMaps.load(f) | 140 maps = ProcMaps.load(f) |
141 | 141 |
142 LOGGER.debug('Listing up symbols.') | 142 LOGGER.debug('Listing up symbols.') |
143 files = {} | 143 files = {} |
144 for entry in maps.iter(ProcMaps.executable): | 144 for entry in maps.iter(ProcMaps.executable): |
145 LOGGER.debug(' %016x-%016x +%06x %s' % ( | 145 LOGGER.debug(' %016x-%016x +%06x %s' % ( |
146 entry.begin, entry.end, entry.offset, entry.name)) | 146 entry.begin, entry.end, entry.offset, entry.name)) |
147 binary_path = entry.name | 147 binary_path = entry.name |
148 for target_path, host_path in fake_directories.iteritems(): | 148 for target_path, host_path in alternative_dirs.iteritems(): |
149 if entry.name.startswith(target_path): | 149 if entry.name.startswith(target_path): |
150 binary_path = entry.name.replace(target_path, host_path, 1) | 150 binary_path = entry.name.replace(target_path, host_path, 1) |
151 nm_filename = _dump_command_result( | 151 nm_filename = _dump_command_result( |
152 'nm -n --format bsd %s | c++filt' % binary_path, | 152 'nm -n --format bsd %s | c++filt' % binary_path, |
153 output_dir_path, os.path.basename(binary_path), '.nm') | 153 output_dir_path, os.path.basename(binary_path), '.nm') |
154 if not nm_filename: | 154 if not nm_filename: |
155 continue | 155 continue |
156 readelf_e_filename = _dump_command_result( | 156 readelf_e_filename = _dump_command_result( |
157 'readelf -eW %s' % binary_path, | 157 'readelf -eW %s' % binary_path, |
158 output_dir_path, os.path.basename(binary_path), '.readelf-e') | 158 output_dir_path, os.path.basename(binary_path), '.readelf-e') |
(...skipping 28 matching lines...) Expand all Loading... |
187 sys.stderr.write('This script work only on Linux.') | 187 sys.stderr.write('This script work only on Linux.') |
188 return 1 | 188 return 1 |
189 | 189 |
190 LOGGER.setLevel(logging.DEBUG) | 190 LOGGER.setLevel(logging.DEBUG) |
191 handler = logging.StreamHandler() | 191 handler = logging.StreamHandler() |
192 handler.setLevel(logging.INFO) | 192 handler.setLevel(logging.INFO) |
193 formatter = logging.Formatter('%(message)s') | 193 formatter = logging.Formatter('%(message)s') |
194 handler.setFormatter(formatter) | 194 handler.setFormatter(formatter) |
195 LOGGER.addHandler(handler) | 195 LOGGER.addHandler(handler) |
196 | 196 |
197 # TODO(dmikurube): Specify |fake_directories| from command line. | 197 # TODO(dmikurube): Specify |alternative_dirs| from command line. |
198 if len(sys.argv) < 2: | 198 if len(sys.argv) < 2: |
199 sys.stderr.write("""Usage: | 199 sys.stderr.write("""Usage: |
200 %s /path/to/maps [/path/to/output_data_dir/] | 200 %s /path/to/maps [/path/to/output_data_dir/] |
201 """ % sys.argv[0]) | 201 """ % sys.argv[0]) |
202 return 1 | 202 return 1 |
203 elif len(sys.argv) == 2: | 203 elif len(sys.argv) == 2: |
204 result, _ = prepare_symbol_info(sys.argv[1]) | 204 result, _ = prepare_symbol_info(sys.argv[1]) |
205 else: | 205 else: |
206 result, _ = prepare_symbol_info(sys.argv[1], sys.argv[2]) | 206 result, _ = prepare_symbol_info(sys.argv[1], sys.argv[2]) |
207 | 207 |
208 return not result | 208 return not result |
209 | 209 |
210 | 210 |
211 if __name__ == '__main__': | 211 if __name__ == '__main__': |
212 sys.exit(main()) | 212 sys.exit(main()) |
OLD | NEW |