| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2017 The Chromium Authors. All rights reserved. | 2 # Copyright 2017 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 """Main Python API for analyzing binary size.""" | 6 """Main Python API for analyzing binary size.""" |
| 7 | 7 |
| 8 import argparse | 8 import argparse |
| 9 import calendar | 9 import calendar |
| 10 import datetime | 10 import datetime |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 args = [tool_prefix + 'readelf', '-S', '--wide', elf_path] | 282 args = [tool_prefix + 'readelf', '-S', '--wide', elf_path] |
| 283 stdout = subprocess.check_output(args) | 283 stdout = subprocess.check_output(args) |
| 284 section_sizes = {} | 284 section_sizes = {} |
| 285 # Matches [ 2] .hash HASH 00000000006681f0 0001f0 003154 04 A 3 0 8 | 285 # Matches [ 2] .hash HASH 00000000006681f0 0001f0 003154 04 A 3 0 8 |
| 286 for match in re.finditer(r'\[[\s\d]+\] (\..*)$', stdout, re.MULTILINE): | 286 for match in re.finditer(r'\[[\s\d]+\] (\..*)$', stdout, re.MULTILINE): |
| 287 items = match.group(1).split() | 287 items = match.group(1).split() |
| 288 section_sizes[items[0]] = int(items[4], 16) | 288 section_sizes[items[0]] = int(items[4], 16) |
| 289 return section_sizes | 289 return section_sizes |
| 290 | 290 |
| 291 | 291 |
| 292 def _ParseGnArgs(args_path): |
| 293 """Returns a list of normalized "key=value" strings.""" |
| 294 args = {} |
| 295 with open(args_path) as f: |
| 296 for l in f: |
| 297 # Strips #s even if within string literal. Not a problem in practice. |
| 298 parts = l.split('#')[0].split('=') |
| 299 if len(parts) != 2: |
| 300 continue |
| 301 args[parts[0].strip()] = parts[1].strip() |
| 302 return ["%s=%s" % x for x in sorted(args.iteritems())] |
| 303 |
| 304 |
| 292 def main(argv): | 305 def main(argv): |
| 293 parser = argparse.ArgumentParser(argv) | 306 parser = argparse.ArgumentParser(argv) |
| 294 parser.add_argument('elf_file', help='Path to input ELF file.') | 307 parser.add_argument('elf_file', help='Path to input ELF file.') |
| 295 parser.add_argument('output_file', help='Path to output .size(.gz) file.') | 308 parser.add_argument('output_file', help='Path to output .size(.gz) file.') |
| 296 parser.add_argument('--map-file', | 309 parser.add_argument('--map-file', |
| 297 help='Path to input .map(.gz) file. Defaults to ' | 310 help='Path to input .map(.gz) file. Defaults to ' |
| 298 '{{elf_file}}.map(.gz)?') | 311 '{{elf_file}}.map(.gz)?') |
| 299 paths.AddOptions(parser) | 312 paths.AddOptions(parser) |
| 300 args = helpers.AddCommonOptionsAndParseArgs(parser, argv) | 313 args = helpers.AddCommonOptionsAndParseArgs(parser, argv) |
| 301 if not args.output_file.endswith('.size'): | 314 if not args.output_file.endswith('.size'): |
| (...skipping 14 matching lines...) Expand all Loading... |
| 316 | 329 |
| 317 lazy_paths = paths.LazyPaths(args=args, input_file=args.elf_file) | 330 lazy_paths = paths.LazyPaths(args=args, input_file=args.elf_file) |
| 318 metadata = None | 331 metadata = None |
| 319 if args.elf_file and not args.elf_file.endswith('.size'): | 332 if args.elf_file and not args.elf_file.endswith('.size'): |
| 320 logging.debug('Constructing metadata') | 333 logging.debug('Constructing metadata') |
| 321 git_rev = _DetectGitRevision(os.path.dirname(args.elf_file)) | 334 git_rev = _DetectGitRevision(os.path.dirname(args.elf_file)) |
| 322 build_id = BuildIdFromElf(args.elf_file, lazy_paths.tool_prefix) | 335 build_id = BuildIdFromElf(args.elf_file, lazy_paths.tool_prefix) |
| 323 timestamp_obj = datetime.datetime.utcfromtimestamp(os.path.getmtime( | 336 timestamp_obj = datetime.datetime.utcfromtimestamp(os.path.getmtime( |
| 324 args.elf_file)) | 337 args.elf_file)) |
| 325 timestamp = calendar.timegm(timestamp_obj.timetuple()) | 338 timestamp = calendar.timegm(timestamp_obj.timetuple()) |
| 339 gn_args = _ParseGnArgs(os.path.join(lazy_paths.output_directory, 'args.gn')) |
| 326 | 340 |
| 327 def relative_to_out(path): | 341 def relative_to_out(path): |
| 328 return os.path.relpath(path, lazy_paths.VerifyOutputDirectory()) | 342 return os.path.relpath(path, lazy_paths.VerifyOutputDirectory()) |
| 329 | 343 |
| 330 metadata = { | 344 metadata = { |
| 331 models.METADATA_GIT_REVISION: git_rev, | 345 models.METADATA_GIT_REVISION: git_rev, |
| 332 models.METADATA_MAP_FILENAME: relative_to_out(map_file_path), | 346 models.METADATA_MAP_FILENAME: relative_to_out(map_file_path), |
| 333 models.METADATA_ELF_FILENAME: relative_to_out(args.elf_file), | 347 models.METADATA_ELF_FILENAME: relative_to_out(args.elf_file), |
| 334 models.METADATA_ELF_MTIME: timestamp, | 348 models.METADATA_ELF_MTIME: timestamp, |
| 335 models.METADATA_ELF_BUILD_ID: build_id, | 349 models.METADATA_ELF_BUILD_ID: build_id, |
| 350 models.METADATA_GN_ARGS: gn_args, |
| 336 } | 351 } |
| 337 | 352 |
| 338 size_info = Analyze(map_file_path, lazy_paths) | 353 size_info = Analyze(map_file_path, lazy_paths) |
| 339 | 354 |
| 340 if metadata: | 355 if metadata: |
| 341 logging.debug('Validating section sizes') | 356 logging.debug('Validating section sizes') |
| 342 elf_section_sizes = _SectionSizesFromElf(args.elf_file, | 357 elf_section_sizes = _SectionSizesFromElf(args.elf_file, |
| 343 lazy_paths.tool_prefix) | 358 lazy_paths.tool_prefix) |
| 344 for k, v in elf_section_sizes.iteritems(): | 359 for k, v in elf_section_sizes.iteritems(): |
| 345 assert v == size_info.section_sizes.get(k), ( | 360 assert v == size_info.section_sizes.get(k), ( |
| 346 'ELF file and .map file do not match.') | 361 'ELF file and .map file do not match.') |
| 347 | 362 |
| 348 size_info.metadata = metadata | 363 size_info.metadata = metadata |
| 349 | 364 |
| 350 logging.info('Recording metadata: %s', | 365 logging.info('Recording metadata: \n %s', |
| 351 describe.DescribeSizeInfoMetadata(size_info)) | 366 '\n '.join(describe.DescribeMetadata(size_info.metadata))) |
| 352 logging.info('Saving result to %s', args.output_file) | 367 logging.info('Saving result to %s', args.output_file) |
| 353 file_format.SaveSizeInfo(size_info, args.output_file) | 368 file_format.SaveSizeInfo(size_info, args.output_file) |
| 354 logging.info('Done') | 369 logging.info('Done') |
| 355 | 370 |
| 356 | 371 |
| 357 if __name__ == '__main__': | 372 if __name__ == '__main__': |
| 358 sys.exit(main(sys.argv)) | 373 sys.exit(main(sys.argv)) |
| OLD | NEW |