'Revisit the entire control flow graph, create Function instances accordingly, and correctly put blocks into
each function.
Although Function objects are crated during the CFG recovery, they are neither sound nor accurate. With a
pre-constructed CFG, this method rebuilds all functions bearing the following rules:
- A block may only belong to one function.
- Small functions lying inside the startpoint and the endpoint of another function will be merged with the
other function
- Tail call optimizations are detected.
- PLT stubs are aligned by 16.
:return: None'

def make_functions(self):

    tmp_functions = self.kb.functions.copy()
    for function in tmp_functions.values():
        function.mark_nonreturning_calls_endpoints()
    self.kb.functions.clear()
    blockaddr_to_function = {}
    traversed_cfg_nodes = set()
    function_nodes = set()
    for (_, dst, data) in self.graph.edges_iter(data=True):
        jumpkind = data.get('jumpkind', '')
        if ((jumpkind == 'Ijk_Call') or jumpkind.startswith('Ijk_Sys')):
            function_nodes.add(dst)
    entry_node = self.get_any_node(self._binary.entry)
    if (entry_node is not None):
        function_nodes.add(entry_node)
    removed_functions = self._process_irrational_functions(tmp_functions, set([n.addr for n in function_nodes]), blockaddr_to_function)
    for n in self.graph.nodes_iter():
        if ((n.addr in tmp_functions) or (n.addr in removed_functions)):
            function_nodes.add(n)
    min_stage_2_progress = 50.0
    max_stage_2_progress = 90.0
    nodes_count = len(function_nodes)
    for (i, fn) in enumerate(sorted(function_nodes, key=(lambda n: n.addr))):
        if (self._show_progressbar or self._progress_callback):
            progress = (min_stage_2_progress + ((max_stage_2_progress - min_stage_2_progress) * ((i * 1.0) / nodes_count)))
            self._update_progress(progress)
        self._graph_bfs_custom(self.graph, [fn], self._graph_traversal_handler, blockaddr_to_function, tmp_functions, traversed_cfg_nodes)
    secondary_function_nodes = set()
    for func_addr in tmp_functions:
        node = self.get_any_node(func_addr)
        if (node is None):
            continue
        if (node.addr not in blockaddr_to_function):
            secondary_function_nodes.add(node)
    missing_cfg_nodes = (set(self.graph.nodes()) - traversed_cfg_nodes)
    missing_cfg_nodes = {node for node in missing_cfg_nodes if (node.function_address is not None)}
    if missing_cfg_nodes:
        l.debug('%d    CFGNodes    are    missing    in    the    first    traversal.', len(missing_cfg_nodes))
        secondary_function_nodes |= missing_cfg_nodes
    min_stage_3_progress = 90.0
    max_stage_3_progress = 99.9
    nodes_count = len(secondary_function_nodes)
    for (i, fn) in enumerate(sorted(secondary_function_nodes, key=(lambda n: n.addr))):
        if (self._show_progressbar or self._progress_callback):
            progress = (min_stage_3_progress + ((max_stage_3_progress - min_stage_3_progress) * ((i * 1.0) / nodes_count)))
            self._update_progress(progress)
        self._graph_bfs_custom(self.graph, [fn], self._graph_traversal_handler, blockaddr_to_function, tmp_functions)
    to_remove = set()
    for fn in self.kb.functions.values():
        addr = (fn.addr - (fn.addr % 16))
        if ((addr != fn.addr) and (addr in self.kb.functions) and self.kb.functions[addr].is_plt):
            to_remove.add(fn.addr)
    for function in self.kb.functions.values():
        if (function.startpoint is None):
            to_remove.add(function.addr)
    for addr in to_remove:
        del self.kb.functions[addr]
    for node in self._nodes.itervalues():
        if (node.addr in blockaddr_to_function):
            node.function_address = blockaddr_to_function[node.addr].addr
    for function in self.kb.functions.values():
        function.mark_nonreturning_calls_endpoints()
