docs: def _shrink_node(self, node, new_size, remove_function=True):
          """
          Shrink the size of a node in CFG.
  
          :param CFGNode node: The CFGNode to shrink
          :param int new_size: The new size of the basic block
          :param bool remove_function: If there is a function starting at `node`, should we remove that function or not.
          :return: None
          """
  
          # Generate the new node
          new_node = CFGNode(node.addr, new_size, self.model,
                             function_address=None if remove_function else node.function_address,
                             instruction_addrs=[i for i in node.instruction_addrs
                                                       if node.addr <= i < node.addr + new_size
                                                     ],
                             thumb=node.thumb,
                             byte_string=None if node.byte_string is None else node.byte_string[:new_size],
                             block_id=node.addr,
                             )
  
          old_in_edges = self.graph.in_edges(node, data=True)
  
          for src, _, data in old_in_edges:
              self.graph.add_edge(src, new_node, **data)
  
          successor_node_addr = node.addr + new_size
          if successor_node_addr in self._nodes:
              successor = self._nodes[successor_node_addr]
          else:
              successor_size = node.size - new_size
              successor = CFGNode(successor_node_addr, successor_size, self.model,
                                  function_address=successor_node_addr if remove_function else node.function_address,
                                  instruction_addrs=[i for i in node.instruction_addrs if i >= node.addr + new_size],
                                  thumb=node.thumb,
                                  byte_string=None if node.byte_string is None else node.byte_string[new_size:]
                                  )
          self.graph.add_edge(new_node, successor, jumpkind='Ijk_Boring')
  
          # if the node B already has resolved targets, we will skip all unresolvable successors when adding old out edges
          # from node A to node B.
          # this matters in cases where node B is resolved as a special indirect jump entry (like a PLT stub), but (node
          # A + node B) wasn't properly resolved.
          unresolvable_target_addrs = (self._unresolvable_jump_target_addr, self._unresolvable_call_target_addr)
  
          has_resolved_targets = any([ node_.addr not in unresolvable_target_addrs
                                       for node_ in self.graph.successors(successor) ]
                                     )
  
          old_out_edges = self.graph.out_edges(node, data=True)
          for _, dst, data in old_out_edges:
              if (has_resolved_targets and dst.addr not in unresolvable_target_addrs) or \
                      not has_resolved_targets:
                  self.graph.add_edge(successor, dst, **data)
  
          # remove the old node from indices
          if node.addr in self._nodes and self._nodes[node.addr] is node:
              del self._nodes[node.addr]
          if node.addr in self._nodes_by_addr and node in self._nodes_by_addr[node.addr]:
              self._nodes_by_addr[node.addr].remove(node)
  
          # remove the old node form the graph
          self.graph.remove_node(node)
  
          # add the new node to indices
          self._nodes[new_node.addr] = new_node
          self._nodes_by_addr[new_node.addr].append(new_node)
  
          # the function starting at this point is probably totally incorrect
          # hopefull future call to `make_functions()` will correct everything
          if node.addr in self.kb.functions:
              del self.kb.functions[node.addr]
  
              if not remove_function:
                  # add functions back
                  self._function_add_node(node, node.addr)
                  successor_node = self.model.get_any_node(successor_node_addr)
                  if successor_node and successor_node.function_address == node.addr:
                      # if there is absolutely no predecessors to successor_node, we'd like to add it as a new function
                      # so that it will not be left behind
                      if not list(self.graph.predecessors(successor_node)):
                          self._function_add_node(successor_node, successor_node_addr)