re: route 1 is viable — XObject::Wait keeps this in %rbx and .eh_frame restores it
Pure static analysis, no run spent. XObject::Wait's prologue does mov %rdi,%rbx at 8fbc9c, so the this pointer lives in a callee-saved register rather than a stack slot. And the binary carries full unwind information: .eh_frame with 127231 FDEs, which survives in Release builds because C++ exceptions need it, including an FDE covering 8fbc90 to 8fbde2 that tracks rbx explicitly. Together those mean that from a thread frozen deep in pthread_cond_wait, moving to the XObject::Wait frame and reading rbx yields the XObject being waited on -- gdb reconstructs callee-saved registers during the unwind from .eh_frame alone, with no DWARF involved. Reading the first quadword at that pointer gives the vtable, and vtable symbols are in the symtab, so the object's concrete type is identifiable too. This revises the previous entry, which listed route 1 as per-frame archaeology that must be redone whenever the binary changes, and route 2, a RelWithDebInfo rebuild, as what would make the question easy. Route 1 is neither expensive nor fragile: two gdb commands per thread, no rebuild, and the oracle stays byte-identical to the binary every other measurement in this corpus was taken against. Not yet executed on a frozen run, which is the next step and is now a small one.
This commit is contained in:
@@ -708,6 +708,17 @@ search cannot find a *schedule*.
|
||||
archaeology; (2) a `RelWithDebInfo` build via `build-canary` — makes this and all
|
||||
future freeze questions easy, at a full compile and a binary differing from the
|
||||
one every other measurement used.
|
||||
* ✅ **(2026-08-25) Route 1 is viable and cheap — `this` is in `%rbx`.**
|
||||
Static analysis, no run spent: `XObject::Wait`'s prologue does `mov %rdi,%rbx`
|
||||
at `8fbc9c`, so `this` sits in a **callee-saved** register rather than a stack
|
||||
slot. And the binary carries **`.eh_frame` with 127 231 FDEs** (Release builds
|
||||
keep it for C++ exceptions), including one covering `8fbc90..8fbde2` that
|
||||
tracks `rbx` explicitly. ⇒ from a frozen thread, **`frame 3` + `info registers
|
||||
rbx` gives the `XObject*` being waited on**, and `x/gx $rbx` → vtable symbol
|
||||
(in symtab) gives its concrete type — **no DWARF and no rebuild needed**.
|
||||
**Revises the previous entry**, which called route 1 "per-frame archaeology"
|
||||
and route 2 (RelWithDebInfo rebuild) the way to make it easy. **Next: execute on
|
||||
a frozen run** — two gdb commands per thread.
|
||||
* ~~🚧 BLOCKER: t=210/240 unreachable in one turn~~ — **superseded, see above**;
|
||||
it rested on an untested assumption that a turn is one shell call. 595 s shell cap − ~220 s boot (a ~190 s title movie that cannot be
|
||||
tapped through) − ~25 s startup = **~350 s observation ≈ 193 game-seconds**.
|
||||
|
||||
Reference in New Issue
Block a user