Skip to content

EMBED_P256_OVERLAY=1 cannot build: LIB_NISTCURVES_P256_CODE overflows OVERLAY_REGION by 644 B #118

Closed

Description

@JC-000

EMBED_P256_OVERLAY=1 is a documented Make flag with a documented two-step bootstrap (Makefile:214-216), and it cannot complete at HEAD.

Measured on master 0f3fa0c, from a clean tree, following the documented workflow exactly:

$ make clean
$ make BACKEND=uci EMBED_P256_OVERLAY=1 USE_OVERLAY_P256_EMBED=0
  -> OK, build/labels.txt produced

$ make BACKEND=uci EMBED_P256_OVERLAY=1
  ld65: Warning: cfg/p256-overlay-verify.cfg(26): Segment 'LIB_NISTCURVES_P256_CODE'
        overflows memory area 'OVERLAY_REGION' by 644 bytes
  ld65: Error: Cannot generate most of the files due to memory area overflow
  make: *** [build/lib/nistcurves-p256-verify.bin] Error 1

The failure is in building the overlay image itself, so the flag's whole purpose is unreachable. Unrelated to the .incbin work in #116/#117 — it reproduces with those merged.

What changed recently, and what didn't

Worth recording because two lanes measured this differently on either side of #117:

So this is now one defect, not two, and it is a region-fit problem: the verify archive's code no longer fits the overlay slot the cfg reserves.

Note on the sibling defect

USE_OVERLAY_P384_EMBED has the same shape and is separately blocked by the SHA-384 table overflowing OVERLAY_REGION by 1,536 B — long-standing and already recorded in CLAUDE.md. Both flags occupy the same $4200 slot and are mutually exclusive, so whoever picks this up should size both against the current pins rather than fixing one and assuming the other.

Why file rather than fix

The region sizing is a memory-map decision, not a mechanical repair: OVERLAY_REGION is 7,680 B and the archive that has to fit it grew across the v0.9.x/v0.10.x pins. Choosing between shrinking the staged archive, enlarging the slot, or splitting the image is a design call worth making deliberately.

Filed from the #112/#116 sequence, where both overlay paths were verified in isolation precisely because a real build cannot reach them.

Activity

  1. JC-000 commented on Aug 15, 2026

    @JC-000
    OwnerAuthor

    Correction to my own issue body — the "two stacked defects" history is wrong. There is one defect, and #117 did not fix a bootstrap step.

    I wrote that before #117 the bootstrap's step 1 also failed with Unresolved external 'p256_overlay_verify_blob', and that #117's cwd-escape fix repaired it. A colleague re-ran the exact command at the exact commit rather than taking my account, and it does not reproduce:

    git checkout --detach ebc600c        # i.e. BEFORE #117
    make clean && make BACKEND=uci EMBED_P256_OVERLAY=1 USE_OVERLAY_P256_EMBED=0
      -> clean; build/labels.txt produced
    make BACKEND=uci EMBED_P256_OVERLAY=1
      -> LIB_NISTCURVES_P256_CODE overflows OVERLAY_REGION by 644 bytes
    

    Identical to the behaviour on master. I verified the mechanism they identified: src/boot.s:971 gates the reference behind .ifdef USE_OVERLAY_P256_EMBED, so with the define off nothing references the symbol at all. The only way to produce that unresolved-external is a mixed object set — boot.o built with the define against p256_overlay_blobs.o built without — which is precisely the "always make clean between flag changes" trap this repo documents, because make cannot see a -D change.

    So, corrected:

    Everything else in the issue stands: the flag is unusable at HEAD, the failure is a region-fit problem, and USE_OVERLAY_P384_EMBED contends for the same $4200 slot with its own 1,536 B overflow, so both want sizing together.

    Worth recording why this happened, since the issue is about build-state confusion in the first place: a peer reported the error, I reproduced step 2's failure, and then attached their step-1 report to my own result without running step 1 at the earlier commit. The observation was real for whoever hit it — a dirty object set will produce it — but it was never a property of that commit.

  2. JC-000 commented on Aug 15, 2026

    @JC-000
    OwnerAuthor

    Addendum — how to produce the spurious Unresolved external, since anyone working this issue is likely to hit it.

    The colleague who originally reported that error traced it precisely, and it is worth recording next to the real defect:

    make clean && make BACKEND=uci EMBED_P256_OVERLAY=1     # defaults USE_OVERLAY_P256_EMBED=1
                                                            # -> boot.o assembled WITH the define,
                                                            #    build dies on the 644 B overflow
    make BACKEND=uci EMBED_P256_OVERLAY=1 USE_OVERLAY_P256_EMBED=0   # no clean
                                                            # -> stale boot.o (with define) linked
                                                            #    against blobs.o (without)
                                                            # -> Unresolved external 'p256_overlay_verify_blob'
    

    make cannot see a -D change, so the second invocation silently reuses the first's objects. The unresolved external is a mixed object set, not a defect in the bootstrap.

    This matters here specifically because the natural way to investigate this issue — try the flag, watch it fail, then try the bootstrap — walks straight into it, and the resulting error points at boot.s rather than at the region overflow that is actually blocking you. make clean between every flag change, including between the two bootstrap steps.

    So the full picture on this issue is: one real defect (the 644 B OVERLAY_REGION overflow at step 2), plus one easy-to-hit build-state artifact that masquerades as a second, earlier one.

  3. JC-000 commented on Aug 16, 2026

    @JC-000
    OwnerAuthor

    Re-checked at master 39a43eb, libs/nistcurves v0.11.2 — still open, unchanged in substance, but the reproduction has two stages and the title only names the second.

    From a clean tree you get a different error first

    $ make clean && make BACKEND=uci EMBED_P256_OVERLAY=1
    make: *** No rule to make target `build/labels.txt',
          needed by `build/lib/nistcurves-p256-verify.bin'.  Stop.
    

    The overlay rules take an order-only | build/labels.txt, but that file is only a side effect of the main link — whose bootstrap rule is gated off under this flag. So the build dies before it can reach the overflow this issue is named for. That is the same ordering defect CLAUDE.md already records for USE_OVERLAY_P384_EMBED, so it is one defect affecting both embed flags, not two.

    The recorded failure is still exactly right, once you get past that

    $ make BACKEND=uci                      # produces build/labels.txt
    $ make BACKEND=uci EMBED_P256_OVERLAY=1
    ld65: Warning: Segment 'LIB_NISTCURVES_P256_CODE' overflows memory area
          'OVERLAY_REGION' by 644 bytes
    

    644 B, unchanged — worth stating explicitly because it is not obviously stable: LIB_NISTCURVES_P256_CODE grew +208 B at v0.7.0's validation gate and _RODATA shrank 288 B at v0.9.0, and the pin has since moved v0.10.1 → v0.11.2 across the whole wave. The figure surviving all of that means the overflow is structural (the region is simply too small for this segment), not a drifting margin that a future bump might close on its own.

    Why this matters for whoever picks it up

    Anyone reproducing from a clean checkout will hit the labels.txt error and reasonably conclude this issue is misfiled. Both failures need fixing and they are independent:

    1. the order-only dependency on a file the gated-off rule never produces — shared with USE_OVERLAY_P384_EMBED
    2. the 644 B OVERLAY_REGION shortfall — needs a cfg change, not a flag change

    Nothing in the §6.1/§8.0 alignment work (#119, PR #122) touched either. EMBED_P256_OVERLAY remains unreachable, and per CLAUDE.md its exclusions are not $(error)-guarded — it silently wins over USE_OVERLAY_P384_EMBED and is untested against USE_X25519_SIBLING. Contract v0.10.5's §6.3 "a knob naming an axis MUST select it or fail loudly" is the rule this violates, consumer-side.

  4. JC-000 commented on Aug 24, 2026

    @JC-000
    OwnerAuthor

    Validated at HEAD (libs/nistcurves v0.11.2): both stages reproduce exactly as described above — the clean-tree build/labels.txt error, then the 644 B OVERLAY_REGION overflow (LIB_NISTCURVES_P256_CODE = 8,324 B vs 7,680 B).

    One finding the thread did not have, and it settles the design call: CRYPTO_OVERLAY is no longer a free paging slot. Every default UCI build keeps TLS_DEFRAME_CODE (1,379 B), CERT_BUF_BSS (2,048 B), X509_NAME_CODE (491 B) and HTTPS_TARGET_RODATA resident in $4389-$578B, so even a fitting image would be DMA'd over the deframer and the leaf certificate by crypto_swap_to_p256_verify — the P-384 hazard class fixed in v0.4.1. Shrink/enlarge/split all presuppose a free slot, and nothing ships or calls the overlay verify.

    Fix in #139: the flag fails at Makefile parse naming both reasons (contract §6.3), for EMBED_P256_OVERLAY=1 and USE_OVERLAY_P256_EMBED=1. Plain make BACKEND=uci is byte-identical across it. Plumbing stays in tree; the labels.txt ordering defect is left as documented since it now only affects USE_OVERLAY_P384_EMBED, which cannot complete regardless.

  5. added a commit that references this issue on Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions