(function: NormalizedFunction)
return dists
:param function:    A normalized Function object.
        :returns:           A dictionary of basic block addresses and their distance to the exit of the function.
:param function:    A normalized Function object.
        :returns:           A dictionary of basic block addresses and their distance to the exit of the function.
: param function : A normalized Function object . : returns : A dictionary of basic block addresses and their distance to the exit of the function .
def _distances_from_function_exit(function: NormalizedFunction):
        """
        :param function:    A normalized Function object.
        :returns:           A dictionary of basic block addresses and their distance to the exit of the function.
        """
        reverse_graph: networkx.DiGraph = function.graph.reverse()
        # we aren't guaranteed to have an exit from the function so explicitly add the node
        reverse_graph.add_node("start")
        found_exits = False
        for n in function.graph.nodes():
            if len(list(function.graph.successors(n))) == 0:
                reverse_graph.add_edge("start", n)
                found_exits = True

        # if there were no exits (a function with a while 1) let's consider the block with the highest address to
        # be the exit. This isn't the most scientific way, but since this case is pretty rare it should be okay
        if not found_exits:
            last = max(function.graph.nodes(), key=lambda x:x.addr)
            reverse_graph.add_edge("start", last)

        dists = networkx.single_source_shortest_path_length(reverse_graph, "start")

        # remove temp node
        del dists["start"]

        # correct for the added node
        for n in dists:
            dists[n] -= 1

        return dists
def _distances_from_function_exit ( function : NormalizedFunction ) : reverse_graph : networkx . DiGraph = function . graph . reverse ( ) # we aren't guaranteed to have an exit from the function so explicitly add the node reverse_graph . add_node ( "start" ) found_exits = False for n in function . graph . nodes ( ) : if len ( list ( function . graph . successors ( n ) ) ) == 0 : reverse_graph . add_edge ( "start" , n ) found_exits = True # if there were no exits (a function with a while 1) let's consider the block with the highest address to # be the exit. This isn't the most scientific way, but since this case is pretty rare it should be okay if not found_exits : last = max ( function . graph . nodes ( ) , key = lambda x : x . addr ) reverse_graph . add_edge ( "start" , last ) dists = networkx . single_source_shortest_path_length ( reverse_graph , "start" ) # remove temp node del dists [ "start" ] # correct for the added node for n in dists : dists [ n ] -= 1 return dists