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 |