// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package verify import ( "testing" ) func loadABIKernel(t *testing.T) *Kernel { t.Helper() k, err := Load("../testdata/verify/abi_amd64.s") if err != nil { t.Fatalf("Load: %v", err) } t.Cleanup(k.Close) return k } func TestABIClean(t *testing.T) { k := loadABIKernel(t) args := make([]byte, 24) PutUint64(args, 0, 3) PutUint64(args, 8, 4) out, report, err := k.CallFuncChecked("cleanAdd", args) if err != nil { t.Fatalf("CallFuncChecked: %v", err) } if got := int64(GetUint64(out, 16)); got != 7 { t.Errorf("cleanAdd(3, 4) = %d, want 7", got) } if !report.OK() { t.Errorf("cleanAdd: %s", report) } } func TestABIBPClobbered(t *testing.T) { k := loadABIKernel(t) args := make([]byte, 16) PutUint64(args, 0, 42) out, report, err := k.CallFuncChecked("dirtyBP", args) if err != nil { t.Fatalf("CallFuncChecked: %v", err) } if got := int64(GetUint64(out, 8)); got != 42 { t.Errorf("dirtyBP(42) = %d, want 42", got) } if !report.FPClobbered { t.Error("dirtyBP: expected BP clobbered, but report says clean") } if report.GClobbered { t.Error("dirtyBP: R14 should not be clobbered") } } func TestABIR14Clobbered(t *testing.T) { k := loadABIKernel(t) args := make([]byte, 16) PutUint64(args, 0, 99) out, report, err := k.CallFuncChecked("dirtyR14", args) if err != nil { t.Fatalf("CallFuncChecked: %v", err) } if got := int64(GetUint64(out, 8)); got != 99 { t.Errorf("dirtyR14(99) = %d, want 99", got) } if !report.GClobbered { t.Error("dirtyR14: expected R14 clobbered, but report says clean") } if report.FPClobbered { t.Error("dirtyR14: BP should not be clobbered") } } func TestCallFuncCheckedErrors(t *testing.T) { k := loadABIKernel(t) // Nonexistent function. _, _, err := k.CallFuncChecked("nope", make([]byte, 8)) if err == nil { t.Fatal("expected error for nonexistent function") } // Arg block too small. _, _, err = k.CallFuncChecked("cleanAdd", make([]byte, 8)) if err == nil { t.Fatal("expected error for too-small arg block") } }