// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package verify // abiResult records register-clobber violations detected by the ABI-checking // trampolines. Bit 0: frame pointer clobbered. Bit 1: goroutine pointer // clobbered. var abiResult uint64 // ABIReport describes the result of an ABI-checking call. The register // fields are architecture-dependent: // // - FPClobbered: the frame pointer the Go runtime maintains // (amd64 BP, arm64 R29). riscv64 and loong64 keep no hardware frame // pointer, so the field is always false there. // - GClobbered: the goroutine pointer (amd64 R14, arm64 R28, // riscv64 X27, loong64 R22). type ABIReport struct { FPClobbered bool GClobbered bool RedZoneHit bool } // OK returns true when no violations were detected. func (r ABIReport) OK() bool { return !r.FPClobbered && !r.GClobbered && !r.RedZoneHit } // String returns a human-readable summary. func (r ABIReport) String() string { if r.OK() { return "ABI clean" } s := "ABI violation:" if r.FPClobbered { s += " frame pointer clobbered" } if r.GClobbered { s += " goroutine pointer clobbered" } if r.RedZoneHit { s += " stack below SP written" } return s } // redZoneSize is the canary window below the prepared stack pointer. On // amd64 it is the System V red zone; on every architecture a Go function // must not write below its own declared frame, so the canary sits below // the frame plus the call margin (see CallCheckedFrame) and any corruption // there is a bug. const redZoneSize = 128 // redZoneFill is the byte pattern used to detect writes below SP. const redZoneFill = 0xA5