// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/ld/processargs.h>
#include <lib/zircon-internal/unique-backtrace.h>
#include <zircon/assert.h>
#include <zircon/startup.h>

#include <cinttypes>
#include <cstddef>
#include <new>

#include "../zircon/vmar.h"
#include "processargs.h"

namespace LIBC_NAMESPACE_DECL {
namespace {

using Buffer = Processargs::Buffer;

// Each string table is just concatenated NUL-terminated strings.  There's no
// way to determine the size of the whole table before scanning it.  But it
// won't be scanned until it's being copied.  That's done by considering the
// tail of the message to be a single string table that goes from the
// earliest of the individual string tables to the end of the whole message.
uint32_t StrtabStart(const Buffer& buffer, Buffer::Actual actual) {
  uint32_t first_strtab = std::min({
      buffer.header.args_off,
      buffer.header.environ_off,
      buffer.header.names_off,
  });
  return std::min(first_strtab, actual.bytes);
}

size_t AllocationSize(const Buffer& buffer, Buffer::Actual actual, uint32_t strtab_off) {
  size_t size = sizeof(Processargs);

  // There are nullptr terminators after argv().last() and envp.last().
  size += (buffer.header.args_num + 1) * sizeof(char*);
  size += (buffer.header.environ_num + 1) * sizeof(char*);

  // That's followed by two more zero words to stand in for the traditional
  // ELF-based Unix layout where the envp array is followed by the auxv array
  // of two-word entries AT_NULL (zero) being the terminator.  This wastes
  // only two words just in case some program tries to look past envp[envc]
  // for an absent auxv.
  size += 2 * sizeof(char*);

  // Then there's space for the handle-indexed arrays.
  size += actual.handles * (sizeof(uint32_t) + sizeof(zx_handle_t));

  // And finally the strings.
  size += actual.bytes - strtab_off;

  return size;
}

}  // namespace

// This is only called here, so it doesn't need to be in the header.
Processargs::Processargs(const Buffer& msg, std::span<const zx_handle_t> msg_handles,
                         Buffer::Actual actual, uint32_t strtab_off)
    : argc_{msg.header.args_num},
      envc_{msg.header.environ_num},
      namec_{msg.header.names_num},
      handlec_{actual.handles},
      strtab_size_{actual.bytes - strtab_off} {
  // Copy the handles and the handle info table.
  assert(msg_handles.size() == handles().size());
  std::ranges::copy(msg_handles, handles().begin());
  std::ranges::copy(msg.handle_info(actual.handles), handle_info().begin());

  // The copied strings will go after those tables.
  uint32_t* arrays_end = handle_arrays().data() + handle_arrays().size();
  std::span strtab{reinterpret_cast<char*>(arrays_end), strtab_size_};

  // Fill the string arrays while copying the strings.
  auto fill_array = [&strtab](std::span<char*> array) {
    return [it = array.begin(), &strtab](std::string_view str) mutable {
      size_t len = str.copy(strtab.data(), strtab.size());
      *it++ = strtab.data();
      // The block is zero-initialized, so there's a NUL terminator already.
      strtab = strtab.subspan(len + 1);
    };
  };

  // The array sizes can be reduced if the message is truncated.
  argc_ = msg.GetArgsStrings(actual.bytes, fill_array(argv()));
  envc_ = msg.GetEnvStrings(actual.bytes, fill_array(envp()));
  namec_ = msg.GetNameStrings(actual.bytes, fill_array(names()));
}

zx_startup_handles_t Processargs::GetHandles(zx_handle_t bootstrap_handle) {
  zx::channel bootstrap{bootstrap_handle};

  // First just check the size of the incoming message without reading it.
  Processargs::Buffer::Actual actual;
  if (zx::result peek = Processargs::Buffer::Peek(bootstrap.borrow()); peek.is_ok()) [[likely]] {
    actual = *peek;
  } else {
    ZX_PANIC("cannot fetch bootstrap message size: %s", peek.status_string());
  }

  // Use stack space for the message and handles buffers.
  alignas(Processargs::Buffer) std::byte buffer[actual.bytes];
  zx_handle_t handles_buffer[actual.handles];
  Processargs::Buffer* message = new (buffer) Processargs::Buffer;
  std::span handles{handles_buffer, actual.handles};

  // Now read the message onto the stack.
  if (zx::result read = message->ReadAfterPeek(bootstrap.borrow(), actual, handles);
      read.is_error()) [[unlikely]] {
    ZX_PANIC("cannot read bootstrap message of %" PRIu32 " bytes, %" PRIu32 " handles: %s",
             actual.bytes, actual.handles, read.status_string());
  }

  if (!message->Valid(actual)) [[unlikely]] {
    ZX_PANIC(
        "invalid zx_proc_args_t format in bootstrap message"
        " of %" PRIu32 " bytes, %" PRIu32 " handles",
        actual.bytes, actual.handles);
  }

  // Collect the essential handles consumed by basic libc startup.
  zx_startup_handles_t startup_handles = {};
  std::span handle_info = message->handle_info(actual.handles);
  for (auto [info, take] : Processargs::HandleTakers(handle_info, handles)) {
    switch (PA_HND_TYPE(info)) {
      case PA_PROC_SELF:
        startup_handles.process_self = take().release();
        continue;
      case PA_THREAD_SELF:
        startup_handles.thread_self = take().release();
        continue;
      case PA_VMAR_ROOT:
        startup_handles.allocation_vmar = take().release();
        continue;
      case PA_VMAR_LOADED:
        startup_handles.executable_image_vmar = take().release();
        continue;
      default:  // Everything else will be picked up in the second phase.
        break;
    }
  }

  zx::unowned_vmar vmar{startup_handles.allocation_vmar};
  if (!*vmar) [[unlikely]] {
    ZX_PANIC("no root VMAR in processargs message; cannot allocate memory");
  }

  // Allocate a block to contain the saved data.
  PageRoundedSize guard_size{1};
  const uint32_t strtab_off = StrtabStart(*message, actual);
  const PageRoundedSize block_size{AllocationSize(*message, actual, strtab_off)};
  zx::result vmo = AllocationVmo::New(block_size);
  if (vmo.is_error()) [[unlikely]] {
    ZX_PANIC("cannot allocate VMO %zu bytes for process arguments", block_size.get());
  }
  GuardedPageBlock block;
  zx::result allocate = block.Allocate<Processargs>(  //
      vmar->borrow(), *vmo, block_size, guard_size, guard_size);
  if (allocate.is_error()) [[unlikely]] {
    ZX_PANIC("cannot map block of %zu bytes for process arguments", block_size.get());
  }

  // Save everything into the new block.
  startup_handles.hook = new (allocate->data()) Processargs(  //
      *message, handles, actual, strtab_off);

  // The block will never be freed; its ownership is no longer tracked.
  std::ignore = block.release();

  return startup_handles;
}

}  // namespace LIBC_NAMESPACE_DECL

// Give it the <zircon/startup.h> name too.
decltype(_zx_startup_get_handles) _zx_startup_get_handles
    [[gnu::alias(LIBC_ASM_LINKAGE_STRING(ProcessargsGetHandles))]];
