def process_one(cg, func, xform_pass): global subiter_cnt, update_cnt upward_queue = [func] downward_queue = [] cnt = 0 cur_queue = upward_queue while upward_queue or downward_queue: subiter_cnt += 1 cnt += 1 if not cur_queue: if cur_queue is upward_queue: cur_queue = downward_queue else: cur_queue = upward_queue func = cur_queue.pop(0) print("--- Next to process: %s ---" % func) progdb.clear_updated() cfg = CFG_MAP["pre"][func].copy() call_lo_union = xform_inter.calc_callsites_live_out(cg, func) progdb.update_cfg_prop(cfg, "callsites_live_out", call_lo_union) print("%s: callsites_live_out set to %s" % (func, utils.repr_stable(call_lo_union))) if "modifieds" in progdb.FUNC_DB[func]: progdb.FUNC_DB[func]["returns"] = arch.ret_filter( progdb.FUNC_DB[func]["modifieds"] & call_lo_union) else: print("%s: doesn't yet have modifieds!" % func) xform_pass.apply(cfg) if progdb.UPDATED_FUNCS: assert len(progdb.UPDATED_FUNCS) == 1, repr(progdb.UPDATED_FUNCS) func2 = progdb.UPDATED_FUNCS.pop() assert func2 == func update_cnt += 1 progdb.update_funcdb(cfg) save_cfg(cfg, ".1") CFG_MAP["pre"][func].props = cfg.props upward_queue.extend(maybesorted(cg.pred(func))) for callee in maybesorted(cg.succ(func)): print("! updating callee", callee) if callee not in downward_queue: downward_queue.insert(0, callee) print("--- Finished processing: %s ---" % func) print("# New up (caller) queue:", upward_queue) print("# New down (callee) queue:", downward_queue) else: print("%s not updated" % func) print("Subiters:", cnt)
def process_preorder(cg, func, xform_pass): print(" pre:", func) cfg = CFG_MAP["pre"][func].copy() xform_pass.apply(cfg) progdb.update_funcdb(cfg) save_cfg(cfg, ".2") for callee in cg.succ(func): process_preorder(cg, callee, xform_pass)
def handle_file_unprotected(args): p = Parser(args.file) cfg = p.parse() cfg.parser = p # If we want to get asm back, i.e. stay close to the input, don't remove # trailing jumps. This will work OK for data flow algos, but will produce # broken or confusing output for control flow algos (for which asm output # shouldn't be used of course). # Update: it's unsafe to use this during dataflow analysis #if args.format != "asm": # foreach_bblock(cfg, remove_trailing_jumps) if args.debug: with open(args.file + ".0.bb", "w") as f: dump_bblocks(cfg, f, no_graph_header=args.no_graph_header) with open(args.file + ".0.dot", "w") as f: dot.dot(cfg, f) if args.script: for s in args.script: mod = __import__(s) mod.apply(cfg) elif hasattr(p, "script"): for op_type, op_name in p.script: if op_type == "xform:": func = globals()[op_name] func(cfg) elif op_type == "xform_bblock:": func = globals()[op_name] foreach_bblock(cfg, func) elif op_type == "xform_inst:": func = globals()[op_name] foreach_inst(cfg, func) elif op_type == "script:": mod = __import__(op_name) mod.apply(cfg) else: assert 0 if args.debug: with open(args.file + ".out.bb", "w") as f: dump_bblocks(cfg, f, no_graph_header=args.no_graph_header) with open(args.file + ".out.dot", "w") as f: dot.dot(cfg, f) if args.output and args.format != "none": out = open(args.output, "w") else: out = sys.stdout if args.no_comments: Inst.show_comments = False if args.format == "bblocks": p = CFGPrinter(cfg, out) if args.no_graph_header: p.print_graph_header = lambda: None p.inst_printer = repr if args.repr else str p.no_dead = args.no_dead p.print() elif args.format == "asm": p = AsmPrinter(cfg, out) p.no_dead = args.no_dead p.print() elif args.format == "c": #foreach_bblock(cfg, remove_trailing_jumps) cfg.number_postorder() Inst.trail = ";" cprinter.no_dead = args.no_dead cprinter.dump_c(cfg, out) if out is not sys.stdout: out.close() progdb.update_funcdb(cfg) return cfg
def process_one(cg, func, xform_pass): global subiter_cnt, update_cnt upward_queue = [func] downward_queue = [] cnt = 0 cur_queue = upward_queue while upward_queue or downward_queue: subiter_cnt += 1 cnt += 1 if not cur_queue: if cur_queue is upward_queue: cur_queue = downward_queue else: cur_queue = upward_queue func = cur_queue.pop(0) print("--- Next to process: %s ---" % func) progdb.clear_updated() cfg = CFG_MAP["pre"][func].copy() call_lo_union = xform_inter.calc_callsites_live_out(cg, func) progdb.update_cfg_prop(cfg, "callsites_live_out", call_lo_union) print("%s: callsites_live_out set to %s" % (func, utils.repr_stable(call_lo_union))) if "modifieds" in progdb.FUNC_DB[func]: progdb.FUNC_DB[func]["returns"] = arch.ret_filter(progdb.FUNC_DB[func]["modifieds"] & call_lo_union) else: print("%s: doesn't yet have modifieds!" % func) xform_pass.apply(cfg) if progdb.UPDATED_FUNCS: func_stats[func][0] += 1 assert len(progdb.UPDATED_FUNCS) == 1, repr(progdb.UPDATED_FUNCS) func2 = progdb.UPDATED_FUNCS.pop() assert func2 == func update_cnt += 1 progdb.update_funcdb(cfg) save_cfg(cfg, ".1") dot.save_dot(cfg, ".1") CFG_MAP["pre"][func].props = cfg.props for x in maybesorted(cg.pred(func)): if x not in upward_queue: upward_queue.append(x) for callee in maybesorted(cg.succ(func)): print("! updating callee", callee) if callee not in downward_queue: downward_queue.append(callee) print("--- Finished processing: %s ---" % func) print("# New up (caller) queue:", upward_queue) print("# New down (callee) queue:", downward_queue) else: func_stats[func][1] += 1 print("%s not updated" % func) # Maybe funcdb properties not updated, but bblocks props can very well be save_cfg(cfg, ".1") dot.save_dot(cfg, ".1") print("Subiters:", cnt)