def one_iter(input, output, iter_no): global FUNC_DB, FUNC_DB_ORG if args.funcdb != "none": dbs = [] if iter_no == 0 and os.path.exists(args.funcdb + ".in"): dbs.append(args.funcdb + ".in") if os.path.exists(args.funcdb): dbs.append(args.funcdb) progdb.load_funcdb(*dbs) FUNC_DB = progdb.FUNC_DB_BY_ADDR FUNC_DB_ORG = copy.deepcopy(FUNC_DB) if args.script: # If script has init() function, call it at the beginning of each # iteration, this is useful to reset some state. E.g., if some # funcdb property is calculated as a union, but we want to find # its lower bound, we need to reset it to empty set at each # iteration. for s in args.script: mod = __import__(s) if hasattr(mod, "init"): mod.init() if os.path.isdir(input): if output and not os.path.isdir(output): os.makedirs(output) for full_name in glob.glob(input + "/*"): if full_name.endswith(".lst") and os.path.isfile(full_name): if args.debug: print(full_name) args.file = full_name if output: base_name = full_name.rsplit("/", 1)[-1] args.output = output + "/" + base_name else: args.output = full_name + args.output_suffix handle_file(args) else: handle_file(args) changed = FUNC_DB != FUNC_DB_ORG if changed and args.funcdb != "none": progdb.save_funcdb(args.funcdb) return changed
else: print("%s not updated" % func) print("Subiters:", cnt) import script_i_func_params_returns iter_cnt = 1 while True: print("=== Iteration %d ===" % iter_cnt) old_funcdb = copy.deepcopy(progdb.FUNC_DB) progdb.clear_updated() for e in maybesorted(callgraph.exits()): print("Processing leaf", e) process_one(callgraph, e, script_i_func_params_returns) progdb.save_funcdb(sys.argv[1] + "/funcdb.yaml.out%d" % iter_cnt) if progdb.FUNC_DB == old_funcdb: break iter_cnt += 1 # if iter_cnt > 3: # break print("Done in %d iterations, %d sub-iterations, %d updates" % (iter_cnt, subiter_cnt, update_cnt))
old_funcdb = copy.deepcopy(progdb.FUNC_DB) progdb.clear_updated() # We start with some leaf node (then eventually with all the rest of # leafs). With leaf (call-less) function, we can know everything about # its parameters. So, we learn that, and then propagate this information # to all its callers, then to callers of its callers. We go in this # upward fashion (propagating parameter information) until we can, and # then we start downward motion, hoping to collect as much information # as possible about function live-outs, i.e. returns. We go in this # zig-zag fashion, until there's something to update. for e in maybesorted(callgraph.exits()): print("Processing leaf", e) process_one(callgraph, e, script_i_func_params_returns) progdb.save_funcdb(sys.argv[1] + "/funcdb.yaml.out%d" % iter_cnt) if progdb.FUNC_DB == old_funcdb: break print("So far: %d iterations, %d sub-iterations, %d updates" % (iter_cnt, subiter_cnt, update_cnt)) iter_cnt += 1 # if iter_cnt > 3: # break print("Done in %d iterations, %d sub-iterations, %d updates" % (iter_cnt, subiter_cnt, update_cnt)) pprint(func_stats) HITS = MISSES = 0