unix: add ProcessVMReadv and ProcessVMWritev on linux

These are Linux-specific system calls for efficiently reading and
writing memory in foreign processes.

A new RemoteIovec type is added for use in these wrappers, as Iovec's
Base field is a pointer, and creating invalid pointers is invalid in
Go.

Change-Id: I329501ab7b4df9d0aebe289369d3a5f77120af02
GitHub-Last-Rev: 262aabed02cc1f604e85fa1b4be1b874c57bd666
GitHub-Pull-Request: golang/sys#74
Reviewed-on: https://go-review.googlesource.com/c/sys/+/243497
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_linux.go b/unix/syscall_linux.go
index e50e4cb..fad483b 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -2122,6 +2122,18 @@
 	return nil
 }
 
+// RemoteIovec is Iovec with the pointer replaced with an integer.
+// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
+// refers to a location in a different process' address space, which
+// would confuse the Go garbage collector.
+type RemoteIovec struct {
+	Base uintptr
+	Len  int
+}
+
+//sys	ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
+//sys	ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
+
 /*
  * Unimplemented
  */
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index df21782..f6603de 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -1847,6 +1847,52 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(localIov) > 0 {
+		_p0 = unsafe.Pointer(&localIov[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	var _p1 unsafe.Pointer
+	if len(remoteIov) > 0 {
+		_p1 = unsafe.Pointer(&remoteIov[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PROCESS_VM_READV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(localIov) > 0 {
+		_p0 = unsafe.Pointer(&localIov[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	var _p1 unsafe.Pointer
+	if len(remoteIov) > 0 {
+		_p1 = unsafe.Pointer(&remoteIov[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PROCESS_VM_WRITEV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func pipe2(p *[2]_C_int, flags int) (err error) {
 	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
 	if e1 != 0 {