lane W2: the three queue items not reached, with the reason and the cheapest next step for each
TShn: the brief's address was wrong -- player+0x274 is observed_techs; the TShn map is ServerSystem+0x274. The real obstacle is that a std::map's nodes are heap-allocated, so there is no fixed leaf to arm; arm the map header to trap the insertion instead. rcex: closed from the corpus, no VM time needed (see rcex-explained.md). Trade/spy workload: not attempted, and lane H's reasons still hold. What is new is that the watchpoint module is the instrument for confirming the workload BEFORE spending a turn on it -- both containers are one add from the arming point, and for the spy vector the trapped return addresses would name the UI nobody has found.
This commit is contained in:
parent
92ad44efb0
commit
cb1ea723e1
1 changed files with 65 additions and 1 deletions
|
|
@ -231,9 +231,73 @@ one build and about six minutes of VM time for two turns, and it answered three
|
|||
consumed parts of four lanes of static reading. **Method rule 18, again: `what writes this?` is a
|
||||
watchpoint.**
|
||||
|
||||
Two things a future user should keep:
|
||||
Two things a future user should keep — and then §8 for the queue items this lane did **not** reach,
|
||||
each with the reason and the cheapest next step.
|
||||
|
||||
- **keep the canary self-test.** It is four lines and it is the difference between "nothing writes
|
||||
this" and "the arm silently failed".
|
||||
- **keep the oracle control.** Loading `ref-turn2.sav` and ending one turn costs nothing extra and
|
||||
proves the run is measuring the un-instrumented game.
|
||||
|
||||
---
|
||||
|
||||
## 8. Not reached, and why — with the cheapest next step for each
|
||||
|
||||
Lane H's account of the trade workload was more useful than the attempt would have been. Same
|
||||
discipline here.
|
||||
|
||||
### 8.1 `TShn` — the brief's address is wrong, and that is the finding
|
||||
|
||||
The lane brief said "watchpoint on the `player+0x274` map". **That is the wrong object.**
|
||||
`player+0x274` is `observed_techs` (lane V, `eventlive-verification.md` §4.3). The `TShn` map is
|
||||
`ServerSystem+0x274` — the `NVO` container — per `system-visibility-record.md` §8, whose own words
|
||||
are "a watchpoint on `ServerSystem+0x274`'s map during one turn". Anyone who armed the briefed
|
||||
address would have watched the tech-observation array and reported a confident nothing.
|
||||
|
||||
The real obstacle is structural, and it is why this was not just a fifth line in `WatchOnApplyAll`:
|
||||
**a `std::map`'s nodes are heap-allocated, so `TShn` has no fixed address to arm before the node
|
||||
exists.** Two ways round it, both cheap now that the module exists:
|
||||
|
||||
1. **Arm the map header** (`ServerSystem+0x274 … +0x27c`) rather than a leaf. That traps the
|
||||
*insertion*, which is arguably the better question — E3's puzzle is which systems get an `NVO`
|
||||
entry, and Spica-vs-Bismol is a question about the gate, not about the value.
|
||||
2. **Arm the leaf directly**, by loading `turn1-state.sav`, walking the map for Spica's node once at
|
||||
`ProcessTurn` entry, and pointing DR0 at that node's `TShn` word. This needs the node layout,
|
||||
which `objects/` has.
|
||||
|
||||
Either is one arming function away. What is *not* solved is the arming point: `ApplyAllTurnCommands`
|
||||
gives `S`, and `ServerSystem`s hang off `S+4+0x40`, so reaching a named system needs a name compare
|
||||
in the arming code. About twenty lines.
|
||||
|
||||
### 8.2 `rcex` — closed without the VM
|
||||
|
||||
See `findings/subsystems/rcex-explained.md`. It is sixteen 4-bit per-player counters; nibble *p* is
|
||||
set to 1 on the turn the system enters player *p*'s `AFlags` and ticked to 0 the next turn, 7/7
|
||||
across two different games. The corpus had the answer; nobody had put the nibble index next to the
|
||||
`AFlags` bit index. **The one part that still wants a watchpoint** is the site of the decrement — the
|
||||
"`rcex` tick" named in `ServerSystem::ProcessTurn`'s body-order note — and `rcex` is at a fixed
|
||||
offset in a fixed object, so it is the *easiest* target this module has.
|
||||
|
||||
### 8.3 The trade-route / spy workload — not attempted, deliberately
|
||||
|
||||
Lane H's reasons (`tail-probes.md` §3.2) all still hold: trade routes need trade-station
|
||||
construction plus its tech, which from `ref-turn2` is tens of End Turns at 30-60 s each with a
|
||||
Build/Research click path per turn, and the turn-23 Zuul save still has none; and **no lane has
|
||||
identified which UI produces a spy-program entry**, so for spies there is still no click path to
|
||||
write down. This lane spent its VM time on the multiplayer demonstration and the watchpoint run
|
||||
because both had falsifiable predictions attached and this does not.
|
||||
|
||||
What is different now, and it is the thing that makes the next attempt materially cheaper:
|
||||
**"confirm the workload took before spending a turn measuring it" is exactly what this module does**,
|
||||
and both containers are one add from the arming point already in the code.
|
||||
|
||||
| container | address at `ApplyAllTurnCommands` entry (`this` = `S`) |
|
||||
|---|---|
|
||||
| trade-route vector (slot 15's body) | `*(void**)(S + 4 + 0x154)` → `tradeManager`, then `tradeManager + 0x3c` (`_Mylast` at `+0x40`) |
|
||||
| spy-program vector (slot 14's body) | `*(void**)(S + 4 + 0x158)` → `spyManager`, then `spyManager + 0x10` (`_Mylast` at `+0x14`) |
|
||||
|
||||
Arm DR0/DR1 on the two `_Mylast` words and the game announces the moment either vector grows, with
|
||||
the EIP and two return addresses of whoever grew it. For the spy vector that is not just workload
|
||||
confirmation — **it is the answer to "which UI produces a spy-program entry", because the return
|
||||
addresses name the caller.** That is a better use of the next VM slot than playing twenty turns
|
||||
blind.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue