Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: tools/binary_size/query.py

Issue 2724253002: V1 of //tools/binary_size rewrite (Closed)
Patch Set: README tweaks, more cases for function parsing Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env python
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
4 # found in the LICENSE file.
5
6 """Tool for analyzing binary size of executables using nm or linker map files.
7
8 Map files can be created by passing "-Map Foo.map" to the linker. If a map file
9 is unavailable, this tool can also be pointed at an unstripped executable, but
10 the information does not seem to be as accurate in this case.
11
12 Inspired by SymbolSort for Windows:
13 https://github.com/adrianstone55/SymbolSort
14 """
15
16 import argparse
17 import code
18 import contextlib
19 import logging
20 import readline
21 import subprocess
22 import sys
23
24 import analyze
25 import helpers
26 import symbols
27
28
29 # Number of lines before using less for Print().
30 _THRESHOLD_FOR_PAGER = 30
31
32
33 @contextlib.contextmanager
34 def _LessPipe():
35 """Output to `less`. Yields the write function."""
36 try:
37 proc = subprocess.Popen(['less'], stdin=subprocess.PIPE, stdout=sys.stdout)
38 yield proc.stdin.write
39 proc.stdin.close()
40
41 proc.wait()
42 except IOError:
43 pass # Happens when less is quit before all data is written.
44 except KeyboardInterrupt:
45 pass # Assume used to break out of less.
46
47
48 def _PrintSymbolGroup(group, show_elided=True, use_pager=None):
49 """Prints out the given list of symbols.
50
51 Args:
52 show_elided: Whether to print out group.filtered_symbols.
53 """
54 by_size = group.Sorted()
55 # TODO(agrieve): Taking line-wrapping into account for groups vs. symbols
56 # would make sense here.
57 if use_pager is None:
58 count = sum(1 if s.IsGroup() else 2 for s in group)
59 if show_elided and group.filtered_symbols:
60 count += 1
61 use_pager = count > _THRESHOLD_FOR_PAGER
62
63 def write_to_func(write):
64 write('Showing {:,} results with total size: {:,} bytes\n'.format(
65 len(group), group.size))
66 for s in by_size:
67 if s.IsGroup():
68 write('{} {:<7,} {} ({})\n'.format(s.section, s.size, s.name, len(s)))
69 else:
70 template = '{}@0x{:<8x} {:<7} {}\n{:22}{}\n'
estevenson 2017/03/20 14:13:03 This might look a little nicer if the two lines we
agrieve 2017/03/20 19:58:09 Leaving as-is for now, because I'm sure we'll fidd
71 write(template.format(s.section, s.address, s.size,
72 s.path or '<no path>', '', s.name or '<no name>'))
73 if show_elided and group.filtered_symbols:
74 elided = group.Inverted()
75 write('* Filtered out {:,} symbols comprising {:<7,} bytes.\n'.format(
76 len(elided), elided.size))
77
78 if use_pager:
79 with _LessPipe() as write:
80 write_to_func(write)
81 else:
82 write_to_func(sys.stdout.write)
83
84
85 def main():
86 parser = argparse.ArgumentParser()
87 parser.add_argument('--query',
88 help='Print the result of the given snippet. Example: '
89 'all_syms.WhereInSection("d").WhereBiggerThan(100)')
90 analyze.AddOptions(parser)
91 helpers.AddCommonOptions(parser)
92 args = parser.parse_args()
93 helpers.HandleCommonOptions(args)
94
95 result = analyze.AnalyzeWithArgs(args)
96
97 variables = {
98 'Print': _PrintSymbolGroup,
99 'all_syms': result.symbol_group,
100 }
101
102 if args.query:
103 logging.info('Running query from command-line.')
104 eval_result = eval(args.query, locals=variables)
105 if isinstance(eval_result, symbols.SymbolGroup):
106 _PrintSymbolGroup(eval_result, show_elided=False, use_pager=False)
107 return
108
109 logging.info('Entering interactive console.')
110
111 print '*' * 80
112 print 'Entering interactive Python shell. Here is some inspiration:'
113 print
114 print '# Show two levels of .text, grouped by first two subdirectories'
115 print 'text_syms = all_syms.WhereInSection("t")'
116 print 'by_path = text_syms.GroupByPath(depth=2)'
117 print 'Print(by_path.WhereBiggerThan(1024, include_filtered=True))'
118 print
119 print '# Show all non-vtable generated symbols'
120 print 'Print(all_syms.WhereNameMatches(r"(?<!vtable)(?<!\[)\]$"))'
121 print
122 print '*' * 80
123 print
124 print 'locals:', variables.keys()
125 print 'method quick reference:', (
126 [m for m in dir(symbols.SymbolGroup) if m[0].isupper()])
127 print
128 print '*' * 80
129
130 # Without initializing readline, arrow keys don't even work!
131 readline.parse_and_bind('tab: complete')
132 code.InteractiveConsole(locals=variables).interact()
133
134
135 if __name__ == '__main__':
136 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698