'Checks the hooking procedure for this address searching for new static
exit points to add to successors (generating entries for them)
if this address has not been traced before. Updates previous CFG nodes
with edges.
:param int addr: The address to begin scanning
:param int current_function_addr: Address of the current function
:param str previous_jumpkind: The jumpkind of the edge going to this node
:param CFGNode previous_src_node: The previous CFGNode
:param int previous_src_stmt_idx: The previous ID of the statement.
:return: List of successors
:rtype: list'

def _scan_procedure(self, addr, current_function_addr, previous_jumpkind, previous_src_node, previous_src_ins_addr, previous_src_stmt_idx):

    try:
        if self.project.is_hooked(addr):
            procedure = self.project.hooked_by(addr)
            name = procedure.display_name
        else:
            procedure = self.project._simos.syscall_from_addr(addr)
            name = procedure.display_name
        if (addr not in self._nodes):
            cfg_node = CFGNode(addr, 0, self, function_address=current_function_addr, simprocedure_name=name, no_ret=procedure.NO_RET, block_id=addr)
            self._nodes[addr] = cfg_node
            self._nodes_by_addr[addr].append(cfg_node)
        else:
            cfg_node = self._nodes[addr]
    except (SimMemoryError, SimEngineError):
        return []
    self._graph_add_edge(cfg_node, previous_src_node, previous_jumpkind, previous_src_ins_addr, previous_src_stmt_idx)
    self._function_add_node(addr, current_function_addr)
    self._changed_functions.add(current_function_addr)
    if (addr in self._traced_addresses):
        return []
    else:
        self._traced_addresses.add(addr)
    entries = []
    if procedure.ADDS_EXITS:
        grandparent_nodes = self.graph.predecessors(previous_src_node)
        if (not grandparent_nodes):
            l.warning('%s    is    supposed    to    yield    new    exits,    but    it    fails    to    do    so.', name)
            return []
        blocks_ahead = [self.project.factory.block(grandparent_nodes[0].addr).vex, self.project.factory.block(previous_src_node.addr).vex]
        procedure.project = self.project
        procedure.arch = self.project.arch
        new_exits = procedure.static_exits(blocks_ahead)
        for (addr_, jumpkind) in new_exits:
            if (isinstance(addr_, claripy.ast.BV) and (not addr_.symbolic)):
                addr_ = addr_._model_concrete.value
            if (not isinstance(addr_, (int, long))):
                continue
            entries += self._create_jobs(addr_, jumpkind, current_function_addr, None, addr_, cfg_node, None, None)
    if (not procedure.NO_RET):
        cfg_node.has_return = True
        self._function_exits[current_function_addr].add(addr)
        self._function_add_return_site(addr, current_function_addr)
    return entries
