Skip to content

edg: -C on the archive too, and the finalization pair EDG leaves open - #618

Merged
staalmannen merged 1 commit into
mainfrom
claude/upgrade-ape-c-library-mmZGd
Oct 8, 2026
Merged

staalmannen merged 1 commit into
mainfrom
claude/upgrade-ape-c-library-mmZGd

Conversation

@staalmannen

Copy link
Copy Markdown
Owner

cpfe linked and then crashed on every run with fault read addr=0x2 pc=0x2'. lib_src/main.c' defines void _main(void)' -- EDG's static-init helper, the one a target's own crt is expected to call -- and _main' is 6l's default entry point (6l/obj.c:305' INITENTRY = "_main"; arch/amd64/main9.s:3' TEXT _main(SB)). 6l makes that name an SXREF at startup and satisfies it from the first archive on the link line that defines it, and `cmd/edg' names libedg.a ahead of libap. So the program's entry became EDG's helper: it ran _Z12__call_ctorsv, which returns immediately (vars.c:49 has __head null and munch_ctors.c defines _ctors[1] = {0}), and then executed a plain RET.

main9.s reads the kernel's argument block at 0(SP), so 0(SP) at entry holds argc -- which is what that RET popped and jumped to. cpfe --help' is argc 2. Falsifiable with no rebuild: cpfe' alone must have given pc=0x1 and `cpfe a b c' pc=0x4.

-C is not implicated. There was no duplicate for dupokall to silence: main9.$O is pulled only to satisfy the entry symbol, its other global _tos being referenced from profile.c alone, so with libedg.a answering first that member never reached the link.

Renamed rather than dropped from OFILES: main.c is compiled with -D_main=__edg_main. Nothing anywhere references _main, so removing the member would have linked equally well and would have thrown away the only entry point into EDG's static-initialisation machinery.

The static-init gap is recorded, not fixed: nothing now calls _Z12__call_ctorsv, so a C++ program cpfe translates would not run its static constructors. cpfe does not need it and does not emit a call to _main either -- the name occurs in the 133-file corpus exactly twice, both in lib_src/main.c, with no string literal of it in the emitter.

One nm says _main is alone: all 51 lib_src files through gcc, then nm --defined-only -g, gives exactly four external definitions that are neither _Z-mangled nor __-prefixed -- _ctors, _dtors, _main, _new_handler -- and the other three collide with nothing. cmd/edg/mkfile asserted that every definition under lib_src is _Z-mangled or __-prefixed; that sentence is the one that would have found this, and it is corrected there.

Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs

cpfe linked and then crashed on every run with `fault read addr=0x2
pc=0x2'.  `lib_src/main.c' defines `void _main(void)' -- EDG's
static-init helper, the one a target's own crt is expected to call --
and `_main' is 6l's default entry point (`6l/obj.c:305'
INITENTRY = "_main"; `arch/amd64/main9.s:3' TEXT _main(SB)).  6l makes
that name an SXREF at startup and satisfies it from the first archive
on the link line that defines it, and `cmd/edg' names libedg.a ahead
of libap.  So the program's entry became EDG's helper: it ran
_Z12__call_ctorsv, which returns immediately (vars.c:49 has __head
null and munch_ctors.c defines _ctors[1] = {0}), and then executed a
plain RET.

main9.s reads the kernel's argument block at 0(SP), so 0(SP) at entry
holds argc -- which is what that RET popped and jumped to.
`cpfe --help' is argc 2.  Falsifiable with no rebuild: `cpfe' alone
must have given pc=0x1 and `cpfe a b c' pc=0x4.

-C is not implicated.  There was no duplicate for dupokall to
silence: main9.$O is pulled only to satisfy the entry symbol, its
other global _tos being referenced from profile.c alone, so with
libedg.a answering first that member never reached the link.

Renamed rather than dropped from OFILES: main.c is compiled with
-D_main=__edg_main.  Nothing anywhere references _main, so removing
the member would have linked equally well and would have thrown away
the only entry point into EDG's static-initialisation machinery.

The static-init gap is recorded, not fixed: nothing now calls
_Z12__call_ctorsv, so a C++ program cpfe translates would not run its
static constructors.  cpfe does not need it and does not emit a call
to _main either -- the name occurs in the 133-file corpus exactly
twice, both in lib_src/main.c, with no string literal of it in the
emitter.

One nm says _main is alone: all 51 lib_src files through gcc, then
nm --defined-only -g, gives exactly four external definitions that
are neither _Z-mangled nor __-prefixed -- _ctors, _dtors, _main,
_new_handler -- and the other three collide with nothing.
cmd/edg/mkfile asserted that every definition under lib_src is
_Z-mangled or __-prefixed; that sentence is the one that would have
found this, and it is corrected there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
@staalmannen
staalmannen merged commit f79c7ba into main Oct 8, 2026
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.

2 participants