bpftrace: runtime suite passes 133/933 from a structural 0

The bpftrace runtime test suite previously couldn't run at all — it
halted on test #1 with FileNotFoundError for ./testprogs/uprobe_test.
After this change, all 38 categories execute and 133 tests pass.

Infrastructure
- scripts/build-bpftrace-testprogs.sh compiles bpftrace's tests/testprogs/
  .c/.cpp sources directly with gcc/g++ (no LLVM/libbpf toolchain). PIE
  and non-PIE pair, _GNU_SOURCE + -pthread; idempotent so re-runs under
  sudo don't clobber the user-owned binaries.
- scripts/patch-bpftrace-engine.py wraps the staged main.py's
  Runner.run_test in try/except FileNotFoundError so missing testprogs
  SKIP instead of crashing the whole suite mid-run.
- Makefile: BPFTRACE_SRC defaults via SUDO_USER's $HOME; PYTHONPATH
  inherits the user's pip --user site so root finds looseversion.

Handshake
- runtime: emit __BPFTRACE_NOTIFY_PROBES_ATTACHED on stdout after attach.
  The engine waits for this exact line before launching AFTER. Single
  biggest unlock — flipped dozens of TIMEOUTs to actual outcomes.

Loader bug fixes
- attach-uprobe canonicalizes the binary path to absolute via truename;
  the kernel's uprobe perf_event_open doesn't resolve relative to cwd.
- vaddr-to-file-offset always returned the VMA unchanged because the
  enclosing let's last form was `vaddr` after the loop, discarding the
  loop's return value. Wrap in (or LOOP-RESULT vaddr).

Typesystem
- Step 1: track element-type on `$a = (T *) X` in *var-ptr-elt-types*;
  `$a[i]` lowers to probe-read of sizeof(elt) at addr+i*sizeof(elt).
  Dispatch helper-fn (probe-read-user vs -kernel) by probe type.
- Step 2: parse in-script `struct A { … }` bodies into a field table
  with computed offsets (natural C alignment). lower-struct-pointer-
  field, offsetof, sizeof consult it before falling back to BTF.
- Step 3: array-field element access `$a.x[i]` — sized probe-read at
  struct+field-off+i*sizeof(elt). Compile-time OOB detection emits
  bpftrace's exact `ERROR: the index N is out of bounds for array of
  size M` message.
- Step 3b: whole-array values — value-array-p/value-array-elt-size on
  minfo, gen-array-field-set emits probe-read+map-update-ptr for `@m =
  struct.x`; keys-need-ptr-ops-p + composite-key-layout + store-key-
  component handle array-field keys for `@m[struct.x]` and composite
  `@m[struct.x, n]`.
- Map round-trip: value-ptr-elt-size flows `(T *)' through map values;
  `@a[0] = (int32 *)X; @a[0][0]' and via-var both subscript correctly.
- Printer: format-key gains :array-elt-size + :array-len → renders
  array keys as bpftrace's `[v1,v2,…]`. Surfaced via :info plist.

Grammar
- lowercase begin/end (bpftrace 0.22+)
- short-form probes: k:/kr:/u:/ur:/t:/i:/p:/f:/fr:
- fentry:MODULE:func / kfunc:MODULE:func (module name prefix)
- multi-dim array fields in struct decls: int y[2][3]
- in-script struct decls with proper field parsing
- enum-decl accept-and-discard at top-form
- block expressions { stmts; expr } in primary
- _ wildcard LHS (discard assignment)
- $1, $2, … positional CLI args
- pre-increment statement (++$x; / --$x; — bpftrace allows both forms)
- for ($i : 0..5) with parens
- primitive-pointer-cast (int32 *)X as separate primary alternative
- bool in primitive-cast type list

Codegen
- print(scalar/string/tuple) — synthesizes printf with inferred format
- lower-incdec: scalar `$x++;` was completely broken before (only maps
  worked, scalar hit "malformed property list"). Now dispatches on
  LHS tag.
- script-uses-printf-p extended to cat/system/errorf/warnf/join/zero/
  strftime AND walks macros/functions for the BT-PRINT map injection.
- collect-vars descends into :block-expr so let-bound vars inside
  block expressions get bound at probe scope.

Diagnostics
- tracefs unreadable: when load-tracepoint-field-sizes can't open the
  format file, track the path in *tp-format-unreadable-paths* and
  surface it in the field-access error so users see "need root or
  chmod a+r" instead of "field access on non-args expressions".

Make targets / scripts
- bpftrace-parse-test skip detection picks up the new tracefs error
  wording.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anthony Green2026-05-29 13:06:29 -0400 661e082115e34769eb32af13d1535ab67c62dc7c
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>