def main(**kwargs):
    the_program = programs.IO.read(kwargs['program'])
    the_program.call_graph.dotify()

    if kwargs['manual']:
        programs.IO.read_properties(the_program, kwargs['manual'])
    else:
        instrumentation_id = 0
        for subprogram in the_program:
            ppg = graphs.ProgramPointGraph.create_from_control_flow_graph(
                subprogram.cfg)
            ppg.dotify()
            ppg.choose_instrumentation()

            old_to_new = {v: v for v in subprogram.cfg}
            for v in ppg:
                if isinstance(v.program_point, vertices.Vertex):
                    instrumentation_id += 1
                    instrumentation = vertices.InstrumentationVertex(
                        vertices.Vertex.get_vertex_id(), ppg.name,
                        instrumentation_id)
                    subprogram.cfg.add_vertex(instrumentation)
                    old_to_new[v.program_point] = instrumentation

                    if subprogram.cfg.entry == v.program_point:
                        subprogram.cfg.entry = instrumentation
                    if subprogram.cfg.exit == v.program_point:
                        subprogram.cfg.exit = instrumentation

                    for edge in subprogram.cfg.successors(v.program_point):
                        subprogram.cfg.add_edge(
                            edges.ControlFlowEdge(instrumentation,
                                                  edge.successor()))
                    for edge in subprogram.cfg.predecessors(v.program_point):
                        subprogram.cfg.add_edge(
                            edges.ControlFlowEdge(edge.predecessor(),
                                                  instrumentation))

                    subprogram.cfg.remove_vertex(v.program_point)

            for v in ppg:
                if isinstance(v.program_point, edges.Edge):
                    instrumentation_id += 1
                    predecessor = old_to_new[v.program_point.predecessor()]
                    successor = old_to_new[v.program_point.successor()]
                    subprogram.cfg.remove_edge(
                        edges.ControlFlowEdge(predecessor, successor))
                    subprogram.cfg.add_edge(
                        edges.InstrumentationEdge(predecessor, successor,
                                                  instrumentation_id))

    programs.IO.write(the_program, kwargs['output'])
示例#2
0
 def connect_nested_loops(self, cfg, nested_loops):
     highest_level = max(self.level_to_vertices.keys())
     candidate_entry_sources = [
         v for v in self._vertices
         if 0 < self._vertex_to_level[v] < highest_level
     ]
     for loop in nested_loops:
         (p, ) = sample(candidate_entry_sources, 1)
         cfg.add_edge(edges.ControlFlowEdge(p, loop.header))
         for exit_source in loop.exits:
             higher_level = randint(self._vertex_to_level[p] + 1,
                                    highest_level)
             candidate_exit_destinations = self.level_to_vertices[
                 higher_level]
             (s, ) = sample(candidate_exit_destinations, 1)
             cfg.add_edge(edges.ControlFlowEdge(exit_source, s))
示例#3
0
 def parse(cls, line):
     lexemes = line.split()
     if lexemes:
         time = int(lexemes[-1])
         if len(lexemes) == 2:
             v = vertices.Vertex.id_pool[int(lexemes[0])]
             return v, time
         else:
             p = vertices.Vertex.id_pool[int(lexemes[0])]
             s = vertices.Vertex.id_pool[int(lexemes[1])]
             edge = edges.ControlFlowEdge(p, s)
             return edge, time
示例#4
0
 def add_edges(self, cfg, fan_out):
     for level in sorted(self.level_to_vertices.keys(), reverse=True):
         if level > 0:
             for s in self.level_to_vertices[level]:
                 candidates = [
                     v for v in self.level_to_vertices[level - 1]
                     if len(cfg.successors(v)) < fan_out
                 ]
                 (p, ) = sample(candidates, 1)
                 cfg.add_edge(edges.ControlFlowEdge(p, s))
                 if len(cfg.successors(p)) == fan_out:
                     candidates.remove(p)
示例#5
0
 def connect_terminal_vertices(self, cfg):
     highest_level = max(self.level_to_vertices.keys())
     for level in sorted(self.level_to_vertices.keys(), reverse=True):
         if 0 < level < highest_level:
             candidate_predecessors = [
                 v for v in self.level_to_vertices[level]
                 if len(cfg.successors(v)) == 0
             ]
             higher_level = randint(level + 1, highest_level)
             candidate_successors = self.level_to_vertices[higher_level]
             for p in candidate_predecessors:
                 (s, ) = sample(candidate_successors, 1)
                 cfg.add_edge(edges.ControlFlowEdge(p, s))
示例#6
0
    def read(cls, filename: str) -> Program:
        messages.debug_message("Reading program from '{}'".format(filename))

        program = Program(filename)
        cfgs = []
        calls = []
        with open(filename) as json_file:
            program_json = json.load(json_file)
            magic_info = program_json[0]
            program.magic = magic_info[1]
            subprograms_json = program_json[1]
            for subprogram_name, (vertices_json,
                                  edges_json) in subprograms_json.items():
                cfg = graphs.ControlFlowGraph(program, subprogram_name)
                cfgs.append(cfg)

                for vertex_json in vertices_json:
                    vertex_id = int(vertex_json[0])
                    vertex = vertices.BasicBlock(int(vertex_id))
                    cfg.add_vertex(vertex)

                    instruction_json = vertex_json[1]
                    for instruction_text in instruction_json:
                        if instruction_text[
                                0] == instructions.CallInstruction.OPCODE:
                            callee = instruction_text[1]
                            calls.append([cfg.name, callee, vertex])
                            vertex.instructions.append(
                                instructions.CallInstruction(callee))
                        elif instruction_text[
                                0] == instructions.BranchInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.BranchInstruction())
                        elif instruction_text[
                                0] == instructions.StoreInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.StoreInstruction())
                        elif instruction_text[
                                0] == instructions.LoadInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.LoadInstruction())
                        elif instruction_text[
                                0] == instructions.AddInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.AddInstruction())
                        elif instruction_text[
                                0] == instructions.SubtractInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.SubtractInstruction())
                        elif instruction_text[
                                0] == instructions.MultiplyInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.MultiplyInstruction())
                        elif instruction_text[
                                0] == instructions.DivideInstruction.OPCODE:
                            vertex.instructions.append(
                                instructions.DivideInstruction())

                for edge_json in edges_json:
                    predecessor_id, successor_id = edge_json
                    predecessor = vertices.Vertex.id_pool[int(predecessor_id)]
                    successor = vertices.Vertex.id_pool[int(successor_id)]
                    cfg.add_edge(edges.ControlFlowEdge(predecessor, successor))

        for cfg in cfgs:
            call = vertices.SubprogramVertex(vertices.Vertex.get_vertex_id(),
                                             cfg.name)
            subprogram = Subprogram(cfg, call)
            program.add_subprogram(subprogram)

            for vertex in cfg:
                if len(cfg.predecessors(vertex)) == 0:
                    assert cfg.entry is None
                    cfg.entry = vertex

                if len(cfg.successors(vertex)) == 0:
                    assert cfg.exit is None
                    cfg.exit = vertex

            cfg.add_edge(edges.ControlFlowEdge(cfg.exit, cfg.entry))

        for caller, callee, site in calls:
            caller = program[caller].call_vertex
            callee = program[callee].call_vertex
            program.call_graph.add_edge(
                edges.CallGraphEdge(caller, callee, site))

        return program
示例#7
0
def create_control_flow_graph(program, loops, nesting_depth, dense,
                              irreducible, number_of_vertices, fan_out,
                              subprg_name):
    def create_artificial_loop_hierarchy():
        # Add abstract vertices to the tree, including an extra one
        # for the dummy outer loop
        lnt = graphs.DirectedGraph()
        for _ in range(1, loops + 2):
            lnt.add_vertex(vertices.Vertex(vertices.Vertex.get_vertex_id()))

        # Add edges to the tree
        vertex_to_level = {vertex: 0 for vertex in lnt}
        (root_vertex, ) = sample(vertex_to_level.keys(), 1)
        parent_vertex = root_vertex
        for vertex in lnt:
            if vertex != root_vertex:
                new_level = vertex_to_level[parent_vertex] + 1
                if new_level <= nesting_depth:
                    lnt.add_edge(edges.Edge(parent_vertex, vertex))
                    vertex_to_level[vertex] = new_level
                else:
                    # The height of the tree now exceeds the maximum depth, so
                    # backtrack to an arbitrary proper ancestor
                    ancestor_vertex = parent_vertex
                    while True:
                        (edge, ) = lnt.predecessors(ancestor_vertex)
                        ancestor_vertex = edge.predecessor()
                        if go_ahead() or ancestor_vertex == root_vertex:
                            break
                    parent_vertex = ancestor_vertex
                    lnt.add_edge(edges.Edge(parent_vertex, vertex))
                    vertex_to_level[
                        vertex] = vertex_to_level[parent_vertex] + 1
                parent_vertex = vertex

        # Compute number of vertices in each loop
        number_of_vertices_remaining = number_of_vertices
        for vertex in lnt:
            # Guarantee each loop has at least 2 vertices plus vertices needed
            # to connect inner nested loops
            vertex.size = 2 + len(lnt.successors(vertex))
            number_of_vertices_remaining -= vertex.size

        # Arbitrarily distribute any remaining vertices to the loop bodies
        while number_of_vertices_remaining > 0:
            for vertex in lnt:
                additional_vertices = randint(0, number_of_vertices_remaining)
                vertex.size += additional_vertices
                number_of_vertices_remaining -= additional_vertices
        return lnt, root_vertex

    def create_loop_body(vertex):
        for edge in lnt.successors(vertex):
            create_loop_body(edge.successor())

        # Post-order actions
        nested_loops = [
            loops[edge.successor()] for edge in lnt.successors(vertex)
        ]
        loops[vertex] = ArtificialLoopBody(fan_out, cfg, vertex.size,
                                           nested_loops,
                                           len(lnt.predecessors(vertex)) == 0)

        if len(lnt.predecessors(vertex)) == 0:
            (edge, ) = cfg.predecessors(loops[vertex].header)
            cfg.entry = edge.successor()
            cfg.exit = edge.predecessor()

    cfg = graphs.ControlFlowGraph(program, subprg_name)
    if not irreducible:
        lnt, root_vertex = create_artificial_loop_hierarchy()
        loops = {}
        create_loop_body(root_vertex)
    else:
        loop = ArtificialLoopBody(fan_out, cfg, number_of_vertices, [], True)
        (edge, ) = cfg.predecessors(loop.header)
        cfg.entry = edge.successor()
        cfg.exit = edge.predecessor()
        candidates = [
            vertex for vertex in cfg
            if vertex != cfg.entry and vertex != cfg.exit
        ]

        min_level = min(loop.level_to_vertices.keys())
        max_level = max(loop.level_to_vertices.keys())
        candidate_levels = [level for level in range(min_level + 1, max_level)]

        if dense:
            max_edges = len(candidates) * len(candidates) * len(candidates)
        else:
            max_edges = len(candidates) + int(len(candidates) / 2)

        level_edges = randint(1, max_edges)
        anywhere_edges = max_edges - level_edges

        start = time()
        if len(candidate_levels) > 2:
            for _ in range(level_edges):
                p_level = choice(candidate_levels[2:])
                s_level = choice(candidate_levels[:p_level - 1])
                p = choice(loop.level_to_vertices[p_level])
                s = choice(loop.level_to_vertices[s_level])
                if not cfg.has_edge(p, s):
                    cfg.add_edge(edges.ControlFlowEdge(p, s))

                if time() - start > 5:
                    break

        start = time()
        for _ in range(anywhere_edges):
            p = choice(candidates)
            s = choice(candidates)
            if not cfg.has_edge(p, s):
                cfg.add_edge(edges.ControlFlowEdge(p, s))

            if time() - start > 5:
                break

    return cfg
示例#8
0
 def add_backedges(self, cfg):
     highest_level = max(self.level_to_vertices.keys())
     for v in self.level_to_vertices[highest_level]:
         cfg.add_edge(edges.ControlFlowEdge(v, self._header))