Skip to content

Commit 501a6e9

Browse files
avrabeclaude
andauthored
track(#354): GI-NPA-004 + repro — per-region .bss/.data split for high-offset init segments (#355)
gale #354: the #345 zero-init split is binary (split_linmem_bss = native_layout && data_segments.is_empty()), so ANY initialized (data) segment makes the whole [0, used_extent) linmem image PROGBITS. A dissolved stack_push seam carries a 12-byte .rodata const (-12/-ENOMEM) at linmem offset 65536, above the 64 KiB shadow stack → 65552-byte PROGBITS .data (MCU-unshippable; mutex is .data=4). This is the mixed-case deferred in the #345 code comment coming due — NOT a v0.11.44 regression; #350 just made stack_push compile far enough to expose it. - artifacts/gale-integration.yaml: GI-NPA-004 (sw-req, proposed, release-v0.11.45). Design: per-region SYMBOLS (zero reservation keeps __synth_wasm_data/.bss; each init segment gets its own PROGBITS section + symbol; selector relocates each static access against its region's symbol) — link-survivable, unlike a naive per-section split (single base symbol + baked addends need contiguity the linker won't grant). Sound iff init-data is statically separable from the zero region — to confirm against gale's stack_push.loom.wasm before implementing. - scripts/repro/high_offset_init_segment_354.wat: minimal reconstruction (SP global init 65536 + 12-byte init segment at 65536 + static load at addr 65544) that reproduces .data=65552 locally with --native-pointer-abi --relocatable. Implementation (selector + ELF) is the next feature-loop; this commit tracks + secures the repro. Frozen differentials unaffected (no code change here). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a22cb9b commit 501a6e9

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

artifacts/gale-integration.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,3 +516,51 @@ artifacts:
516516
pass-criteria: >
517517
Linked dissolved seam runs with no runtime and matches the native
518518
reference behavior; no MPU fault from mis-addressed statics or stack.
519+
520+
- id: GI-NPA-004
521+
type: sw-req
522+
title: Per-region .bss/.data split for high-offset init segments (#354)
523+
description: >
524+
The #345 zero-init split is binary: `split_linmem_bss =
525+
native_layout.is_some() && data_segments.is_empty()` (synth-cli
526+
build_relocatable_elf). When ANY initialized `(data)` segment is
527+
present the whole `[0, used_extent)` linmem image is emitted as one
528+
PROGBITS `.data`. gale #354: a dissolved stack_push seam carries a
529+
12-byte `.rodata` const (`0xfffffff4` = -12/-ENOMEM) at linmem offset
530+
65536 — above the 64 KiB shadow stack — so the entire zero stack-gap
531+
ships as 65552 bytes of PROGBITS `.data` (MCU-unshippable; the mutex
532+
seam, with no init segment, is `.data=4`/`.bss=65536`). synth shall
533+
split the linmem image PER REGION: each initialized byte-range as a
534+
small PROGBITS section and the surrounding zero runs as SHT_NOBITS
535+
`.bss`, so `.data` is bounded to the initialized bytes. Because a
536+
single `__synth_wasm_data` base symbol + selector-baked addends cannot
537+
span independently-placed sections (the link-fragility deferred in the
538+
#345 code comment), the split shall use PER-REGION SYMBOLS: the zero
539+
reservation keeps `__synth_wasm_data` (.bss); each init segment gets
540+
its own PROGBITS section + symbol; the selector relocates each static
541+
access against the symbol of the region the offset falls in. Sound
542+
only if init-data accesses are statically separable from the zero
543+
region (the rodata const is reached only by a static address, never by
544+
a dynamic pointer that also walks the shadow stack) — to be confirmed
545+
against gale's stack_push.loom.wasm before implementation.
546+
status: proposed
547+
tags: [gale, native-pointer-abi, bss, elf, mcu-shippability, release-v0.11.45]
548+
links:
549+
- type: derives-from
550+
target: GI-NPA-001
551+
- type: traces-to
552+
target: gale:354
553+
fields:
554+
req-type: functional
555+
priority: must
556+
verification-criteria: >
557+
scripts/repro/high_offset_init_segment_354.wat (SP global init
558+
65536 + 12-byte init segment at 65536 + a static load at addr
559+
65544) compiled with --native-pointer-abi --relocatable
560+
--all-exports yields `.data` bounded to the initialized bytes (~12 B)
561+
with the zero stack-gap as SHT_NOBITS `.bss` (matching the mutex
562+
shape); mutex_unlock stays `.data=4`/`.bss=65536`; the four frozen
563+
differentials (control_step 0x00210A55, flight_seam 0x07FDF307,
564+
div_const 338/338, mutex_pressure) stay byte-identical; gale's
565+
stack_push runs correctly on G474RE (loads the -12 const, walks the
566+
shadow stack) under the differential oracle.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(module
2+
(memory (export "memory") 2)
3+
(global $sp (mut i32) (i32.const 65536))
4+
(data (i32.const 65536) "\00\00\00\00\00\00\00\00\f4\ff\ff\ff")
5+
(func (export "stack_push_decide") (result i32)
6+
;; static address >= wasm_data_base (65536) -> __synth_wasm_data-relative
7+
i32.const 65544
8+
i32.load))

0 commit comments

Comments
 (0)