ReviewOS

zig-utils/zig-js

JIT: make the macOS LLDB JIT-loader gate deterministic

#508
Closed chris opened this 8 days ago ·
8 days ago

Parent: #501 Related: #483

Problem

zig build native-observability-lldb-test is nondeterministic on macOS. The same untouched binary can pass once and then let the process exit without resolving the pending generated-code breakpoint.

LLDB JIT logging reports:

JITLoaderGDB::SetJITBreakpoint failed to find JIT descriptor address

At the stopped main image, image dump symtab exposes three descriptor rows: the private Zig data symbol, a zero-address undefined external __jit_debug_descriptor, and the valid defined external __jit_debug_descriptor. The GDB-JIT loader intermittently selects the zero-address debug-map entry. A baseline checkout at fec74a36 reproduces the same pass/fail behavior, so this is not caused by the executable-memory migration in 95948fb3.

When an explicit breakpoint stops inside __jit_debug_register_code, the live descriptor has action_flag = register and valid relevant_entry / first_entry pointers; continuing lets the real LLDB loader adopt the generated Mach-O and resolve exact symbol/source breakpoints. Publisher unit tests and native signal/crash fixtures remain clean.

Goal

Make the real LLDB GDB-JIT loader fixture deterministic while preserving the production protocol and default-library symbol boundary.

Acceptance

  • The linked fixture exposes one unambiguous defined descriptor address to LLDB symbol lookup.
  • At least 20 consecutive clean launches resolve baseline and optimizer symbol/source breakpoints and validate deregistration.
  • The test still exercises LLDBs real GDB-JIT loader and the production publisher.
  • The default libzig-js.a still emits no opt-in process-global GDB-JIT symbols.
  • No sleeps, blind retries, manual in-memory object parsing, or debugger-only codegen.
8 days ago

Fixed on main by aef1cf88.

The opt-in LLDB fixture is now stripped at link time, removing the undefined debug-map descriptor row while retaining the one defined external GDB-JIT descriptor/callback. Generated JavaScript DWARF and unwind records remain artifact-owned and were still consumed by the real LLDB loader.

Validation:

  • 20/20 consecutive zig build native-observability-lldb-test launches passed;
  • each launch resolved baseline and optimizer names, exact JS line/column rows, native caller unwind, and post-retirement removal;
  • the stripped fixture symbol table contains one defined descriptor and callback;
  • native signal/crash attribution passed;
  • default libzig-js.a contains no __jit_debug_descriptor or __jit_debug_register_code globals.

Test262 flips: 0; fixture link metadata only.

Sign in to comment on this issue.