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