Example #1
0
    def execute(self, *args, **kwargs):
        self.global_variables = self.init_global_variables()

        # calculate summaries for functions
        for node in gcc.get_callgraph_nodes():
            if not self.is_analyzed(node):
                self.analyze_node(node)

        # find thread entry points and concretize summaries
        self.find_races()
Example #2
0
 def to_dot(self):
     result = 'digraph Callgraph {\n'
     #result += ' subgraph cluster_callgraph {\n'
     result += '  node [shape=box];\n'
     for cgn in gcc.get_callgraph_nodes():
         result += ('  %s [label=<%s>];\n'
                    % (self.node_id(cgn), self.node_to_dot_label(cgn)))
         for edge in cgn.callers:
             result += self.edge_to_dot(edge)
     #result += ' }\n'
     result += '}\n'
     return result
 def to_dot(self):
     result = 'digraph Callgraph {\n'
     #result += ' subgraph cluster_callgraph {\n'
     result += '  node [shape=box];\n'
     for cgn in gcc.get_callgraph_nodes():
         result += ('  %s [label=<%s>];\n' %
                    (self.node_id(cgn), self.node_to_dot_label(cgn)))
         for edge in cgn.callers:
             result += self.edge_to_dot(edge)
     #result += ' }\n'
     result += '}\n'
     return result
Example #4
0
def sorted_callgraph():
    """
    Return the callgraph, in topologically-sorted order
    """
    return topological_sort(gcc.get_callgraph_nodes(),
                            get_srcs=lambda n: [edge.caller
                                                for edge in n.callers
                                                # Strip out recursive calls:
                                                if edge.caller != n],
                            get_dsts=lambda n: [edge.callee
                                                for edge in n.callees
                                                # Strip out recursive calls:
                                                if edge.callee != n])
Example #5
0
 def get_graph(self, medges):
     graph = {}
     for cgn in gcc.get_callgraph_nodes():
         fname = self.gcc_node_to_str(cgn)
         callees = [] if medges else set()
         callers = [] if medges else set()
         for edge in cgn.callees:
             add = callees.append if medges else callees.add
             add(self.gcc_node_to_str(edge.callee))
         for edge in cgn.callers:
             add = callers.append if medges else callers.add
             add(self.gcc_node_to_str(edge.caller))
         graph[fname] = Node(callers, callees)
     self.clean_lib_functions(graph)
     return graph
Example #6
0
 def to_dot(self):
     result = 'digraph Callgraph {\n'
     result += '  node [shape=ellipse];\n'
     # Consolidate duplicate edges together
     counts = { }
     for cgn in gcc.get_callgraph_nodes():
         for edge in cgn.callers:
             edge_name = self.edge_to_dot(edge)
             counts[edge_name] = counts.get(edge_name, 0.0) + 0.001
     # Print the accumulated edges
     for edge_name in counts:
         result += ('   %s ' % edge_name)
         result += ('[ label = %.3f ];\n' % counts[edge_name])
     result += '}\n'
     return result
Example #7
0
def on_pass_execution(p, fn):
    #if p.name == '*warn_function_return':
    if p.name == '*free_lang_data':
        if 0:
            dot = callgraph_to_dot()
            invoke_dot(dot)

        for cgn in gcc.get_callgraph_nodes():
            print('cgn:')
            # print(dir(cgn))
            print('  cgn.decl: %r' % cgn.decl)
            print('  cgn.callers: %r' % cgn.callers)
            print('  cgn.callees: %r' % cgn.callees)
            for e in cgn.callers:
                print(e)
                print('e.caller: %r' % e.caller)
                print('e.callee: %r' % e.callee)
                print('e.call_stmt: %r %s' % (e.call_stmt, e.call_stmt))
Example #8
0
def on_pass_execution(p, fn):
    if p.name == '*free_lang_data':
        sf = StateFinder()

        # Locate uses of such variables:
        for node in gcc.get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                cfg = fun.cfg
                if cfg:
                    for bb in cfg.basic_blocks:
                        stmts = bb.gimple
                        if stmts:
                            for stmt in stmts:
                                stmt.walk_tree(sf.find_state_users, stmt.loc)

        # Flush the data that was found:
        sf.flush()
Example #9
0
def on_pass_execution(p, fn):
    if p.name == '*free_lang_data':
        sf = StateFinder()

        # Locate uses of such variables:
        for node in gcc.get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                cfg = fun.cfg
                if cfg:
                    for bb in cfg.basic_blocks:
                        stmts = bb.gimple
                        if stmts:
                            for stmt in stmts:
                                stmt.walk_tree(sf.find_state_users,
                                               stmt.loc)

        # Flush the data that was found:
        sf.flush()
Example #10
0
 def get_node_by_name(self, name):
     # Returns node if exists, otherwise - None
     for node in gcc.get_callgraph_nodes():
         if node.decl.name == name:
             return node
     return None
Example #11
0
def on_pass_execution(p, fn):
    if p.name == '*free_lang_data':
        global publisher
        fname = ""
        arguments = {}
        tvars = {}
        data = {}
        callees_list = []
        callers_list = []
        parent_types_list = []
        restr1 = r'[A-Z]\.[0-9]+'
        restr2 = r'_[0-9]+'
        rexp1 = re.compile(restr1)
        rexp2 = re.compile(restr2)

        for node in gcc.get_callgraph_nodes():

            try:
                fn = node.decl.function
                cl = node.callees
                cr = node.callers

                parent = str(fn.decl.name) + '@' + str(fn.decl.location.file) \
                        + '_L' + str(fn.decl.location.line) + '_C' \
                        + str(fn.decl.location.column)
                data['parent'] = parent

                parent_type = str(fn.decl.type.type)
                data['parent_type'] = parent_type

                for edge in cl:
                    callees_list.append(str(edge.call_stmt.fn) + '@' \
                            + str(edge.call_stmt.loc.file) + '_L' \
                            + str(edge.call_stmt.loc.line) + '_C' \
                            + str(edge.call_stmt.loc.column))
                data['callees'] = callees_list

                for edge in cr:
                    callers_list.append(str(edge.caller.decl.name) + '@' \
                            + str(edge.caller.decl.location.file) + '_L' \
                            + str(edge.caller.decl.location.line) + '_C' \
                            + str(edge.caller.decl.location.column))
                data['callers'] = callers_list

                for arg in fn.decl.type.argument_types:
                    parent_types_list.append(str(arg))

                data['parent_argument_types'] = parent_types_list
            except AttributeError:
                continue
            """
            print("IN FUNCTION:")
            print(parent)
            print("WHICH TYPE IS:")
            print(parent_type)
            print('AND ITS ARGUMENT\'S TYPES ARE: %r' \
                    % [str(arg) for arg in fn.decl.type.argument_types])
            print("THAT CALLS:")
            print(callees_list)
            print("AND IS CALLED BY")
            print(callers_list)
            print("ALL FUNCTION CALLS")
            """

            try:
                for bb in fn.cfg.basic_blocks:
                    for stmt in bb.gimple:
                        tvars = intake(stmt, tvars)
                        if isinstance(stmt, gcc.GimpleCall):
                            fnmatch1 = rexp1.search(str(stmt.fn))
                            fnmatch2 = rexp2.search(str(stmt.fn))

                            if fnmatch1:
                                fname = str(unfold(tvars, fnmatch1.group())) \
                                        + '@' + str(stmt.loc.file) \
                                        + '_L' + str(stmt.loc.line) + '_C' \
                                        + str(stmt.loc.column)
                                #print(fname)
                            elif fnmatch2:
                                fname = str(unfold(tvars, fnmatch2.group())) \
                                        + '@' + str(stmt.loc.file) \
                                        + '_L' + str(stmt.loc.line) + '_C' \
                                        + str(stmt.loc.column)
                                #print(fname)
                            else:
                                fname = str(stmt.fn) + '@' + str(stmt.loc.file) \
                                        + '_L' + str(stmt.loc.line) + '_C' \
                                        + str(stmt.loc.column)
                                #print(fname)

                            for i, arg in enumerate(stmt.args):
                                m1 = rexp1.search(str(stmt.args[i]))
                                m2 = rexp2.search(str(stmt.args[i]))
                                if m1:
                                    arguments[i] = unfold(tvars, m1.group())
                                elif m2:
                                    arguments[i] = unfold(tvars, m2.group())
                                else:
                                    arguments[i] = str(stmt.args[i])
                            #print(arguments)
                            data[fname] = arguments
                            arguments = {}

                #print("----------------------------------")
            except AttributeError:
                continue

            data_string = pickle.dumps(data)
            publisher.send(data_string)
            data.clear()
            del callees_list[:]
            del callers_list[:]
            del parent_types_list[:]

            #pprint.pprint(tvars)

    if p.name == "ssa":
        publisher.send(b"GCC_DISCONNECT")
Example #12
0
    def __init__(self, split_phi_nodes, add_fake_entry_node):
        Graph.__init__(self)
        self.supernode_for_stmtnode = {}
        # 1st pass: locate interprocedural instances of gcc.GimpleCall
        # i.e. where both caller and callee are within the supergraph
        # (perhaps the same function)
        ipcalls = set()
        from gcc import get_callgraph_nodes
        for node in get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                for edge in node.callees:
                    if edge.callee.decl.function:
                        ipcalls.add(edge.call_stmt)

        # 2nd pass: construct a StmtGraph for each function in the callgraph
        # and add nodes and edges to "self" wrapping the nodes and edges
        # within each StmtGraph:
        self.stmtg_for_fun = {}
        for node in get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                stmtg = StmtGraph(fun, split_phi_nodes)
                self.stmtg_for_fun[fun] = stmtg
                # Clone the stmtg nodes and edges into the Supergraph:
                stmtg.supernode_for_stmtnode = {}
                for node in stmtg.nodes:
                    if node.stmt in ipcalls:
                        # These nodes will have two supernodes, a CallNode
                        # and a ReturnNode:
                        callnode = self.add_node(CallNode(node, stmtg))
                        returnnode = self.add_node(ReturnNode(node, stmtg))
                        callnode.returnnode = returnnode
                        returnnode.callnode = callnode
                        stmtg.supernode_for_stmtnode[node] = (callnode, returnnode)
                        self.add_edge(
                            callnode, returnnode,
                            CallToReturnSiteEdge, None)
                    else:
                        stmtg.supernode_for_stmtnode[node] = \
                            self.add_node(SupergraphNode(node, stmtg))
                for edge in stmtg.edges:
                    if edge.srcnode.stmt in ipcalls:
                        # Begin the superedge from the ReturnNode:
                        srcsupernode = stmtg.supernode_for_stmtnode[edge.srcnode][1]
                    else:
                        srcsupernode = stmtg.supernode_for_stmtnode[edge.srcnode]
                    if edge.dstnode.stmt in ipcalls:
                        # End the superedge at the CallNode:
                        dstsupernode = stmtg.supernode_for_stmtnode[edge.dstnode][0]
                    else:
                        dstsupernode = stmtg.supernode_for_stmtnode[edge.dstnode]
                    superedge = self.add_edge(srcsupernode, dstsupernode,
                                              SupergraphEdge, edge)

        # 3rd pass: add the interprocedural edges (call and return):
        for node in get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                for edge in node.callees:
                    if edge.callee.decl.function:
                        calling_stmtg = self.stmtg_for_fun[fun]
                        called_stmtg = self.stmtg_for_fun[edge.callee.decl.function]

                        calling_stmtnode = calling_stmtg.node_for_stmt[edge.call_stmt]
                        assert calling_stmtnode

                        entry_stmtnode = called_stmtg.entry
                        assert entry_stmtnode

                        exit_stmtnode = called_stmtg.exit
                        assert exit_stmtnode

                        superedge_call = self.add_edge(
                            calling_stmtg.supernode_for_stmtnode[calling_stmtnode][0],
                            called_stmtg.supernode_for_stmtnode[entry_stmtnode],
                            CallToStart,
                            None)
                        superedge_return = self.add_edge(
                            called_stmtg.supernode_for_stmtnode[exit_stmtnode],
                            calling_stmtg.supernode_for_stmtnode[calling_stmtnode][1],
                            ExitToReturnSite,
                            None)
                        superedge_return.calling_stmtnode = calling_stmtnode

        # 4th pass: create fake entry node:
        if not add_fake_entry_node:
            self.fake_entry_node = None
            return

        self.fake_entry_node = self.add_node(FakeEntryNode(None, None))
        """
	/* At file scope, the presence of a `static' or `register' storage
	   class specifier, or the absence of all storage class specifiers
	   makes this declaration a definition (perhaps tentative).  Also,
	   the absence of `static' makes it public.  */
	if (current_scope == file_scope)
	  {
	    TREE_PUBLIC (decl) = storage_class != csc_static;
	    TREE_STATIC (decl) = !extern_ref;
	  }
          """
        # For now, assume all non-static functions are possible entrypoints:
        for fun in self.stmtg_for_fun:
            # Only for non-static functions:
            if fun.decl.is_public:
                stmtg = self.stmtg_for_fun[fun]
                self.add_edge(self.fake_entry_node,
                              stmtg.supernode_for_stmtnode[stmtg.entry],
                              FakeEntryEdge,
                              None)
Example #13
0
    def __init__(self, split_phi_nodes, add_fake_entry_node):
        Graph.__init__(self)
        self.supernode_for_stmtnode = {}
        # 1st pass: locate interprocedural instances of gcc.GimpleCall
        # i.e. where both caller and callee are within the supergraph
        # (perhaps the same function)
        ipcalls = set()
        from gcc import get_callgraph_nodes
        for node in get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                for edge in node.callees:
                    if edge.callee.decl.function:
                        ipcalls.add(edge.call_stmt)

        # 2nd pass: construct a StmtGraph for each function in the callgraph
        # and add nodes and edges to "self" wrapping the nodes and edges
        # within each StmtGraph:
        self.stmtg_for_fun = {}
        for node in get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                stmtg = StmtGraph(fun, split_phi_nodes)
                self.stmtg_for_fun[fun] = stmtg
                # Clone the stmtg nodes and edges into the Supergraph:
                stmtg.supernode_for_stmtnode = {}
                for node in stmtg.nodes:
                    if node.stmt in ipcalls:
                        # These nodes will have two supernodes, a CallNode
                        # and a ReturnNode:
                        callnode = self.add_node(CallNode(node, stmtg))
                        returnnode = self.add_node(ReturnNode(node, stmtg))
                        callnode.returnnode = returnnode
                        returnnode.callnode = callnode
                        stmtg.supernode_for_stmtnode[node] = (callnode,
                                                              returnnode)
                        self.add_edge(callnode, returnnode,
                                      CallToReturnSiteEdge, None)
                    else:
                        stmtg.supernode_for_stmtnode[node] = \
                            self.add_node(SupergraphNode(node, stmtg))
                for edge in stmtg.edges:
                    if edge.srcnode.stmt in ipcalls:
                        # Begin the superedge from the ReturnNode:
                        srcsupernode = stmtg.supernode_for_stmtnode[
                            edge.srcnode][1]
                    else:
                        srcsupernode = stmtg.supernode_for_stmtnode[
                            edge.srcnode]
                    if edge.dstnode.stmt in ipcalls:
                        # End the superedge at the CallNode:
                        dstsupernode = stmtg.supernode_for_stmtnode[
                            edge.dstnode][0]
                    else:
                        dstsupernode = stmtg.supernode_for_stmtnode[
                            edge.dstnode]
                    superedge = self.add_edge(srcsupernode, dstsupernode,
                                              SupergraphEdge, edge)

        # 3rd pass: add the interprocedural edges (call and return):
        for node in get_callgraph_nodes():
            fun = node.decl.function
            if fun:
                for edge in node.callees:
                    if edge.callee.decl.function:
                        calling_stmtg = self.stmtg_for_fun[fun]
                        called_stmtg = self.stmtg_for_fun[
                            edge.callee.decl.function]

                        calling_stmtnode = calling_stmtg.node_for_stmt[
                            edge.call_stmt]
                        assert calling_stmtnode

                        entry_stmtnode = called_stmtg.entry
                        assert entry_stmtnode

                        exit_stmtnode = called_stmtg.exit
                        assert exit_stmtnode

                        superedge_call = self.add_edge(
                            calling_stmtg.
                            supernode_for_stmtnode[calling_stmtnode][0],
                            called_stmtg.
                            supernode_for_stmtnode[entry_stmtnode],
                            CallToStart, None)
                        superedge_return = self.add_edge(
                            called_stmtg.supernode_for_stmtnode[exit_stmtnode],
                            calling_stmtg.
                            supernode_for_stmtnode[calling_stmtnode][1],
                            ExitToReturnSite, None)
                        superedge_return.calling_stmtnode = calling_stmtnode

        # 4th pass: create fake entry node:
        if not add_fake_entry_node:
            self.fake_entry_node = None
            return

        self.fake_entry_node = self.add_node(FakeEntryNode(None, None))
        """
	/* At file scope, the presence of a `static' or `register' storage
	   class specifier, or the absence of all storage class specifiers
	   makes this declaration a definition (perhaps tentative).  Also,
	   the absence of `static' makes it public.  */
	if (current_scope == file_scope)
	  {
	    TREE_PUBLIC (decl) = storage_class != csc_static;
	    TREE_STATIC (decl) = !extern_ref;
	  }
          """
        # For now, assume all non-static functions are possible entrypoints:
        for fun in self.stmtg_for_fun:
            # Only for non-static functions:
            if fun.decl.is_public:
                stmtg = self.stmtg_for_fun[fun]
                self.add_edge(self.fake_entry_node,
                              stmtg.supernode_for_stmtnode[stmtg.entry],
                              FakeEntryEdge, None)