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 |
11 import subprocess | 11 import subprocess |
12 import sys | 12 import sys |
13 import tempfile | 13 import tempfile |
14 | 14 |
15 from parse_proc_maps import parse_proc_maps | 15 from parse_proc_maps import parse_proc_maps |
16 from util import executable_condition | 16 from util import executable_condition |
17 | 17 |
18 | 18 |
19 def _dump_command_result(command, output_dir_path, basename, suffix): | |
20 with tempfile.NamedTemporaryFile( | |
21 prefix=basename + '.', suffix=suffix, delete=False, mode='w', | |
22 dir=output_dir_path) as f: | |
23 filename = os.path.realpath(f.name) | |
24 try: | |
M-A Ruel
2012/07/27 13:38:14
You should use tempfile.mkstemp() in that case;
ha
Dai Mikurube (NOT FULLTIME)
2012/07/30 04:18:38
Done.
| |
25 subprocess.check_call('%s > %s' % (command, filename), shell=True) | |
26 except: | |
27 os.remove(filename) | |
28 | |
29 if os.path.exists(filename) and os.path.getsize(filename) == 0: | |
30 os.remove(filename) | |
31 return None | |
32 if not os.path.exists(filename): | |
33 return None | |
34 | |
35 return filename | |
36 | |
37 | |
19 def prepare_symbol_info(maps_path, output_dir_path=None, loglevel=logging.WARN): | 38 def prepare_symbol_info(maps_path, output_dir_path=None, loglevel=logging.WARN): |
20 log = logging.getLogger('prepare_symbol_info') | 39 log = logging.getLogger('prepare_symbol_info') |
21 log.setLevel(loglevel) | 40 log.setLevel(loglevel) |
22 handler = logging.StreamHandler() | 41 handler = logging.StreamHandler() |
23 handler.setLevel(loglevel) | 42 handler.setLevel(loglevel) |
24 formatter = logging.Formatter('%(message)s') | 43 formatter = logging.Formatter('%(message)s') |
25 handler.setFormatter(formatter) | 44 handler.setFormatter(formatter) |
26 log.addHandler(handler) | 45 log.addHandler(handler) |
27 | 46 |
28 if not output_dir_path: | 47 if not output_dir_path: |
(...skipping 22 matching lines...) Expand all Loading... | |
51 | 70 |
52 if output_dir_path_exists: | 71 if output_dir_path_exists: |
53 return 1 | 72 return 1 |
54 | 73 |
55 shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps')) | 74 shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps')) |
56 | 75 |
57 with open(maps_path, mode='r') as f: | 76 with open(maps_path, mode='r') as f: |
58 maps = parse_proc_maps(f) | 77 maps = parse_proc_maps(f) |
59 | 78 |
60 log.debug('Listing up symbols.') | 79 log.debug('Listing up symbols.') |
61 nm_files = {} | 80 files = {} |
62 for entry in maps.iter(executable_condition): | 81 for entry in maps.iter(executable_condition): |
63 log.debug(' %016x-%016x +%06x %s' % ( | 82 log.debug(' %016x-%016x +%06x %s' % ( |
64 entry.begin, entry.end, entry.offset, entry.name)) | 83 entry.begin, entry.end, entry.offset, entry.name)) |
65 with tempfile.NamedTemporaryFile( | 84 nm_filename = _dump_command_result( |
66 prefix=os.path.basename(entry.name) + '.', | 85 'nm -n --format bsd %s | c++filt' % entry.name, |
M-A Ruel
2012/07/27 13:38:14
Please do not use the shell if possible. You can c
Dai Mikurube (NOT FULLTIME)
2012/07/30 04:18:38
I avoided self-made pipes to avoid subprocess.PIPE
| |
67 suffix='.nm', delete=False, mode='w', dir=output_dir_path) as f: | 86 output_dir_path, os.path.basename(entry.name), '.nm') |
68 nm_filename = os.path.realpath(f.name) | 87 if not nm_filename: |
69 nm_succeeded = False | 88 continue |
70 cppfilt_succeeded = False | 89 readelf_e_filename = _dump_command_result( |
71 p_nm = subprocess.Popen( | 90 'readelf -e %s' % entry.name, |
72 'nm -n --format bsd %s' % entry.name, shell=True, | 91 output_dir_path, os.path.basename(entry.name), '.readelf-e') |
73 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 92 if not readelf_e_filename: |
74 p_cppfilt = subprocess.Popen( | 93 continue |
75 'c++filt', shell=True, | |
76 stdin=p_nm.stdout, stdout=f, stderr=subprocess.PIPE) | |
77 | 94 |
78 if p_nm.wait() == 0: | 95 files[entry.name] = {} |
79 nm_succeeded = True | 96 files[entry.name]['nm'] = { |
80 for line in p_nm.stderr: | |
81 log.debug(line.rstrip()) | |
82 if p_cppfilt.wait() == 0: | |
83 cppfilt_succeeded = True | |
84 for line in p_cppfilt.stderr: | |
85 log.debug(line.rstrip()) | |
86 | |
87 if nm_succeeded and cppfilt_succeeded: | |
88 nm_files[entry.name] = { | |
89 'file': os.path.basename(nm_filename), | 97 'file': os.path.basename(nm_filename), |
90 'format': 'bsd', | 98 'format': 'bsd', |
91 'mangled': False} | 99 'mangled': False} |
92 else: | 100 files[entry.name]['readelf-e'] = { |
93 os.remove(nm_filename) | 101 'file': os.path.basename(readelf_e_filename)} |
94 | 102 |
95 with open(os.path.join(output_dir_path, 'nm.json'), 'w') as f: | 103 with open(os.path.join(output_dir_path, 'files.json'), 'w') as f: |
96 json.dump(nm_files, f, indent=2, sort_keys=True) | 104 json.dump(files, f, indent=2, sort_keys=True) |
97 | 105 |
98 log.info('Collected symbol information at "%s".' % output_dir_path) | 106 log.info('Collected symbol information at "%s".' % output_dir_path) |
99 return 0 | 107 return 0 |
100 | 108 |
101 | 109 |
102 def main(): | 110 def main(): |
103 if not sys.platform.startswith('linux'): | 111 if not sys.platform.startswith('linux'): |
104 sys.stderr.write('This script work only on Linux.') | 112 sys.stderr.write('This script work only on Linux.') |
105 return 1 | 113 return 1 |
106 | 114 |
107 if len(sys.argv) < 2: | 115 if len(sys.argv) < 2: |
108 sys.stderr.write("""Usage: | 116 sys.stderr.write("""Usage: |
109 %s /path/to/maps [/path/to/output_data_dir/] | 117 %s /path/to/maps [/path/to/output_data_dir/] |
110 """ % sys.argv[0]) | 118 """ % sys.argv[0]) |
111 return 1 | 119 return 1 |
112 elif len(sys.argv) == 2: | 120 elif len(sys.argv) == 2: |
113 sys.exit(prepare_symbol_info(sys.argv[1], loglevel=logging.DEBUG)) | 121 sys.exit(prepare_symbol_info(sys.argv[1], loglevel=logging.DEBUG)) |
114 else: | 122 else: |
115 sys.exit(prepare_symbol_info(sys.argv[1], sys.argv[2], | 123 sys.exit(prepare_symbol_info(sys.argv[1], sys.argv[2], |
116 loglevel=logging.INFO)) | 124 loglevel=logging.INFO)) |
117 return 0 | 125 return 0 |
118 | 126 |
119 | 127 |
120 if __name__ == '__main__': | 128 if __name__ == '__main__': |
121 sys.exit(main()) | 129 sys.exit(main()) |
OLD | NEW |