OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 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 """Utilities to get and manipulate symbols from a binary.""" | 6 """Utilities to get and manipulate symbols from a binary.""" |
7 | 7 |
8 import collections | 8 import collections |
| 9 import logging |
9 import os | 10 import os |
10 import re | 11 import re |
11 import subprocess | 12 import subprocess |
12 import sys | 13 import sys |
13 | 14 |
14 sys.path.insert( | 15 sys.path.insert( |
15 0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, | 16 0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, |
16 'third_party', 'android_platform', 'development', | 17 'third_party', 'android_platform', 'development', |
17 'scripts')) | 18 'scripts')) |
18 import symbol | 19 import symbol |
19 | 20 |
| 21 _MAX_WARNINGS_TO_PRINT = 200 |
20 | 22 |
21 SymbolInfo = collections.namedtuple('SymbolInfo', ('name', 'offset', 'size', | 23 SymbolInfo = collections.namedtuple('SymbolInfo', ('name', 'offset', 'size', |
22 'section')) | 24 'section')) |
23 | 25 |
24 def SetArchitecture(arch): | 26 def SetArchitecture(arch): |
25 """Set the architecture for binaries to be symbolized.""" | 27 """Set the architecture for binaries to be symbolized.""" |
26 symbol.ARCH = arch | 28 symbol.ARCH = arch |
27 | 29 |
28 | 30 |
29 def _FromObjdumpLine(line): | 31 def _FromObjdumpLine(line): |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 symbol_infos: iterable of SymbolInfo instances | 101 symbol_infos: iterable of SymbolInfo instances |
100 | 102 |
101 Returns: | 103 Returns: |
102 a dict {offset: [symbol_info1, ...], ...} | 104 a dict {offset: [symbol_info1, ...], ...} |
103 """ | 105 """ |
104 offset_to_symbol_infos = collections.defaultdict(list) | 106 offset_to_symbol_infos = collections.defaultdict(list) |
105 for symbol_info in symbol_infos: | 107 for symbol_info in symbol_infos: |
106 offset_to_symbol_infos[symbol_info.offset].append(symbol_info) | 108 offset_to_symbol_infos[symbol_info.offset].append(symbol_info) |
107 return dict(offset_to_symbol_infos) | 109 return dict(offset_to_symbol_infos) |
108 | 110 |
| 111 def GroupSymbolInfosByName(symbol_infos): |
| 112 """Create a dict {name: [symbol_info1, ...], ...}. |
| 113 |
| 114 A symbol can have several offsets, this is a 1-to-many relationship. |
| 115 |
| 116 Args: |
| 117 symbol_infos: iterable of SymbolInfo instances |
| 118 |
| 119 Returns: |
| 120 a dict {name: [symbol_info1, ...], ...} |
| 121 """ |
| 122 name_to_symbol_infos = collections.defaultdict(list) |
| 123 for symbol_info in symbol_infos: |
| 124 name_to_symbol_infos[symbol_info.name].append(symbol_info) |
| 125 return dict(name_to_symbol_infos) |
109 | 126 |
110 def CreateNameToSymbolInfo(symbol_infos): | 127 def CreateNameToSymbolInfo(symbol_infos): |
111 """Create a dict {name: symbol_info, ...}. | 128 """Create a dict {name: symbol_info, ...}. |
112 | 129 |
113 Args: | 130 Args: |
114 symbol_infos: iterable of SymbolInfo instances | 131 symbol_infos: iterable of SymbolInfo instances |
115 | 132 |
116 Returns: | 133 Returns: |
117 a dict {name: symbol_info, ...} | 134 a dict {name: symbol_info, ...} |
| 135 If a symbol name corresponds to more than one symbol_info, the symbol_info |
| 136 with the lowest offset is chosen. |
118 """ | 137 """ |
119 return {symbol_info.name: symbol_info for symbol_info in symbol_infos} | 138 #TODO(azarchs): move the functionality in this method into check_orderfile. |
| 139 symbol_infos_by_name = {} |
| 140 collision_count = 0 |
| 141 for infos in GroupSymbolInfosByName(symbol_infos).itervalues(): |
| 142 first_symbol_info = min(infos, key=lambda x:x.offset) |
| 143 symbol_infos_by_name[first_symbol_info.name] = first_symbol_info |
| 144 if len(infos) > 1: |
| 145 collision_count += 1 |
| 146 if collision_count <= _MAX_WARNINGS_TO_PRINT: |
| 147 logging.warning('Symbol %s appears at %d offsets: %s' % |
| 148 (first_symbol_info.name, |
| 149 len(infos), |
| 150 ','.join([hex(x.offset) for x in infos]))) |
| 151 if collision_count > _MAX_WARNINGS_TO_PRINT: |
| 152 logging.warning('%d symbols at multiple offsets. First %d shown.' % |
| 153 (collision_count, _MAX_WARNINGS_TO_PRINT)) |
| 154 return symbol_infos_by_name |
OLD | NEW |