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 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
537 def _find_in_system_path(binary): | 537 def _find_in_system_path(binary): |
538 """Locate the full path to binary in the system path or return None | 538 """Locate the full path to binary in the system path or return None |
539 if not found.""" | 539 if not found.""" |
540 system_path = os.environ["PATH"].split(os.pathsep) | 540 system_path = os.environ["PATH"].split(os.pathsep) |
541 for path in system_path: | 541 for path in system_path: |
542 binary_path = os.path.join(path, binary) | 542 binary_path = os.path.join(path, binary) |
543 if os.path.isfile(binary_path): | 543 if os.path.isfile(binary_path): |
544 return binary_path | 544 return binary_path |
545 return None | 545 return None |
546 | 546 |
547 def CheckDebugFormatSupport(library, addr2line_binary, nm_binary): | |
548 """There are two common versions of the DWARF debug formats and | |
Primiano Tucci (use gerrit)
2014/05/27 09:40:10
Nit: docstring format (1 line + blank line + descr
Daniel Bratell
2014/06/04 13:31:02
Done.
| |
549 since we are right now transitioning from DWARF2 to newer formats, | |
550 it's possible to have a mix of tools that are not compatible. Detect | |
551 that and abort rather than produce meaningless output.""" | |
552 tool_output = subprocess.check_output([addr2line_binary, "--version"]) | |
553 version_re = re.compile(r"^GNU [^ ]+ .* (\d+).(\d+).*?$", re.M) | |
Primiano Tucci (use gerrit)
2014/05/27 09:40:10
Please be consistent with quotes (double vs single
Daniel Bratell
2014/06/04 13:31:02
Done.
| |
554 parsed_output = version_re.match(tool_output) | |
555 major = int(parsed_output.group(1)) | |
556 minor = int(parsed_output.group(2)) | |
557 supports_dwarf4 = major > 2 or major == 2 and minor > 22 | |
558 | |
559 if supports_dwarf4: | |
560 return | |
561 | |
562 print("Checking version of debug information in %s." % library) | |
563 debug_info = subprocess.check_output(["readelf", "--debug-dump=info", | |
564 "--dwarf-depth=1", library]) | |
565 dwarf_version_re = re.compile(r"^\s+Version:\s+(\d+)$", re.M) | |
566 parsed_dwarf_format_output = dwarf_version_re.search(debug_info) | |
567 version = int(parsed_dwarf_format_output.group(1)) | |
568 if version > 2: | |
569 print("""\ | |
Primiano Tucci (use gerrit)
2014/05/27 09:40:10
From code style:
Yes:
print ("This is much nice
Daniel Bratell
2014/06/04 13:31:02
Will fix, but the suggested format is really bad i
| |
570 The supplied tools only support DWARF2 debug data but the binary | |
571 uses DWARF%d. Update the tools or compile the binary with -gdwarf-2.""" % | |
572 version) | |
573 sys.exit(1) | |
574 | |
547 | 575 |
548 def main(): | 576 def main(): |
549 usage = """%prog [options] | 577 usage = """%prog [options] |
550 | 578 |
551 Runs a spatial analysis on a given library, looking up the source locations | 579 Runs a spatial analysis on a given library, looking up the source locations |
552 of its symbols and calculating how much space each directory, source file, | 580 of its symbols and calculating how much space each directory, source file, |
553 and so on is taking. The result is a report that can be used to pinpoint | 581 and so on is taking. The result is a report that can be used to pinpoint |
554 sources of large portions of the binary, etceteras. | 582 sources of large portions of the binary, etceteras. |
555 | 583 |
556 Under normal circumstances, you only need to pass two arguments, thusly: | 584 Under normal circumstances, you only need to pass two arguments, thusly: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
631 'Use --addr2line-binary to specify location.' | 659 'Use --addr2line-binary to specify location.' |
632 | 660 |
633 if opts.nm_binary: | 661 if opts.nm_binary: |
634 assert os.path.isfile(opts.nm_binary) | 662 assert os.path.isfile(opts.nm_binary) |
635 nm_binary = opts.nm_binary | 663 nm_binary = opts.nm_binary |
636 else: | 664 else: |
637 nm_binary = _find_in_system_path('nm') | 665 nm_binary = _find_in_system_path('nm') |
638 assert nm_binary, 'Unable to find nm in the path. Use --nm-binary '\ | 666 assert nm_binary, 'Unable to find nm in the path. Use --nm-binary '\ |
639 'to specify location.' | 667 'to specify location.' |
640 | 668 |
669 print('addr2line: %s' % addr2line_binary) | |
641 print('nm: %s' % nm_binary) | 670 print('nm: %s' % nm_binary) |
642 print('addr2line: %s' % addr2line_binary) | 671 |
672 CheckDebugFormatSupport(opts.library, addr2line_binary, nm_binary) | |
643 | 673 |
644 symbols = GetNmSymbols(opts.nm_in, opts.nm_out, opts.library, | 674 symbols = GetNmSymbols(opts.nm_in, opts.nm_out, opts.library, |
645 opts.jobs, opts.verbose is True, | 675 opts.jobs, opts.verbose is True, |
646 addr2line_binary, nm_binary) | 676 addr2line_binary, nm_binary) |
647 if not os.path.exists(opts.destdir): | 677 if not os.path.exists(opts.destdir): |
648 os.makedirs(opts.destdir, 0755) | 678 os.makedirs(opts.destdir, 0755) |
649 | 679 |
650 | 680 |
651 if opts.legacy: # legacy report | 681 if opts.legacy: # legacy report |
652 DumpTreemap(symbols, os.path.join(opts.destdir, 'treemap-dump.js')) | 682 DumpTreemap(symbols, os.path.join(opts.destdir, 'treemap-dump.js')) |
(...skipping 28 matching lines...) Expand all Loading... | |
681 print('Copying index.html') | 711 print('Copying index.html') |
682 shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir) | 712 shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir) |
683 shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir) | 713 shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir) |
684 | 714 |
685 if opts.verbose: | 715 if opts.verbose: |
686 print 'Report saved to ' + opts.destdir + '/index.html' | 716 print 'Report saved to ' + opts.destdir + '/index.html' |
687 | 717 |
688 | 718 |
689 if __name__ == '__main__': | 719 if __name__ == '__main__': |
690 sys.exit(main()) | 720 sys.exit(main()) |
OLD | NEW |