| 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 |