OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 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 """Generate a spatial analysis against an arbitrary library. | 6 """Generate a spatial analysis against an arbitrary library. |
7 | 7 |
8 To use, build the 'binary_size_tool' target. Then run this tool, passing | 8 To use, build the 'binary_size_tool' target. Then run this tool, passing |
9 in the location of the library to be analyzed along with any other options | 9 in the location of the library to be analyzed along with any other options |
10 you desire. | 10 you desire. |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 else: | 448 else: |
449 speed = 0 | 449 speed = 0 |
450 progress_percent = (100.0 * (progress.count + progress.skip_count) / | 450 progress_percent = (100.0 * (progress.count + progress.skip_count) / |
451 nm_output_lines_len) | 451 nm_output_lines_len) |
452 print('%.1f%%: Looked up %d symbols (%d collisions) - %.1f lookups/s.' % | 452 print('%.1f%%: Looked up %d symbols (%d collisions) - %.1f lookups/s.' % |
453 (progress_percent, progress.count, progress.collisions, speed)) | 453 (progress_percent, progress.count, progress.collisions, speed)) |
454 | 454 |
455 symbolizer = elf_symbolizer.ELFSymbolizer(library, addr2line_binary, | 455 symbolizer = elf_symbolizer.ELFSymbolizer(library, addr2line_binary, |
456 map_address_symbol, | 456 map_address_symbol, |
457 max_concurrent_jobs=jobs) | 457 max_concurrent_jobs=jobs) |
458 for line in nm_output_lines: | 458 user_interrupted = False |
459 match = sNmPattern.match(line) | 459 try: |
460 if match: | 460 for line in nm_output_lines: |
461 location = match.group(5) | 461 match = sNmPattern.match(line) |
462 if not location: | 462 if match: |
463 addr = int(match.group(1), 16) | 463 location = match.group(5) |
464 size = int(match.group(2), 16) | 464 if not location: |
465 if addr in address_symbol: # Already looked up, shortcut ELFSymbolizer. | 465 addr = int(match.group(1), 16) |
466 map_address_symbol(address_symbol[addr], addr) | 466 size = int(match.group(2), 16) |
467 continue | 467 if addr in address_symbol: # Already looked up, shortcut |
468 elif size == 0: | 468 # ELFSymbolizer. |
469 # Save time by not looking up empty symbols (do they even exist?) | 469 map_address_symbol(address_symbol[addr], addr) |
470 print('Empty symbol: ' + line) | 470 continue |
471 else: | 471 elif size == 0: |
472 symbolizer.SymbolizeAsync(addr, addr) | 472 # Save time by not looking up empty symbols (do they even exist?) |
473 continue | 473 print('Empty symbol: ' + line) |
| 474 else: |
| 475 symbolizer.SymbolizeAsync(addr, addr) |
| 476 continue |
474 | 477 |
475 progress.skip_count += 1 | 478 progress.skip_count += 1 |
| 479 except KeyboardInterrupt: |
| 480 user_interrupted = True |
| 481 print('Interrupting - killing subprocesses. Please wait.') |
476 | 482 |
477 symbolizer.Join() | 483 try: |
| 484 symbolizer.Join() |
| 485 except KeyboardInterrupt: |
| 486 # Don't want to abort here since we will be finished in a few seconds. |
| 487 user_interrupted = True |
| 488 print('Patience you must have my young padawan.') |
| 489 |
| 490 if user_interrupted: |
| 491 print('Skipping the rest of the file mapping. ' |
| 492 'Output will not be fully classified.') |
478 | 493 |
479 with open(outfile, 'w') as out: | 494 with open(outfile, 'w') as out: |
480 for line in nm_output_lines: | 495 for line in nm_output_lines: |
481 match = sNmPattern.match(line) | 496 match = sNmPattern.match(line) |
482 if match: | 497 if match: |
483 location = match.group(5) | 498 location = match.group(5) |
484 if not location: | 499 if not location: |
485 addr = int(match.group(1), 16) | 500 addr = int(match.group(1), 16) |
486 symbol = address_symbol[addr] | 501 symbol = address_symbol.get(addr) |
487 path = '??' | 502 if symbol is not None: |
488 if symbol.source_path is not None: | 503 path = '??' |
489 path = symbol.source_path | 504 if symbol.source_path is not None: |
490 line_number = 0 | 505 path = symbol.source_path |
491 if symbol.source_line is not None: | 506 line_number = 0 |
492 line_number = symbol.source_line | 507 if symbol.source_line is not None: |
493 out.write('%s\t%s:%d\n' % (line, path, line_number)) | 508 line_number = symbol.source_line |
494 continue | 509 out.write('%s\t%s:%d\n' % (line, path, line_number)) |
| 510 continue |
495 | 511 |
496 out.write('%s\n' % line) | 512 out.write('%s\n' % line) |
497 | 513 |
498 print('%d symbols in the results.' % len(address_symbol)) | 514 print('%d symbols in the results.' % len(address_symbol)) |
499 | 515 |
500 | 516 |
501 def RunNm(binary, nm_binary): | 517 def RunNm(binary, nm_binary): |
502 print('Starting nm') | 518 print('Starting nm') |
503 cmd = [nm_binary, '-C', '--print-size', binary] | 519 cmd = [nm_binary, '-C', '--print-size', '--size-sort', '--reverse-sort', |
| 520 binary] |
504 nm_process = subprocess.Popen(cmd, | 521 nm_process = subprocess.Popen(cmd, |
505 stdout=subprocess.PIPE, | 522 stdout=subprocess.PIPE, |
506 stderr=subprocess.PIPE) | 523 stderr=subprocess.PIPE) |
507 (process_output, err_output) = nm_process.communicate() | 524 (process_output, err_output) = nm_process.communicate() |
508 | 525 |
509 if nm_process.returncode != 0: | 526 if nm_process.returncode != 0: |
510 if err_output: | 527 if err_output: |
511 raise Exception, err_output | 528 raise Exception, err_output |
512 else: | 529 else: |
513 raise Exception, process_output | 530 raise Exception, process_output |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 if not os.path.exists(d3_out): | 688 if not os.path.exists(d3_out): |
672 os.makedirs(d3_out, 0755) | 689 os.makedirs(d3_out, 0755) |
673 d3_src = os.path.join(os.path.dirname(__file__), | 690 d3_src = os.path.join(os.path.dirname(__file__), |
674 '..', | 691 '..', |
675 '..', | 692 '..', |
676 'third_party', 'd3', 'src') | 693 'third_party', 'd3', 'src') |
677 template_src = os.path.join(os.path.dirname(__file__), | 694 template_src = os.path.join(os.path.dirname(__file__), |
678 'template') | 695 'template') |
679 shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out) | 696 shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out) |
680 shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out) | 697 shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out) |
681 print('Copying index.html') | |
682 shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir) | 698 shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir) |
683 shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir) | 699 shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir) |
684 | 700 |
685 if opts.verbose: | 701 print 'Report saved to ' + opts.destdir + '/index.html' |
686 print 'Report saved to ' + opts.destdir + '/index.html' | |
687 | 702 |
688 | 703 |
689 if __name__ == '__main__': | 704 if __name__ == '__main__': |
690 sys.exit(main()) | 705 sys.exit(main()) |
OLD | NEW |