OLD | NEW |
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). |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 """ | 95 """ |
96 command = 'nm -S -n %s | egrep "( t )|( W )|( T )"' % binary_filename | 96 command = 'nm -S -n %s | egrep "( t )|( W )|( T )"' % binary_filename |
97 p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) | 97 p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) |
98 try: | 98 try: |
99 result = _GetSymbolInfosFromStream(p.stdout) | 99 result = _GetSymbolInfosFromStream(p.stdout) |
100 return result | 100 return result |
101 finally: | 101 finally: |
102 p.wait() | 102 p.wait() |
103 | 103 |
104 | 104 |
| 105 def _StripPrefix(line): |
| 106 """Get the symbol from a line with a linker section name. |
| 107 |
| 108 Args: |
| 109 line: a line from an orderfile, usually in the form: |
| 110 .text.SymbolName |
| 111 |
| 112 Returns: |
| 113 The symbol, SymbolName in the example above. |
| 114 """ |
| 115 line = line.rstrip('\n') |
| 116 for prefix in _PREFIXES: |
| 117 if line.startswith(prefix): |
| 118 return line[len(prefix):] |
| 119 return line # Unprefixed case |
| 120 |
| 121 |
105 def _GetSymbolsFromStream(lines): | 122 def _GetSymbolsFromStream(lines): |
106 """Get the symbols from an iterable of lines. | 123 """Get the symbols from an iterable of lines. |
| 124 Filters out wildcards and lines which do not correspond to symbols. |
107 | 125 |
108 Args: | 126 Args: |
109 lines: iterable of lines from an orderfile. | 127 lines: iterable of lines from an orderfile. |
110 | 128 |
111 Returns: | 129 Returns: |
112 Same as GetSymbolsFromOrderfile | 130 Same as GetSymbolsFromOrderfile |
113 """ | 131 """ |
114 # TODO(lizeb): Retain the prefixes later in the processing stages. | 132 # TODO(lizeb): Retain the prefixes later in the processing stages. |
115 symbols = [] | 133 symbols = [] |
| 134 unique_symbols = set() |
116 for line in lines: | 135 for line in lines: |
117 line = line.rstrip('\n') | 136 line = _StripPrefix(line) |
118 for prefix in _PREFIXES: | |
119 if line.startswith(prefix): | |
120 line = line[len(prefix):] | |
121 break | |
122 name = _RemoveClone(line) | 137 name = _RemoveClone(line) |
123 if name == '': | 138 if name == '' or name == '*' or name == '.text': |
124 continue | 139 continue |
125 symbols.append(line) | 140 if not line in unique_symbols: |
| 141 symbols.append(line) |
| 142 unique_symbols.add(line) |
126 return symbols | 143 return symbols |
127 | 144 |
128 | 145 |
129 def _GetSymbolsFromOrderfile(filename): | 146 def _GetSymbolsFromOrderfile(filename): |
130 """Return the symbols from an orderfile. | 147 """Return the symbols from an orderfile. |
131 | 148 |
132 Args: | 149 Args: |
133 filename: The name of the orderfile. | 150 filename: The name of the orderfile. |
134 | 151 |
135 Returns: | 152 Returns: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 for symbol in symbol_infos: | 201 for symbol in symbol_infos: |
185 if symbol.offset not in seen_offsets: | 202 if symbol.offset not in seen_offsets: |
186 seen_offsets.add(symbol.offset) | 203 seen_offsets.add(symbol.offset) |
187 matching_symbols += [ | 204 matching_symbols += [ |
188 s.name for s in offset_to_symbol_infos[symbol.offset]] | 205 s.name for s in offset_to_symbol_infos[symbol.offset]] |
189 return matching_symbols | 206 return matching_symbols |
190 | 207 |
191 | 208 |
192 def _PrintSymbolsWithPrefixes(symbol_names, output_file): | 209 def _PrintSymbolsWithPrefixes(symbol_names, output_file): |
193 """For each symbol, outputs it to output_file with the prefixes.""" | 210 """For each symbol, outputs it to output_file with the prefixes.""" |
| 211 unique_outputs = set() |
194 for name in symbol_names: | 212 for name in symbol_names: |
195 output_file.write('\n'.join(prefix + name for prefix in _PREFIXES) + '\n') | 213 for prefix in _PREFIXES: |
| 214 linker_section = prefix + name |
| 215 if not linker_section in unique_outputs: |
| 216 output_file.write(linker_section + '\n') |
| 217 unique_outputs.add(linker_section) |
196 | 218 |
197 | 219 |
198 def main(argv): | 220 def main(argv): |
199 if len(argv) != 3: | 221 if len(argv) != 3: |
200 print 'Usage: %s <unpatched_orderfile> <libchrome.so>' % argv[0] | 222 print 'Usage: %s <unpatched_orderfile> <libchrome.so>' % argv[0] |
201 return 1 | 223 return 1 |
202 orderfile_filename = argv[1] | 224 orderfile_filename = argv[1] |
203 binary_filename = argv[2] | 225 binary_filename = argv[2] |
204 (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( | 226 (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( |
205 binary_filename) | 227 binary_filename) |
206 profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) | 228 profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) |
207 matched_symbols = _MatchProfiledSymbols( | 229 matched_symbols = _MatchProfiledSymbols( |
208 profiled_symbols, name_to_symbol_infos) | 230 profiled_symbols, name_to_symbol_infos) |
209 symbols_by_offset = _ExpandSymbolsWithDupsFromSameOffset( | 231 symbols_by_offset = _ExpandSymbolsWithDupsFromSameOffset( |
210 matched_symbols, offset_to_symbol_infos) | 232 matched_symbols, offset_to_symbol_infos) |
211 _PrintSymbolsWithPrefixes(symbols_by_offset, sys.stdout) | 233 _PrintSymbolsWithPrefixes(symbols_by_offset, sys.stdout) |
212 # The following is needed otherwise Gold only applies a partial sort. | 234 # The following is needed otherwise Gold only applies a partial sort. |
213 print '.text' # gets methods not in a section, such as assembly | 235 print '.text' # gets methods not in a section, such as assembly |
214 print '.text.*' # gets everything else | 236 print '.text.*' # gets everything else |
215 return 0 | 237 return 0 |
216 | 238 |
217 | 239 |
218 if __name__ == '__main__': | 240 if __name__ == '__main__': |
219 logging.basicConfig(level=logging.INFO) | 241 logging.basicConfig(level=logging.INFO) |
220 sys.exit(main(sys.argv)) | 242 sys.exit(main(sys.argv)) |
OLD | NEW |