unix: add ptrace support for FreeBSD

Change-Id: Iaf95e3e7bd3d33ad7e214c45ed87b9e967b16631
GitHub-Last-Rev: e0308dc7ad566b70922a499e81610a746afe84ac
GitHub-Pull-Request: golang/sys#34
Reviewed-on: https://go-review.googlesource.com/c/sys/+/179099
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/syscall_bsd.go b/unix/syscall_bsd.go
index 33c8b5f..41c33e9 100644
--- a/unix/syscall_bsd.go
+++ b/unix/syscall_bsd.go
@@ -86,6 +86,7 @@
 	shift = 8
 
 	exited  = 0
+	killed  = 9
 	stopped = 0x7F
 )
 
@@ -112,6 +113,8 @@
 
 func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
 
+func (w WaitStatus) Killed() bool { return w&mask == killed && syscall.Signal(w>>shift) != SIGKILL }
+
 func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
 
 func (w WaitStatus) StopSignal() syscall.Signal {
diff --git a/unix/syscall_freebsd.go b/unix/syscall_freebsd.go
index 1b6abe1..c0dbbc6 100644
--- a/unix/syscall_freebsd.go
+++ b/unix/syscall_freebsd.go
@@ -521,6 +521,70 @@
 	return sendfile(outfd, infd, offset, count)
 }
 
+//sys	ptrace(request int, pid int, addr uintptr, data int) (err error)
+
+func PtraceAttach(pid int) (err error) {
+	return ptrace(PTRACE_ATTACH, pid, 0, 0)
+}
+
+func PtraceCont(pid int, signal int) (err error) {
+	return ptrace(PTRACE_CONT, pid, 1, signal)
+}
+
+func PtraceDetach(pid int) (err error) {
+	return ptrace(PTRACE_DETACH, pid, 1, 0)
+}
+
+func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) {
+	return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
+}
+
+func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
+	return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
+}
+
+func PtraceGetRegs(pid int, regsout *Reg) (err error) {
+	return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
+}
+
+func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
+	ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint(countin)}
+	err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
+	return int(ioDesc.Len), err
+}
+
+func PtraceLwpEvents(pid int, enable int) (err error) {
+	return ptrace(PTRACE_LWPEVENTS, pid, 0, enable)
+}
+
+func PtraceLwpInfo(pid int, info uintptr) (err error) {
+	return ptrace(PTRACE_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{})))
+}
+
+func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
+	return PtraceIO(PIOD_READ_D, pid, addr, out, SizeofLong)
+}
+
+func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
+	return PtraceIO(PIOD_READ_I, pid, addr, out, SizeofLong)
+}
+
+func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
+	return PtraceIO(PIOD_WRITE_D, pid, addr, data, SizeofLong)
+}
+
+func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
+	return PtraceIO(PIOD_WRITE_I, pid, addr, data, SizeofLong)
+}
+
+func PtraceSetRegs(pid int, regs *Reg) (err error) {
+	return ptrace(PTRACE_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0)
+}
+
+func PtraceSingleStep(pid int) (err error) {
+	return ptrace(PTRACE_SINGLESTEP, pid, 1, 0)
+}
+
 /*
  * Exposed directly
  */
diff --git a/unix/types_freebsd.go b/unix/types_freebsd.go
index 7470798..a121dc3 100644
--- a/unix/types_freebsd.go
+++ b/unix/types_freebsd.go
@@ -243,11 +243,55 @@
 // Ptrace requests
 
 const (
-	PTRACE_TRACEME = C.PT_TRACE_ME
-	PTRACE_CONT    = C.PT_CONTINUE
-	PTRACE_KILL    = C.PT_KILL
+	PTRACE_ATTACH     = C.PT_ATTACH
+	PTRACE_CONT       = C.PT_CONTINUE
+	PTRACE_DETACH     = C.PT_DETACH
+	PTRACE_GETFPREGS  = C.PT_GETFPREGS
+	PTRACE_GETFSBASE  = C.PT_GETFSBASE
+	PTRACE_GETLWPLIST = C.PT_GETLWPLIST
+	PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS
+	PTRACE_GETREGS    = C.PT_GETREGS
+	PTRACE_GETXSTATE  = C.PT_GETXSTATE
+	PTRACE_IO         = C.PT_IO
+	PTRACE_KILL       = C.PT_KILL
+	PTRACE_LWPEVENTS  = C.PT_LWP_EVENTS
+	PTRACE_LWPINFO    = C.PT_LWPINFO
+	PTRACE_SETFPREGS  = C.PT_SETFPREGS
+	PTRACE_SETREGS    = C.PT_SETREGS
+	PTRACE_SINGLESTEP = C.PT_STEP
+	PTRACE_TRACEME    = C.PT_TRACE_ME
 )
 
+const (
+	PIOD_READ_D  = C.PIOD_READ_D
+	PIOD_WRITE_D = C.PIOD_WRITE_D
+	PIOD_READ_I  = C.PIOD_READ_I
+	PIOD_WRITE_I = C.PIOD_WRITE_I
+)
+
+const (
+	PL_FLAG_BORN   = C.PL_FLAG_BORN
+	PL_FLAG_EXITED = C.PL_FLAG_EXITED
+	PL_FLAG_SI     = C.PL_FLAG_SI
+)
+
+const (
+	TRAP_BRKPT = C.TRAP_BRKPT
+	TRAP_TRACE = C.TRAP_TRACE
+)
+
+type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo
+
+type __Siginfo C.struct___siginfo
+
+type Sigset_t C.sigset_t
+
+type Reg C.struct_reg
+
+type FpReg C.struct_fpreg
+
+type PtraceIoDesc C.struct_ptrace_io_desc
+
 // Events (kqueue, kevent)
 
 type Kevent_t C.struct_kevent_freebsd11
diff --git a/unix/zsyscall_freebsd_386.go b/unix/zsyscall_freebsd_386.go
index 2707c01..a783306 100644
--- a/unix/zsyscall_freebsd_386.go
+++ b/unix/zsyscall_freebsd_386.go
@@ -387,6 +387,16 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func ptrace(request int, pid int, addr uintptr, data int) (err error) {
+	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Getcwd(buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
diff --git a/unix/zsyscall_freebsd_amd64.go b/unix/zsyscall_freebsd_amd64.go
index 8e3c0ce..f995520 100644
--- a/unix/zsyscall_freebsd_amd64.go
+++ b/unix/zsyscall_freebsd_amd64.go
@@ -387,6 +387,16 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func ptrace(request int, pid int, addr uintptr, data int) (err error) {
+	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Getcwd(buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
diff --git a/unix/zsyscall_freebsd_arm.go b/unix/zsyscall_freebsd_arm.go
index 641f86a..d681acd 100644
--- a/unix/zsyscall_freebsd_arm.go
+++ b/unix/zsyscall_freebsd_arm.go
@@ -387,6 +387,16 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func ptrace(request int, pid int, addr uintptr, data int) (err error) {
+	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Getcwd(buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
diff --git a/unix/zsyscall_freebsd_arm64.go b/unix/zsyscall_freebsd_arm64.go
index 68fbccf..5049b2e 100644
--- a/unix/zsyscall_freebsd_arm64.go
+++ b/unix/zsyscall_freebsd_arm64.go
@@ -404,6 +404,16 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func ptrace(request int, pid int, addr uintptr, data int) (err error) {
+	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/ztypes_freebsd_386.go b/unix/ztypes_freebsd_386.go
index 0edc540..7312e95 100644
--- a/unix/ztypes_freebsd_386.go
+++ b/unix/ztypes_freebsd_386.go
@@ -324,11 +324,108 @@
 )
 
 const (
-	PTRACE_TRACEME = 0x0
-	PTRACE_CONT    = 0x7
-	PTRACE_KILL    = 0x8
+	PTRACE_ATTACH     = 0xa
+	PTRACE_CONT       = 0x7
+	PTRACE_DETACH     = 0xb
+	PTRACE_GETFPREGS  = 0x23
+	PTRACE_GETFSBASE  = 0x47
+	PTRACE_GETLWPLIST = 0xf
+	PTRACE_GETNUMLWPS = 0xe
+	PTRACE_GETREGS    = 0x21
+	PTRACE_GETXSTATE  = 0x45
+	PTRACE_IO         = 0xc
+	PTRACE_KILL       = 0x8
+	PTRACE_LWPEVENTS  = 0x18
+	PTRACE_LWPINFO    = 0xd
+	PTRACE_SETFPREGS  = 0x24
+	PTRACE_SETREGS    = 0x22
+	PTRACE_SINGLESTEP = 0x9
+	PTRACE_TRACEME    = 0x0
 )
 
+const (
+	PIOD_READ_D  = 0x1
+	PIOD_WRITE_D = 0x2
+	PIOD_READ_I  = 0x3
+	PIOD_WRITE_I = 0x4
+)
+
+const (
+	PL_FLAG_BORN   = 0x100
+	PL_FLAG_EXITED = 0x200
+	PL_FLAG_SI     = 0x20
+)
+
+const (
+	TRAP_BRKPT = 0x1
+	TRAP_TRACE = 0x2
+)
+
+type PtraceLwpInfoStruct struct {
+	Lwpid        int32
+	Event        int32
+	Flags        int32
+	Sigmask      Sigset_t
+	Siglist      Sigset_t
+	Siginfo      __Siginfo
+	Tdname       [20]int8
+	Child_pid    int32
+	Syscall_code uint32
+	Syscall_narg uint32
+}
+
+type __Siginfo struct {
+	Signo    int32
+	Errno    int32
+	Code     int32
+	Pid      int32
+	Uid      uint32
+	Status   int32
+	Addr     *byte
+	Value    [4]byte
+	X_reason [32]byte
+}
+
+type Sigset_t struct {
+	Val [4]uint32
+}
+
+type Reg struct {
+	Fs     uint32
+	Es     uint32
+	Ds     uint32
+	Edi    uint32
+	Esi    uint32
+	Ebp    uint32
+	Isp    uint32
+	Ebx    uint32
+	Edx    uint32
+	Ecx    uint32
+	Eax    uint32
+	Trapno uint32
+	Err    uint32
+	Eip    uint32
+	Cs     uint32
+	Eflags uint32
+	Esp    uint32
+	Ss     uint32
+	Gs     uint32
+}
+
+type FpReg struct {
+	Env   [7]uint32
+	Acc   [8][10]uint8
+	Ex_sw uint32
+	Pad   [64]uint8
+}
+
+type PtraceIoDesc struct {
+	Op   int32
+	Offs *byte
+	Addr *byte
+	Len  uint
+}
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
diff --git a/unix/ztypes_freebsd_amd64.go b/unix/ztypes_freebsd_amd64.go
index 8881ce8..29ba2f5 100644
--- a/unix/ztypes_freebsd_amd64.go
+++ b/unix/ztypes_freebsd_amd64.go
@@ -322,11 +322,115 @@
 )
 
 const (
-	PTRACE_TRACEME = 0x0
-	PTRACE_CONT    = 0x7
-	PTRACE_KILL    = 0x8
+	PTRACE_ATTACH     = 0xa
+	PTRACE_CONT       = 0x7
+	PTRACE_DETACH     = 0xb
+	PTRACE_GETFPREGS  = 0x23
+	PTRACE_GETFSBASE  = 0x47
+	PTRACE_GETLWPLIST = 0xf
+	PTRACE_GETNUMLWPS = 0xe
+	PTRACE_GETREGS    = 0x21
+	PTRACE_GETXSTATE  = 0x45
+	PTRACE_IO         = 0xc
+	PTRACE_KILL       = 0x8
+	PTRACE_LWPEVENTS  = 0x18
+	PTRACE_LWPINFO    = 0xd
+	PTRACE_SETFPREGS  = 0x24
+	PTRACE_SETREGS    = 0x22
+	PTRACE_SINGLESTEP = 0x9
+	PTRACE_TRACEME    = 0x0
 )
 
+const (
+	PIOD_READ_D  = 0x1
+	PIOD_WRITE_D = 0x2
+	PIOD_READ_I  = 0x3
+	PIOD_WRITE_I = 0x4
+)
+
+const (
+	PL_FLAG_BORN   = 0x100
+	PL_FLAG_EXITED = 0x200
+	PL_FLAG_SI     = 0x20
+)
+
+const (
+	TRAP_BRKPT = 0x1
+	TRAP_TRACE = 0x2
+)
+
+type PtraceLwpInfoStruct struct {
+	Lwpid        int32
+	Event        int32
+	Flags        int32
+	Sigmask      Sigset_t
+	Siglist      Sigset_t
+	Siginfo      __Siginfo
+	Tdname       [20]int8
+	Child_pid    int32
+	Syscall_code uint32
+	Syscall_narg uint32
+}
+
+type __Siginfo struct {
+	Signo  int32
+	Errno  int32
+	Code   int32
+	Pid    int32
+	Uid    uint32
+	Status int32
+	Addr   *byte
+	Value  [8]byte
+	_      [40]byte
+}
+
+type Sigset_t struct {
+	Val [4]uint32
+}
+
+type Reg struct {
+	R15    int64
+	R14    int64
+	R13    int64
+	R12    int64
+	R11    int64
+	R10    int64
+	R9     int64
+	R8     int64
+	Rdi    int64
+	Rsi    int64
+	Rbp    int64
+	Rbx    int64
+	Rdx    int64
+	Rcx    int64
+	Rax    int64
+	Trapno uint32
+	Fs     uint16
+	Gs     uint16
+	Err    uint32
+	Es     uint16
+	Ds     uint16
+	Rip    int64
+	Cs     int64
+	Rflags int64
+	Rsp    int64
+	Ss     int64
+}
+
+type FpReg struct {
+	Env   [4]uint64
+	Acc   [8][16]uint8
+	Xacc  [16][16]uint8
+	Spare [12]uint64
+}
+
+type PtraceIoDesc struct {
+	Op   int32
+	Offs *byte
+	Addr *byte
+	Len  uint
+}
+
 type Kevent_t struct {
 	Ident  uint64
 	Filter int16
diff --git a/unix/ztypes_freebsd_arm.go b/unix/ztypes_freebsd_arm.go
index fc71399..b4090ef 100644
--- a/unix/ztypes_freebsd_arm.go
+++ b/unix/ztypes_freebsd_arm.go
@@ -322,11 +322,92 @@
 )
 
 const (
-	PTRACE_TRACEME = 0x0
-	PTRACE_CONT    = 0x7
-	PTRACE_KILL    = 0x8
+	PTRACE_ATTACH     = 0xa
+	PTRACE_CONT       = 0x7
+	PTRACE_DETACH     = 0xb
+	PTRACE_GETFPREGS  = 0x23
+	PTRACE_GETFSBASE  = 0x47
+	PTRACE_GETLWPLIST = 0xf
+	PTRACE_GETNUMLWPS = 0xe
+	PTRACE_GETREGS    = 0x21
+	PTRACE_GETXSTATE  = 0x45
+	PTRACE_IO         = 0xc
+	PTRACE_KILL       = 0x8
+	PTRACE_LWPEVENTS  = 0x18
+	PTRACE_LWPINFO    = 0xd
+	PTRACE_SETFPREGS  = 0x24
+	PTRACE_SETREGS    = 0x22
+	PTRACE_SINGLESTEP = 0x9
+	PTRACE_TRACEME    = 0x0
 )
 
+const (
+	PIOD_READ_D  = 0x1
+	PIOD_WRITE_D = 0x2
+	PIOD_READ_I  = 0x3
+	PIOD_WRITE_I = 0x4
+)
+
+const (
+	PL_FLAG_BORN   = 0x100
+	PL_FLAG_EXITED = 0x200
+	PL_FLAG_SI     = 0x20
+)
+
+const (
+	TRAP_BRKPT = 0x1
+	TRAP_TRACE = 0x2
+)
+
+type PtraceLwpInfoStruct struct {
+	Lwpid        int32
+	Event        int32
+	Flags        int32
+	Sigmask      Sigset_t
+	Siglist      Sigset_t
+	Siginfo      __Siginfo
+	Tdname       [20]int8
+	Child_pid    int32
+	Syscall_code uint32
+	Syscall_narg uint32
+}
+
+type __Siginfo struct {
+	Signo    int32
+	Errno    int32
+	Code     int32
+	Pid      int32
+	Uid      uint32
+	Status   int32
+	Addr     *byte
+	Value    [4]byte
+	X_reason [32]byte
+}
+
+type Sigset_t struct {
+	Val [4]uint32
+}
+
+type Reg struct {
+	R      [13]uint32
+	R_sp   uint32
+	R_lr   uint32
+	R_pc   uint32
+	R_cpsr uint32
+}
+
+type FpReg struct {
+	Fpr_fpsr uint32
+	Fpr      [8][3]uint32
+}
+
+type PtraceIoDesc struct {
+	Op   int32
+	Offs *byte
+	Addr *byte
+	Len  uint
+}
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
diff --git a/unix/ztypes_freebsd_arm64.go b/unix/ztypes_freebsd_arm64.go
index 5a0753e..1542a87 100644
--- a/unix/ztypes_freebsd_arm64.go
+++ b/unix/ztypes_freebsd_arm64.go
@@ -322,11 +322,93 @@
 )
 
 const (
-	PTRACE_TRACEME = 0x0
-	PTRACE_CONT    = 0x7
-	PTRACE_KILL    = 0x8
+	PTRACE_ATTACH     = 0xa
+	PTRACE_CONT       = 0x7
+	PTRACE_DETACH     = 0xb
+	PTRACE_GETFPREGS  = 0x23
+	PTRACE_GETFSBASE  = 0x47
+	PTRACE_GETLWPLIST = 0xf
+	PTRACE_GETNUMLWPS = 0xe
+	PTRACE_GETREGS    = 0x21
+	PTRACE_GETXSTATE  = 0x45
+	PTRACE_IO         = 0xc
+	PTRACE_KILL       = 0x8
+	PTRACE_LWPEVENTS  = 0x18
+	PTRACE_LWPINFO    = 0xd
+	PTRACE_SETFPREGS  = 0x24
+	PTRACE_SETREGS    = 0x22
+	PTRACE_SINGLESTEP = 0x9
+	PTRACE_TRACEME    = 0x0
 )
 
+const (
+	PIOD_READ_D  = 0x1
+	PIOD_WRITE_D = 0x2
+	PIOD_READ_I  = 0x3
+	PIOD_WRITE_I = 0x4
+)
+
+const (
+	PL_FLAG_BORN   = 0x100
+	PL_FLAG_EXITED = 0x200
+	PL_FLAG_SI     = 0x20
+)
+
+const (
+	TRAP_BRKPT = 0x1
+	TRAP_TRACE = 0x2
+)
+
+type PtraceLwpInfoStruct struct {
+	Lwpid        int32
+	Event        int32
+	Flags        int32
+	Sigmask      Sigset_t
+	Siglist      Sigset_t
+	Siginfo      __Siginfo
+	Tdname       [20]int8
+	Child_pid    int32
+	Syscall_code uint32
+	Syscall_narg uint32
+}
+
+type __Siginfo struct {
+	Signo    int32
+	Errno    int32
+	Code     int32
+	Pid      int32
+	Uid      uint32
+	Status   int32
+	Addr     *byte
+	Value    [8]byte
+	X_reason [40]byte
+}
+
+type Sigset_t struct {
+	Val [4]uint32
+}
+
+type Reg struct {
+	X    [30]uint64
+	Lr   uint64
+	Sp   uint64
+	Elr  uint64
+	Spsr uint32
+}
+
+type FpReg struct {
+	Fp_q  [32]uint128
+	Fp_sr uint32
+	Fp_cr uint32
+}
+
+type PtraceIoDesc struct {
+	Op   int32
+	Offs *byte
+	Addr *byte
+	Len  uint
+}
+
 type Kevent_t struct {
 	Ident  uint64
 	Filter int16