1#!/usr/bin/env vpython 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 4# found in the LICENSE file. 5 6from __future__ import print_function 7 8import collections 9import os 10import re 11import sys 12import unittest 13 14import cyglog_to_orderfile 15import symbol_extractor 16 17import test_utils 18from test_utils import SimpleTestSymbol 19 20 21sys.path.insert( 22 0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 23 'build', 'android')) 24 25import pylib.constants.host_paths as host_paths 26 27 28# Used for fake demangling on bots where c++filt does not exist. 29CTOR_PATTERN = re.compile(r'EEEC[12]Ev$') 30CTOR_REPLACEMENT = 'EEECEv' 31DTOR_PATTERN = re.compile(r'EEED[12]Ev$') 32DTOR_REPLACEMENT = 'EEEDEv' 33 34 35SectionTestSymbol = collections.namedtuple( 36 'SectionTestSymbol', ['name', 'section']) 37 38 39class TestObjectFileProcessor(cyglog_to_orderfile.ObjectFileProcessor): 40 def __init__(self, symbol_to_sections): 41 super(TestObjectFileProcessor, self).__init__(None) 42 self._symbol_to_sections_map = symbol_to_sections 43 44 45class TestCyglogToOrderfile(unittest.TestCase): 46 def setUp(self): 47 self._old_demangle = None 48 if not os.path.exists(host_paths.ToolPath('c++filt', 'arm')): 49 print('Using fake demangling due to missing c++filt binary') 50 self._old_demangle = symbol_extractor.DemangleSymbol 51 symbol_extractor.DemangleSymbol = _FakeDemangle 52 53 def tearDown(self): 54 if self._old_demangle is not None: 55 symbol_extractor.DemangleSymbol = self._old_demangle 56 57 def assertDictWithUnorderedListEqual(self, expected, observed): 58 unexpected = set() 59 missing = set() 60 for i in expected: 61 if i not in observed: 62 missing.add(i) 63 else: 64 try: 65 self.assertListEqual(sorted(expected[i]), sorted(observed[i])) 66 except self.failureException, e: 67 raise self.failureException('For key {}: {}'.format(i, e)) 68 for i in observed: 69 # All i that are in expected have already been tested. 70 if i not in expected: 71 unexpected.add(i) 72 failure_items = [] 73 if unexpected: 74 failure_items.append('Unexpected keys: {}'.format(' '.join(unexpected))) 75 if missing: 76 failure_items.append('Missing keys: {}'.format(' '.join(missing))) 77 if failure_items: 78 raise self.failureException('\n'.join(failure_items)) 79 80 def testWarnAboutDuplicates(self): 81 offsets = [0x1, 0x2, 0x3] 82 self.assertTrue(cyglog_to_orderfile._WarnAboutDuplicates(offsets)) 83 offsets.append(0x1) 84 self.assertFalse(cyglog_to_orderfile._WarnAboutDuplicates(offsets)) 85 86 def testSymbolsAtOffsetExactMatch(self): 87 symbol_infos = [SimpleTestSymbol('1', 0x10, 0x13)] 88 generator = cyglog_to_orderfile.OffsetOrderfileGenerator( 89 test_utils.TestSymbolOffsetProcessor(symbol_infos), None) 90 syms = generator._SymbolsAtOffset(0x10) 91 self.assertEquals(1, len(syms)) 92 self.assertEquals(symbol_infos[0], syms[0]) 93 94 def testSymbolsAtOffsetInexectMatch(self): 95 symbol_infos = [SimpleTestSymbol('1', 0x10, 0x13)] 96 generator = cyglog_to_orderfile.OffsetOrderfileGenerator( 97 test_utils.TestSymbolOffsetProcessor(symbol_infos), None) 98 syms = generator._SymbolsAtOffset(0x11) 99 self.assertEquals(1, len(syms)) 100 self.assertEquals(symbol_infos[0], syms[0]) 101 102 def testSameCtorOrDtorNames(self): 103 same_name = cyglog_to_orderfile.ObjectFileProcessor._SameCtorOrDtorNames 104 self.assertTrue(same_name( 105 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEEC1Ev', 106 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEEC2Ev')) 107 self.assertTrue(same_name( 108 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev', 109 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED2Ev')) 110 self.assertFalse(same_name( 111 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEEC1Ev', 112 '_ZNSt3__119foo_iteratorIcNS_11char_traitsIcEEEC1Ev')) 113 self.assertFalse(same_name( 114 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEE', 115 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEE')) 116 117 def testGetSymbolToSectionsMap(self): 118 processor = cyglog_to_orderfile.ObjectFileProcessor(None) 119 processor._GetAllSymbolInfos = lambda: [ 120 SectionTestSymbol('.LTHUNK.foobar', 'unused'), 121 SectionTestSymbol('_Znwj', '.text._Znwj'), 122 SectionTestSymbol( # Ctor/Dtor same name. 123 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev', 124 '.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev'), 125 SectionTestSymbol( 126 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev', 127 '.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED2Ev'), 128 SectionTestSymbol( # Ctor/Dtor different name. 129 '_ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev', 130 ('.text. _ZNSt3__119istreambuf2_iteratorIcNS_11char_' 131 'traitsIcEEEC1Ev')), 132 SectionTestSymbol( 133 '_ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev', 134 '.text._ZNSt3__119foo_iteratorIcNS_11char_traitsIcEEEC1Ev'), 135 SectionTestSymbol('_AssemblyFunction', '.text'), 136 SectionTestSymbol('_UnknownSection', '.surprise._UnknownSection'), 137 SectionTestSymbol('_Znwj', '.text._another_section_for_Znwj')] 138 self.assertDictWithUnorderedListEqual( 139 {'_Znwj': ['.text._Znwj', '.text._another_section_for_Znwj'], 140 # Ctor/Dtor same name. 141 '_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev': 142 ['.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev', 143 '.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED2Ev'], 144 # Ctor/Dtor different name; a warning is emitted but the sections are 145 # still added to the map. 146 '_ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev': 147 ['.text. _ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev', 148 '.text._ZNSt3__119foo_iteratorIcNS_11char_traitsIcEEEC1Ev'], 149 }, 150 processor.GetSymbolToSectionsMap()) 151 152 def testOutputOrderfile(self): 153 # One symbol not matched, one with an odd address, one regularly matched 154 # And two symbols aliased to the same address 155 symbols = [SimpleTestSymbol('Symbol', 0x10, 0x100), 156 SimpleTestSymbol('Symbol2', 0x12, 0x100), 157 SimpleTestSymbol('Symbol3', 0x16, 0x100), 158 SimpleTestSymbol('Symbol3.2', 0x16, 0x0)] 159 generator = cyglog_to_orderfile.OffsetOrderfileGenerator( 160 test_utils.TestSymbolOffsetProcessor(symbols), 161 TestObjectFileProcessor({ 162 'Symbol': ['.text.Symbol'], 163 'Symbol2': ['.text.Symbol2', '.text.hot.Symbol2'], 164 'Symbol3': ['.text.Symbol3'], 165 'Symbol3.2': ['.text.Symbol3.2']})) 166 ordered_sections = generator.GetOrderedSections([0x12, 0x17]) 167 self.assertListEqual( 168 ['.text.Symbol2', 169 '.text.hot.Symbol2', 170 '.text.Symbol3', 171 '.text.Symbol3.2'], 172 ordered_sections) 173 174 175def _FakeDemangle(mangled): 176 unmangled = CTOR_PATTERN.sub(CTOR_REPLACEMENT, mangled) 177 unmangled = DTOR_PATTERN.sub(DTOR_REPLACEMENT, unmangled) 178 return unmangled 179 180 181if __name__ == '__main__': 182 unittest.main() 183