go-sandbox/ptracer/context_helper.go
2019-08-30 00:57:07 -07:00

84 lines
1.6 KiB
Go

package ptracer
import (
"syscall"
"unsafe"
unix "golang.org/x/sys/unix"
)
// TODO: make this method not to call ptrace too much
func ptraceReadStr(pid int, addr uintptr, buff []byte) {
syscall.PtracePeekData(pid, addr, buff)
}
func processVMReadv(pid int, localIov, remoteIov []unix.Iovec,
flags uintptr) (r1, r2 uintptr, err syscall.Errno) {
return syscall.Syscall6(unix.SYS_PROCESS_VM_READV, uintptr(pid),
uintptr(unsafe.Pointer(&localIov[0])), uintptr(len(localIov)),
uintptr(unsafe.Pointer(&remoteIov[0])), uintptr(len(remoteIov)),
flags)
}
func vmRead(pid int, addr uintptr, buff []byte) (int, error) {
l := len(buff)
localIov := getIovecs(&buff[0], l)
remoteIov := getIovecs((*byte)(unsafe.Pointer(addr)), l)
n, _, err := processVMReadv(pid, localIov, remoteIov, uintptr(0))
if err == 0 {
return int(n), nil
}
return int(n), err
}
func getIovecs(base *byte, l int) []unix.Iovec {
return []unix.Iovec{getIovec(base, l)}
}
func vmReadStr(pid int, addr uintptr, buff []byte) error {
// Deal with unaligned addr
n := 0
r := pageSize - int(addr%uintptr(pageSize))
if r == 0 {
r = pageSize
}
for len(buff) > 0 {
if l := len(buff); r < l {
r = l
}
nn, err := vmRead(pid, addr+uintptr(n), buff[:r])
if err != nil {
return err
}
if hasNull(buff[:nn]) {
return nil
}
n += nn
buff = buff[nn:]
r = pageSize
}
return nil
}
func hasNull(buff []byte) bool {
for _, b := range buff {
if b == 0 {
return true
}
}
return false
}
func clen(b []byte) int {
for i := 0; i < len(b); i++ {
if b[i] == 0 {
return i
}
}
return len(b) + 1
}