Chromium Code Reviews| 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 _StripPrefixes(line): | |
|
pasko
2015/01/22 17:37:14
it strips only one prefix, so maybe name it _Strip
azarchs
2015/01/22 17:44:30
Done.
| |
| 106 """Get the symbol from a line with a linker section name | |
|
pasko
2015/01/22 17:37:14
nit: full stop at the end of the sentence. (here a
azarchs
2015/01/22 17:44:30
Done.
| |
| 107 | |
| 108 Args: | |
| 109 line: a line from an orderfile, usually in the form | |
| 110 .text.SymbolName | |
|
pasko
2015/01/22 17:37:14
nit: 4 chars shift to the right
azarchs
2015/01/22 17:44:30
Done.
| |
| 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 | |
|
Benoit L
2015/01/22 16:49:53
nit: You can also use the
for prefix in _PREFIXES
azarchs
2015/01/22 17:10:12
Maybe it's because I'm used to C, C++, Java, C#, B
| |
| 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. |
| 107 | 124 |
| 108 Args: | 125 Args: |
| 109 lines: iterable of lines from an orderfile. | 126 lines: iterable of lines from an orderfile. |
| 110 | 127 |
| 111 Returns: | 128 Returns: |
| 112 Same as GetSymbolsFromOrderfile | 129 Same as GetSymbolsFromOrderfile |
| 113 """ | 130 """ |
| 114 # TODO(lizeb): Retain the prefixes later in the processing stages. | 131 # TODO(lizeb): Retain the prefixes later in the processing stages. |
| 115 symbols = [] | 132 symbols = [] |
| 133 unique_symbols = set() | |
| 116 for line in lines: | 134 for line in lines: |
| 117 line = line.rstrip('\n') | 135 line = _StripPrefixes(line) |
| 118 for prefix in _PREFIXES: | |
| 119 if line.startswith(prefix): | |
| 120 line = line[len(prefix):] | |
| 121 break | |
| 122 name = _RemoveClone(line) | 136 name = _RemoveClone(line) |
| 123 if name == '': | 137 if name == '' or name == '*' or name == '.text': |
|
pasko
2015/01/22 17:37:14
please enhance testGetSymbolsFromStream to verify
azarchs
2015/01/22 17:44:30
Done.
| |
| 124 continue | 138 continue |
| 125 symbols.append(line) | 139 if not line in unique_symbols: |
| 140 symbols.append(line) | |
| 141 unique_symbols.add(line) | |
| 126 return symbols | 142 return symbols |
| 127 | 143 |
| 128 | 144 |
| 129 def _GetSymbolsFromOrderfile(filename): | 145 def _GetSymbolsFromOrderfile(filename): |
| 130 """Return the symbols from an orderfile. | 146 """Return the symbols from an orderfile. |
| 131 | 147 |
| 132 Args: | 148 Args: |
| 133 filename: The name of the orderfile. | 149 filename: The name of the orderfile. |
| 134 | 150 |
| 135 Returns: | 151 Returns: |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 for symbol in symbol_infos: | 200 for symbol in symbol_infos: |
| 185 if symbol.offset not in seen_offsets: | 201 if symbol.offset not in seen_offsets: |
| 186 seen_offsets.add(symbol.offset) | 202 seen_offsets.add(symbol.offset) |
| 187 matching_symbols += [ | 203 matching_symbols += [ |
| 188 s.name for s in offset_to_symbol_infos[symbol.offset]] | 204 s.name for s in offset_to_symbol_infos[symbol.offset]] |
| 189 return matching_symbols | 205 return matching_symbols |
| 190 | 206 |
| 191 | 207 |
| 192 def _PrintSymbolsWithPrefixes(symbol_names, output_file): | 208 def _PrintSymbolsWithPrefixes(symbol_names, output_file): |
| 193 """For each symbol, outputs it to output_file with the prefixes.""" | 209 """For each symbol, outputs it to output_file with the prefixes.""" |
| 210 unique_outputs = set() | |
| 194 for name in symbol_names: | 211 for name in symbol_names: |
| 195 output_file.write('\n'.join(prefix + name for prefix in _PREFIXES) + '\n') | 212 for prefix in _PREFIXES: |
| 213 linker_section = prefix + name | |
| 214 if not linker_section in unique_outputs: | |
| 215 output_file.write(linker_section + '\n') | |
| 216 unique_outputs.add(linker_section) | |
| 196 | 217 |
| 197 | 218 |
| 198 def main(argv): | 219 def main(argv): |
| 199 if len(argv) != 3: | 220 if len(argv) != 3: |
| 200 print 'Usage: %s <unpatched_orderfile> <libchrome.so>' % argv[0] | 221 print 'Usage: %s <unpatched_orderfile> <libchrome.so>' % argv[0] |
| 201 return 1 | 222 return 1 |
| 202 orderfile_filename = argv[1] | 223 orderfile_filename = argv[1] |
| 203 binary_filename = argv[2] | 224 binary_filename = argv[2] |
| 204 (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( | 225 (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( |
| 205 binary_filename) | 226 binary_filename) |
| 206 profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) | 227 profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) |
| 207 matched_symbols = _MatchProfiledSymbols( | 228 matched_symbols = _MatchProfiledSymbols( |
| 208 profiled_symbols, name_to_symbol_infos) | 229 profiled_symbols, name_to_symbol_infos) |
| 209 symbols_by_offset = _ExpandSymbolsWithDupsFromSameOffset( | 230 symbols_by_offset = _ExpandSymbolsWithDupsFromSameOffset( |
| 210 matched_symbols, offset_to_symbol_infos) | 231 matched_symbols, offset_to_symbol_infos) |
| 211 _PrintSymbolsWithPrefixes(symbols_by_offset, sys.stdout) | 232 _PrintSymbolsWithPrefixes(symbols_by_offset, sys.stdout) |
| 212 # The following is needed otherwise Gold only applies a partial sort. | 233 # The following is needed otherwise Gold only applies a partial sort. |
| 213 print '.text' # gets methods not in a section, such as assembly | 234 print '.text' # gets methods not in a section, such as assembly |
| 214 print '.text.*' # gets everything else | 235 print '.text.*' # gets everything else |
| 215 return 0 | 236 return 0 |
| 216 | 237 |
| 217 | 238 |
| 218 if __name__ == '__main__': | 239 if __name__ == '__main__': |
| 219 logging.basicConfig(level=logging.INFO) | 240 logging.basicConfig(level=logging.INFO) |
| 220 sys.exit(main(sys.argv)) | 241 sys.exit(main(sys.argv)) |
| OLD | NEW |