[FEATURE] Implement the C runtime and libc required by the admitted toolchain #1

Open
opened 2026-09-12 07:56:26 +02:00 by erikinkinen · 0 comments
Owner

Problem and motivation

EriX-hosted compilers and supporting tools require C startup, allocation, per-thread errors, stdio and POSIX adapters. Existing native Rust stream helpers do not provide that C ABI or runtime behavior.

Proposed behavior and scope

Build documented libc artifacts, headers, startup objects and exports; implement the selected workload’s memory, stdio, file, process, thread, time and locale surfaces. Validate them through independent C probes, C/Rust interoperation and actual runtime workloads.

This issue records planned work; its unchecked criteria are not implementation proof. The normative basis is Phase 6 and AC1–AC24.

The bounded addition implements strnlen alone. Retained imports from the
selected Cargo and Bash artifacts require it; that evidence establishes demand,
not guest closure, call frequency or a symbol-version promise. The semantic
reference is POSIX.1-2024 strnlen.

Return the first NUL index below maximum, otherwise maximum, using the full
size_t count and result. Read only successive initialized bytes, stopping at
that NUL or before the bound. A bounded nonterminated array is valid. Positive
counts require live readable storage through the first NUL or the bound,
nonwrapping accessed addresses and preserved lifetime/concurrency rules. Do not
scan with strlen first, compute an unchecked end pointer, narrow the count or
impose an additional length cap. The function writes nothing, retains nothing,
uses no heap or service authority and leaves errno unchanged on valid input.

Zero maximum accesses no storage and returns zero. The namespaced raw EriX
interface may accept null only in this case; conventional C pointer validity
remains distinct, and no portable C/builtin null-pointer waiver is claimed.
This is not Annex K strnlen_s, recoverable invalid-pointer handling or complete
libc conformance.

Append one original scalar leaf and its zero-instruction C alias to the existing
query sources. Preserve the earlier 152-byte query prefix and complete memory,
writer and span instruction sections. Add matching Rustdoc, an unsafe Rust
declaration and the partial prefixed C header declaration. Keep all seventeen
prior functions and export policies; no dependency, native-consumer pin, host
fallback, feature macro or duplicate instruction owner changes.

Acceptance requires independent bounded-array oracles, all nonzero byte values,
unaligned and unchanged input, early/exact/outside-bound NUL cases, and owned
read-only guard pages that expose reads before or beyond accessible input.
Short valid strings with counts above 32 bits and at SIZE_MAX must expose count
truncation without pretending to validate a returned length above 32 bits.
Real C/Rust calls and callbacks, including pointer/count stack placement after
six scalar arguments, must preserve the full return width. Inspect actual
relocations, alias properties and emitted bytes; a separate old-seventeen
negative must isolate precisely the conventional and namespaced strnlen symbols.
Run the existing strict Rust, object/archive, independent-array, guard, producer
and link-negative matrix with finite original-owner limits. Update canonical
component documentation and matching manual/API after signed source publication.
The signed implementation and actual local results are recorded below; full libc and guest acceptance remain open.

Authority, security and reliability

Initialize solely from validated launch input and mediate operations through the caller’s posixd route. Document FFI pointer ownership and overflow behavior; do not add provider shortcuts, ambient discovery or host syscall fallback. Thread state and fork/exec cleanup must remain well-defined.

Apply the priority order: security, reliability, then performance. Keep suspected vulnerabilities in the repository’s restricted SECURITY.md reporting channel.

Acceptance criteria

  • Define static/shared libc artifacts, C headers, symbol/export versioning, startup
    objects, calling conventions and supported C language ABI.
  • Implement C entry/exit, argc/argv/env/auxiliary data, atexit and initialized
    runtime state from validated launch input; no ambient discovery.
  • Implement memory/string/byte functions with overlap/alignment/ zero-length/overflow
    tests and documented FFI pointer contracts.
  • Implement malloc/calloc/realloc/free/aligned allocation using kernel#1, covering
    ownership, failure atomicity, zeroing and threaded use.
  • Implement errno and error strings per thread with stable native error mapping;
    unrelated calls/threads must not overwrite each other's state.
  • Implement buffered stdio, formatting/scanning and conversion surfaces required by
    tools; cover partial I/O, flush-on-exit, stream locking, binary data, locale, numeric bounds
    and varargs ABI.
  • Implement libc file/directory/poll/terminal adapters over posixd; no direct
    provider routes or host-OS syscall fallback may bypass mediation.
  • Implement process/signal/thread adapters over reviewed native mechanisms; libc
    process-global state must have defined fork/exec behavior.
  • Implement time/sleep, locale/ctype/multibyte, environment, sorting, search and
    required math/runtime helpers with deterministic documented behavior.
  • Implement only required additional C/POSIX interfaces identified in integration#1; track
    every unsupported extension with explicit behavior and tool configuration/port justification,
    not success-returning stubs.
  • Build independent C conformance probes for layout, linking, constructors, TLS,
    allocation, stdio, files, threads, signals and process lifecycle.
  • Validate FFI safety and C/Rust interoperability under errors, malformed inputs and
    stress; publish rustdoc/header/manual contracts and pass full strict CI for lib-cstd and
    changed consumers.

For each implementation slice, retain actual formatting, strict Clippy, unit/doctest and warning-denied build results for all altered Rust repositories and valid configurations. Add relevant runtime VM coverage, monitor older unit/VM regressions in exact-head CI, and update canonical component documents and affected technical-manual/API material. Every authored code file must remain below 1,000 physical lines, with meaningful inline documentation and missing_docs enforcement in Rust crates.

Alternatives and tradeoffs

Success-returning stubs conceal missing semantics. Track unsupported extensions explicitly and justify tool configuration or ports, while implementing every required interface with real error and lifecycle behavior.

Tracking and rollout

Dependencies: lib-posixabi#1, posixd#2, kernel#1, posixd#3

Dependencies identify required contracts and closure gates; preparatory inventory/design can proceed in parallel under one owner per edited file. Link bounded implementation issues and their PRs here before claiming acceptance. Use feature/posix-compat, regular signed commits in the canonical contribution format, and WIP PRs linked to the exact coherent component graph. All cross-repository Cargo/catalog selections and CI helpers use full 40-character lowercase commit hashes, including transitive dependencies; do not substitute branch, tag or implicit HEAD selection.

Close criteria only with their own reviewed deliverables and validation evidence. Pending, skipped, cancelled, failed or predecessor-only results remain distinct. Keep main images unchanged until explicit promotion direction; technical completion does not authorize merges, release tags or publication.

Signed bdcbbea43550e8b99cd9a8221e4bc5a645637990 in PR #3 provides eighteen original byte/string operations. The new strnlen leaf preserves full-width count/result values, reads only through the first NUL or bound, and returns an exhausted bound before advancing the cursor again. It has no stack scratch, allocation, syscall, errno access or shared state; it obtains no authority and retains no pointer.

Rust 1.97.1 formatting, strict Clippy, warning-denied host/freestanding builds and private rustdoc pass. Actual local validation passes 132 Rust case executions (33 in each of four selections), 90 independent array cases, 23 producer controls and twelve mixed C/Rust programs. Guarded read-only ranges exercise NUL/count edges; real callbacks put full-width pointer/count arguments after six scalar words. Large bounds over short strings test input width, not returned lengths above 2^32. Forty intentional linker failures reject missing, duplicate and preceding companions; the isolated old-seventeen control requires exactly both new symbol names. The 178-byte query section retains its original 152-byte prefix, and the 234/136/344-byte other sections remain unchanged. All nine Markdown files, workflow syntax and final source checks pass without warnings.

Push CI 11 and PR CI 12 both pass for signed bdcbbea, ending by 05:40:42 UTC on September 13. All four complete logs are retained (64,532 bytes), with no compiler or lint warnings. Each runtime job completes the source-bound checker with 211 main commands, twelve host programs and forty intended link controls, including all four new length programs and four old-seventeen controls. The separate nested CI case counts and artifact bytes were not retrieved; the detailed Rust/array/producer totals remain local results. Each Markdown job checks nine files with zero errors. Matching Docs 7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00 is signed and pushed in Docs PR #4. Its original-source references select ABI 2417b283 and eighteen-function libc bdcbbea, with 161 and twenty API routes respectively. All 44 documentation tests, both API checks and 55 Markdown files pass. The complete 2,339-page manual passes in 154.64 seconds with zero final warnings; all 425,255 word boxes fit and nine actual previews pass visual review. The first render was interrupted by an outer watchdog that could not observe the inner log; its failed statuses and clean cleanup are retained. The corrected outer budget preserves the inner hard/progress limits, and passing API/unit checks were reused. Matching Docs push CI 837 and PR CI 838 both pass for signed 7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00, ending by 05:58:35 UTC on September 14. All four complete logs total 752,104 bytes and are correlated with the original workflow and build/publish scripts. Each manual job passes 44 tests and finishes at 2,339 pages with zero final-pass warnings; thirty first-pass and one second-pass convergence warnings resolve. Each Markdown job checks 55 files with zero errors. The logged CI PDF size is 4,105,617 bytes; CI artifact bytes and geometry were not independently inspected. Local layout and visual evidence remain separate. This adds no native metadata operation, companion migration or complete guest build result. Preceding push CI 9 and PR CI 10 pass for seventeen-function source4207509. Signed Docs 928ff81a1d6dea09145f49fd4fbe07ab84525000, its nineteen API routes, complete 2,331-page manual and passing CI 833/834 remain evidence for that preceding interface. The next manual/API update is tracked in Docs PR #4.

Integration PR #12 still selects memory-only lib-cstd 8270170c221260c444d923865461231e6ce622b2 for native kernel/shared links. At the native memory selection checkpoint, CI1587 passes all 486 catalog scenarios, development/release image construction, development disk reproducibility and both canonical boots before the separately reported release serial native-time failure (Integration #43). CI1588 fails the separately corrected host serial utility fixture (Integration #41); corrected-source CI remains pending. These consumers do not yet select the newer string routines. The partial interfaces leave the full memory/string criterion, libc, native workloads and complete build inside EriX open.

## Problem and motivation EriX-hosted compilers and supporting tools require C startup, allocation, per-thread errors, stdio and POSIX adapters. Existing native Rust stream helpers do not provide that C ABI or runtime behavior. ## Proposed behavior and scope Build documented libc artifacts, headers, startup objects and exports; implement the selected workload’s memory, stdio, file, process, thread, time and locale surfaces. Validate them through independent C probes, C/Rust interoperation and actual runtime workloads. This issue records planned work; its unchecked criteria are not implementation proof. The normative basis is [Phase 6 and AC1–AC24](https://git.erikinkinen.fi/erix/docs/src/branch/main/phases/6.md). The bounded addition implements `strnlen` alone. Retained imports from the selected Cargo and Bash artifacts require it; that evidence establishes demand, not guest closure, call frequency or a symbol-version promise. The semantic reference is [POSIX.1-2024 strnlen](https://pubs.opengroup.org/onlinepubs/9799919799/functions/strnlen.html). Return the first NUL index below `maximum`, otherwise `maximum`, using the full `size_t` count and result. Read only successive initialized bytes, stopping at that NUL or before the bound. A bounded nonterminated array is valid. Positive counts require live readable storage through the first NUL or the bound, nonwrapping accessed addresses and preserved lifetime/concurrency rules. Do not scan with strlen first, compute an unchecked end pointer, narrow the count or impose an additional length cap. The function writes nothing, retains nothing, uses no heap or service authority and leaves errno unchanged on valid input. Zero maximum accesses no storage and returns zero. The namespaced raw EriX interface may accept null only in this case; conventional C pointer validity remains distinct, and no portable C/builtin null-pointer waiver is claimed. This is not Annex K strnlen_s, recoverable invalid-pointer handling or complete libc conformance. Append one original scalar leaf and its zero-instruction C alias to the existing query sources. Preserve the earlier 152-byte query prefix and complete memory, writer and span instruction sections. Add matching Rustdoc, an unsafe Rust declaration and the partial prefixed C header declaration. Keep all seventeen prior functions and export policies; no dependency, native-consumer pin, host fallback, feature macro or duplicate instruction owner changes. Acceptance requires independent bounded-array oracles, all nonzero byte values, unaligned and unchanged input, early/exact/outside-bound NUL cases, and owned read-only guard pages that expose reads before or beyond accessible input. Short valid strings with counts above 32 bits and at SIZE_MAX must expose count truncation without pretending to validate a returned length above 32 bits. Real C/Rust calls and callbacks, including pointer/count stack placement after six scalar arguments, must preserve the full return width. Inspect actual relocations, alias properties and emitted bytes; a separate old-seventeen negative must isolate precisely the conventional and namespaced strnlen symbols. Run the existing strict Rust, object/archive, independent-array, guard, producer and link-negative matrix with finite original-owner limits. Update canonical component documentation and matching manual/API after signed source publication. The signed implementation and actual local results are recorded below; full libc and guest acceptance remain open. ## Authority, security and reliability Initialize solely from validated launch input and mediate operations through the caller’s posixd route. Document FFI pointer ownership and overflow behavior; do not add provider shortcuts, ambient discovery or host syscall fallback. Thread state and fork/exec cleanup must remain well-defined. Apply the priority order: security, reliability, then performance. Keep suspected vulnerabilities in the repository’s restricted SECURITY.md reporting channel. ## Acceptance criteria - [ ] Define static/shared libc artifacts, C headers, symbol/export versioning, startup objects, calling conventions and supported C language ABI. - [ ] Implement C entry/exit, argc/argv/env/auxiliary data, atexit and initialized runtime state from validated launch input; no ambient discovery. - [ ] Implement memory/string/byte functions with overlap/alignment/ zero-length/overflow tests and documented FFI pointer contracts. - [ ] Implement malloc/calloc/realloc/free/aligned allocation using [kernel#1](https://git.erikinkinen.fi/erix/kernel/issues/1), covering ownership, failure atomicity, zeroing and threaded use. - [ ] Implement errno and error strings per thread with stable native error mapping; unrelated calls/threads must not overwrite each other's state. - [ ] Implement buffered stdio, formatting/scanning and conversion surfaces required by tools; cover partial I/O, flush-on-exit, stream locking, binary data, locale, numeric bounds and varargs ABI. - [ ] Implement libc file/directory/poll/terminal adapters over `posixd`; no direct provider routes or host-OS syscall fallback may bypass mediation. - [ ] Implement process/signal/thread adapters over reviewed native mechanisms; libc process-global state must have defined fork/exec behavior. - [ ] Implement time/sleep, locale/ctype/multibyte, environment, sorting, search and required math/runtime helpers with deterministic documented behavior. - [ ] Implement only required additional C/POSIX interfaces identified in [integration#1](https://git.erikinkinen.fi/erix/integration/issues/1); track every unsupported extension with explicit behavior and tool configuration/port justification, not success-returning stubs. - [ ] Build independent C conformance probes for layout, linking, constructors, TLS, allocation, stdio, files, threads, signals and process lifecycle. - [ ] Validate FFI safety and C/Rust interoperability under errors, malformed inputs and stress; publish rustdoc/header/manual contracts and pass full strict CI for `lib-cstd` and changed consumers. For each implementation slice, retain actual formatting, strict Clippy, unit/doctest and warning-denied build results for all altered Rust repositories and valid configurations. Add relevant runtime VM coverage, monitor older unit/VM regressions in exact-head CI, and update canonical component documents and affected technical-manual/API material. Every authored code file must remain below 1,000 physical lines, with meaningful inline documentation and missing_docs enforcement in Rust crates. ## Alternatives and tradeoffs Success-returning stubs conceal missing semantics. Track unsupported extensions explicitly and justify tool configuration or ports, while implementing every required interface with real error and lifecycle behavior. ## Tracking and rollout Dependencies: [lib-posixabi#1](https://git.erikinkinen.fi/erix/lib-posixabi/issues/1), [posixd#2](https://git.erikinkinen.fi/erix/posixd/issues/2), [kernel#1](https://git.erikinkinen.fi/erix/kernel/issues/1), [posixd#3](https://git.erikinkinen.fi/erix/posixd/issues/3) Dependencies identify required contracts and closure gates; preparatory inventory/design can proceed in parallel under one owner per edited file. Link bounded implementation issues and their PRs here before claiming acceptance. Use `feature/posix-compat`, regular signed commits in the canonical contribution format, and WIP PRs linked to the exact coherent component graph. All cross-repository Cargo/catalog selections and CI helpers use full 40-character lowercase commit hashes, including transitive dependencies; do not substitute branch, tag or implicit HEAD selection. Close criteria only with their own reviewed deliverables and validation evidence. Pending, skipped, cancelled, failed or predecessor-only results remain distinct. Keep main images unchanged until explicit promotion direction; technical completion does not authorize merges, release tags or publication. Signed `bdcbbea43550e8b99cd9a8221e4bc5a645637990` in [PR #3](https://git.erikinkinen.fi/erix/lib-cstd/pulls/3) provides eighteen original byte/string operations. The new `strnlen` leaf preserves full-width count/result values, reads only through the first NUL or bound, and returns an exhausted bound before advancing the cursor again. It has no stack scratch, allocation, syscall, errno access or shared state; it obtains no authority and retains no pointer. Rust 1.97.1 formatting, strict Clippy, warning-denied host/freestanding builds and private rustdoc pass. Actual local validation passes 132 Rust case executions (33 in each of four selections), 90 independent array cases, 23 producer controls and twelve mixed C/Rust programs. Guarded read-only ranges exercise NUL/count edges; real callbacks put full-width pointer/count arguments after six scalar words. Large bounds over short strings test input width, not returned lengths above 2^32. Forty intentional linker failures reject missing, duplicate and preceding companions; the isolated old-seventeen control requires exactly both new symbol names. The 178-byte query section retains its original 152-byte prefix, and the 234/136/344-byte other sections remain unchanged. All nine Markdown files, workflow syntax and final source checks pass without warnings. [Push CI 11](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/11) and [PR CI 12](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/12) both pass for signed bdcbbea, ending by 05:40:42 UTC on September 13. All four complete logs are retained (64,532 bytes), with no compiler or lint warnings. Each runtime job completes the source-bound checker with 211 main commands, twelve host programs and forty intended link controls, including all four new length programs and four old-seventeen controls. The separate nested CI case counts and artifact bytes were not retrieved; the detailed Rust/array/producer totals remain local results. Each Markdown job checks nine files with zero errors. Matching Docs `7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00` is signed and pushed in [Docs PR #4](https://git.erikinkinen.fi/erix/docs/pulls/4). Its original-source references select ABI 2417b283 and eighteen-function libc bdcbbea, with 161 and twenty API routes respectively. All 44 documentation tests, both API checks and 55 Markdown files pass. The complete 2,339-page manual passes in 154.64 seconds with zero final warnings; all 425,255 word boxes fit and nine actual previews pass visual review. The first render was interrupted by an outer watchdog that could not observe the inner log; its failed statuses and clean cleanup are retained. The corrected outer budget preserves the inner hard/progress limits, and passing API/unit checks were reused. Matching Docs [push CI 837](https://git.erikinkinen.fi/erix/docs/actions/runs/837) and [PR CI 838](https://git.erikinkinen.fi/erix/docs/actions/runs/838) both pass for signed `7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00`, ending by 05:58:35 UTC on September 14. All four complete logs total 752,104 bytes and are correlated with the original workflow and build/publish scripts. Each manual job passes 44 tests and finishes at 2,339 pages with zero final-pass warnings; thirty first-pass and one second-pass convergence warnings resolve. Each Markdown job checks 55 files with zero errors. The logged CI PDF size is 4,105,617 bytes; CI artifact bytes and geometry were not independently inspected. Local layout and visual evidence remain separate. This adds no native metadata operation, companion migration or complete guest build result. Preceding [push CI 9](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/9) and [PR CI 10](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/10) pass for seventeen-function source4207509. Signed Docs `928ff81a1d6dea09145f49fd4fbe07ab84525000`, its nineteen API routes, complete 2,331-page manual and passing [CI 833](https://git.erikinkinen.fi/erix/docs/actions/runs/833)/[834](https://git.erikinkinen.fi/erix/docs/actions/runs/834) remain evidence for that preceding interface. The next manual/API update is tracked in [Docs PR #4](https://git.erikinkinen.fi/erix/docs/pulls/4). [Integration PR #12](https://git.erikinkinen.fi/erix/integration/pulls/12) still selects memory-only lib-cstd `8270170c221260c444d923865461231e6ce622b2` for native kernel/shared links. At the native memory selection checkpoint, CI1587 passes all 486 catalog scenarios, development/release image construction, development disk reproducibility and both canonical boots before the separately reported release serial native-time failure ([Integration #43](https://git.erikinkinen.fi/erix/integration/issues/43)). CI1588 fails the separately corrected host serial utility fixture ([Integration #41](https://git.erikinkinen.fi/erix/integration/issues/41)); corrected-source CI remains pending. These consumers do not yet select the newer string routines. The partial interfaces leave the full memory/string criterion, libc, native workloads and complete build inside EriX open.
erikinkinen changed title from [FEATURE] [P10] Implement the C runtime and libc required by the admitted toolchain to [FEATURE] Implement the C runtime and libc required by the admitted toolchain 2026-09-12 08:02:05 +02:00
Sign in to join this conversation.
No description provided.