def program_to_text(program): """Generate a text (CFG nodes + assignments) version of a program. For debugging only. Args: program: An instance of cfg.Program Returns: A string representing all of the data for this program. """ s = StringIO.StringIO() seen = set() for node in utils.order_nodes(program.cfg_nodes): seen.add(node) s.write("%s\n" % node.Label()) s.write(" From: %s\n" % ", ".join(n.Label() for n in node.incoming)) s.write(" To: %s\n" % ", ".join(n.Label() for n in node.outgoing)) s.write("\n") variables = set(value.variable for value in node.bindings) for var in sorted(variables, key=lambda v: v.id): # If a variable is bound in more than one node then it will be listed # redundantly multiple times. One alternative would be to only list the # values that occur in the given node, and then also list the other nodes # that assign the same variable. # Write the variable, indenting by two spaces. s.write(" %s\n" % _pretty_variable(var).replace("\n", "\n ")) s.write("\n") return s.getvalue()
def testOrderNodes4(self): # n1 --> n3 --> n2 # ^ | # +------+ n1 = self.prog.NewCFGNode("n1") n3 = n1.ConnectNew("n3") n2 = n3.ConnectNew("n2") n3.ConnectTo(n1) order = utils.order_nodes([n1, n2, n3]) self.assertItemsEqual([n1, n3, n2], order)
def testOrderNodes6(self): # +-------------------+ # | v # n1 --> n2 --> n3 --> n5 # ^ | # +------n4 n1 = self.prog.NewCFGNode("n1") n2 = n1.ConnectNew("n2") n3 = n2.ConnectNew("n3") n4 = n3.ConnectNew("n4") n4.ConnectTo(n2) n5 = n3.ConnectNew("n5") n1.ConnectTo(n5) order = utils.order_nodes([n1, n5, n4, n3, n2]) self.assertItemsEqual([n1, n2, n3, n4, n5], order)
def program_to_pseudocode(program): """Generate a pseudocode (CFG nodes + assignments) version of a program. For debugging only. Args: program: An instance of cfg.Program Returns: A string, the "pseudocode" of this program. """ s = StringIO.StringIO() seen = set() for node in utils.order_nodes(program.cfg_nodes): seen.add(node) s.write("<%d>%s\n" % (node.id, node.name)) for value in node.values: s.write(" %s\n" % pretty_assignment(value)) overwritten = False for cfg_node, source_sets in value.origins: if node != cfg_node: overwritten = True continue if source_sets == [set()]: pass # don't print trivially true source_sets else: src = utils.pretty_dnf([[pretty_assignment(v, short=True) for v in source_set] for source_set in source_sets]) s.write(" from: %s\n" % src) if overwritten: s.write(" (also set to this value in other nodes)\n") for out in node.outgoing: s.write(" jump to <%d>%s\n" % (out.id, out.name)) # "stray" nodes are nodes that are unreachable in the CFG. stray_nodes = set(program.cfg_nodes) - seen if stray_nodes: s.write("Stray nodes:\n") for node in stray_nodes: s.write("<%d>%s\n" % (node.id, node.name)) return s.getvalue()
def testOrderNodes7(self): # +---------------------------------+ # | v # n1 --> n2 --> n3 --> n4 --> n5 --> n6 # ^ | ^ | # | v | v # +------n7 +------n8 n1 = self.prog.NewCFGNode("n1") n2 = n1.ConnectNew("n2") n3 = n2.ConnectNew("n3") n4 = n3.ConnectNew("n4") n5 = n4.ConnectNew("n5") n6 = n5.ConnectNew("n6") n7 = n3.ConnectNew("n7") n7.ConnectTo(n2) n8 = n5.ConnectNew("n8") n8.ConnectTo(n4) n1.ConnectTo(n6) order = utils.order_nodes([n1, n2, n3, n4, n5, n6, n7, n8]) self.assertItemsEqual([n1, n2, n3, n7, n4, n5, n8, n6], order)
def compute_order(bytecode): """Split bytecode into blocks and order the blocks. This builds an "ancestor first" ordering of the basic blocks of the bytecode. Args: bytecode: A list of instances of opcodes.Opcode. (E.g. returned from opcodes.dis()) Returns: A list of Block instances. """ blocks = _split_bytecode(bytecode) first_op_to_block = {block.code[0]: block for block in blocks} for i, block in enumerate(blocks): next_block = blocks[i + 1] if i < len(blocks) - 1 else None last_op = block.code[-1] if next_block and not last_op.no_next(): block.connect_outgoing(next_block) if last_op.target: block.connect_outgoing(first_op_to_block[last_op.target]) if last_op.block_target: block.connect_outgoing(first_op_to_block[last_op.block_target]) return utils.order_nodes(blocks)
def testOrderNodes2(self): # n1 n2(dead) n1 = self.prog.NewCFGNode("n1") n2 = self.prog.NewCFGNode("n2") order = utils.order_nodes([n1, n2]) self.assertItemsEqual([n1], order)
def testOrderNodes1(self): # n1 --> n2 n1 = self.prog.NewCFGNode("n1") n2 = n1.ConnectNew("n2") order = utils.order_nodes([n1, n2]) self.assertItemsEqual([n1, n2], order)
def testOrderNodes0(self): order = utils.order_nodes([]) self.assertItemsEqual(order, [])