示例#1
0
文件: retrace.py 项目: rtnpro/faf
def retrace_symbol_wrapper(session, source, binary_dir, debuginfo_dir):
    '''
    Handle database references. Delete old symbol with '??' if
    reference count is 1 and add new symbol if there is no such
    symbol already.
    '''

    result = retrace_symbol(source.path, source.offset, binary_dir,
        debuginfo_dir)

    logging.info('Result: {0}'.format(result))
    if result is not None:
        normalized_path = get_libname(source.path)

        if len(result) > 1:
            # <ugly>We have no offset for inlined functions,
            # so use -1 * line_number</ugly>
            inlined_name, inlined_source_path, inlined_line_number = result[1]
            inlined_line_number = int(inlined_line_number)

            logging.debug("Handling inlined function '{0}'".format(inlined_name))
            inlined_source = session.query(SymbolSource) \
                             .filter((SymbolSource.build_id == source.build_id) &
                                     (SymbolSource.path == source.path) &
                                     (SymbolSource.offset == -inlined_line_number)) \
                             .first()

            if not inlined_source:
                logging.debug("Creating new SymbolSource")
                inlined_source = SymbolSource()
                inlined_source.build_id = source.build_id
                inlined_source.path = source.path
                inlined_source.offset = -inlined_line_number
                inlined_source.line_number = inlined_line_number
                inlined_source.source_path = inlined_source_path

                inlined_symbol = session.query(Symbol) \
                                 .filter((Symbol.name == inlined_name) &
                                         (Symbol.normalized_path == normalized_path)) \
                                 .first()

                if not inlined_symbol:
                    logging.debug("Creating new Symbol")
                    inlined_symbol = Symbol()
                    inlined_symbol.name = inlined_name

                    demangled = cpp_demangle(inlined_symbol.name)
                    if demangled != inlined_symbol.name:
                        inlined_symbol.nice_name = demangled

                    inlined_symbol.normalized_path = normalized_path
                    session.add(inlined_symbol)
                    session.flush()

                inlined_source.symbol_id = inlined_symbol.id
                session.add(inlined_source)
                session.flush()
            else:
                # although this is strange, it happens
                # it is probably a bug somewhere
                # ToDo: fix it
                if inlined_source.line_number != inlined_line_number:
                    logging.warn("Different line number for same"
                                 " build_id+soname+offset")
                    inlined_line_number = inlined_source.line_number

                if inlined_source.source_path != inlined_source_path:
                    logging.warn("Different source_path for same"
                                 " build_id+soname+offset")
                    inlined_source_path = inlined_source.source_path

            affected = session.query(ReportBtFrame) \
                       .filter(ReportBtFrame.symbolsource_id == source.id).all()

            for frame in affected:
                order = frame.order
                prevframe = frame.backtrace.frames[order - 1]
                if prevframe.inlined and \
                   prevframe.symbolsource_id == inlined_source.id:
                    logging.debug("Already separated, skipping")
                    continue

                bt_shift_frames(session, frame.backtrace, order)

                logging.debug("Creating new ReportBtFrame")
                newframe = ReportBtFrame()
                newframe.backtrace_id = frame.backtrace_id
                newframe.order = order
                newframe.symbolsource_id = inlined_source.id
                newframe.inlined = True
                session.add(newframe)
                session.flush()

        (symbol_name, source.source_path, source.line_number) = result[0]

        # Handle eu-addr2line not returing correct function name
        if symbol_name == '??':
            symbol_name = source.symbol.name

            logging.warning('eu-addr2line failed to return function'
                ' name, using reported name: "{0}"'.format(symbol_name))

        # Search for already existing identical symbol.
        symbol = (session.query(Symbol).filter(
            (Symbol.name == symbol_name) &
            (Symbol.normalized_path == normalized_path))).first()

        possible_duplicates = []

        if symbol:
            # Some symbol has been found.
            logging.debug('Already got this symbol')
            source.symbol = symbol

            for frame in source.frames:
                possible_duplicates.append(frame.backtrace)
        else:
            # Create new symbol.
            symbol = Symbol()
            symbol.name = symbol_name

            demangled = cpp_demangle(symbol.name)
            if demangled != symbol.name:
                symbol.nice_name = demangled

            symbol.normalized_path = normalized_path
            session.add(symbol)
            source.symbol = symbol

        if not is_duplicate_source(session, source):
            session.add(source)

        session.flush()

        # delete unreferenced symbols
        session.query(Symbol).filter(
            (Symbol.name == '??') &
            (Symbol.sources == None)).delete(False)

        check_duplicate_backtraces(session, possible_duplicates)