Beispiel #1
0
        def check(ret_part,
                  name_part,
                  params_part,
                  after_part='',
                  name_without_templates=None):
            if name_without_templates is None:
                name_without_templates = re.sub(r'<.*?>', '<>',
                                                name_part) + after_part

            signature = ''.join((name_part, params_part, after_part))
            got_full_name, got_template_name, got_name = (
                function_signature.Parse(signature))
            self.assertEqual(name_without_templates, got_name)
            self.assertEqual(name_part + after_part, got_template_name)
            self.assertEqual(name_part + params_part + after_part,
                             got_full_name)
            if ret_part:
                signature = ''.join(
                    (ret_part, name_part, params_part, after_part))
                got_full_name, got_template_name, got_name = (
                    function_signature.Parse(signature))
                self.assertEqual(name_without_templates, got_name)
                self.assertEqual(name_part + after_part, got_template_name)
                self.assertEqual(name_part + params_part + after_part,
                                 got_full_name)
 def check(ret_part, name_part, params_part, after_part=''):
     signature = ''.join((name_part, params_part, after_part))
     got_full, got_name = function_signature.Parse(signature)
     self.assertEqual(name_part + after_part, got_name)
     self.assertEqual(name_part + params_part + after_part, got_full)
     if ret_part:
         signature = ''.join(
             (ret_part, name_part, params_part, after_part))
         got_full, got_name = function_signature.Parse(signature)
         self.assertEqual(name_part + after_part, got_name)
         self.assertEqual(name_part + params_part + after_part,
                          got_full)
Beispiel #3
0
def _NormalizeNames(symbol_group):
    """Ensures that all names are formatted in a useful way.

  This includes:
    - Assigning of |full_name|.
    - Stripping of return types in |full_name| and |name| (for functions).
    - Stripping parameters from |name|.
    - Moving "vtable for" and the like to be suffixes rather than prefixes.
  """
    found_prefixes = set()
    for symbol in symbol_group:
        if symbol.name.startswith('*'):
            # See comment in _RemoveDuplicatesAndCalculatePadding() about when this
            # can happen.
            continue

        # E.g.: vtable for FOO
        idx = symbol.name.find(' for ', 0, 30)
        if idx != -1:
            found_prefixes.add(symbol.name[:idx + 4])
            symbol.name = symbol.name[idx +
                                      5:] + ' [' + symbol.name[:idx] + ']'

        # E.g.: virtual thunk to FOO
        idx = symbol.name.find(' to ', 0, 30)
        if idx != -1:
            found_prefixes.add(symbol.name[:idx + 3])
            symbol.name = symbol.name[idx +
                                      4:] + ' [' + symbol.name[:idx] + ']'

        # Strip out return type, and identify where parameter list starts.
        if symbol.section == 't':
            symbol.full_name, symbol.name = function_signature.Parse(
                symbol.name)

        # Remove anonymous namespaces (they just harm clustering).
        non_anonymous = symbol.name.replace('(anonymous namespace)::', '')
        if symbol.name != non_anonymous:
            symbol.is_anonymous = True
            symbol.name = non_anonymous
            symbol.full_name = symbol.full_name.replace(
                '(anonymous namespace)::', '')

        if symbol.section != 't' and '(' in symbol.name:
            # Pretty rare. Example:
            # blink::CSSValueKeywordsHash::findValueImpl(char const*)::value_word_list
            symbol.full_name = symbol.name
            symbol.name = re.sub(r'\(.*\)', '', symbol.full_name)

        # Don't bother storing both if they are the same.
        if symbol.full_name == symbol.name:
            symbol.full_name = ''

    logging.debug('Found name prefixes of: %r', found_prefixes)
Beispiel #4
0
    def testParseFunctionSignature(self):
        def check(ret_part,
                  name_part,
                  params_part,
                  after_part='',
                  name_without_templates=None):
            if name_without_templates is None:
                name_without_templates = re.sub(r'<.*?>', '<>',
                                                name_part) + after_part

            signature = ''.join((name_part, params_part, after_part))
            got_full_name, got_template_name, got_name = (
                function_signature.Parse(signature))
            self.assertEqual(name_without_templates, got_name)
            self.assertEqual(name_part + after_part, got_template_name)
            self.assertEqual(name_part + params_part + after_part,
                             got_full_name)
            if ret_part:
                signature = ''.join(
                    (ret_part, name_part, params_part, after_part))
                got_full_name, got_template_name, got_name = (
                    function_signature.Parse(signature))
                self.assertEqual(name_without_templates, got_name)
                self.assertEqual(name_part + after_part, got_template_name)
                self.assertEqual(name_part + params_part + after_part,
                                 got_full_name)

        check('bool ', 'foo::Bar<unsigned int, int>::Do<unsigned int>',
              '(unsigned int)')
        check('base::internal::CheckedNumeric<int>& ',
              'base::internal::CheckedNumeric<int>::operator+=<int>', '(int)')
        check('base::internal::CheckedNumeric<int>& ',
              'b::i::CheckedNumeric<int>::MathOp<b::i::CheckedAddOp, int>',
              '(int)')
        check('', '(anonymous namespace)::GetBridge', '(long long)')
        check('', 'operator delete', '(void*)')
        check(
            '', 'b::i::DstRangeRelationToSrcRangeImpl<long long, long long, '
            'std::__ndk1::numeric_limits, (b::i::Integer)1>::Check',
            '(long long)')
        check('',
              'cc::LayerIterator::operator cc::LayerIteratorPosition const',
              '()', ' const')
        check('decltype ({parm#1}((SkRecords::NoOp)())) ',
              'SkRecord::Record::visit<SkRecords::Draw&>',
              '(SkRecords::Draw&)', ' const')
        check('', 'base::internal::BindStateBase::BindStateBase',
              '(void (*)(), void (*)(base::internal::BindStateBase const*))')
        check('int ', 'std::__ndk1::__c11_atomic_load<int>',
              '(std::__ndk1::<int> volatile*, std::__ndk1::memory_order)')
        check('std::basic_ostream<char, std::char_traits<char> >& ',
              'std::operator<< <std::char_traits<char> >',
              '(std::basic_ostream<char, std::char_traits<char> >&, char)',
              name_without_templates='std::operator<< <>')
        check('', 'std::basic_istream<char, std::char_traits<char> >'
              '::operator>>',
              '(unsigned int&)',
              name_without_templates='std::basic_istream<>::operator>>')
        check('',
              'std::operator><std::allocator<char> >',
              '()',
              name_without_templates='std::operator><>')
        check('',
              'std::operator>><std::allocator<char> >',
              '(std::basic_istream<char, std::char_traits<char> >&)',
              name_without_templates='std::operator>><>')
        check('',
              'std::basic_istream<char>::operator>',
              '(unsigned int&)',
              name_without_templates='std::basic_istream<>::operator>')
        check(
            'v8::internal::SlotCallbackResult ',
            'v8::internal::UpdateTypedSlotHelper::UpdateCodeTarget'
            '<v8::PointerUpdateJobTraits<(v8::Direction)1>::Foo(v8::Heap*, '
            'v8::MemoryChunk*)::{lambda(v8::SlotType, unsigned char*)#2}::'
            'operator()(v8::SlotType, unsigned char*, unsigned char*) '
            'const::{lambda(v8::Object**)#1}>',
            '(v8::RelocInfo, v8::Foo<(v8::PointerDirection)1>::Bar(v8::Heap*)::'
            '{lambda(v8::SlotType)#2}::operator()(v8::SlotType) const::'
            '{lambda(v8::Object**)#1})',
            name_without_templates=(
                'v8::internal::UpdateTypedSlotHelper::UpdateCodeTarget<>'))
        check(
            '',
            'WTF::StringAppend<WTF::String, WTF::String>::operator WTF::String',
            '()', ' const')
        # Make sure []s are not removed from the name part.
        check('', 'Foo', '()', ' [virtual thunk]')
        # Template function that accepts an anonymous lambda.
        check(
            '',
            'blink::FrameView::ForAllNonThrottledFrameViews<blink::FrameView::Pre'
            'Paint()::{lambda(FrameView&)#2}>',
            '(blink::FrameView::PrePaint()::{lambda(FrameView&)#2} const&)',
            '')

        # Test with multiple template args.
        check('int ',
              'Foo<int()>::bar<a<b> >',
              '()',
              name_without_templates='Foo<>::bar<>')

        # SkArithmeticImageFilter.cpp has class within function body. e.g.:
        #   ArithmeticFP::onCreateGLSLInstance() looks like:
        # class ArithmeticFP {
        #   GrGLSLFragmentProcessor* onCreateGLSLInstance() const {
        #     class GLSLFP {
        #       void emitCode(EmitArgs& args) { ... }
        #     };
        #     ...
        #   }
        # };
        SIG = '(anonymous namespace)::Foo::Baz() const::GLSLFP::onData(Foo, Bar)'
        got_full_name, got_template_name, got_name = (
            function_signature.Parse(SIG))
        self.assertEqual('(anonymous namespace)::Foo::Baz', got_name)
        self.assertEqual('(anonymous namespace)::Foo::Baz', got_template_name)
        self.assertEqual(SIG, got_full_name)

        # Top-level lambda.
        # Note: Inline lambdas do not seem to be broken into their own symbols.
        SIG = 'cc::{lambda(cc::PaintOp*)#63}::_FUN(cc::PaintOp*)'
        got_full_name, got_template_name, got_name = (
            function_signature.Parse(SIG))
        self.assertEqual('cc::$lambda#63', got_name)
        self.assertEqual('cc::$lambda#63', got_template_name)
        self.assertEqual('cc::$lambda#63(cc::PaintOp*)', got_full_name)

        SIG = 'cc::$_63::__invoke(cc::PaintOp*)'
        got_full_name, got_template_name, got_name = (
            function_signature.Parse(SIG))
        self.assertEqual('cc::$lambda#63', got_name)
        self.assertEqual('cc::$lambda#63', got_template_name)
        self.assertEqual('cc::$lambda#63(cc::PaintOp*)', got_full_name)

        # Data members
        check('', 'blink::CSSValueKeywordsHash::findValueImpl',
              '(char const*)', '::value_word_list')
        check('',
              'foo::Bar<Z<Y> >::foo<bar>',
              '(abc)',
              '::var<baz>',
              name_without_templates='foo::Bar<>::foo<>::var<>')
    def testParseFunctionSignature(self):
        def check(ret_part, name_part, params_part, after_part=''):
            signature = ''.join((name_part, params_part, after_part))
            got_full, got_name = function_signature.Parse(signature)
            self.assertEqual(name_part + after_part, got_name)
            self.assertEqual(name_part + params_part + after_part, got_full)
            if ret_part:
                signature = ''.join(
                    (ret_part, name_part, params_part, after_part))
                got_full, got_name = function_signature.Parse(signature)
                self.assertEqual(name_part + after_part, got_name)
                self.assertEqual(name_part + params_part + after_part,
                                 got_full)

        check('bool ', 'foo::Bar<unsigned int, int>::Do<unsigned int>',
              '(unsigned int)')
        check('base::internal::CheckedNumeric<int>& ',
              'base::internal::CheckedNumeric<int>::operator+=<int>', '(int)')
        check('base::internal::CheckedNumeric<int>& ',
              'b::i::CheckedNumeric<int>::MathOp<b::i::CheckedAddOp, int>',
              '(int)')
        check('', '(anonymous namespace)::GetBridge', '(long long)')
        check('', 'operator delete', '(void*)')
        check(
            '', 'b::i::DstRangeRelationToSrcRangeImpl<long long, long long, '
            'std::__ndk1::numeric_limits, (b::i::Integer)1>::Check',
            '(long long)')
        check('',
              'cc::LayerIterator::operator cc::LayerIteratorPosition const',
              '()', ' const')
        check('decltype ({parm#1}((SkRecords::NoOp)())) ',
              'SkRecord::Record::visit<SkRecords::Draw&>',
              '(SkRecords::Draw&)', ' const')
        check('', 'base::internal::BindStateBase::BindStateBase',
              '(void (*)(), void (*)(base::internal::BindStateBase const*))')
        check('int ', 'std::__ndk1::__c11_atomic_load<int>',
              '(std::__ndk1::<int> volatile*, std::__ndk1::memory_order)')
        check('std::basic_ostream<char, std::char_traits<char> >& ',
              'std::operator<< <std::char_traits<char> >',
              '(std::basic_ostream<char, std::char_traits<char> >&, char)')
        check(
            'v8::internal::SlotCallbackResult ',
            'v8::internal::UpdateTypedSlotHelper::UpdateCodeTarget'
            '<v8::PointerUpdateJobTraits<(v8::Direction)1>::Foo(v8::Heap*, '
            'v8::MemoryChunk*)::{lambda(v8::SlotType, unsigned char*)#2}::'
            'operator()(v8::SlotType, unsigned char*, unsigned char*) '
            'const::{lambda(v8::Object**)#1}>',
            '(v8::RelocInfo, v8::Foo<(v8::PointerDirection)1>::Bar(v8::Heap*)::'
            '{lambda(v8::SlotType)#2}::operator()(v8::SlotType) const::'
            '{lambda(v8::Object**)#1})')
        check(
            '',
            'WTF::StringAppend<WTF::String, WTF::String>::operator WTF::String',
            '()', ' const')
        # Make sure []s are not removed from the name part.
        check('', 'Foo', '()', ' [virtual thunk]')

        # SkArithmeticImageFilter.cpp has class within function body. e.g.:
        #   ArithmeticFP::onCreateGLSLInstance() looks like:
        # class ArithmeticFP {
        #   GrGLSLFragmentProcessor* onCreateGLSLInstance() const {
        #     class GLSLFP {
        #       void emitCode(EmitArgs& args) { ... }
        #     };
        #     ...
        #   }
        # };
        SIG = '(anonymous namespace)::Foo::Baz() const::GLSLFP::onData(Foo, Bar)'
        got_full, got_name = function_signature.Parse(SIG)
        self.assertEqual('(anonymous namespace)::Foo::Baz', got_name)
        self.assertEqual(SIG, got_full)
Beispiel #6
0
def _NormalizeNames(raw_symbols):
  """Ensures that all names are formatted in a useful way.

  This includes:
    - Deriving |name| and |template_name| from |full_name|.
    - Stripping of return types (for functions).
    - Moving "vtable for" and the like to be suffixes rather than prefixes.
  """
  found_prefixes = set()
  for symbol in raw_symbols:
    full_name = symbol.full_name
    if full_name.startswith('*'):
      # See comment in _CalculatePadding() about when this
      # can happen.
      symbol.template_name = full_name
      symbol.name = full_name
      continue

    # Remove [clone] suffix, and set flag accordingly.
    # Search from left-to-right, as multiple [clone]s can exist.
    # Example name suffixes:
    #     [clone .part.322]  # GCC
    #     [clone .isra.322]  # GCC
    #     [clone .constprop.1064]  # GCC
    #     [clone .11064]  # clang
    # http://unix.stackexchange.com/questions/223013/function-symbol-gets-part-suffix-after-compilation
    idx = full_name.find(' [clone ')
    if idx != -1:
      full_name = full_name[:idx]
      symbol.flags |= models.FLAG_CLONE

    # Clones for C symbols.
    if symbol.section == 't':
      idx = full_name.rfind('.')
      if idx != -1 and full_name[idx + 1:].isdigit():
        new_name = full_name[:idx]
        # Generated symbols that end with .123 but are not clones.
        # Find these via:
        #   size_info.symbols.WhereInSection('t').WhereIsGroup().SortedByCount()
        if new_name not in ('__tcf_0', 'startup'):
          full_name = new_name
          symbol.flags |= models.FLAG_CLONE
          # Remove .part / .isra / .constprop.
          idx = full_name.rfind('.', 0, idx)
          if idx != -1:
            full_name = full_name[:idx]

    # E.g.: vtable for FOO
    idx = full_name.find(' for ', 0, 30)
    if idx != -1:
      found_prefixes.add(full_name[:idx + 4])
      full_name = '{} [{}]'.format(full_name[idx + 5:], full_name[:idx])

    # E.g.: virtual thunk to FOO
    idx = full_name.find(' to ', 0, 30)
    if idx != -1:
      found_prefixes.add(full_name[:idx + 3])
      full_name = '{} [{}]'.format(full_name[idx + 4:], full_name[:idx])

    # Strip out return type, and split out name, template_name.
    # Function parsing also applies to non-text symbols. E.g. Function statics.
    symbol.full_name, symbol.template_name, symbol.name = (
        function_signature.Parse(full_name))

    # Remove anonymous namespaces (they just harm clustering).
    symbol.template_name = symbol.template_name.replace(
        '(anonymous namespace)::', '')
    symbol.full_name = symbol.full_name.replace(
        '(anonymous namespace)::', '')
    non_anonymous_name = symbol.name.replace('(anonymous namespace)::', '')
    if symbol.name != non_anonymous_name:
      symbol.flags |= models.FLAG_ANONYMOUS
      symbol.name = non_anonymous_name

    # Allow using "is" to compare names (and should help with RAM).
    function_signature.InternSameNames(symbol)

  logging.debug('Found name prefixes of: %r', found_prefixes)