fix(linux): compute cave-pair displacements at load time; apply pairs atomically - #6
Open
crombieman wants to merge 2 commits into
Open
fix(linux): compute cave-pair displacements at load time; apply pairs atomically#6crombieman wants to merge 2 commits into
crombieman wants to merge 2 commits into
Conversation
… atomically Two related fixes for the Linux cave-pair patches: 1. Atomic pair application (ports the fix from CS2-Bot-Improver PR #106): a "<name>_Cave" and its "<name>" partner are now applied cave-first, with the partner skipped if the cave's signature no longer matches and the cave rolled back if the partner fails. Previously a half-applied pair left a jmp into unpatched bytes (segfault in CCSBot::UpdateLookAround under bot combat). 2. Computed displacements: the rel32 fields inside all three cave pairs (and OnBombPlanted_AllBotsLearnSite) are now computed at load time from the resolved addresses instead of hardcoded. Loading is three-phase - resolve every signature first (a cave patch overwrites its own CC-padding signature), compute, then write. The cross-function cave<->site distance changes on most game updates; on the pre-14172 build the hardcoded LoopEntry displacement was exactly 0x20 short of the relocated cave, so a sig-matched pair jumped into a neighboring function's bytes - no crash, just silently corrupted bot vision. Also: - Cave signatures no longer pin the build-specific tail jmp rel32 (generalizes the ed0ard#5 revival fix to all three caves). - AttackState_RetreatOnSniper_Disable / BombPickup_CT_GlobalHearRange rewrite only the opcode byte; the rel8 displacement can't go stale. - Vision_AlwaysWatchApproachPoints_LoopEntry_Cave's signature now pins all 32 padding bytes it writes (was 30). - TBot_BombsiteSearch_UseKnownPlantedSite kept exactly as revalidated in ed0ard#5 (its call target can't be derived from the patch site; the hardcoded expectedOriginal is what makes it fail safe on drift). Validated on build 14172: 42/42 patches apply, and the computed rel32 values reproduce the hand-revalidated displacements from ed0ard#5 exactly. Multi-day runtime on a production Linux DM server with no crashes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
|
Thanks for the fix. Windows was the side I couldn't test, so good to have that covered. The Linux side has been applying cleanly across the last few game updates on my server. Let me know if you want anything else tested before merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Two related fixes for the Linux cave-pair patches, building directly on the excellent build-14172 revalidation in #5:
Atomic pair application (ports the fix accepted for testing in CS2-Bot-Improver PR #106): caves are applied before their partners, a partner is skipped cleanly if its cave's signature no longer matches, and an orphaned cave is rolled back. Previously a half-applied pair left a
jmpinto unpatched bytes — that was the segfault inCCSBot::UpdateLookAroundunder bot combat (~3–5 min MTTF on my server before the fix).Load-time computed displacements: the rel32 fields inside all three cave pairs (and
OnBombPlanted_AllBotsLearnSite) are computed from the resolved signature addresses instead of hardcoded. Loading is now three-phase — resolve every signature first (a cave patch overwrites its own CC-padding signature), compute, then write.Why
The cave↔site distance spans function boundaries and shifts on most game updates. The failure mode is nastier than a dead signature: on the pre-14172 build,
Vision_AlwaysWatchApproachPoints_LoopEntry's hardcoded displacement was exactly 0x20 short of where the cave actually resolved — both signatures still matched, the pair "applied" cleanly, and the jump executed a neighboring function's bytes. No crash, just silently corrupted bot vision behavior (bot-vs-bot kill rate on my DM server dropped ~3.5× with the pair applied). #5's comments document the same 0x20 shift from the other direction. With this change, that entire failure class is gone: whatever the new geometry is, the computed jump lands on the cave.Validation
site+0x1D34A,WatchApproachPointsexits at the original jz target and fall-through). Two independent derivations agreeing was a nice confirmation of both.WatchApproachPoints_Cave's signature was dead there, and the pair skipped/rolled back cleanly instead of half-applying.Also included
jmprel32 — generalizes fix(linux): revalidate patches + m_gameState 0x5100 for build 14172 #5's revival fix forWatchApproachPoints_Caveto all three caves (the other two carry the same landmine and have survived by luck).AttackState_RetreatOnSniper_Disable/BombPickup_CT_GlobalHearRangenow rewrite only the opcode byte (je/jne→jmp), matching the Windows definitions' approach, so their rel8 can't go stale.LoopEntry_Cave's signature pins all 32 padding bytes it writes (was 30 — the last two were only covered byexpectedOriginal).TBot_BombsiteSearch_UseKnownPlantedSiteis kept exactly as revalidated in fix(linux): revalidate patches + m_gameState 0x5100 for build 14172 #5 — its call target can't be derived from the patch site, and the hardcodedexpectedOriginalis precisely what makes it fail safe on drift. The comment sketches a possible future signature-based route if you ever want it drift-proof too.Caveats / notes for review
ModuleVersionat 1.8.7 — version bump is your call.Thanks to @mrc4tt for the 14172 revalidation that both revived the third pair and gave me the reference values to verify the computation against, and to @AmagiReina for testing the atomicity fix on Linux over in Bot-Improver #106.
🤖 Generated with Claude Code