Пример #1
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)
Пример #2
0
def calc_callsites_live_out(cg, callee):
    """Calculate function's callsites_live_out property.

    Go thru function's callers (using callgraph), and union their
    calls_live_out information pertinent to this function.
    """

    callers = maybesorted(cg.pred(callee))
    # If there're no callers, will return empty set, which
    # is formally correct - if there're no callers, the
    # function is dead. However, realistically that means
    # that callers aren't known, and we should treat that
    # specially.
    call_lo_union = set()
    for c in callers:
        clo = progdb.FUNC_DB[c].get("calls_live_out", [])
        #print("  %s: calls_live_out: %s" % (c, utils.repr_stable(clo)))
        for bbaddr, callee_expr, live_out in clo:
            if is_addr(callee_expr) and callee_expr.addr == callee:
                print("  %s: calls_live_out[%s]: %s" % (c, callee, utils.repr_stable((bbaddr, callee_expr, live_out))))
                call_lo_union.update(live_out)

    progdb.FUNC_DB[callee]["callsites_live_out"] = call_lo_union

    return call_lo_union
Пример #3
0
def calc_callsites_live_out(cg, callee):
    """Calculate function's callsites_live_out property.

    Go thru function's callers (using callgraph), and union their
    calls_live_out information pertinent to this function.
    """

    callers = maybesorted(cg.pred(callee))
    # If there're no callers, will return empty set, which
    # is formally correct - if there're no callers, the
    # function is dead. However, realistically that means
    # that callers aren't known, and we should treat that
    # specially.
    call_lo_union = set()
    for c in callers:
        clo = progdb.FUNC_DB[c].get("calls_live_out", [])
        #print("  %s: calls_live_out: %s" % (c, utils.repr_stable(clo)))
        for bbaddr, callee_expr, live_out in clo:
            if is_addr(callee_expr) and callee_expr.addr == callee:
                print("  %s: calls_live_out[%s]: %s" %
                      (c, callee,
                       utils.repr_stable((bbaddr, callee_expr, live_out))))
                call_lo_union.update(live_out)

    progdb.FUNC_DB[callee]["callsites_live_out"] = call_lo_union

    return call_lo_union
Пример #4
0
def calc_callsites_live_out(cg, callee):
    callers = maybesorted(cg.pred(callee))
    # If there're no callers, will return empty set, which
    # is formally correct - if there're no callers, the
    # function is dead. However, realistically that means
    # that callers aren't known, and we should treat that
    # specially.
    call_lo_union = set()
    for c in callers:
        clo = progdb.FUNC_DB[c].get("calls_live_out", [])
        print("%s: calls_live_out: %s" % (c, clo))
        for bbaddr, callee_expr, live_out in clo:
            if is_addr(callee_expr) and callee_expr.addr == callee:
                call_lo_union.update(live_out)
    return call_lo_union
Пример #5
0
def dump_level(func, props):
    if get_group(props["label"]):
        return
    for propname in ("calls", "func_refs"):
        if propname == "func_refs" and args.no_refs:
            continue
        for callee in maybesorted(props.get(propname, [])):
            if callee in IGNORE:
                continue
            callee = map_group(callee)

            if not args.each_call:
                if (props["label"], callee) in dup_set:
                    continue
                dup_set.add((props["label"], callee))
            attrs = {"func_refs": " [style=dashed]"}.get(propname, "")
            out.write("%s -> %s%s\n" % (props["label"], callee, attrs))
Пример #6
0
def dump_level(func, props):
    if get_group(props["label"]):
        return
    for propname in ("calls", "func_refs"):
        if propname == "func_refs" and args.no_refs:
            continue
        for callee in maybesorted(props.get(propname, [])):
            if callee in IGNORE:
                continue
            callee = map_group(callee)

            if not args.each_call:
                if (props["label"], callee) in dup_set:
                    continue
                dup_set.add((props["label"], callee))
            attrs = {"func_refs": " [style=dashed]"}.get(propname, "")
            out.write("%s -> %s%s\n" % (props["label"], callee, attrs))
Пример #7
0
        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))
Пример #8
0
            if not args.each_call:
                if (props["label"], callee) in dup_set:
                    continue
                dup_set.add((props["label"], callee))
            attrs = {"func_refs": " [style=dashed]"}.get(propname, "")
            out.write("%s -> %s%s\n" % (props["label"], callee, attrs))


out.write("digraph G {\n")

if args.func:
    index_by_name(FUNC_DB)
    todo = [args.func]
    done = set()
    while todo:
        f = todo.pop()
        props = FUNC_DB.get(f)
        if not props:
            continue
        dump_level(f, props)
        done.add(f)
        for callee in props["calls"]:
            if callee not in done:
                todo.append(callee)
else:
    for func, props in maybesorted(FUNC_DB.items()):
        dump_level(func, props)

out.write("}\n")
Пример #9
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)
Пример #10
0
iter_cnt = 1

while True:
    print("=== Iteration %d ===" % iter_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

Пример #11
0
            if not args.each_call:
                if (props["label"], callee) in dup_set:
                    continue
                dup_set.add((props["label"], callee))
            attrs = {"func_refs": " [style=dashed]"}.get(propname, "")
            out.write("%s -> %s%s\n" % (props["label"], callee, attrs))


out.write("digraph G {\n")

if args.func:
    index_by_name(FUNC_DB)
    todo = [args.func]
    done = set()
    while todo:
        f = todo.pop()
        props = FUNC_DB.get(f)
        if not props:
            continue
        dump_level(f, props)
        done.add(f)
        for callee in props["calls"]:
            if callee not in done:
                todo.append(callee)
else:
    for func, props in maybesorted(FUNC_DB.items()):
        dump_level(func, props)

out.write("}\n")