You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sanitizer violation reports currently name the faulting PC and address:
invalid 1-byte write at 0x00002ee0 (heap redzone) from PC 0x00002af6
Enforcer's reports also dump all sixteen CPU registers at the moment of the fault, and that is not decoration — it is often how you identify the culprit, because the registers tell you where the bad pointer came from when the faulting instruction itself only says move.l (a4),d0.
The evidence that this matters
LawBreaker (from the Enforcer package, see #70) goes out of its way to make the point. Before committing any violation it loads every single register with a recognisable pattern:
$AAAAnnnn in the address registers, $DDDDnnnn in the data registers, each numbered by register. That pattern exists solely so that a human reading Enforcer's register dump can verify at a glance which register the report attributed the fault to. A test program designed around the register dump is decent evidence the dump is the valuable part of the report.
Proposal
Capture a register snapshot when a violation is recorded and include it in the report.
Design notes:
ShadowMap::record currently has access to the PC only, published per-instruction by the run loop (backend.rs, set_current_pc). The registers live on the Cpu, which the shadow map cannot see. The cheapest approach consistent with the existing design is for the run loop to publish the registers alongside the PC, the same way it already publishes the PC — but note that would mean copying 16 longwords per instruction, on the hot path, to be used only in the rare violation case. Measure before committing to that; a cheaper option is to have the run loop notice that the violation count changed after an instruction and only then attach a snapshot.
Keep the one-line summary form for scanning, with registers as an indented block underneath, so a report with many violations stays readable. Enforcer's format is worth looking at directly for the layout.
Possible follow-up worth noting here
volamos's loader now parses (and skips) HUNK_DEBUG blocks as of #70. LawBreaker's own debug hunks contain HEADDBGV01 source-line information referencing LawBreaker.asm, and the binary embeds a LINE marker. That raises a genuinely interesting possibility: translating a faulting PC back to a hunk:offset, or even a source file and line number, when the binary was built with debug info. That is now filed as #74, with the LINE debug-hunk format fully decoded and verified against LawBreaker's instruction boundaries.
Scope
Capture a register snapshot (D0-D7, A0-A7, PC, and SR if cheap) on the first occurrence of each violation.
Decide the capture strategy and measure its cost on the interpreter hot path before adopting a per-instruction copy.
Render registers as an indented block under the existing one-line summary.
Verify against LawBreaker: the $AAAAnnnn/$DDDDnnnn patterns should be plainly visible in the dump, which makes it self-verifying.
Related: #65, #68 (per-PC rollup, which interacts with where a snapshot attaches), #70, #71, #72.
Sanitizer violation reports currently name the faulting PC and address:
Enforcer's reports also dump all sixteen CPU registers at the moment of the fault, and that is not decoration — it is often how you identify the culprit, because the registers tell you where the bad pointer came from when the faulting instruction itself only says
move.l (a4),d0.The evidence that this matters
LawBreaker (from the Enforcer package, see #70) goes out of its way to make the point. Before committing any violation it loads every single register with a recognisable pattern:
$AAAAnnnnin the address registers,$DDDDnnnnin the data registers, each numbered by register. That pattern exists solely so that a human reading Enforcer's register dump can verify at a glance which register the report attributed the fault to. A test program designed around the register dump is decent evidence the dump is the valuable part of the report.Proposal
Capture a register snapshot when a violation is recorded and include it in the report.
Design notes:
ShadowMap::recordcurrently has access to the PC only, published per-instruction by the run loop (backend.rs,set_current_pc). The registers live on theCpu, which the shadow map cannot see. The cheapest approach consistent with the existing design is for the run loop to publish the registers alongside the PC, the same way it already publishes the PC — but note that would mean copying 16 longwords per instruction, on the hot path, to be used only in the rare violation case. Measure before committing to that; a cheaper option is to have the run loop notice that the violation count changed after an instruction and only then attach a snapshot.(pc, addr, kind)with a hit count (Add --sanitize, a valgrind/ASan-style memory sanitizer (issue #65) #66) and rolled up per PC (proposed in Optional --sanitize-uninit: uninitialized-read detection as an opt-in extra (issue #65 increment 3) #68). A snapshot should therefore be attached to the first occurrence, with the report making clear it is from that occurrence and not the most recent.Possible follow-up worth noting here
volamos's loader now parses (and skips)
HUNK_DEBUGblocks as of #70. LawBreaker's own debug hunks containHEADDBGV01source-line information referencingLawBreaker.asm, and the binary embeds aLINEmarker. That raises a genuinely interesting possibility: translating a faulting PC back to a hunk:offset, or even a source file and line number, when the binary was built with debug info. That is now filed as #74, with theLINEdebug-hunk format fully decoded and verified against LawBreaker's instruction boundaries.Scope
$AAAAnnnn/$DDDDnnnnpatterns should be plainly visible in the dump, which makes it self-verifying.Related: #65, #68 (per-PC rollup, which interacts with where a snapshot attaches), #70, #71, #72.