// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause //go:build linux && loong64 package debug import ( "fmt" "syscall" "unsafe" ) // GetRegs reads the general-purpose registers of the stopped debuggee. func (s *Session) GetRegs() (Regs, error) { var regs Regs _, _, errno := syscall.Syscall6( syscall.SYS_PTRACE, uintptr(syscall.PTRACE_GETREGS), uintptr(s.pid), 0, uintptr(unsafe.Pointer(®s)), 0, 0, ) if errno != 0 { return regs, fmt.Errorf("debug: PTRACE_GETREGS: %w", errno) } return regs, nil } // SetRegs writes the general-purpose registers of the stopped debuggee. func (s *Session) SetRegs(regs *Regs) error { _, _, errno := syscall.Syscall6( syscall.SYS_PTRACE, uintptr(syscall.PTRACE_SETREGS), uintptr(s.pid), 0, uintptr(unsafe.Pointer(regs)), 0, 0, ) if errno != 0 { return fmt.Errorf("debug: PTRACE_SETREGS: %w", errno) } return nil } // ntPrFPREG is the NT_PRFPREG note type (ELF NT ver): the FP register set. const ntPrFPREG = 0x2 // FPRegs holds the LoongArch FP register state, matching the kernel's // user_fp_struct layout (32 64-bit FP registers, the fcc condition flags, // and fcsr). type FPRegs struct { F [32]uint64 // F0-F31 (64-bit FP registers) FCC uint64 // eight per-register condition flags, packed FCSR uint32 } // GetFPRegs retrieves the FP register state via PTRACE_GETREGSET with // NT_PRFPREG (this architecture has no PTRACE_GETFPREGS request). func (s *Session) GetFPRegs() (FPRegs, error) { var fp FPRegs iovec := syscall.Iovec{ Base: (*byte)(unsafe.Pointer(&fp)), Len: uint64(unsafe.Sizeof(fp)), } _, _, errno := syscall.Syscall6( syscall.SYS_PTRACE, uintptr(syscall.PTRACE_GETREGSET), uintptr(s.pid), uintptr(ntPrFPREG), uintptr(unsafe.Pointer(&iovec)), 0, 0, ) if errno != 0 { return fp, fmt.Errorf("debug: PTRACE_GETREGSET (NT_PRFPREG): %w", errno) } return fp, nil } // VectorRegs holds the FP register state shown by the regs command // (the scalar FP subset: 32 64-bit registers, fcc and fcsr; the LSX/LASX // vector files are not read yet). type VectorRegs struct { F [32]uint64 FCC uint64 FCSR uint32 } // GetVectorRegs retrieves the FP registers. func (s *Session) GetVectorRegs() (VectorRegs, error) { fp, err := s.GetFPRegs() if err != nil { return VectorRegs{}, err } return VectorRegs{F: fp.F, FCC: fp.FCC, FCSR: fp.FCSR}, nil }