def simpll_cache(): yield SimpLLCache(mkdtemp())
def compare(args): """ Compare snapshots of linux kernels. Runs the semantic comparison and shows information about the compared functions that are semantically different. """ # Parse both the new and the old snapshot. old_snapshot = Snapshot.load_from_dir(args.snapshot_dir_old) new_snapshot = Snapshot.load_from_dir(args.snapshot_dir_new) # Set the output directory if not args.stdout: if args.output_dir: output_dir = args.output_dir if os.path.isdir(output_dir): sys.stderr.write("Error: output directory exists\n") sys.exit(errno.EEXIST) else: output_dir = default_output_dir(args.snapshot_dir_old, args.snapshot_dir_new) else: output_dir = None if args.function: old_snapshot.filter([args.function]) new_snapshot.filter([args.function]) config = Config(old_snapshot, new_snapshot, args.show_diff, args.output_llvm_ir, args.control_flow_only, args.print_asm_diffs, args.verbose, args.enable_simpll_ffi, args.semdiff_tool) result = Result(Result.Kind.NONE, args.snapshot_dir_old, args.snapshot_dir_old, start_time=default_timer()) for group_name, group in sorted(old_snapshot.fun_groups.items()): group_printed = False # Set the group directory if output_dir is not None and group_name is not None: group_dir = os.path.join(output_dir, group_name) else: group_dir = None result_graph = None cache = SimpLLCache(mkdtemp()) if args.enable_module_cache: module_cache = _generate_module_cache(group.functions.items(), group_name, new_snapshot, 3) else: module_cache = None for fun, old_fun_desc in sorted(group.functions.items()): # Check if the function exists in the other snapshot new_fun_desc = new_snapshot.get_by_name(fun, group_name) if not new_fun_desc: continue # Check if the module exists in both snapshots if old_fun_desc.mod is None or new_fun_desc.mod is None: result.add_inner(Result(Result.Kind.UNKNOWN, fun, fun)) if group_name is not None and not group_printed: print("{}:".format(group_name)) group_printed = True print("{}: unknown".format(fun)) continue # If function has a global variable, set it glob_var = KernelParam(old_fun_desc.glob_var) \ if old_fun_desc.glob_var else None # Run the semantic diff fun_result = functions_diff(mod_first=old_fun_desc.mod, mod_second=new_fun_desc.mod, fun_first=fun, fun_second=fun, glob_var=glob_var, config=config, prev_result_graph=result_graph, function_cache=cache, module_cache=module_cache) result_graph = fun_result.graph if fun_result is not None: if args.regex_filter is not None: # Filter results by regex pattern = re.compile(args.regex_filter) for called_res in fun_result.inner.values(): if pattern.search(called_res.diff): break else: fun_result.kind = Result.Kind.EQUAL_SYNTAX result.add_inner(fun_result) # Printing information about failures and non-equal functions. if fun_result.kind in [ Result.Kind.NOT_EQUAL, Result.Kind.ERROR, Result.Kind.UNKNOWN ]: if fun_result.kind == Result.Kind.NOT_EQUAL: # Create the output directory if needed if output_dir is not None: if not os.path.isdir(output_dir): os.mkdir(output_dir) # Create the group directory or print the group name # if needed if group_dir is not None: if not os.path.isdir(group_dir): os.mkdir(group_dir) elif group_name is not None and not group_printed: print("{}:".format(group_name)) group_printed = True print_syntax_diff( snapshot_dir_old=args.snapshot_dir_old, snapshot_dir_new=args.snapshot_dir_new, fun=fun, fun_result=fun_result, fun_tag=old_fun_desc.tag, output_dir=group_dir if group_dir else output_dir, show_diff=args.show_diff, initial_indent=2 if (group_name is not None and group_dir is None) else 0) else: # Print the group name if needed if group_name is not None and not group_printed: print("{}:".format(group_name)) group_printed = True print("{}: {}".format(fun, str(fun_result.kind))) # Clean LLVM modules (allow GC to collect the occupied memory) old_fun_desc.mod.clean_module() new_fun_desc.mod.clean_module() LlvmKernelModule.clean_all() old_snapshot.finalize() new_snapshot.finalize() if output_dir is not None and os.path.isdir(output_dir): print("Differences stored in {}/".format(output_dir)) if args.report_stat: print("") print("Statistics") print("----------") result.stop_time = default_timer() result.report_stat(args.show_errors) return 0
def cache_file(): yield SimpLLCache.CacheFile(mkdtemp(), "/test/f1/1.ll", "/test/f2/2.ll")