Archive Format Guide
0x0 static archives use the standard Unix archive container with deterministic
GNU-style symbol indexes. The repository-owned writer is tools/zero-ar.py;
host ar is not part of the production archive path.
Command Line
zero-ar cr output.a object...
zero-ar t output.a
zero-ar symbols output.a
zero-ar cr writes:
- the
!<arch>\nglobal header; - a
/symbol index member; - one deterministic member header per input object;
- original compiler-emitted object bytes as member payloads;
- newline padding for odd-sized members.
The writer computes the symbol index and deterministic member offsets before
opening the output stream. During symbol-index construction it reads only the
ELF header, section headers, string table, and symbol table needed to discover
defined global function symbols. It then writes the global header, index member,
and each object member sequentially from the input object files. The writer has
no whole-object byte-buffer parser in the archive creation path; it streams
object member payloads instead of retaining a full archive-sized live set. The
final archive is not materialized as one whole-archive byte value. Completed
archives are written to a same-directory temporary file and atomically replace
the requested output path only after the stream closes successfully.
Every header uses timestamp 0, uid 0, gid 0, and mode 0644. Member size fields are decimal non-negative byte counts. Member ordering follows command-line object order. Long member names are rejected until the project owns a long-name table. Member basenames must be unique within an archive so linker diagnostics and selected-member labels are unambiguous.
Symbol Index
The / member stores:
- big-endian
u32symbol count; - one big-endian
u32archive member offset per symbol; - NUL-terminated UTF-8 symbol names.
Only defined global function and data symbols from compiler-emitted ELF objects
enter the index. Local symbols such as .text.local are retained in the object
symbol table for inspection but are not exported through the archive index.
Duplicate archive symbols are rejected by the writer with:
duplicate archive symbol: <name>
Diagnostics
Archive and object diagnostics are stable enough for tests:
unsupported object: missing ELF magic
malformed object: ELF header out of range
unsupported object: expected ELF64 little-endian
unsupported object: expected System V ELF ABI
unsupported object: expected clear ELF ident padding
unsupported object: expected ELF version 1
unsupported object: expected 64-byte ELF header
unsupported object: expected ET_REL
unsupported object: expected clear ELF flags
unsupported object: expected no entry point
unsupported object: expected no program headers
unsupported object: expected 64-byte section headers
unsupported object: expected STRTAB section names
unsupported object: expected SYMTAB .symtab
unsupported object: expected STRTAB symbol strings
unsupported object: expected 24-byte symbols
unsupported object: expected PROGBITS .text
unsupported object: expected PROGBITS .rodata
unsupported object: expected PROGBITS .data
unsupported object: expected NOBITS .bss
unsupported object: expected AX .text
unsupported object: expected A .rodata
unsupported object: expected WA .data
unsupported object: expected WA .bss
unsupported object: expected metadata flags clear <section>
unsupported object: expected x86-64
malformed object: section header table out of range
malformed object: invalid shstrndx
malformed object: section payload out of range
malformed object: section payloads overlap
malformed object: section name offset out of range
malformed object: duplicate section: <name>
malformed object: section alignment missing
malformed object: section alignment not power of two
malformed object: section alignment mismatch
malformed object: symtab string link out of range
malformed object: symbol name offset out of range
malformed object: unnamed defined symbol
malformed object: unnamed undefined symbol
malformed object: duplicate defined symbol: <name>
malformed object: symbol section index out of range
unsupported object: expected symbol in loadable section
malformed object: undefined symbol payload nonzero
malformed object: symbol range out of section
malformed object: string table missing initial NUL
malformed object: string table entry missing NUL
malformed object: string table entry is not UTF-8
malformed object: symbol table size not aligned
malformed object: symtab local info out of range
malformed object: missing null symbol
malformed object: invalid null symbol
malformed object: invalid null section
unsupported object: expected default symbol visibility
unsupported object: expected local/global symbol binding
malformed object: symbol binding order mismatch
unsupported object: expected function/object symbol type
malformed archive: <path> missing global header
input object not found: <path>
archive not found: <path>
output directory not found: <path>
output path is a directory: <path>
temporary output path is a symlink: <path>
temporary output path is a directory: <path>
malformed archive: <path> invalid member header
malformed archive: <path> non-deterministic member header
malformed archive: <path> invalid member name
malformed archive: <path> member name is not UTF-8
malformed archive: <path> member name is not ASCII
unsupported archive: <path> long member names
archive member name is not ASCII: <name>
duplicate archive member: <name>
malformed archive: <path> duplicate member name: <name>
malformed archive: <path> invalid member size
malformed archive: <path> truncated member
malformed archive: <path> missing member padding
malformed archive: <path> invalid member padding
malformed archive: <path> empty symbol index
unsupported archive: <path> missing symbol index
malformed archive: <path> symbol index must be first
malformed archive: <path> duplicate symbol index
malformed archive: <path> symbol index member mismatch: <name>
malformed archive: <path> truncated symbol index
malformed archive: <path> truncated symbol names
malformed archive: <path> extra symbol names
malformed archive: <path> symbol index offset out of range
malformed archive: <path> empty symbol name
malformed archive: <path> symbol name is not UTF-8
duplicate archive symbol: <name>
Linker Use
zero-link reads the archive symbol index directly. It starts from direct input
objects and the required main symbol, then extracts archive members only when
their indexed symbol satisfies an unresolved relocation or entry requirement.
The linker keeps member offsets and sizes from the archive header and reads the
selected member bytes only when they are needed.
The current gate compares an archive-linked executable against the same direct
object link. The outputs must match byte-for-byte, proving unused archive
members were not linked.
Validation
make archive-source-check verifies that zero-ar's source-level contract for
deterministic Unix archive layout, GNU-style symbol index encoding, object
symbol extraction, duplicate symbol rejection, diagnostics, and documented
tests stays synchronized with release metadata.
make memory-architecture-check verifies the archive writer's RAM contract:
member payloads must be streamed to the output file with deterministic padding
rather than joined into a whole-archive byte string. The same gate verifies
archive readers keep member payloads lazy until symbol resolution selects them
and archive creation scans ELF symbol metadata without reading whole object
payloads.
make archive-check verifies:
- deterministic archive bytes;
- indexed helper and unused symbols, without local
.text.localentries; zero-linkarchive extraction through the symbol index;- byte-identical output between direct object linking and archive linking;
- missing archive symbol diagnostics;
- duplicate archive symbol diagnostics.
make archive-diagnostics-check verifies malformed object metadata rejection
in zero-ar cr and malformed archive rejection in zero-ar t and
zero-ar symbols without invoking the compiler or linker.
make lib0x0-archive-fixture-check verifies the release-metadata fixture path
without compiling the compiler. It constructs ABI-compatible runtime and user
objects, builds a deterministic lib0x0.a with zero-ar, checks the symbol
index, links through zero-link, compares archive-linked and direct-linked
executables byte-for-byte, runs the linked result, and hashes every fixture
artifact for release review. The same fixture builds a data-only archive member
and proves STT_OBJECT symbols in the archive index can cause member
extraction.
make lib0x0-archive-check verifies the first runtime archive artifact:
runtime/lib0x0.a
The archive is built from compiler-emitted runtime/lib0x0_abi.0x0 object bytes
and linked by zero-link into a user executable.