Skip to content

PERRY_SHADOW_STACK=0 + PERRY_STATEPOINTS=1 silently emits a binary with no precise roots #7326

Description

@proggeramlug

PERRY_SHADOW_STACK=0 combined with PERRY_STATEPOINTS=1 produces a binary with no precise frame roots at all, silently.

Measured: the statepoint + shadow-off build emits no __perry_gcmap section and is the same size as the plain shadow-off build — yet it ran and printed the correct answer, so nothing about the run suggests the roots are gone.

Why this happens, and why it matters more than the knob

reserve_shadow_slot() is the single entry point that, under native_stack_roots_enabled(), allocates a stack-map slot instead of a shadow-stack slot. Turning the shadow stack off therefore turns statepoints off with it.

Statepoints are an alternative lowering of the shadow stack's root-set analysis, not an independent mechanism. That has a consequence well beyond this knob: "delete the shadow stack and keep statepoints" is not currently expressible. Any plan that treats them as two interchangeable mechanisms — including the adoption plan in docs/engine-plan.md — rests on a premise the code does not support.

Asks

  1. Make this combination a hard error. A rootless binary that runs and prints the right answer is the worst possible failure mode: it fails open, and nothing observable distinguishes it from a correct build until a collection frees a live object.
  2. Record in the plan that the two mechanisms share their root-set analysis, so the "swap one for the other" framing gets corrected before anyone builds on it.

Found during the statepoint adoption soak.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions