Skip to content

[nvx] E: Cut over to nvx-crt0 startup crate#25

Open
esaurez wants to merge 1 commit into
feat/nvx-crt0-skeletonfrom
feat/nvx-crt0-cutover
Open

[nvx] E: Cut over to nvx-crt0 startup crate#25
esaurez wants to merge 1 commit into
feat/nvx-crt0-skeletonfrom
feat/nvx-crt0-cutover

Conversation

@esaurez

@esaurez esaurez commented May 29, 2026

Copy link
Copy Markdown
Owner

[nvx] E: Cut over to nvx-crt0 startup crate

Completes PR-11 by moving the executable startup code (_do_start / _start / c_trampoline / ARGC/ARGV / environ / __nanvix_env_init invocation / argp/envp parsing) out of nvx exclusively into the nvx-crt0 crate that was added in PR-11a (#24).

After this commit:

  • libposix.a no longer contains _start / _do_start / main UND, so it is safe to embed in .so shared objects.
  • libnvx_crt0.a becomes the sole provider of those symbols and must be linked (under --whole-archive) into every guest executable.
  • The ad-hoc objcopy --weaken-symbol=main post-link hook (the POST_STATICLIB_HOOK_posix macro in build/make/generic-guest-staticlibs.mk) is no longer required and is removed.

What changed:

  • src/libs/nvx trimmed to pub mod pie + pub fn init() / pub fn cleanup() + panic handler. Removed default staticlib / standalone features that previously gated the startup code. Module-level docs point readers to nvx-crt0.
  • src/libs/posix: dropped staticlib = ["nvx/staticlib"] feature and the corresponding staticlib default. pwd / utime / sys::ioctl #[cfg(all(syscall, staticlib))] simplified to #[cfg(syscall)] (same effective behaviour: syscall was always on whenever staticlib was).
  • 29 Rust no_std guest binaries (benchmarks / daemons / tests / hello) now declare nvx-crt0 = { workspace = true, features = ["rust-main"] } plus the matching log-level feature forwarding (trace / debug / info / warn / error / panic). Each main.rs adds extern crate nvx_crt0; so the static lib is force-loaded.
  • 5 binaries that read the kernel argv blob directly migrated from nvx::ARGC / nvx::ARGV to nvx_crt0::ARGC / nvx_crt0::ARGV.
  • 3 binaries that pulled nvx/standalone (mount-bench / mount-test / mount-multipart-test) dropped that feature — standalone-mode gating now lives entirely in the application crate.
  • build/make/generic-guest-staticlibs.mk: dropped staticlib from the default GUEST_STATICLIB_FEATURES and deleted POST_STATICLIB_HOOK_posix plus both call sites.

Validated end-to-end:

  • hello-c (single ELF, multi-process mode) prints expected output.
  • hello-cpp (libstdc++ static ctors + _init / _fini) works.
  • envtest (argv / environ / getenv) works.
  • hello-c in standalone+ramfs mode works.
  • CPython hello + lxml + HTTP-server smoke tests PASS in standalone mode (483 ms hello execution) when paired with PR-11b-cpython ([nanvix] E: Link libnvx_crt0.a into python.elf cpython#2) which adds $(LIBNVX_CRT0) to python.elf's LIBS. See dependency note below.

IMPORTANT downstream dependency:

After this commit, any C executable that previously relied on libposix.a's _start MUST be relinked against libnvx_crt0.a under --whole-archive. Without it, the link silently succeeds (no undefined-reference error) because libc.a ships a WEAK fallback _start from newlib — but the resulting binary hangs at runtime, as the newlib default _start does not understand Nanvix's process-spawn trap-frame layout. The matching CPython change is PR-11b-cpython (esaurez/cpython#2, stacked on esaurez/cpython#1 / PR-10).

Stacked on PR-11a (#24).

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Completes PR-11 by moving the executable startup code (`_do_start` /
`_start` / `c_trampoline` / ARGC/ARGV / `environ` /
`__nanvix_env_init` invocation / argp/envp parsing) out of `nvx`
exclusively into the `nvx-crt0` crate that was added in PR-11a (#24).

After this commit:

  - `libposix.a` no longer contains `_start` / `_do_start` / `main`
    UND, so it is safe to embed in `.so` shared objects.
  - `libnvx_crt0.a` becomes the sole provider of those symbols and
    must be linked (under `--whole-archive`) into every guest
    executable.
  - The ad-hoc `objcopy --weaken-symbol=main` post-link hook (the
    `POST_STATICLIB_HOOK_posix` macro in
    `build/make/generic-guest-staticlibs.mk`) is no longer required
    and is removed.

What changed:

  - `src/libs/nvx` trimmed to `pub mod pie` + `pub fn init()` /
    `pub fn cleanup()` + panic handler.  Removed default
    `staticlib` / `standalone` features that previously gated the
    startup code.  Module-level docs point readers to `nvx-crt0`.
  - `src/libs/posix`: dropped `staticlib = ["nvx/staticlib"]` feature
    and the corresponding `staticlib` default.  `pwd` / `utime` /
    `sys::ioctl` `#[cfg(all(syscall, staticlib))]` simplified to
    `#[cfg(syscall)]` (same effective behaviour: `syscall` was
    always on whenever `staticlib` was).
  - 29 Rust no_std guest binaries (benchmarks / daemons / tests / hello)
    now declare `nvx-crt0 = { workspace = true, features =
    ["rust-main"] }` plus the matching log-level feature forwarding
    (`trace` / `debug` / `info` / `warn` / `error` /
    `panic`).  Each `main.rs` adds `extern crate nvx_crt0;` so
    the static lib is force-loaded.
  - 5 binaries that read the kernel argv blob directly migrated from
    `nvx::ARGC` / `nvx::ARGV` to `nvx_crt0::ARGC` /
    `nvx_crt0::ARGV`.
  - 3 binaries that pulled `nvx/standalone` (mount-bench / mount-test /
    mount-multipart-test) dropped that feature -- standalone-mode
    gating now lives entirely in the application crate.
  - `build/make/generic-guest-staticlibs.mk`: dropped `staticlib`
    from the default `GUEST_STATICLIB_FEATURES` and deleted
    `POST_STATICLIB_HOOK_posix` plus both call sites.

Validated end-to-end:

  - `hello-c` (single ELF, multi-process mode) prints expected output.
  - `hello-cpp` (libstdc++ static ctors + `_init`/`_fini`) works.
  - `envtest` (argv / environ / getenv) works.
  - `hello-c` in standalone+ramfs mode works.
  - CPython hello + lxml + HTTP-server smoke tests PASS in standalone
    mode (483 ms hello execution) when paired with PR-11b-cpython
    (esaurez/cpython#2) which adds $(LIBNVX_CRT0) to python.elf's
    LIBS.  See dependency note below.

IMPORTANT downstream dependency:

  After this commit, any C executable that previously relied on
  `libposix.a`'s `_start` MUST be relinked against
  `libnvx_crt0.a` under `--whole-archive`.  Without it, the link
  silently succeeds (no undefined-reference error) because
  `libc.a` ships a WEAK fallback `_start` from newlib -- but the
  resulting binary hangs at runtime, as the newlib default `_start`
  does not understand Nanvix's process-spawn trap-frame layout.  The
  matching CPython change is PR-11b-cpython (esaurez/cpython#2,
  stacked on esaurez/cpython#1 / PR-10).

Stacked on PR-11a (#24).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant