Index: tools/cygprofile/symbol_extractor.py |
diff --git a/tools/cygprofile/symbol_extractor.py b/tools/cygprofile/symbol_extractor.py |
index 81c6e66d8fbca2805ba8b7c673d12eb18a3d8d14..dbd625b2979e9cdb0b7f6f8a272f112e544d291b 100755 |
--- a/tools/cygprofile/symbol_extractor.py |
+++ b/tools/cygprofile/symbol_extractor.py |
@@ -6,6 +6,7 @@ |
"""Utilities to get and manipulate symbols from a binary.""" |
import collections |
+import logging |
import os |
import re |
import subprocess |
@@ -17,6 +18,7 @@ sys.path.insert( |
'scripts')) |
import symbol |
+_MAX_WARNINGS_TO_PRINT = 200 |
SymbolInfo = collections.namedtuple('SymbolInfo', ('name', 'offset', 'size', |
'section')) |
@@ -106,6 +108,21 @@ def GroupSymbolInfosByOffset(symbol_infos): |
offset_to_symbol_infos[symbol_info.offset].append(symbol_info) |
return dict(offset_to_symbol_infos) |
+def GroupSymbolInfosByName(symbol_infos): |
+ """Create a dict {name: [symbol_info1, ...], ...}. |
+ |
+ A symbol can have several offsets, this is a 1-to-many relationship. |
+ |
+ Args: |
+ symbol_infos: iterable of SymbolInfo instances |
+ |
+ Returns: |
+ a dict {name: [symbol_info1, ...], ...} |
+ """ |
+ name_to_symbol_infos = collections.defaultdict(list) |
+ for symbol_info in symbol_infos: |
+ name_to_symbol_infos[symbol_info.name].append(symbol_info) |
+ return dict(name_to_symbol_infos) |
def CreateNameToSymbolInfo(symbol_infos): |
"""Create a dict {name: symbol_info, ...}. |
@@ -115,5 +132,23 @@ def CreateNameToSymbolInfo(symbol_infos): |
Returns: |
a dict {name: symbol_info, ...} |
+ If a symbol name corresponds to more than one symbol_info, the symbol_info |
+ with the lowest offset is chosen. |
""" |
- return {symbol_info.name: symbol_info for symbol_info in symbol_infos} |
+ #TODO(azarchs): move the functionality in this method into check_orderfile. |
+ symbol_infos_by_name = {} |
+ collision_count = 0 |
+ for infos in GroupSymbolInfosByName(symbol_infos).itervalues(): |
+ first_symbol_info = min(infos, key=lambda x:x.offset) |
+ symbol_infos_by_name[first_symbol_info.name] = first_symbol_info |
+ if len(infos) > 1: |
+ collision_count += 1 |
+ if collision_count <= _MAX_WARNINGS_TO_PRINT: |
+ logging.warning('Symbol %s appears at %d offsets: %s' % |
+ (first_symbol_info.name, |
+ len(infos), |
+ ','.join([hex(x.offset) for x in infos]))) |
+ if collision_count > _MAX_WARNINGS_TO_PRINT: |
+ logging.warning('%d symbols at multiple offsets. First %d shown.' % |
+ (collision_count, _MAX_WARNINGS_TO_PRINT)) |
+ return symbol_infos_by_name |