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)