def testSectionMatchingRules(self): symbol_name1 = 'symbol1' symbol_name2 = 'symbol2' symbol_name3 = 'symbol3' section_name1 = '.text.' + symbol_name1 section_name3 = '.text.foo' suffixed = set([section_name3]) name_to_symbol_infos = {symbol_name1: [ symbol_extractor.SymbolInfo(symbol_name1, 0x42, 0x12, section='.text')]} offset_to_symbol_infos = { 0x42: [symbol_extractor.SymbolInfo(symbol_name1, 0x42, 0x12, section='.text'), symbol_extractor.SymbolInfo(symbol_name2, 0x42, 0x12, section='.text')]} section_to_symbols_map = {section_name1: [symbol_name1], section_name3: [symbol_name1, symbol_name3]} symbol_to_sections_map = {symbol_name1: [section_name1, section_name3], symbol_name3: [section_name3]} expected = [ section_name1, section_name3, section_name3 + '.*', '.text.startup.' + symbol_name1, '.text.hot.' + symbol_name1, '.text.unlikely.' + symbol_name1, '.text.startup.symbol2', '.text.hot.symbol2', '.text.unlikely.symbol2', '.text.symbol2'] self.assertEqual(expected, list(patch_orderfile._SectionMatchingRules( section_name1, name_to_symbol_infos, offset_to_symbol_infos, section_to_symbols_map, symbol_to_sections_map, suffixed)))
def testExpandSymbols(self): symbol_name = "dummySymbol" symbol_name2 = "other" profiled_symbol_names = [symbol_name, "symbolThatShouldntMatch"] name_to_symbol_infos = { symbol_name: [ symbol_extractor.SymbolInfo(symbol_name, 0x42, 0x12, section='.text') ] } offset_to_symbol_infos = { 0x42: [ symbol_extractor.SymbolInfo(symbol_name, 0x42, 0x12, section='.text'), symbol_extractor.SymbolInfo(symbol_name2, 0x42, 0x12, section='.text') ] } 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 testOutputOrderfile(self): class FakeOutputFile(object): def __init__(self): self.writes = [] def write(self, data): self.writes.append(data) # One symbol not matched, one with an odd address, one regularly matched # And two symbols aliased to the same address offsets = [0x12, 0x17] offset_to_symbol_infos = { 0x10: [symbol_extractor.SymbolInfo( name='Symbol', offset=0x10, size=0x13, section='dummy')], 0x12: [symbol_extractor.SymbolInfo( name='Symbol2', offset=0x12, size=0x13, section='dummy')], 0x16: [symbol_extractor.SymbolInfo( name='Symbol3', offset=0x16, size=0x13, section='dummy'), symbol_extractor.SymbolInfo( name='Symbol32', offset=0x16, size=0x13, section='dummy'),]} symbol_to_sections_map = { 'Symbol': ['.text.Symbol'], 'Symbol2': ['.text.Symbol2', '.text.hot.Symbol2'], 'Symbol3': ['.text.Symbol3'], 'Symbol32': ['.text.Symbol32']} fake_output = FakeOutputFile() cyglog_to_orderfile._OutputOrderfile( offsets, offset_to_symbol_infos, symbol_to_sections_map, fake_output) expected = """.text.Symbol2 .text.hot.Symbol2 .text.Symbol3 .text.Symbol32 """ self.assertEquals(expected, ''.join(fake_output.writes))
def testSymbolsWithSameOffset(self): symbol_name = "dummySymbol" symbol_name2 = "other" name_to_symbol_infos = { symbol_name: [ symbol_extractor.SymbolInfo(symbol_name, 0x42, 0x12, section='.text') ] } offset_to_symbol_infos = { 0x42: [ symbol_extractor.SymbolInfo(symbol_name, 0x42, 0x12, section='.text'), symbol_extractor.SymbolInfo(symbol_name2, 0x42, 0x12, section='.text') ] } symbol_names = patch_orderfile._SymbolsWithSameOffset( symbol_name, name_to_symbol_infos, offset_to_symbol_infos) self.assertEquals(len(symbol_names), 2) self.assertEquals(symbol_names[0], symbol_name) self.assertEquals(symbol_names[1], symbol_name2) self.assertEquals([], patch_orderfile._SymbolsWithSameOffset( "symbolThatShouldntMatch", name_to_symbol_infos, offset_to_symbol_infos))
def setUp(self): self.symbol_infos = [ symbol_extractor.SymbolInfo('firstNameAtOffset', 0x42, 42, '.text'), symbol_extractor.SymbolInfo('secondNameAtOffset', 0x42, 42, '.text'), symbol_extractor.SymbolInfo('thirdSymbol', 0x64, 20, '.text') ]
def testGroupSymbolsByOffset(self): symbol_infos = ( symbol_extractor.SymbolInfo(name='aSymbol', offset=0x42, size=0x12, section='.text'), symbol_extractor.SymbolInfo(name='anotherSymbol', offset=0x42, size=1, section='.text')) (offset_to_symbol_infos, _) = \ patch_orderfile._GroupSymbolInfos(symbol_infos) self.assertEquals(len(offset_to_symbol_infos), 1) self.assertEquals(tuple(offset_to_symbol_infos[0x42]), symbol_infos)
def testSymbolInfosFromStream(self): lines = [ 'Garbage', '', '00c1c05c l F .text 0000002c first', '' 'more garbage', '00155 g F .text 00000012 second' ] symbol_infos = symbol_extractor._SymbolInfosFromStream(lines) self.assertEquals(len(symbol_infos), 2) first = symbol_extractor.SymbolInfo('first', 0x00c1c05c, 0x2c, '.text') self.assertEquals(first, symbol_infos[0]) second = symbol_extractor.SymbolInfo('second', 0x00155, 0x12, '.text') self.assertEquals(second, symbol_infos[1])
def testAliasClonedSymbols(self): symbol_infos = [ symbol_extractor.SymbolInfo(name='aSymbol', offset=0x42, size=0x12, section='.text'), symbol_extractor.SymbolInfo(name='aSymbol.clone.', offset=8, size=1, section='.text')] (offset_to_symbol_infos, name_to_symbol_infos) = \ patch_orderfile._GroupSymbolInfos(symbol_infos) self.assertEquals(len(offset_to_symbol_infos), 2) for i in range(2): s = symbol_infos[i] matching = offset_to_symbol_infos[s.offset][0] self.assertEquals(matching.offset, s.offset) self.assertEquals(matching.size, s.size) self.assertEquals(len(name_to_symbol_infos), 1) self.assertEquals(len(name_to_symbol_infos['aSymbol']), 2)
class TestCheckOrderFile(unittest.TestCase): _SYMBOL_INFOS = [ symbol_extractor.SymbolInfo('first', 0x1, 0, ''), symbol_extractor.SymbolInfo('second', 0x2, 0, ''), symbol_extractor.SymbolInfo('notProfiled', 0x4, 0, ''), symbol_extractor.SymbolInfo('third', 0x3, 0, ''), ] def testVerifySymbolOrder(self): self.assertTrue( check_orderfile._VerifySymbolOrder( ['.second', 'first', 'eighth', 'third'], self._SYMBOL_INFOS, 0)) self.assertFalse( check_orderfile._VerifySymbolOrder( ['second', 'first', 'eighth', 'third'], self._SYMBOL_INFOS, 0)) self.assertTrue( check_orderfile._VerifySymbolOrder( ['second', 'first', 'eighth', 'third'], self._SYMBOL_INFOS, 1))
def testFindSymbolInfosAtOffsetNoMatch(self): offset_map = { 0x10: [ symbol_extractor.SymbolInfo(name='Symbol', offset=0x10, size=0x13, section='.text') ] } self.assertRaises(cyglog_to_orderfile.SymbolNotFoundException, cyglog_to_orderfile._FindSymbolInfosAtOffset, offset_map, 0x12)
def testFindSymbolInfosAtOffsetInexactMatch(self): offset_map = { 0x10: [ symbol_extractor.SymbolInfo(name='Symbol', offset=0x10, size=0x13, section='.text') ] } functions = cyglog_to_orderfile._FindSymbolInfosAtOffset( offset_map, 0x11) self.assertEquals(len(functions), 1) self.assertEquals(functions[0], offset_map[0x10][0])
def testSymbolCollisions(self): symbol_infos_with_collision = list(self.symbol_infos) symbol_infos_with_collision.append( symbol_extractor.SymbolInfo('secondNameAtOffset', 0x84, 42, '.text')) # The symbol added above should not affect the output. name_to_symbol_info = symbol_extractor.CreateNameToSymbolInfo( self.symbol_infos) self.assertEquals(len(name_to_symbol_info), 3) for i in range(3): name = self.symbol_infos[i].name self.assertIn(name, name_to_symbol_info) self.assertEquals(self.symbol_infos[i], name_to_symbol_info[name])
class TestCheckOrderFile(unittest.TestCase): _SYMBOL_INFOS = [ symbol_extractor.SymbolInfo('first', 0x1, 0, ''), symbol_extractor.SymbolInfo('second', 0x2, 0, ''), symbol_extractor.SymbolInfo('notProfiled', 0x4, 0, ''), symbol_extractor.SymbolInfo('third', 0x3, 0, ''), ] def testMatchesSymbols(self): symbols = ['first', 'second', 'third'] (misordered_pairs_count, matched_count, missing_count) = (check_orderfile._CountMisorderedSymbols( symbols, self._SYMBOL_INFOS)) self.assertEquals( (misordered_pairs_count, matched_count, missing_count), (0, 3, 0)) def testMissingMatches(self): symbols = ['second', 'third', 'other', 'first'] (_, matched_count, unmatched_count) = (check_orderfile._CountMisorderedSymbols( symbols, self._SYMBOL_INFOS)) self.assertEquals(matched_count, 3) self.assertEquals(unmatched_count, 1) def testNoUnorderedSymbols(self): symbols = ['first', 'other', 'second', 'third', 'noMatchEither'] (misordered_pairs_count, _, _) = (check_orderfile._CountMisorderedSymbols(symbols, self._SYMBOL_INFOS)) self.assertEquals(misordered_pairs_count, 0) def testUnorderedSymbols(self): symbols = ['first', 'other', 'third', 'second', 'noMatchEither'] (misordered_pairs_count, _, _) = (check_orderfile._CountMisorderedSymbols(symbols, self._SYMBOL_INFOS)) self.assertEquals(misordered_pairs_count, 1)
def _CountMisorderedSymbols(symbols, symbol_infos): """Count the number of misordered symbols, and log them. Args: symbols: ordered sequence of symbols from the orderfile symbol_infos: ordered list of SymbolInfo from the binary Returns: (misordered_pairs_count, matched_symbols_count, unmatched_symbols_count) """ name_to_symbol_info = symbol_extractor.CreateNameToSymbolInfo(symbol_infos) matched_symbol_infos = [] missing_count = 0 misordered_count = 0 # Find the SymbolInfo matching the orderfile symbols in the binary. for symbol in symbols: if symbol in name_to_symbol_info: matched_symbol_infos.append(name_to_symbol_info[symbol]) else: missing_count += 1 if missing_count < _MAX_WARNINGS_TO_PRINT: logging.warning( 'Symbol "%s" is in the orderfile, not in the binary' % symbol) logging.info( '%d matched symbols, %d un-matched (Only the first %d unmatched' ' symbols are shown)' % (len(matched_symbol_infos), missing_count, _MAX_WARNINGS_TO_PRINT)) # In the order of the orderfile, find all the symbols that are at an offset # smaller than their immediate predecessor, and record the pair. previous_symbol_info = symbol_extractor.SymbolInfo(name='', offset=-1, size=0, section='') for symbol_info in matched_symbol_infos: if symbol_info.offset < previous_symbol_info.offset and not ( _IsSameMethod(symbol_info.name, previous_symbol_info.name)): logging.warning('Misordered pair: %s - %s' % (str(previous_symbol_info), str(symbol_info))) misordered_count += 1 previous_symbol_info = symbol_info return (misordered_count, len(matched_symbol_infos), missing_count)
def _GroupSymbolInfos(symbol_infos): """Groups the symbol infos by name and offset. Args: symbol_infos: an iterable of SymbolInfo Returns: The same output as _GroupSymbolInfosFromBinary. """ # Map the addresses to symbols. offset_to_symbol_infos = collections.defaultdict(list) name_to_symbol_infos = collections.defaultdict(list) for symbol in symbol_infos: symbol = symbol_extractor.SymbolInfo(name=RemoveSuffixes(symbol.name), offset=symbol.offset, size=symbol.size, section=symbol.section) offset_to_symbol_infos[symbol.offset].append(symbol) name_to_symbol_infos[symbol.name].append(symbol) return (dict(offset_to_symbol_infos), dict(name_to_symbol_infos))