| OLD | NEW |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2017 The Chromium Authors. All rights reserved. | 1 # Copyright 2017 The Chromium Authors. All rights reserved. |
| 3 # 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 |
| 4 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 5 | 4 |
| 6 """Main Python API for analyzing binary size.""" | 5 """Main Python API for analyzing binary size.""" |
| 7 | 6 |
| 8 import argparse | 7 import argparse |
| 9 import calendar | 8 import calendar |
| 10 import collections | 9 import collections |
| 11 import datetime | 10 import datetime |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 with open(args_path) as f: | 392 with open(args_path) as f: |
| 394 for l in f: | 393 for l in f: |
| 395 # Strips #s even if within string literal. Not a problem in practice. | 394 # Strips #s even if within string literal. Not a problem in practice. |
| 396 parts = l.split('#')[0].split('=') | 395 parts = l.split('#')[0].split('=') |
| 397 if len(parts) != 2: | 396 if len(parts) != 2: |
| 398 continue | 397 continue |
| 399 args[parts[0].strip()] = parts[1].strip() | 398 args[parts[0].strip()] = parts[1].strip() |
| 400 return ["%s=%s" % x for x in sorted(args.iteritems())] | 399 return ["%s=%s" % x for x in sorted(args.iteritems())] |
| 401 | 400 |
| 402 | 401 |
| 403 def main(argv): | 402 def AddArguments(parser): |
| 404 parser = argparse.ArgumentParser(argv) | 403 parser.add_argument('size_file', help='Path to output .size file.') |
| 405 parser.add_argument('--elf-file', required=True, | 404 parser.add_argument('--elf-file', required=True, |
| 406 help='Path to input ELF file. Currently used for ' | 405 help='Path to input ELF file. Currently used for ' |
| 407 'capturing metadata. Pass "" to skip metadata ' | 406 'capturing metadata. Pass "" to skip ' |
| 408 'collection.') | 407 'metadata collection.') |
| 409 parser.add_argument('--map-file', | 408 parser.add_argument('--map-file', |
| 410 help='Path to input .map(.gz) file. Defaults to ' | 409 help='Path to input .map(.gz) file. Defaults to ' |
| 411 '{{elf_file}}.map(.gz)?') | 410 '{{elf_file}}.map(.gz)?') |
| 412 parser.add_argument('--output-file', required=True, | |
| 413 help='Path to output .size file.') | |
| 414 parser.add_argument('--no-source-paths', action='store_true', | 411 parser.add_argument('--no-source-paths', action='store_true', |
| 415 help='Do not use .ninja files to map ' | 412 help='Do not use .ninja files to map ' |
| 416 'object_path -> source_path') | 413 'object_path -> source_path') |
| 417 paths.AddOptions(parser) | 414 parser.add_argument('--tool-prefix', default='', |
| 418 args = helpers.AddCommonOptionsAndParseArgs(parser, argv) | 415 help='Path prefix for c++filt.') |
| 419 if not args.output_file.endswith('.size'): | 416 parser.add_argument('--output-directory', |
| 420 parser.error('output_file must end with .size') | 417 help='Path to the root build directory.') |
| 418 |
| 419 |
| 420 def Run(args, parser): |
| 421 if not args.size_file.endswith('.size'): |
| 422 parser.error('size_file must end with .size') |
| 421 | 423 |
| 422 if args.map_file: | 424 if args.map_file: |
| 423 if (not args.map_file.endswith('.map') | 425 if (not args.map_file.endswith('.map') |
| 424 and not args.map_file.endswith('.map.gz')): | 426 and not args.map_file.endswith('.map.gz')): |
| 425 parser.error('Expected --map-file to end with .map or .map.gz') | 427 parser.error('Expected --map-file to end with .map or .map.gz') |
| 426 map_file_path = args.map_file | 428 map_file_path = args.map_file |
| 427 else: | 429 else: |
| 428 map_file_path = args.elf_file + '.map' | 430 map_file_path = args.elf_file + '.map' |
| 429 if not os.path.exists(map_file_path): | 431 if not os.path.exists(map_file_path): |
| 430 map_file_path += '.gz' | 432 map_file_path += '.gz' |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 size_info.metadata = metadata | 464 size_info.metadata = metadata |
| 463 logging.debug('Validating section sizes') | 465 logging.debug('Validating section sizes') |
| 464 elf_section_sizes = _SectionSizesFromElf(args.elf_file, | 466 elf_section_sizes = _SectionSizesFromElf(args.elf_file, |
| 465 lazy_paths.tool_prefix) | 467 lazy_paths.tool_prefix) |
| 466 for k, v in elf_section_sizes.iteritems(): | 468 for k, v in elf_section_sizes.iteritems(): |
| 467 assert v == size_info.section_sizes.get(k), ( | 469 assert v == size_info.section_sizes.get(k), ( |
| 468 'ELF file and .map file do not match.') | 470 'ELF file and .map file do not match.') |
| 469 | 471 |
| 470 logging.info('Recording metadata: \n %s', | 472 logging.info('Recording metadata: \n %s', |
| 471 '\n '.join(describe.DescribeMetadata(size_info.metadata))) | 473 '\n '.join(describe.DescribeMetadata(size_info.metadata))) |
| 472 logging.info('Saving result to %s', args.output_file) | 474 logging.info('Saving result to %s', args.size_file) |
| 473 file_format.SaveSizeInfo(size_info, args.output_file) | 475 file_format.SaveSizeInfo(size_info, args.size_file) |
| 474 logging.info('Done') | 476 logging.info('Done') |
| 475 | |
| 476 | |
| 477 if __name__ == '__main__': | |
| 478 sys.exit(main(sys.argv)) | |
| OLD | NEW |