def _find_crashfn(self, db, problemplugin, query_all=False): db_backtraces = get_backtraces_by_type(db, problemplugin.name, query_all=query_all) db_backtraces_count = db_backtraces.count() i = 0 for db_backtrace in db_backtraces.yield_per(100): i += 1 try: crashfn = (demangle(problemplugin.find_crash_function( db_backtrace))[:column_len(ReportBacktrace, "crashfn")]) except Exception as ex: self.log_warn("Unable to find crash function: {0}" .format(str(ex))) continue if db_backtrace.crashfn != crashfn: self.log_info("[{0} / {1}] Updating backtrace #{2}: {3} ~> {4}" .format(i, db_backtraces_count, db_backtrace.id, db_backtrace.crashfn, crashfn)) db_backtrace.crashfn = crashfn else: self.log_info("[{0} / {1}] Backtrace #{2} up to date: {3}" .format(i, db_backtraces_count, db_backtrace.id, db_backtrace.crashfn)) if (i % 100) == 0: db.session.flush() db.session.flush()
def retrace(self, db, task): new_symbols = {} new_symbolsources = {} debug_paths = set(os.path.join(task.debuginfo.unpacked_path, fname[1:]) for fname in task.debuginfo.debug_files) if task.debuginfo.debug_files is not None: db_debug_pkg = task.debuginfo.db_package if db_debug_pkg.has_lob("offset_map"): with db_debug_pkg.get_lob_fd("offset_map") as fd: offset_map = pickle.load(fd) else: offset_map = get_function_offset_map(debug_paths) db_debug_pkg.save_lob("offset_map", pickle.dumps(offset_map)) else: offset_map = {} for bin_pkg, db_ssources in task.binary_packages.items(): i = 0 for db_ssource in db_ssources: i += 1 module = db_ssource.path self.log_info(u"[{0} / {1}] Processing '{2}' @ '{3}'" .format(i, len(db_ssources), db_ssource.symbol.name, module)) if db_ssource.path == "vmlinux": address = db_ssource.offset if address < 0: address += (1 << 64) else: if module not in offset_map: self.log_debug("Module '{0}' not found in package '{1}'" .format(module, task.debuginfo.nvra)) db_ssource.retrace_fail_count += 1 continue module_map = offset_map[module] symbol_name = db_ssource.symbol.name if symbol_name not in module_map: symbol_name = symbol_name.lstrip("_") if symbol_name not in module_map: self.log_debug("Function '{0}' not found in module " "'{1}'".format(db_ssource.symbol.name, module)) db_ssource.retrace_fail_count += 1 continue address = module_map[symbol_name] + db_ssource.func_offset debug_dir = os.path.join(task.debuginfo.unpacked_path, "usr", "lib", "debug") debug_path = self._get_debug_path(db, module, task.debuginfo.db_package) if debug_path is None: db_ssource.retrace_fail_count += 1 continue try: abspath = os.path.join(task.debuginfo.unpacked_path, debug_path[1:]) results = addr2line(abspath, address, debug_dir) results.reverse() except FafError as ex: self.log_debug("addr2line failed: {0}".format(str(ex))) db_ssource.retrace_fail_count += 1 continue inl_id = 0 while len(results) > 1: inl_id += 1 funcname, srcfile, srcline = results.pop() self.log_debug("Unwinding inlined function '{0}'" .format(funcname)) # hack - we have no offset for inlined symbols # let's use minus source line to avoid collisions offset = -srcline db_ssource_inl = get_ssource_by_bpo(db, db_ssource.build_id, db_ssource.path, offset) if db_ssource_inl is None: key = (db_ssource.build_id, db_ssource.path, offset) if key in new_symbolsources: db_ssource_inl = new_symbolsources[key] else: db_symbol_inl = get_symbol_by_name_path(db, funcname, module) if db_symbol_inl is None: sym_key = (funcname, module) if sym_key in new_symbols: db_symbol_inl = new_symbols[sym_key] else: db_symbol_inl = Symbol() db_symbol_inl.name = funcname db_symbol_inl.normalized_path = module db.session.add(db_symbol_inl) new_symbols[sym_key] = db_symbol_inl db_ssource_inl = SymbolSource() db_ssource_inl.symbol = db_symbol_inl db_ssource_inl.build_id = db_ssource.build_id db_ssource_inl.path = module db_ssource_inl.offset = offset db_ssource_inl.source_path = srcfile db_ssource_inl.line_number = srcline db.session.add(db_ssource_inl) new_symbolsources[key] = db_ssource_inl for db_frame in db_ssource.frames: db_frames = sorted(db_frame.thread.frames, key=lambda f: f.order) idx = db_frames.index(db_frame) if idx > 0: prevframe = db_frame.thread.frames[idx - 1] if (prevframe.inlined and prevframe.symbolsource == db_ssource_inl): continue db_newframe = ReportBtFrame() db_newframe.symbolsource = db_ssource_inl db_newframe.thread = db_frame.thread db_newframe.inlined = True db_newframe.order = db_frame.order - inl_id db.session.add(db_newframe) funcname, srcfile, srcline = results.pop() self.log_debug("Result: {0}".format(funcname)) db_symbol = get_symbol_by_name_path(db, funcname, module) if db_symbol is None: key = (funcname, module) if key in new_symbols: db_symbol = new_symbols[key] else: self.log_debug("Creating new symbol '{0}' @ '{1}'" .format(funcname, module)) db_symbol = Symbol() db_symbol.name = funcname db_symbol.normalized_path = module db.session.add(db_symbol) new_symbols[key] = db_symbol if db_symbol.nice_name is None: db_symbol.nice_name = demangle(funcname) db_ssource.symbol = db_symbol db_ssource.source_path = srcfile db_ssource.line_number = srcline if task.debuginfo is not None: self.log_debug("Removing {0}".format(task.debuginfo.unpacked_path)) shutil.rmtree(task.debuginfo.unpacked_path, ignore_errors=True) if task.source is not None and task.source.unpacked_path is not None: self.log_debug("Removing {0}".format(task.source.unpacked_path)) shutil.rmtree(task.source.unpacked_path, ignore_errors=True)
def retrace(self, db, task): new_symbols = {} new_symbolsources = {} for bin_pkg, db_ssources in task.binary_packages.items(): self.log_info("Retracing symbols from package {0}" .format(bin_pkg.nvra)) i = 0 for db_ssource in db_ssources: i += 1 self.log_debug("[{0} / {1}] Processing '{2}' @ '{3}'" .format(i, len(db_ssources), ssource2funcname(db_ssource), db_ssource.path)) norm_path = get_libname(db_ssource.path) binary = os.path.join(bin_pkg.unpacked_path, db_ssource.path[1:]) try: address = get_base_address(binary) + db_ssource.offset except FafError as ex: self.log_debug("get_base_address failed: {0}" .format(str(ex))) continue try: debug_path = os.path.join(task.debuginfo.unpacked_path, "usr", "lib", "debug") results = addr2line(binary, address, debug_path) results.reverse() except Exception as ex: self.log_debug("addr2line failed: {0}".format(str(ex))) continue inl_id = 0 while len(results) > 1: inl_id += 1 funcname, srcfile, srcline = results.pop() self.log_debug("Unwinding inlined function '{0}'" .format(funcname)) # hack - we have no offset for inlined symbols # let's use minus source line to avoid collisions offset = -srcline db_ssource_inl = get_ssource_by_bpo(db, db_ssource.build_id, db_ssource.path, offset) if db_ssource_inl is None: key = (db_ssource.build_id, db_ssource.path, offset) if key in new_symbolsources: db_ssource_inl = new_symbolsources[key] else: db_symbol_inl = get_symbol_by_name_path(db, funcname, norm_path) if db_symbol_inl is None: sym_key = (funcname, norm_path) if sym_key in new_symbols: db_symbol_inl = new_symbols[sym_key] else: db_symbol_inl = Symbol() db_symbol_inl.name = funcname db_symbol_inl.normalized_path = norm_path db.session.add(db_symbol_inl) new_symbols[sym_key] = db_symbol_inl db_ssource_inl = SymbolSource() db_ssource_inl.symbol = db_symbol_inl db_ssource_inl.build_id = db_ssource.build_id db_ssource_inl.path = db_ssource.path db_ssource_inl.offset = offset db_ssource_inl.source_path = srcfile db_ssource_inl.line_number = srcline db.session.add(db_ssource_inl) new_symbolsources[key] = db_ssource_inl for db_frame in db_ssource.frames: db_frames = sorted(db_frame.thread.frames, key=lambda f: f.order) idx = db_frames.index(db_frame) if idx > 0: prevframe = db_frame.thread.frames[idx - 1] if (prevframe.inlined and prevframe.symbolsource == db_ssource_inl): continue db_newframe = ReportBtFrame() db_newframe.symbolsource = db_ssource_inl db_newframe.thread = db_frame.thread db_newframe.inlined = True db_newframe.order = db_frame.order - inl_id db.session.add(db_newframe) funcname, srcfile, srcline = results.pop() self.log_debug("Result: {0}".format(funcname)) db_symbol = get_symbol_by_name_path(db, funcname, norm_path) if db_symbol is None: key = (funcname, norm_path) if key in new_symbols: db_symbol = new_symbols[key] else: self.log_debug("Creating new symbol '{0}' @ '{1}'" .format(funcname, db_ssource.path)) db_symbol = Symbol() db_symbol.name = funcname db_symbol.normalized_path = norm_path db.session.add(db_symbol) new_symbols[key] = db_symbol if db_symbol.nice_name is None: db_symbol.nice_name = demangle(funcname) db_ssource.symbol = db_symbol db_ssource.source_path = srcfile db_ssource.line_number = srcline if task.debuginfo.unpacked_path is not None: self.log_debug("Removing {0}".format(task.debuginfo.unpacked_path)) shutil.rmtree(task.debuginfo.unpacked_path, ignore_errors=True) if task.source is not None and task.source.unpacked_path is not None: self.log_debug("Removing {0}".format(task.source.unpacked_path)) shutil.rmtree(task.source.unpacked_path, ignore_errors=True) for bin_pkg in task.binary_packages.keys(): if bin_pkg.unpacked_path is not None: self.log_debug("Removing {0}".format(bin_pkg.unpacked_path)) shutil.rmtree(bin_pkg.unpacked_path, ignore_errors=True)
def retrace(self, db, task): new_symbols = {} new_symbolsources = {} for bin_pkg, db_ssources in task.binary_packages.items(): self.log_info("Retracing symbols from package {0}".format( bin_pkg.nvra)) i = 0 for db_ssource in db_ssources: i += 1 self.log_debug("[%d / %d] Processing '%s' @ '%s'", i, len(db_ssources), ssource2funcname(db_ssource), db_ssource.path) norm_path = get_libname(db_ssource.path) if bin_pkg.unpacked_path is None: self.log_debug( "fail: path to unpacked binary package not found") db_ssource.retrace_fail_count += 1 continue binary = os.path.join(bin_pkg.unpacked_path, db_ssource.path[1:]) try: address = get_base_address(binary) + db_ssource.offset except FafError as ex: self.log_debug("get_base_address failed: %s", str(ex)) db_ssource.retrace_fail_count += 1 continue try: debug_path = os.path.join(task.debuginfo.unpacked_path, "usr", "lib", "debug") results = addr2line(binary, address, debug_path) results.reverse() except Exception as ex: # pylint: disable=broad-except self.log_debug("addr2line failed: %s", str(ex)) db_ssource.retrace_fail_count += 1 continue inl_id = 0 while len(results) > 1: inl_id += 1 funcname, srcfile, srcline = results.pop() self.log_debug("Unwinding inlined function '%s'", funcname) # hack - we have no offset for inlined symbols # let's use minus source line to avoid collisions offset = -srcline db_ssource_inl = get_ssource_by_bpo( db, db_ssource.build_id, db_ssource.path, offset) if db_ssource_inl is None: key = (db_ssource.build_id, db_ssource.path, offset) if key in new_symbolsources: db_ssource_inl = new_symbolsources[key] else: db_symbol_inl = get_symbol_by_name_path( db, funcname, norm_path) if db_symbol_inl is None: sym_key = (funcname, norm_path) if sym_key in new_symbols: db_symbol_inl = new_symbols[sym_key] else: db_symbol_inl = Symbol() db_symbol_inl.name = funcname db_symbol_inl.normalized_path = norm_path db.session.add(db_symbol_inl) new_symbols[sym_key] = db_symbol_inl db_ssource_inl = SymbolSource() db_ssource_inl.symbol = db_symbol_inl db_ssource_inl.build_id = db_ssource.build_id db_ssource_inl.path = db_ssource.path db_ssource_inl.offset = offset db_ssource_inl.source_path = srcfile db_ssource_inl.line_number = srcline db.session.add(db_ssource_inl) new_symbolsources[key] = db_ssource_inl for db_frame in db_ssource.frames: db_frames = sorted(db_frame.thread.frames, key=lambda f: f.order) idx = db_frames.index(db_frame) if idx > 0: prevframe = db_frame.thread.frames[idx - 1] if (prevframe.inlined and prevframe.symbolsource == db_ssource_inl): continue db_newframe = ReportBtFrame() db_newframe.symbolsource = db_ssource_inl db_newframe.thread = db_frame.thread db_newframe.inlined = True db_newframe.order = db_frame.order - inl_id db.session.add(db_newframe) funcname, srcfile, srcline = results.pop() self.log_debug("Result: %s", funcname) db_symbol = get_symbol_by_name_path(db, funcname, norm_path) if db_symbol is None: key = (funcname, norm_path) if key in new_symbols: db_symbol = new_symbols[key] else: self.log_debug("Creating new symbol '%s' @ '%s'", funcname, db_ssource.path) db_symbol = Symbol() db_symbol.name = funcname db_symbol.normalized_path = norm_path db.session.add(db_symbol) new_symbols[key] = db_symbol if db_symbol.nice_name is None: db_symbol.nice_name = demangle(funcname) db_ssource.symbol = db_symbol db_ssource.source_path = srcfile db_ssource.line_number = srcline if task.debuginfo.unpacked_path is not None: self.log_debug("Removing %s", task.debuginfo.unpacked_path) shutil.rmtree(task.debuginfo.unpacked_path, ignore_errors=True) if task.source is not None and task.source.unpacked_path is not None: self.log_debug("Removing %s", task.source.unpacked_path) shutil.rmtree(task.source.unpacked_path, ignore_errors=True) for bin_pkg in task.binary_packages.keys(): if bin_pkg.unpacked_path is not None: self.log_debug("Removing %s", bin_pkg.unpacked_path) shutil.rmtree(bin_pkg.unpacked_path, ignore_errors=True)