Beispiel #1
0
def collect_params(cfg):
    func_addr = cfg.entry()
    e = cfg[func_addr]
    args = set(
        REG(r.name[:-2] if r.name.endswith("_0") else r.name)
        for r in e["live_in"])
    progdb.update_cfg_prop(cfg, "params", args)
Beispiel #2
0
def collect_reach_exit(cfg):
    all_defs1 = foreach_bblock(cfg, lambda b: b.defs(True), set_union)
    exit = cfg.exit()
    if "reachdef_out" in cfg.node(exit):
        all_defs2 = set(x[0] for x in cfg.node(exit)["reachdef_out"])
        assert all_defs1 == all_defs2, "%r vs %r" % (all_defs1, all_defs2)
    progdb.update_cfg_prop(cfg, "reach_exit", all_defs1)
    return all_defs1
Beispiel #3
0
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)
Beispiel #4
0
def collect_reach_exit(cfg):
    all_defs = foreach_bblock(cfg, lambda b: b.defs(True), set_union)
    exit = cfg.exit()
    if "reachdef_out" in cfg.node(exit):
        all_defs2 = set(x[0] for x in cfg.node(exit)["reachdef_out"] if x[1] is not None)
        if "_DEADEND_" not in cfg:
            assert all_defs == all_defs2, "%r vs %r" % (all_defs, all_defs2)
        all_defs = all_defs2
    progdb.update_cfg_prop(cfg, "reach_exit", all_defs)
Beispiel #5
0
def collect_reach_exit(cfg):
    all_defs = foreach_bblock(cfg, lambda b: b.defs(True), set_union)
    exit = cfg.exit()
    if "reachdef_out" in cfg.node(exit):
        all_defs2 = set(x[0] for x in cfg.node(exit)["reachdef_out"] if x[1] is not None)
        if "_DEADEND_" not in cfg:
            assert all_defs == all_defs2, "%r vs %r" % (all_defs, all_defs2)
        all_defs = all_defs2
    progdb.update_cfg_prop(cfg, "reach_exit", all_defs)
def collect_preserveds(cfg):
    exit_addr = cfg.exit()
    exit_bblock = cfg[exit_addr]["val"]
    state_out = exit_bblock.props["state_out"]
    preserveds = set()
    for k, v in state_out.items():
        if is_reg(k) and is_reg(v):
            if v.name == k.name + "_0":
                preserveds.add(k)
    progdb.update_cfg_prop(cfg, "preserveds", preserveds)
Beispiel #7
0
def collect_preserveds(cfg):
    exit_addr = cfg.exit()
    exit_bblock = cfg[exit_addr]["val"]
    state_out = exit_bblock.props["state_out"]
    preserveds = set()
    for k, v in state_out.items():
        if is_reg(k) and is_reg(v):
            if v.name == k.name + "_0":
                preserveds.add(k)
    progdb.update_cfg_prop(cfg, "preserveds", preserveds)
def collect_reach_exit_maybe(cfg):
    exit = cfg.exit()
    vardict = {}
    for var, addr in cfg.node(exit)["reachdef_out"]:
        vardict.setdefault(var, set()).add(addr)
    mod_maybe = set()

    for var, addrs in vardict.items():
        if len(addrs) > 1 and None in addrs:
            mod_maybe.add(var)

    if 1:  #mod_maybe or "reach_exit_maybe" in cfg.props:
        progdb.update_cfg_prop(cfg, "reach_exit_maybe", mod_maybe)
Beispiel #9
0
def estimate_params(cfg):
    #ana = dataflow.LiveVarAnalysis(cfg, skip_calls=True)
    #ana.solve()
    check_prop(cfg, "live_in", "This pass requires live variable information")
    func_addr = cfg.entry()
    assert func_addr == ".ENTRY", "cfg_preheader pass required"
    real_entry = cfg.succ(func_addr)
    assert len(real_entry) == 1
    real_entry = real_entry[0]
    e = cfg[real_entry]
    args = set(REG(r.name[:-2] if r.name.endswith("_0") else r.name) for r in e["live_in"])
    args -= set([REG("sp")])
    progdb.update_cfg_prop(cfg, "estimated_params", args)
Beispiel #10
0
def estimate_params(cfg):
    #ana = dataflow.LiveVarAnalysis(cfg, skip_calls=True)
    #ana.solve()
    check_prop(cfg, "live_in", "This pass requires live variable information")
    func_addr = cfg.entry()
    assert func_addr == ".ENTRY", "cfg_preheader pass required"
    real_entry = cfg.succ(func_addr)
    assert len(real_entry) == 1
    real_entry = real_entry[0]
    e = cfg[real_entry]
    args = set(REG(r.name[:-2] if r.name.endswith("_0") else r.name) for r in e["live_in"])
    args -= set([REG("sp")])
    progdb.update_cfg_prop(cfg, "estimated_params", args)
Beispiel #11
0
def collect_reach_exit_maybe(cfg):
    exit = cfg.exit()
    vardict = {}
    for var, addr in cfg.node(exit)["reachdef_out"]:
        vardict.setdefault(var, set()).add(addr)
    mod_maybe = set()

    for var, addrs in vardict.items():
        if len(addrs) > 1 and None in addrs:
            mod_maybe.add(var)

    if 1: #mod_maybe or "reach_exit_maybe" in cfg.props:
        progdb.update_cfg_prop(cfg, "reach_exit_maybe", mod_maybe)
Beispiel #12
0
def collect_call_live_out(cfg):

    calls_live_out = []
    def collect(node):
        bb = node["val"]
        if bb.items and bb[-1].op == "call":
            inst = bb[-1]
            arg = inst.args[0]
            # TODO: Perhaps filter in the real regs?
            regs = {r for r in node["live_out"] if not r.name.endswith("_0")}
            calls_live_out.append((bb.addr, arg, regs))

    foreach_node(cfg, collect)
    progdb.update_cfg_prop(cfg, "calls_live_out", calls_live_out)
Beispiel #13
0
def collect_call_live_out(cfg):

    calls_live_out = []
    def collect(node):
        bb = node["val"]
        if bb.items and bb[-1].op == "call":
            inst = bb[-1]
            arg = inst.args[0]
            # TODO: Perhaps filter in the real regs?
            regs = {r for r in node["live_out"] if not r.name.endswith("_0")}
            calls_live_out.append((bb.addr, arg, regs))

    foreach_node(cfg, collect)
    progdb.update_cfg_prop(cfg, "calls_live_out", calls_live_out)
Beispiel #14
0
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)
Beispiel #15
0
def collect_params(cfg):
    func_addr = cfg.entry()
    e = cfg[func_addr]
    args = set(REG(r.name[:-2] if r.name.endswith("_0") else r.name) for r in e["live_in"])
    args = arch.param_filter(args)
    progdb.update_cfg_prop(cfg, "params", args)