From 558e29eef91e33896a37bef044c637e8d73cc036 Mon Sep 17 00:00:00 2001 From: azarchs Date: Fri, 23 Jan 2015 11:42:01 -0800 Subject: [PATCH] Keep all symbols from the profiled orderfile in the patched one. Do not discard symbols which aren't present in the uninstrumented build (for example if they were inlined). This should make the orderfile more robust against minor changes in compiler decisions. From local testing, I expect this to fix the out-of-order symbol error that is keeping the bot red. Review URL: https://codereview.chromium.org/871043002 Cr-Commit-Position: refs/heads/master@{#312899} --- tools/cygprofile/patch_orderfile.py | 71 +++++++++++--------- tools/cygprofile/patch_orderfile_unittest.py | 19 ++---- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/tools/cygprofile/patch_orderfile.py b/tools/cygprofile/patch_orderfile.py index 6c8bc431413e65..9f50b211a925f4 100755 --- a/tools/cygprofile/patch_orderfile.py +++ b/tools/cygprofile/patch_orderfile.py @@ -155,26 +155,53 @@ def _GetSymbolsFromOrderfile(filename): with open(filename, 'r') as f: return _GetSymbolsFromStream(f.xreadlines()) +def _SymbolsWithSameOffset(profiled_symbol, name_to_symbol_info, + offset_to_symbol_info): + """Expand a profiled symbol to include all symbols which share an offset + with that symbol. + Args: + profiled_symbol: the string symbol name to be expanded. + name_to_symbol_info: {name: [symbol_info1], ...}, as returned by + GetSymbolInfosFromBinary + offset_to_symbol_info: {offset: [symbol_info1, ...], ...} -def _MatchProfiledSymbols(profiled_symbols, name_to_symbol_infos): - """Filter name_to_symbol_infos with the keys from profiled_symbols. + Returns: + A list of symbol names, or an empty list if profiled_symbol was not in + name_to_symbol_info. + """ + if not profiled_symbol in name_to_symbol_info: + return [] + symbol_infos = name_to_symbol_info[profiled_symbol] + expanded = [] + for symbol_info in symbol_infos: + expanded += (s.name for s in offset_to_symbol_info[symbol_info.offset]) + return expanded + +def _ExpandSymbols(profiled_symbols, name_to_symbol_infos, + offset_to_symbol_infos): + """Expand all of the symbols in profiled_symbols to include any symbols which + share the same address. Args: profiled_symbols: Symbols to match - name_to_symbol_infos: {name: [symbol_infos], ...}, as returned by + name_to_symbol_infos: {name: [symbol_info1], ...}, as returned by GetSymbolInfosFromBinary + offset_to_symbol_infos: {offset: [symbol_info1, ...], ...} Returns: - A list of the symbol infos that have been matched. + A list of the symbol names. """ found_symbols = 0 missing_symbols = [] - symbol_infos = [] + all_symbols = [] for name in profiled_symbols: - if name in name_to_symbol_infos: - symbol_infos += name_to_symbol_infos[name] + expansion = _SymbolsWithSameOffset(name, + name_to_symbol_infos, offset_to_symbol_infos) + if expansion: found_symbols += 1 + all_symbols += expansion else: + all_symbols.append(name) missing_symbols.append(name) logging.info('symbols found: %d\n' % found_symbols) if missing_symbols > 0: @@ -183,27 +210,7 @@ def _MatchProfiledSymbols(profiled_symbols, name_to_symbol_infos): logging.warning('First %d missing symbols:\n%s' % ( missing_symbols_to_show, '\n'.join(missing_symbols[:missing_symbols_to_show]))) - return symbol_infos - - -def _ExpandSymbolsWithDupsFromSameOffset(symbol_infos, offset_to_symbol_infos): - """Return the SymbolInfo sharing the same offset as those from symbol_infos. - - Args: - symbol_infos: list of symbols to look for - offset_to_symbol_infos: {offset: [symbol_info1, ...], ...} - - Returns: - A list of matching symbol names - """ - seen_offsets = set() - matching_symbols = [] - for symbol in symbol_infos: - if symbol.offset not in seen_offsets: - seen_offsets.add(symbol.offset) - matching_symbols += [ - s.name for s in offset_to_symbol_infos[symbol.offset]] - return matching_symbols + return all_symbols def _PrintSymbolsWithPrefixes(symbol_names, output_file): @@ -226,11 +233,9 @@ def main(argv): (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( binary_filename) profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) - matched_symbols = _MatchProfiledSymbols( - profiled_symbols, name_to_symbol_infos) - symbols_by_offset = _ExpandSymbolsWithDupsFromSameOffset( - matched_symbols, offset_to_symbol_infos) - _PrintSymbolsWithPrefixes(symbols_by_offset, sys.stdout) + expanded_symbols = _ExpandSymbols( + profiled_symbols, name_to_symbol_infos, offset_to_symbol_infos) + _PrintSymbolsWithPrefixes(expanded_symbols, sys.stdout) # The following is needed otherwise Gold only applies a partial sort. print '.text' # gets methods not in a section, such as assembly print '.text.*' # gets everything else diff --git a/tools/cygprofile/patch_orderfile_unittest.py b/tools/cygprofile/patch_orderfile_unittest.py index 7066e2eebf729c..207ff57c37942e 100755 --- a/tools/cygprofile/patch_orderfile_unittest.py +++ b/tools/cygprofile/patch_orderfile_unittest.py @@ -78,28 +78,21 @@ def testGetSymbolsFromStream(self): names[1], "_ZN2v88internal33HEnvironmentLivenessAnalysisPhase3RunEv") - def testMatchProfiledSymbols(self): + def testExpandSymbols(self): symbol_name = "dummySymbol" + symbol_name2 = "other" profiled_symbol_names = [symbol_name, "symbolThatShouldntMatch"] name_to_symbol_infos = {symbol_name: [ patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name)]} - matched_symbols = patch_orderfile._MatchProfiledSymbols( - profiled_symbol_names, name_to_symbol_infos) - self.assertEquals(len(matched_symbols), 1) - self.assertEquals(matched_symbols[0], name_to_symbol_infos[symbol_name][0]) - - def testExpandSymbolsWithDupsFromSameOffset(self): - symbol_name = "dummySymbol" - symbol_name2 = "other" - symbols = [patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name)] offset_to_symbol_infos = { 0x42: [patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name), patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name2)]} - symbol_names = patch_orderfile._ExpandSymbolsWithDupsFromSameOffset( - symbols, offset_to_symbol_infos) - self.assertEquals(len(symbol_names), 2) + symbol_names = patch_orderfile._ExpandSymbols( + profiled_symbol_names, name_to_symbol_infos, offset_to_symbol_infos) + self.assertEquals(len(symbol_names), 3) self.assertEquals(symbol_names[0], symbol_name) self.assertEquals(symbol_names[1], symbol_name2) + self.assertEquals(symbol_names[2], "symbolThatShouldntMatch") def testPrintSymbolWithPrefixes(self): class FakeOutputFile(object):