LoadCommand* Binary::add(const LoadCommand& command, size_t index) {
  static constexpr uint32_t shift_value = 0x4000;

  // If index is "too" large <=> push_back
  if (index >= commands_.size()) {
    return add(command);
  }

  int32_t size_aligned = align(command.size(), pointer_size());
  LIEF_DEBUG("available_command_space_: 0x{:06x} (required: 0x{:06x})",
             available_command_space_, size_aligned);

  // Check that we have enough space
  if (available_command_space_ <= size_aligned) {
    shift(shift_value);
    available_command_space_ += shift_value;
    return add(command, index);
  }
  LIEF_DEBUG("No need to shift");

  available_command_space_ -= size_aligned;


  // Update the Header according to the new command
  Header& header = this->header();

  header.sizeof_cmds(header.sizeof_cmds() + size_aligned);
  header.nb_cmds(header.nb_cmds() + 1);

  // Get offset of the LC border
  LoadCommand* cmd_border = commands_[index].get();
  size_t border_off = cmd_border->command_offset();

  std::unique_ptr<LoadCommand> copy{command.clone()};
  copy->command_offset(cmd_border->command_offset());

  // Patch LC offsets that follow the LC border
  for (std::unique_ptr<LoadCommand>& lc : commands_) {
    if (lc->command_offset() >= border_off) {
      lc->command_offset(lc->command_offset() + size_aligned);
    }
  }

  if (DylibCommand::classof(copy.get())) {
    libraries_.push_back(copy->as<DylibCommand>());
  }

  if (SegmentCommand::classof(copy.get())) {
    add_cached_segment(*copy->as<SegmentCommand>());
  }
  LoadCommand* copy_ptr = copy.get();
  commands_.insert(std::begin(commands_) + index, std::move(copy));
  return copy_ptr;
}
LoadCommand* Binary::add(const LoadCommand& command, size_t index) {
  static constexpr uint32_t shift_value = 0x4000;

   
  if (index >= commands_.size()) {
    return add(command);
  }

  int32_t size_aligned = align(command.size(), pointer_size());
  LIEF_DEBUG("available_command_space_: 0x{:06x} (required: 0x{:06x})",
             available_command_space_, size_aligned);

   
  if (available_command_space_ <= size_aligned) {
    shift(shift_value);
    available_command_space_ += shift_value;
    return add(command, index);
  }
  LIEF_DEBUG("No need to shift");

  available_command_space_ -= size_aligned;


   
  Header& header = this->header();

  header.sizeof_cmds(header.sizeof_cmds() + size_aligned);
  header.nb_cmds(header.nb_cmds() + 1);

   
  LoadCommand* cmd_border = commands_[index].get();
  size_t border_off = cmd_border->command_offset();

  std::unique_ptr<LoadCommand> copy{command.clone()};
  copy->command_offset(cmd_border->command_offset());

   
  for (std::unique_ptr<LoadCommand>& lc : commands_) {
    if (lc->command_offset() >= border_off) {
      lc->command_offset(lc->command_offset() + size_aligned);
    }
  }

  if (DylibCommand::classof(copy.get())) {
    libraries_.push_back(copy->as<DylibCommand>());
  }

  if (SegmentCommand::classof(copy.get())) {
    add_cached_segment(*copy->as<SegmentCommand>());
  }
  LoadCommand* copy_ptr = copy.get();
  commands_.insert(std::begin(commands_) + index, std::move(copy));
  return copy_ptr;
}