예제 #1
0
def update_cfg_prop(cfg, prop, new_val):
    if cfg.props.get(prop) != new_val:
        mark_updated(cfg.props["name"])
        print("%s: %s updated from %s to %s" %
              (cfg.props["name"], prop, utils.repr_stable(
                  cfg.props.get(prop)), utils.repr_stable(new_val)))
    cfg.props[prop] = new_val
예제 #2
0
    def print_header(self):
        if self.addr_in_header:
            print("// %s" % self.addr, file=self.stream)
        print("// Predecessors: %s" % sorted(self.cfg.pred(self.addr)),
              file=self.stream)

        if self.node_props:
            print("// Node props:", file=self.stream)
            for k in sorted(self.node_props.keys()):
                v = self.node_props[k]
                v = utils.repr_stable(v)
                v = v.replace("$", self.header_reg_prefix)
                print("//  %s: %s" % (k, v), file=self.stream)

        if self.bblock_props:
            print("// BBlock props:", file=self.stream)

            for k in sorted(self.bblock_props.keys()):
                v = self.bblock_props[k]
                if k.startswith("state_"):
                    v = repr_state(v)
                else:
                    v = utils.repr_stable(v)
                v = v.replace("$", self.header_reg_prefix)
                print("//  %s: %s" % (k, v), file=self.stream)
예제 #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):
    """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
예제 #5
0
 def strarg(expr, arg):
     if isinstance(arg, (set, frozenset)):
         s = utils.repr_stable(arg)
     else:
         s = str(arg)
     preced_my = EXPR.preced(expr)
     preced_arg = EXPR.preced(arg)
     full_assoc = expr.op in {"+", "*", "&", "^", "|"}
     if preced_arg == preced_my and full_assoc:
         # Render repeated fully associative operators without extra parens
         pass
     elif preced_arg > preced_my or (preced_arg == preced_my and preced_arg != 1):
         # Otherwise, if precedence rules require parens, render them, unless
         # the arg is a unary/primary term
         s = "(%s)" % s
     else:
         # Parens would not be required per the precedence rules, but
         # handle common cases of confusing precedence in C, where parens
         # are usually suggested.
         if expr.op in ("&", "^", "|") and preced_arg != 1:
             # Any binary op subexpression of bitwise ops in parens
             s = "(%s)" % s
         elif expr.op in ("<<", ">>") and preced_arg != 1:
             # Any binary op subexpression of shift in parens
             s = "(%s)" % s
     return s
예제 #6
0
 def strarg(expr, arg):
     if isinstance(arg, (set, frozenset)):
         s = utils.repr_stable(arg)
     else:
         s = str(arg)
     preced_my = EXPR.preced(expr)
     preced_arg = EXPR.preced(arg)
     full_assoc = expr.op in {"+", "*", "&", "^", "|"}
     if preced_arg == preced_my and full_assoc:
         # Render repeated fully associative operators without extra parens
         pass
     elif preced_arg > preced_my or (preced_arg == preced_my and preced_arg != 1):
         # Otherwise, if precedence rules require parens, render them, unless
         # the arg is a unary/primary term
         s = "(%s)" % s
     else:
         # Parens would not be required per the precedence rules, but
         # handle common cases of confusing precedence in C, where parens
         # are usually suggested.
         if expr.op in ("&", "^", "|") and preced_arg != 1:
             # Any binary op subexpression of bitwise ops in parens
             s = "(%s)" % s
         elif expr.op in ("<<", ">>") and preced_arg != 1:
             # Any binary op subexpression of shift in parens
             s = "(%s)" % s
     return s
예제 #7
0
 def print_graph_header(self):
     if self.cfg.props:
         print("// Graph props:", file=self.stream)
         for k in sorted(self.cfg.props.keys()):
             v = self.cfg.props[k]
             v = utils.repr_stable(v)
             print("//  %s: %s" % (k, v), file=self.stream)
         print(file=self.stream)
예제 #8
0
 def print_graph_header(self):
     if self.cfg.props:
         print("// Graph props:", file=self.stream)
         for k in sorted(self.cfg.props.keys()):
             v = self.cfg.props[k]
             v = utils.repr_stable(v)
             print("//  %s: %s" % (k, v), file=self.stream)
         print(file=self.stream)
예제 #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:
            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)
예제 #10
0
    def print_header(self):
        if self.addr_in_header:
            print("// %s" % self.addr, file=self.stream)
        print("// Predecessors: %s" % sorted(self.cfg.pred(self.addr)), file=self.stream)

        if self.node_props:
            print("// Node props:", file=self.stream)
            for k in sorted(self.node_props.keys()):
                v = self.node_props[k]
                v = utils.repr_stable(v)
                v = v.replace("$", self.header_reg_prefix)
                print("//  %s: %s" % (k, v), file=self.stream)

        if self.bblock_props:
            print("// BBlock props:", file=self.stream)

            for k in sorted(self.bblock_props.keys()):
                v = self.bblock_props[k]
                if k.startswith("state_"):
                    v = repr_state(v)
                else:
                    v = utils.repr_stable(v)
                v = v.replace("$", self.header_reg_prefix)
                print("//  %s: %s" % (k, v), file=self.stream)
예제 #11
0
 def strarg(expr, arg):
     if isinstance(arg, (set, frozenset)):
         s = utils.repr_stable(arg)
     else:
         s = str(arg)
     preced_my = EXPR.preced(expr)
     preced_arg = EXPR.preced(arg)
     non_assoc = expr.op in {"-", "/"}
     if preced_arg > preced_my or (preced_arg == preced_my and non_assoc):
         s = "(%s)" % s
     else:
         # Common cases of confusing precedence in C, where parens is usually
         # suggested.
         if expr.op in ("<<", ">>") and (preced_arg != 1 and arg.op in ("+", "-")):
             s = "(%s)" % s
     return s
예제 #12
0
    def print_header(self):
        print("// Predecessors: %s" % sorted(self.cfg.pred(self.addr)), file=self.stream)

        if self.node_props:
            print("// Node props:", file=self.stream)
            for k in sorted(self.node_props.keys()):
                v = self.node_props[k]
                v = utils.repr_stable(v)
                print("//  %s: %s" % (k, v), file=self.stream)

        if self.bblock_props:
            print("// BBlock props:", file=self.stream)

            for k in sorted(self.bblock_props.keys()):
                v = self.bblock_props[k]
                if k.startswith("state_"):
                    v = repr_state(v)
                elif isinstance(v, dict):
                    v = utils.repr_stable_dict(v)
                print("//  %s: %s" % (k, v), file=self.stream)
예제 #13
0
def update_cfg_prop(cfg, prop, new_val):
    if cfg.props.get(prop) != new_val:
        mark_updated(cfg.props["name"])
        log.info("%s: %s updated from %s to %s" % (cfg.props["name"], prop,
            utils.repr_stable(cfg.props.get(prop)), utils.repr_stable(new_val)))
    cfg.props[prop] = new_val
예제 #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)
예제 #15
0
def check_invariants(cfg):
    if "reach_exit" in cfg.props:
        reach = cfg.props["reach_exit"]
        reach_maybe = cfg.props.get("reach_exit_maybe", set())
        assert reach_maybe.issubset(reach), "%s: maybe: %s, sure: %s" % (
            cfg.props["name"], repr_stable(reach_maybe), repr_stable(reach))
예제 #16
0
 def __repr__(self):
     if self.op in ("in", "not in"):
         return "COND(%r %s %s)" % (self.arg1, self.op, utils.repr_stable(self.arg2))
     return "COND(%r %s %r)" % (self.arg1, self.op, self.arg2)
예제 #17
0
def check_invariants(cfg):
    if "reach_exit" in cfg.props:
        reach = cfg.props["reach_exit"]
        reach_maybe = cfg.props.get("reach_exit_maybe", set())
        assert reach_maybe.issubset(reach), "%s: maybe: %s, sure: %s" % (cfg.props["name"],
            repr_stable(reach_maybe), repr_stable(reach))