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

Side by Side Diff: tools/cygprofile/patch_orderfile.py

Issue 884113002: Refactor the symbol parsing, and move to NDK's nm. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Missing blank line. Created 5 years, 10 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
« no previous file with comments | « no previous file | tools/cygprofile/patch_orderfile_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright 2013 The Chromium Authors. All rights reserved. 2 # Copyright 2013 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 """Patch an orderfile. 6 """Patch an orderfile.
7 7
8 Starting with a list of symbols in a binary and an orderfile (ordered list of 8 Starting with a list of symbols in a binary and an orderfile (ordered list of
9 symbols), matches the symbols in the orderfile and augments each symbol with the 9 symbols), matches the symbols in the orderfile and augments each symbol with the
10 symbols residing at the same address (due to having identical code). 10 symbols residing at the same address (due to having identical code).
11 11
12 Note: It is possible to have. 12 Note: It is possible to have.
13 - Several symbols mapping to the same offset in the binary. 13 - Several symbols mapping to the same offset in the binary.
14 - Several offsets for a given symbol (because we strip the ".clone." suffix) 14 - Several offsets for a given symbol (because we strip the ".clone." suffix)
15 15
16 TODO(lizeb): Since the suffix ".clone." is only used with -O3 that we don't 16 TODO(lizeb): Since the suffix ".clone." is only used with -O3 that we don't
17 currently use, simplify the logic by removing the suffix handling. 17 currently use, simplify the logic by removing the suffix handling.
18 18
19 The general pipeline is: 19 The general pipeline is:
20 1. Get the symbol infos (offset, length, name) from the binary 20 1. Get the symbol infos (offset, length, name) from the binary
21 2. Get the symbol names from the orderfile 21 2. Get the symbol names from the orderfile
22 3. Find the orderfile symbol names in the symbols coming from the binary 22 3. Find the orderfile symbol names in the symbols coming from the binary
23 4. For each symbol found, get all the symbols at the same address 23 4. For each symbol found, get all the symbols at the same address
24 5. Output them to an updated orderfile, with several different prefixes 24 5. Output them to an updated orderfile, with several different prefixes
25 """ 25 """
26 26
27 import collections 27 import collections
28 import logging 28 import logging
29 import subprocess
30 import sys 29 import sys
31 30
31 import symbol_extractor
32
32 # Prefixes for the symbols. We strip them from the incoming symbols, and add 33 # Prefixes for the symbols. We strip them from the incoming symbols, and add
33 # them back in the output file. 34 # them back in the output file.
34 _PREFIXES = ('.text.startup.', '.text.hot.', '.text.unlikely.', '.text.') 35 _PREFIXES = ('.text.startup.', '.text.hot.', '.text.unlikely.', '.text.')
35 36
36 37
37 SymbolInfo = collections.namedtuple('SymbolInfo', ['offset', 'size', 'name'])
38
39
40 def _RemoveClone(name): 38 def _RemoveClone(name):
41 """Return name up to the ".clone." marker.""" 39 """Return name up to the ".clone." marker."""
42 clone_index = name.find('.clone.') 40 clone_index = name.find('.clone.')
43 if clone_index != -1: 41 if clone_index != -1:
44 return name[:clone_index] 42 return name[:clone_index]
45 return name 43 return name
46 44
47 45
48 def _GetSymbolInfosFromStream(nm_lines): 46 def _GroupSymbolInfos(symbol_infos):
49 """Parses the output of nm, and get all the symbols from a binary. 47 """Group the symbol infos by name and offset.
50 48
51 Args: 49 Args:
52 nm_lines: An iterable of lines 50 symbol_infos: an iterable of SymbolInfo
53 51
54 Returns: 52 Returns:
55 The same output as GetSymbolsFromBinary. 53 The same output as _GroupSymbolInfosFromBinary.
56 """ 54 """
57 # TODO(lizeb): Consider switching to objdump to simplify parsing.
58 symbol_infos = []
59 for line in nm_lines:
60 # We are interested in two types of lines:
61 # This:
62 # 00210d59 00000002 t _ZN34BrowserPluginHostMsg_Attach_ParamsD2Ev
63 # offset size <symbol_type> symbol_name
64 # And that:
65 # 0070ee8c T WebRtcSpl_ComplexBitReverse
66 # In the second case we don't have a size, so use -1 as a sentinel
67 parts = line.split()
68 if len(parts) == 4:
69 symbol_infos.append(SymbolInfo(
70 offset=int(parts[0], 16), size=int(parts[1], 16), name=parts[3]))
71 elif len(parts) == 3:
72 symbol_infos.append(SymbolInfo(
73 offset=int(parts[0], 16), size=-1, name=parts[2]))
74 # Map the addresses to symbols. 55 # Map the addresses to symbols.
75 offset_to_symbol_infos = collections.defaultdict(list) 56 offset_to_symbol_infos = collections.defaultdict(list)
76 name_to_symbol_infos = collections.defaultdict(list) 57 name_to_symbol_infos = collections.defaultdict(list)
77 for symbol in symbol_infos: 58 for symbol in symbol_infos:
78 symbol = SymbolInfo(symbol[0], symbol[1], _RemoveClone(symbol[2])) 59 symbol = symbol_extractor.SymbolInfo(name=_RemoveClone(symbol.name),
60 offset=symbol.offset,
61 size=symbol.size)
79 offset_to_symbol_infos[symbol.offset].append(symbol) 62 offset_to_symbol_infos[symbol.offset].append(symbol)
80 name_to_symbol_infos[symbol.name].append(symbol) 63 name_to_symbol_infos[symbol.name].append(symbol)
81 return (offset_to_symbol_infos, name_to_symbol_infos) 64 return (dict(offset_to_symbol_infos), dict(name_to_symbol_infos))
82 65
83 66
84 def _GetSymbolInfosFromBinary(binary_filename): 67 def _GroupSymbolInfosFromBinary(binary_filename):
85 """Runs nm to get all the symbols from a binary. 68 """Group all the symbols from a binary by name and offset.
86 69
87 Args: 70 Args:
88 binary_filename: path to the binary. 71 binary_filename: path to the binary.
89 72
90 Returns: 73 Returns:
91 A tuple of collection.defaultdict: 74 A tuple of dict:
92 (offset_to_symbol_infos, name_to_symbol_infos): 75 (offset_to_symbol_infos, name_to_symbol_infos):
93 - offset_to_symbol_infos: {offset: [symbol_info1, ...]} 76 - offset_to_symbol_infos: {offset: [symbol_info1, ...]}
94 - name_to_symbol_infos: {name: [symbol_info1, ...]} 77 - name_to_symbol_infos: {name: [symbol_info1, ...]}
95 """ 78 """
96 command = 'nm -S -n %s | egrep "( t )|( W )|( T )"' % binary_filename 79 symbol_infos = symbol_extractor.SymbolInfosFromBinary(binary_filename)
97 p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) 80 return _GroupSymbolInfos(symbol_infos)
98 try:
99 result = _GetSymbolInfosFromStream(p.stdout)
100 return result
101 finally:
102 p.wait()
103 81
104 82
105 def _StripPrefix(line): 83 def _StripPrefix(line):
106 """Get the symbol from a line with a linker section name. 84 """Get the symbol from a line with a linker section name.
107 85
108 Args: 86 Args:
109 line: a line from an orderfile, usually in the form: 87 line: a line from an orderfile, usually in the form:
110 .text.SymbolName 88 .text.SymbolName
111 89
112 Returns: 90 Returns:
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 output_file.write(linker_section + '\n') 201 output_file.write(linker_section + '\n')
224 unique_outputs.add(linker_section) 202 unique_outputs.add(linker_section)
225 203
226 204
227 def main(argv): 205 def main(argv):
228 if len(argv) != 3: 206 if len(argv) != 3:
229 print 'Usage: %s <unpatched_orderfile> <libchrome.so>' % argv[0] 207 print 'Usage: %s <unpatched_orderfile> <libchrome.so>' % argv[0]
230 return 1 208 return 1
231 orderfile_filename = argv[1] 209 orderfile_filename = argv[1]
232 binary_filename = argv[2] 210 binary_filename = argv[2]
233 (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( 211 (offset_to_symbol_infos, name_to_symbol_infos) = _GroupSymbolInfosFromBinary(
234 binary_filename) 212 binary_filename)
235 profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) 213 profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename)
236 expanded_symbols = _ExpandSymbols( 214 expanded_symbols = _ExpandSymbols(
237 profiled_symbols, name_to_symbol_infos, offset_to_symbol_infos) 215 profiled_symbols, name_to_symbol_infos, offset_to_symbol_infos)
238 _PrintSymbolsWithPrefixes(expanded_symbols, sys.stdout) 216 _PrintSymbolsWithPrefixes(expanded_symbols, sys.stdout)
239 # The following is needed otherwise Gold only applies a partial sort. 217 # The following is needed otherwise Gold only applies a partial sort.
240 print '.text' # gets methods not in a section, such as assembly 218 print '.text' # gets methods not in a section, such as assembly
241 print '.text.*' # gets everything else 219 print '.text.*' # gets everything else
242 return 0 220 return 0
243 221
244 222
245 if __name__ == '__main__': 223 if __name__ == '__main__':
246 logging.basicConfig(level=logging.INFO) 224 logging.basicConfig(level=logging.INFO)
247 sys.exit(main(sys.argv)) 225 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | tools/cygprofile/patch_orderfile_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698