OLD | NEW |
1 # Copyright 2017 The Chromium Authors. All rights reserved. | 1 # Copyright 2017 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Main Python API for analyzing binary size.""" | 5 """Main Python API for analyzing binary size.""" |
6 | 6 |
7 import argparse | 7 import argparse |
8 import calendar | 8 import calendar |
9 import collections | 9 import collections |
10 import datetime | 10 import datetime |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 # Convert ../../third_party/... -> third_party/... | 136 # Convert ../../third_party/... -> third_party/... |
137 path = path[6:] | 137 path = path[6:] |
138 if path.endswith(')'): | 138 if path.endswith(')'): |
139 # Convert foo/bar.a(baz.o) -> foo/bar.a/baz.o | 139 # Convert foo/bar.a(baz.o) -> foo/bar.a/baz.o |
140 start_idx = path.index('(') | 140 start_idx = path.index('(') |
141 path = os.path.join(path[:start_idx], path[start_idx + 1:-1]) | 141 path = os.path.join(path[:start_idx], path[start_idx + 1:-1]) |
142 return path | 142 return path |
143 | 143 |
144 | 144 |
145 def _NormalizeSourcePath(path): | 145 def _NormalizeSourcePath(path): |
| 146 """Returns (is_generated, normalized_path)""" |
146 if path.startswith('gen/'): | 147 if path.startswith('gen/'): |
147 # Convert gen/third_party/... -> third_party/... | 148 # Convert gen/third_party/... -> third_party/... |
148 return path[4:] | 149 return True, path[4:] |
149 if path.startswith('../../'): | 150 if path.startswith('../../'): |
150 # Convert ../../third_party/... -> third_party/... | 151 # Convert ../../third_party/... -> third_party/... |
151 return path[6:] | 152 return False, path[6:] |
152 return path | 153 return True, path |
153 | 154 |
154 | 155 |
155 def _SourcePathForObjectPath(object_path, source_mapper): | 156 def _SourcePathForObjectPath(object_path, source_mapper): |
| 157 """Returns (is_generated, normalized_path)""" |
156 # We don't have source info for prebuilt .a files. | 158 # We don't have source info for prebuilt .a files. |
157 if not os.path.isabs(object_path) and not object_path.startswith('..'): | 159 if not os.path.isabs(object_path) and not object_path.startswith('..'): |
158 source_path = source_mapper.FindSourceForPath(object_path) | 160 source_path = source_mapper.FindSourceForPath(object_path) |
159 if source_path: | 161 if source_path: |
160 return _NormalizeSourcePath(source_path) | 162 return _NormalizeSourcePath(source_path) |
161 return '' | 163 return False, '' |
162 | 164 |
163 | 165 |
164 def _ExtractSourcePaths(raw_symbols, source_mapper): | 166 def _ExtractSourcePaths(raw_symbols, source_mapper): |
165 """Fills in the |source_path| attribute.""" | 167 """Fills in the |source_path| attribute.""" |
166 logging.debug('Parsed %d .ninja files.', source_mapper.parsed_file_count) | 168 logging.debug('Parsed %d .ninja files.', source_mapper.parsed_file_count) |
167 for symbol in raw_symbols: | 169 for symbol in raw_symbols: |
168 object_path = symbol.object_path | 170 object_path = symbol.object_path |
169 if object_path and not symbol.source_path: | 171 if object_path and not symbol.source_path: |
170 symbol.source_path = _SourcePathForObjectPath(object_path, source_mapper) | 172 symbol.generated_source, symbol.source_path = ( |
| 173 _SourcePathForObjectPath(object_path, source_mapper)) |
171 | 174 |
172 | 175 |
173 def _ComputeAnscestorPath(path_list): | 176 def _ComputeAnscestorPath(path_list): |
174 """Returns the common anscestor of the given paths.""" | 177 """Returns the common anscestor of the given paths.""" |
175 # Ignore missing paths. | 178 # Ignore missing paths. |
176 path_list = [p for p in path_list if p] | 179 path_list = [p for p in path_list if p] |
177 prefix = os.path.commonprefix(path_list) | 180 prefix = os.path.commonprefix(path_list) |
178 # Put the path count as a subdirectory to allow for better grouping when | 181 # Put the path count as a subdirectory to allow for better grouping when |
179 # path-based breakdowns. | 182 # path-based breakdowns. |
180 if not prefix: | 183 if not prefix: |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 continue | 227 continue |
225 | 228 |
226 if symbol.object_path and symbol.object_path not in object_paths: | 229 if symbol.object_path and symbol.object_path not in object_paths: |
227 if num_path_mismatches < 10: | 230 if num_path_mismatches < 10: |
228 logging.warning('Symbol path reported by .map not found by nm.') | 231 logging.warning('Symbol path reported by .map not found by nm.') |
229 logging.warning('sym=%r', symbol) | 232 logging.warning('sym=%r', symbol) |
230 logging.warning('paths=%r', object_paths) | 233 logging.warning('paths=%r', object_paths) |
231 num_path_mismatches += 1 | 234 num_path_mismatches += 1 |
232 | 235 |
233 if source_mapper: | 236 if source_mapper: |
234 source_paths = [ | 237 tups = [ |
235 _SourcePathForObjectPath(p, source_mapper) for p in object_paths] | 238 _SourcePathForObjectPath(p, source_mapper) for p in object_paths] |
236 symbol.source_path = _ComputeAnscestorPath(source_paths) | 239 symbol.source_path = _ComputeAnscestorPath(t[1] for t in tups) |
| 240 symbol.generated_source = all(t[0] for t in tups) |
237 | 241 |
238 object_paths = [_NormalizeObjectPath(p) for p in object_paths] | 242 object_paths = [_NormalizeObjectPath(p) for p in object_paths] |
239 symbol.object_path = _ComputeAnscestorPath(object_paths) | 243 symbol.object_path = _ComputeAnscestorPath(object_paths) |
240 | 244 |
241 logging.debug('Cross-referenced %d symbols with nm output. ' | 245 logging.debug('Cross-referenced %d symbols with nm output. ' |
242 'num_unknown_names=%d num_path_mismatches=%d ' | 246 'num_unknown_names=%d num_path_mismatches=%d ' |
243 'num_unused_aliases=%d', num_found_paths, num_unknown_names, | 247 'num_unused_aliases=%d', num_found_paths, num_unknown_names, |
244 num_path_mismatches, num_unmatched_aliases) | 248 num_path_mismatches, num_unmatched_aliases) |
245 | 249 |
246 | 250 |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 logging.warning('Packed section not present: %s', packed_section_name) | 675 logging.warning('Packed section not present: %s', packed_section_name) |
672 else: | 676 else: |
673 size_info.section_sizes['%s (unpacked)' % packed_section_name] = ( | 677 size_info.section_sizes['%s (unpacked)' % packed_section_name] = ( |
674 unstripped_section_sizes.get(packed_section_name)) | 678 unstripped_section_sizes.get(packed_section_name)) |
675 | 679 |
676 logging.info('Recording metadata: \n %s', | 680 logging.info('Recording metadata: \n %s', |
677 '\n '.join(describe.DescribeMetadata(size_info.metadata))) | 681 '\n '.join(describe.DescribeMetadata(size_info.metadata))) |
678 logging.info('Saving result to %s', args.size_file) | 682 logging.info('Saving result to %s', args.size_file) |
679 file_format.SaveSizeInfo(size_info, args.size_file) | 683 file_format.SaveSizeInfo(size_info, args.size_file) |
680 logging.info('Done') | 684 logging.info('Done') |
OLD | NEW |