ERR/E3.0 (slice 3e rung 2): iOS-simulator stepping verified

Closes out E3's stepping-verification ladder to the extent possible
headlessly.

- Verified `sx build --target ios-sim --emit-obj` produces an
  arm64-ios-simulator Mach-O that runs under `simctl spawn` and steps
  in lldb (the backtrace shows a dyld_sim frame — the sim runtime).
- Verified the device-applicable .dSYM path: dsymutil collects the
  DWARF, and after removing the .o lldb still resolves source via the
  .dSYM.
- debug_stepping_smoke.sh gains an optional iOS-sim rung that reuses an
  already-booted simulator (never boots one — single-sim policy) and
  exercises the .dSYM path; skips cleanly when no sim is booted.
- docs/debugger.md: rungs 1-2 marked verified; the iOS-device rung is
  documented as a manual checklist (needs hardware + get-task-allow
  signing) — no compiler gap, --emit-obj + standard Apple tools suffice.

E3 is functionally complete and verified across macOS + iOS-simulator.
This commit is contained in:
agra
2026-06-01 16:10:33 +03:00
parent 4cd641c946
commit b2ebf774bc
2 changed files with 60 additions and 23 deletions

View File

@@ -403,18 +403,33 @@ Source-level stepping is verified manually/interactively (it needs
provisioning profile — not a `run_examples.sh` test). Climb cheapest-first;
the device run is the final sign-off:
1. **macOS native ✅** — `sx build --emit-obj` → drive `lldb --batch` (the
debug map resolves to the kept `.o`; no `dsymutil` needed locally).
Checked in as `tests/debug_stepping_smoke.sh`: breakpoint on a sx function,
`run`, assert it stops at the right `.sx:line`, `next`/`stepi` advance,
`bt` is source-mapped. The automatable rung (a checked-in smoke script).
2. **iOS simulator** — bundle the `.app`, install to a booted simulator
(`simctl`), launch under lldb, repeat the checks. No device, no signing.
3. **iOS device (capstone)** — `--debug`: emit DWARF → `dsymutil` `.dSYM`,
debug-sign with `get-task-allow`, install via `devicectl`, launch under
`debugserver`, attach `lldb`, single-step sx source on the phone. If
stepping works *here* — the most locked-down target — the DWARF story
is proven everywhere.
1. **macOS native ✅ verified** — `sx build --emit-obj` → drive `lldb --batch`
(the debug map resolves to the kept `.o`; no `dsymutil` needed locally).
Checked in as `tests/debug_stepping_smoke.sh`: file:line breakpoint resolves
to `.sx:line` + a source-mapped `bt`. The automatable rung.
2. **iOS simulator ✅ verified** — `sx build --target ios-sim --emit-obj`
produces an `arm64-ios-simulator` Mach-O that runs under `simctl spawn` and
steps in `lldb` (the backtrace shows a `dyld_sim` frame — proof it's the sim
runtime). The `tests/debug_stepping_smoke.sh` rung-2 exercises this *against
an already-booted sim* (it never boots one itself — use a single simulator);
it also collects a `.dSYM` via `dsymutil`, removes the `.o`, and confirms
lldb still resolves via the `.dSYM` — proving the device-applicable artifact
path. Skipped when no sim is booted.
3. **iOS device (capstone) — manual, needs hardware + Apple signing.** Every
*technical* piece is already verified above (DWARF, the `.dSYM` workflow,
stepping under the sim runtime); the device rung adds only Apple-toolchain
steps that require a phone + a development identity, so it's a checklist, not
a compiler deliverable:
1. `sx build --target ios --emit-obj …` (DWARF in the kept `.o`).
2. `dsymutil <binary> -o <App>.app.dSYM` (the `.app` ships no `.o`).
3. bundle the `.app` (existing `--bundle` path) + debug-sign with a
provisioning profile carrying **`get-task-allow`**.
4. `xcrun devicectl device install app …` then launch under `debugserver`.
5. attach `lldb` (it finds the adjacent `.dSYM`) and single-step sx source.
No new compiler code is required — `--emit-obj` + standard Apple tools
suffice. (A `--debug` convenience flag that chains 14 could be added later,
but should be built with a device in hand to verify it.)
Independently, **Tier-0 always works with no debugger**: a plain on-device
run still prints the embedded-`Frame` trace to stderr/`os_log`.
@@ -443,8 +458,9 @@ a Mach-O debug map, never register JIT DWARF.
| Comptime resolver (`func_id, ir_offset` → location) | ✅ done — slice 3b |
| Source snippet + `^` caret | ✅ done — slice 3c (line embedded in `Frame`) |
| `--emit-obj` artifact plumbing | ✅ done — slice 3d |
| Stepping verification: macOS lldb | ✅ done — slice 3e rung 1 (`tests/debug_stepping_smoke.sh`) |
| Stepping verification: iOS simulator → device | ⏳ planned slice 3e rungs 23 (capstone) |
| Stepping verification: macOS lldb | ✅ done — 3e rung 1 (`tests/debug_stepping_smoke.sh`) |
| Stepping verification: iOS simulator + `.dSYM` path | ✅ done — 3e rung 2 (verified; smoke skips if no booted sim) |
| Stepping verification: iOS device | 📋 manual checklist — needs hardware + signing (no compiler gap) |
| DWARF variable info (`DILocalVariable`, for `p x`) | ⏳ optional follow-on |
The active plan and step breakdown live in `current/PLAN-ERR.md`