Example #1
0
 def __cut_add_vertex(self, v, mz, vaddr, mo):
     oldnode = mo.data.val
     if oldnode == v:
         return oldnode
     # so v cuts an existing block:
     # if vaddr matches an oldblock instr, cut it:
     cutdone = oldnode.cut(vaddr)
     if not cutdone:
         if mz is self.overlay:
             logger.warning("double overlay block at %s" % vaddr)
             v = super(graph, self).add_vertex(v)
             v.misc["double-overlay"] = 1
             return v
         overlay = self.overlay or MemoryZone()
         return self.add_vertex(v, support=overlay)
     else:
         oldnode.misc["cut"] = cutdone
         v = super(graph,
                   self).add_vertex(v)  # ! avoid recursion for add_edge
         mz.write(vaddr, v)
         self.add_edge(link(oldnode, v))
         for n in oldnode.N(+1):
             self.add_edge(link(v, n))
             self.remove_edge(oldnode.e_to(n))
         return v
Example #2
0
 def add_vertex(self, v, support=None):
     if v.data._is_func:
         return super(graph, self).add_vertex(v)
     # insert block:
     vaddr = v.data.address
     if support is None:
         support = self.support
     else:
         logger.verbose("add overlay block at %s" % vaddr)
         self.overlay = support
     i = support.locate(vaddr)
     # check if block intersects others:
     if i is not None:
         mo = support._map[i]
         if vaddr in mo:
             return self.__cut_add_vertex(v, support, vaddr, mo)
         else:  # v does not cut an existing block,
             try:  # but may swallow next one...
                 nextmo = support._map[i + 1]
             except IndexError:
                 # no more nodes here so back to default case:
                 pass
             else:
                 nextnode = nextmo.data.val
                 if vaddr + len(v) > nextnode.data.address:
                     # nextnode is inside v...
                     # try to cut v at nextnode bound:
                     cutdone = v.cut(nextnode.data.address)
                     if not cutdone:
                         # nextnode address does not match an instruction in v...
                         # thats an overlay:
                         if support is self.overlay:
                             # we already are in overlay...
                             logger.warning("double overlay block at %s" %
                                            vaddr)
                             v = super(graph, self).add_vertex(v)
                             v.misc["double-overlay"] = 1
                             return v
                         support = self.overlay or MemoryZone()
     v = super(graph, self).add_vertex(v)  # before support write !!
     support.write(vaddr, v)
     return v
Example #3
0
 def __init__(self,*args,**kargs):
     self.support = MemoryZone()
     self.overlay = None
     super(graph,self).__init__(*args,**kargs)
Example #4
0
class graph(Graph):
    """a :ref:`<grandalf:Graph>` that represents a set of functions as its
    individual connected components.

    Args:
        V (iterable[node]) : the set of (possibly detached) nodes.
        E (iterable[link]) : the set of links of this graph.

    Attributes:
        C : the list of :class:`graph_core <grandalf:graph_core>` connected
            components of the graph.
        support (:class:`~system.core.MemoryZone`): the abstract memory zone
            holding all nodes contained in this graph.
        overlay : defaults to None, another instance of MemoryZone
            with nodes of the graph that overlap other nodes already mapped
            in :attr:`support`.

    Methods:
        get_by_name(name): get the node with the given name (as string).

        get_with_address(vaddr): get the node that contains the given *vaddr*
            :class:`~cas.expressions.cst` expression.

        add_vertex(v,[support=None]): add node v to the graph and declare
            node support in the default MemoryZone or the overlay zone if
            provided as support argument. This method deals with a node v
            that cuts or swallows a previously added node.

        remove_vertex(v): remove node v from the graph.

        add_edge(e): add link to the graph as well as possible new nodes.

        remove_edge(e): remove the provided link.

        get_vertices_count(): a synonym for :meth:`order`.

        V(): generator of all nodes of the graph.

        E(): generator of all links of the graph.

        N(v,f_io=0): returns the neighbors of node v in direction f_io.

        path(x,y,f_io=0,hook=None):

        order(): number of nodes in the graph.

        norm(): number of links in the graph.

        deg_min(): minimum degree of nodes.

        deg_max(): maximum degree of nodes.

        deg_avg(): average degree of nodes.

        eps(): ratio of links over nodes (norm/order).

        connected(): boolean flag indicating that the graph as
            only one connected component.

        components(): synonym for attribute :attr:`C`.

    """
    def __init__(self,*args,**kargs):
        self.support = MemoryZone()
        self.overlay = None
        super(graph,self).__init__(*args,**kargs)

    def __cut_add_vertex(self,v,mz,vaddr,mo):
        oldnode = mo.data.val
        if oldnode==v: return oldnode
        # so v cuts an existing block:
        # if vaddr matches an oldblock instr, cut it:
        cutdone = oldnode.cut(vaddr)
        if not cutdone:
            if mz is self.overlay:
                logger.warning(u"double overlay block at %s"%vaddr)
                v = super(graph,self).add_vertex(v)
                v.misc[u'double-overlay'] = 1
                return v
            overlay = self.overlay or MemoryZone()
            return self.add_vertex(v,support=overlay)
        else:
            oldnode.misc['cut'] = cutdone
            v = super(graph,self).add_vertex(v) # ! avoid recursion for add_edge
            mz.write(vaddr,v)
            self.add_edge(link(oldnode,v))
            for n in oldnode.N(+1):
                self.add_edge(link(v,n))
                self.remove_edge(oldnode.e_to(n))
            return v

    def add_vertex(self,v,support=None):
        if v.data._is_func:
            return super(graph,self).add_vertex(v)
        # insert block:
        vaddr=v.data.address
        if support is None:
            support=self.support
        else:
            logger.verbose(u"add overlay block at %s"%vaddr)
            self.overlay = support
        i = support.locate(vaddr)
        # check if block intersects others:
        if i is not None:
            mo = support._map[i]
            if vaddr in mo:
                return self.__cut_add_vertex(v,support,vaddr,mo)
            else: #v does not cut an existing block,
                try: # but may swallow next one...
                    nextmo = support._map[i+1]
                except IndexError:
                    # no more nodes here so back to default case:
                    pass
                else:
                    nextnode = nextmo.data.val
                    if vaddr+len(v)>nextnode.data.address:
                        #nextnode is inside v...
                        #try to cut v at nextnode bound:
                        cutdone = v.cut(nextnode.data.address)
                        if not cutdone:
                            # nextnode address does not match an instruction in v...
                            # thats an overlay:
                            if support is self.overlay:
                                # we already are in overlay...
                                logger.warning(u"double overlay block at %s"%vaddr)
                                v = super(graph,self).add_vertex(v)
                                v.misc[u'double-overlay'] = 1
                                return v
                            support = self.overlay or MemoryZone()
        v = super(graph,self).add_vertex(v) # before support write !!
        support.write(vaddr,v)
        return v

    def get_by_name(self,name):
        for v in self.V():
            if v.name==name: return v
        return None

    def get_with_address(self,vaddr):
        i = self.support.locate(vaddr)
        if i is not None:
            mo = self.support._map[i]
            if vaddr in mo:
                return mo.data.val
        return None

    def to_dot(self,name=None,full=True):
        dot  = "digraph G {\n"
        dot += '    graph [orientation=landscape, labeljust=left];\n'
        dot += "    node [shape=box,fontname=monospace,fontsize=8];\n"
        if name:
            g = self.get_by_name(name).c
        else:
            g = self
        for v in g.V():
            txt = u"%s"%v.data if full else "%s [%d]"%(v.name,len(v.data.instr))
            dot += '    "%s" [label="%s"];\n'%(id(v),txt)
        for e in g.E():
            dot += '    "%s" -> "%s"'%(id(e.v[0]),id(e.v[1]))
            dot += " [style=bold];\n" if e.feedback else ';\n'
        dot += '}\n'
        return dot