diff --git a/debug/disasm_linux_arm64.go b/debug/disasm_linux_arm64.go index 166bccf..e4dd813 100644 --- a/debug/disasm_linux_arm64.go +++ b/debug/disasm_linux_arm64.go @@ -30,7 +30,7 @@ func (s *Session) Disassemble(addr uint64) (string, int, error) { func (s *Session) DisassembleN(addr uint64, n int) string { var result string pc := addr - for i := range n { + for range n { text, length, err := s.Disassemble(pc) if err != nil { result += fmt.Sprintf(" %#08x: \n", pc, err) diff --git a/debug/disasm_linux_loong64.go b/debug/disasm_linux_loong64.go index 3bf0f85..93f881e 100644 --- a/debug/disasm_linux_loong64.go +++ b/debug/disasm_linux_loong64.go @@ -22,7 +22,7 @@ func (s *Session) Disassemble(addr uint64) (string, int, error) { if err != nil { return "???", 4, nil } - text := loong64asm.GoSyntax(inst, addr, nil, nil) + text := loong64asm.GoSyntax(inst, addr, nil) return text, 4, nil } @@ -30,7 +30,7 @@ func (s *Session) Disassemble(addr uint64) (string, int, error) { func (s *Session) DisassembleN(addr uint64, n int) string { var result string pc := addr - for i := range n { + for range n { text, length, err := s.Disassemble(pc) if err != nil { result += fmt.Sprintf(" %#08x: \n", pc, err) diff --git a/debug/disasm_linux_riscv64.go b/debug/disasm_linux_riscv64.go index e9dfab9..7ff0ceb 100644 --- a/debug/disasm_linux_riscv64.go +++ b/debug/disasm_linux_riscv64.go @@ -30,7 +30,7 @@ func (s *Session) Disassemble(addr uint64) (string, int, error) { func (s *Session) DisassembleN(addr uint64, n int) string { var result string pc := addr - for i := range n { + for range n { text, length, err := s.Disassemble(pc) if err != nil { result += fmt.Sprintf(" %#08x: \n", pc, err) diff --git a/debug/ptrace_linux_arm64.go b/debug/ptrace_linux_arm64.go index 44eef31..c497d85 100644 --- a/debug/ptrace_linux_arm64.go +++ b/debug/ptrace_linux_arm64.go @@ -44,26 +44,35 @@ func (s *Session) SetRegs(regs *Regs) error { return nil } -// FPRegs holds the NEON/FP register state (V0-V31, FPCR, FPSR). +// ntPrFPREG is the NT_PRFPREG note type (ELF NT ver): the FP register set. +const ntPrFPREG = 0x2 + +// FPRegs holds the arm64 FP/NEON register state, matching the kernel's +// user_fpsimd_struct layout (32 128-bit V registers, then FPSR and FPCR). type FPRegs struct { V [32][16]byte // V0-V31 (128-bit NEON/FP registers) - FPCR uint32 FPSR uint32 + FPCR uint32 } -// GetFPRegs retrieves the NEON/FP register state. +// 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_GETFPREGS), + uintptr(syscall.PTRACE_GETREGSET), uintptr(s.pid), - 0, - uintptr(unsafe.Pointer(&fp)), + uintptr(ntPrFPREG), + uintptr(unsafe.Pointer(&iovec)), 0, 0, ) if errno != 0 { - return fp, fmt.Errorf("debug: PTRACE_GETFPREGS: %w", errno) + return fp, fmt.Errorf("debug: PTRACE_GETREGSET (NT_PRFPREG): %w", errno) } return fp, nil } diff --git a/debug/ptrace_linux_loong64.go b/debug/ptrace_linux_loong64.go index b6355fc..077364d 100644 --- a/debug/ptrace_linux_loong64.go +++ b/debug/ptrace_linux_loong64.go @@ -44,25 +44,36 @@ func (s *Session) SetRegs(regs *Regs) error { return nil } -// FPRegs holds the LoongArch FP register state (F0-F31). +// 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][16]byte // F0-F31 (128-bit, lower 64 bits used for double) + 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. +// 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_GETFPREGS), + uintptr(syscall.PTRACE_GETREGSET), uintptr(s.pid), - 0, - uintptr(unsafe.Pointer(&fp)), + uintptr(ntPrFPREG), + uintptr(unsafe.Pointer(&iovec)), 0, 0, ) if errno != 0 { - return fp, fmt.Errorf("debug: PTRACE_GETFPREGS: %w", errno) + return fp, fmt.Errorf("debug: PTRACE_GETREGSET (NT_PRFPREG): %w", errno) } return fp, nil } diff --git a/debug/ptrace_linux_riscv64.go b/debug/ptrace_linux_riscv64.go index f017635..68dd0cb 100644 --- a/debug/ptrace_linux_riscv64.go +++ b/debug/ptrace_linux_riscv64.go @@ -44,25 +44,34 @@ func (s *Session) SetRegs(regs *Regs) error { return nil } -// FPRegs holds the RISC-V FP register state (F0-F31). +// ntPrFPREG is the NT_PRFPREG note type (ELF NT ver): the FP register set. +const ntPrFPREG = 0x2 + +// FPRegs holds the RISC-V FP register state, matching the kernel's +// user_fp_struct layout (32 64-bit FP registers plus fcsr). type FPRegs struct { - F [32][16]byte // F0-F31 (128-bit, lower 64 bits used for double) + F [32]uint64 // F0-F31 (64-bit FP registers) FCSR uint32 } -// GetFPRegs retrieves the FP register state. +// 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_GETFPREGS), + uintptr(syscall.PTRACE_GETREGSET), uintptr(s.pid), - 0, - uintptr(unsafe.Pointer(&fp)), + uintptr(ntPrFPREG), + uintptr(unsafe.Pointer(&iovec)), 0, 0, ) if errno != 0 { - return fp, fmt.Errorf("debug: PTRACE_GETFPREGS: %w", errno) + return fp, fmt.Errorf("debug: PTRACE_GETREGSET (NT_PRFPREG): %w", errno) } return fp, nil } diff --git a/debug/target_linux_arm64.go b/debug/target_linux_arm64.go index 6e5d97a..d808312 100644 --- a/debug/target_linux_arm64.go +++ b/debug/target_linux_arm64.go @@ -86,7 +86,7 @@ func RunTarget(asmPath, funcName, argsFile, tmpDir string) error { bufSpecFile := tmpDir + "/bufspec" if bufSpec, err := os.ReadFile(bufSpecFile); err == nil && len(bufSpec) > 0 { - args, err = setupBuffers(string(bufSpec), args, fl.Args, tmpDir) + args, err = setupBuffers(string(bufSpec), args, tmpDir) if err != nil { return fmt.Errorf("debug target: setup buffers: %w", err) } @@ -107,7 +107,7 @@ func RunTarget(asmPath, funcName, argsFile, tmpDir string) error { stackArgs := make([]byte, fl.Args) copy(stackArgs, args) - _, callErr := verify.Call(stackArgs) + _, callErr := verify.Call(fnAddr, stackArgs) if callErr != nil { os.Exit(1) } diff --git a/debug/target_linux_loong64.go b/debug/target_linux_loong64.go index de560a9..e3039dd 100644 --- a/debug/target_linux_loong64.go +++ b/debug/target_linux_loong64.go @@ -107,7 +107,7 @@ func RunTarget(asmPath, funcName, argsFile, tmpDir string) error { stackArgs := make([]byte, fl.Args) copy(stackArgs, args) - _, callErr := verify.Call(stackArgs) + _, callErr := verify.Call(fnAddr, stackArgs) if callErr != nil { os.Exit(1) } diff --git a/debug/target_linux_riscv64.go b/debug/target_linux_riscv64.go index 70f1543..2baa2a7 100644 --- a/debug/target_linux_riscv64.go +++ b/debug/target_linux_riscv64.go @@ -28,15 +28,7 @@ func RunTarget(asmPath, funcName, argsFile, tmpDir string) error { return fmt.Errorf("debug target: parse: %v", errs[0]) } - var img *asm.Image - switch "riscv64" { - case "arm64": - img, err = asm.AssembleFileARM64(file) - case "riscv64": - img, err = asm.AssembleFileRISCV(file) - case "loong64": - img, err = asm.AssembleFileLOONG64(file) - } + img, err := asm.AssembleFileRISCV(file) if err != nil { return fmt.Errorf("debug target: assemble: %w", err) } @@ -107,7 +99,7 @@ func RunTarget(asmPath, funcName, argsFile, tmpDir string) error { stackArgs := make([]byte, fl.Args) copy(stackArgs, args) - _, callErr := verify.Call(stackArgs) + _, callErr := verify.Call(fnAddr, stackArgs) if callErr != nil { os.Exit(1) } diff --git a/debug/watchpoint_linux_arm64.go b/debug/watchpoint_linux_arm64.go index 8bdebb0..3003e3d 100644 --- a/debug/watchpoint_linux_arm64.go +++ b/debug/watchpoint_linux_arm64.go @@ -145,7 +145,7 @@ func (s *Session) getHWBreakState() (*hwBreakState, error) { var state hwBreakState iovec := syscall.Iovec{ Base: (*byte)(unsafe.Pointer(&state)), - Len: uint32(unsafe.Sizeof(state)), + Len: uint64(unsafe.Sizeof(state)), } _, _, errno := syscall.Syscall6( syscall.SYS_PTRACE, @@ -164,7 +164,7 @@ func (s *Session) getHWBreakState() (*hwBreakState, error) { func (s *Session) setHWBreakState(state *hwBreakState) error { iovec := syscall.Iovec{ Base: (*byte)(unsafe.Pointer(state)), - Len: uint32(unsafe.Sizeof(*state)), + Len: uint64(unsafe.Sizeof(*state)), } _, _, errno := syscall.Syscall6( syscall.SYS_PTRACE,