blob: 60462c4813f8674321f731958f7c3900d447f9dd [file] [log] [blame]
#!/usr/bin/env vpython3
# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import print_function
import collections
import os
import re
import sys
import unittest
import cyglog_to_orderfile
import symbol_extractor
import test_utils
from test_utils import SimpleTestSymbol
# Used for fake demangling on bots where c++filt does not exist.
CTOR_PATTERN = re.compile(r'EEEC[12]Ev$')
CTOR_REPLACEMENT = 'EEECEv'
DTOR_PATTERN = re.compile(r'EEED[12]Ev$')
DTOR_REPLACEMENT = 'EEEDEv'
SectionTestSymbol = collections.namedtuple(
'SectionTestSymbol', ['name', 'section'])
class TestObjectFileProcessor(cyglog_to_orderfile.ObjectFileProcessor):
def __init__(self, symbol_to_sections):
super().__init__(None)
self._symbol_to_sections_map = symbol_to_sections
class TestCyglogToOrderfile(unittest.TestCase):
def setUp(self):
self._old_demangle = symbol_extractor.DemangleSymbol
symbol_extractor.DemangleSymbol = _FakeDemangle
def tearDown(self):
if self._old_demangle is not None:
symbol_extractor.DemangleSymbol = self._old_demangle
def assertDictWithUnorderedListEqual(self, expected, observed):
unexpected = set()
missing = set()
for i in expected:
if i not in observed:
missing.add(i)
else:
try:
self.assertListEqual(sorted(expected[i]), sorted(observed[i]))
except self.failureException as e:
raise self.failureException('For key {}: {}'.format(i, e))
for i in observed:
# All i that are in expected have already been tested.
if i not in expected:
unexpected.add(i)
failure_items = []
if unexpected:
failure_items.append('Unexpected keys: {}'.format(' '.join(unexpected)))
if missing:
failure_items.append('Missing keys: {}'.format(' '.join(missing)))
if failure_items:
raise self.failureException('\n'.join(failure_items))
def testWarnAboutDuplicates(self):
offsets = [0x1, 0x2, 0x3]
self.assertTrue(cyglog_to_orderfile._WarnAboutDuplicates(offsets))
offsets.append(0x1)
self.assertFalse(cyglog_to_orderfile._WarnAboutDuplicates(offsets))
def testSymbolsAtOffsetExactMatch(self):
symbol_infos = [SimpleTestSymbol('1', 0x10, 0x13)]
generator = cyglog_to_orderfile.OffsetOrderfileGenerator(
test_utils.TestSymbolOffsetProcessor(symbol_infos), None)
syms = generator._SymbolsAtOffset(0x10)
self.assertEquals(1, len(syms))
self.assertEquals(symbol_infos[0], syms[0])
def testSymbolsAtOffsetInexectMatch(self):
symbol_infos = [SimpleTestSymbol('1', 0x10, 0x13)]
generator = cyglog_to_orderfile.OffsetOrderfileGenerator(
test_utils.TestSymbolOffsetProcessor(symbol_infos), None)
syms = generator._SymbolsAtOffset(0x11)
self.assertEquals(1, len(syms))
self.assertEquals(symbol_infos[0], syms[0])
def testSameCtorOrDtorNames(self):
same_name = cyglog_to_orderfile.ObjectFileProcessor._SameCtorOrDtorNames
self.assertTrue(same_name(
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEEC1Ev',
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEEC2Ev'))
self.assertTrue(same_name(
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev',
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED2Ev'))
self.assertFalse(same_name(
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEEC1Ev',
'_ZNSt3__119foo_iteratorIcNS_11char_traitsIcEEEC1Ev'))
self.assertFalse(same_name(
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEE',
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEE'))
def testGetSymbolToSectionsMap(self):
processor = cyglog_to_orderfile.ObjectFileProcessor(None)
processor._GetAllSymbolInfos = lambda: [
SectionTestSymbol('.LTHUNK.foobar', 'unused'),
SectionTestSymbol('_Znwj', '.text._Znwj'),
SectionTestSymbol( # Ctor/Dtor same name.
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev',
'.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev'),
SectionTestSymbol(
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev',
'.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED2Ev'),
SectionTestSymbol( # Ctor/Dtor different name.
'_ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev',
('.text. _ZNSt3__119istreambuf2_iteratorIcNS_11char_'
'traitsIcEEEC1Ev')),
SectionTestSymbol(
'_ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev',
'.text._ZNSt3__119foo_iteratorIcNS_11char_traitsIcEEEC1Ev'),
SectionTestSymbol('_AssemblyFunction', '.text'),
SectionTestSymbol('_UnknownSection', '.surprise._UnknownSection'),
SectionTestSymbol('_Znwj', '.text._another_section_for_Znwj')]
self.assertDictWithUnorderedListEqual(
{'_Znwj': ['.text._Znwj', '.text._another_section_for_Znwj'],
# Ctor/Dtor same name.
'_ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev':
['.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED1Ev',
'.text._ZNSt3__119istreambuf_iteratorIcNS_11char_traitsIcEEED2Ev'],
# Ctor/Dtor different name; a warning is emitted but the sections are
# still added to the map.
'_ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev':
['.text. _ZNSt3__119istreambuf2_iteratorIcNS_11char_traitsIcEEEC1Ev',
'.text._ZNSt3__119foo_iteratorIcNS_11char_traitsIcEEEC1Ev'],
},
processor.GetSymbolToSectionsMap())
def testOutputOrderfile(self):
# One symbol not matched, one with an odd address, one regularly matched
# And two symbols aliased to the same address
symbols = [SimpleTestSymbol('Symbol', 0x10, 0x100),
SimpleTestSymbol('Symbol2', 0x12, 0x100),
SimpleTestSymbol('Symbol3', 0x16, 0x100),
SimpleTestSymbol('Symbol3.2', 0x16, 0x0)]
generator = cyglog_to_orderfile.OffsetOrderfileGenerator(
test_utils.TestSymbolOffsetProcessor(symbols),
TestObjectFileProcessor({
'Symbol': ['.text.Symbol'],
'Symbol2': ['.text.Symbol2', '.text.hot.Symbol2'],
'Symbol3': ['.text.Symbol3'],
'Symbol3.2': ['.text.Symbol3.2']}))
ordered_sections = generator.GetOrderedSections([0x12, 0x17])
self.assertListEqual(
['.text.Symbol2',
'.text.hot.Symbol2',
'.text.Symbol3',
'.text.Symbol3.2'],
ordered_sections)
def _FakeDemangle(mangled):
unmangled = CTOR_PATTERN.sub(CTOR_REPLACEMENT, mangled)
unmangled = DTOR_PATTERN.sub(DTOR_REPLACEMENT, unmangled)
return unmangled
if __name__ == '__main__':
unittest.main()