delve/pkg/proc/native/ptrace_freebsd.go
Joel Sing 9c5777e762
pkg/proc: fix and improve freebsd register handling (#3019)
* pkg/proc: convert freebsd ptrace code to cgo

There is little point in having cgo call a custom C function, when the same
can be done directly from cgo (with less code and effort). Split the amd64
specific code into ptrace_freebsd_amd64.go. Also avoid mixing C.ptrace()
with syscall.SYS_PTRACE.

This will make further changes easier - no functional change intended.

* pkg/proc: check return values of ptrace calls on freebsd

The return values of the PT_GETNUMLWPS and PT_GETLWPLIST ptrace calls were
previously unchecked. While these should not fail, panic instead of using
-1 with slice allocation/handling.

* pkg/proc: return *amd64util.AMD64Xstate from freebsd ptraceGetRegset

Return a pointer to a struct, rather than a struct - this simplifies the
code in both the caller and the ptraceGetRegset function, while also avoiding
struct copying.

* pkg/proc: fix floating point register setting on freebsd

The original code could never work - PT_SETREGS on freebsd does not
take an iovec, nor does it set FP registers. Furthermore, the xsave
bytes were not stored in the amd64util.AMD64Xstate struct.

Updates #3001

* pkg/proc: re-enable function call injection on freebsd

Floating point registers can now be set and restored correctly.

This is a partial revert of 51090f003bace1f8cc37b8480ffdb6f6cc91fa5a.

Fixes #3001

* pkg/proc: deduplicate register setting code on freebsd
2022-05-31 16:04:36 -07:00

69 lines
1.7 KiB
Go

package native
// #cgo LDFLAGS: -lutil
//#include <sys/types.h>
//#include <sys/ptrace.h>
//
// #include <stdlib.h>
//
import "C"
import (
"unsafe"
sys "golang.org/x/sys/unix"
)
// ptraceAttach executes the sys.PtraceAttach call.
// pid must be a PID, not a LWPID
func ptraceAttach(pid int) error {
return sys.PtraceAttach(pid)
}
// ptraceDetach calls ptrace(PTRACE_DETACH).
func ptraceDetach(pid int) error {
return sys.PtraceDetach(pid)
}
// ptraceCont executes ptrace PTRACE_CONT
// id may be a PID or an LWPID
func ptraceCont(id, sig int) error {
return sys.PtraceCont(id, sig)
}
// ptraceSingleStep executes ptrace PTRACE_SINGLE_STEP.
// id may be a PID or an LWPID
func ptraceSingleStep(id int) error {
return sys.PtraceSingleStep(id)
}
// Get a list of the thread ids of a process
func ptraceGetLwpList(pid int) (tids []int32) {
numLWPS := C.ptrace(C.PT_GETNUMLWPS, C.pid_t(pid), C.caddr_t(unsafe.Pointer(uintptr(0))), C.int(0))
if numLWPS < 0 {
panic("PT_GETNUMLWPS failed")
}
tids = make([]int32, numLWPS)
n := C.ptrace(C.PT_GETLWPLIST, C.pid_t(pid), C.caddr_t(unsafe.Pointer(&tids[0])), C.int(numLWPS))
if n < 0 {
panic("PT_GETLWPLIST failed")
}
return tids[0:n]
}
// Get info of the thread that caused wpid's process to stop.
func ptraceGetLwpInfo(wpid int) (info sys.PtraceLwpInfoStruct, err error) {
err = sys.PtraceLwpInfo(wpid, uintptr(unsafe.Pointer(&info)))
return info, err
}
// id may be a PID or an LWPID
func ptraceReadData(id int, addr uintptr, data []byte) (n int, err error) {
return sys.PtraceIO(sys.PIOD_READ_D, id, addr, data, len(data))
}
// id may be a PID or an LWPID
func ptraceWriteData(id int, addr uintptr, data []byte) (n int, err error) {
return sys.PtraceIO(sys.PIOD_WRITE_D, id, addr, data, len(data))
}