github.com/criyle/go-sandbox@v0.10.3/ptracer/context_helper_linux.go (about)

     1  package ptracer
     2  
     3  import (
     4  	"syscall"
     5  	"unsafe"
     6  
     7  	unix "golang.org/x/sys/unix"
     8  )
     9  
    10  // TODO: make this method not to call ptrace too much
    11  func ptraceReadStr(pid int, addr uintptr, buff []byte) {
    12  	syscall.PtracePeekData(pid, addr, buff)
    13  }
    14  
    15  func processVMReadv(pid int, localIov, remoteIov []unix.Iovec,
    16  	flags uintptr) (r1, r2 uintptr, err syscall.Errno) {
    17  	return syscall.Syscall6(unix.SYS_PROCESS_VM_READV, uintptr(pid),
    18  		uintptr(unsafe.Pointer(&localIov[0])), uintptr(len(localIov)),
    19  		uintptr(unsafe.Pointer(&remoteIov[0])), uintptr(len(remoteIov)),
    20  		flags)
    21  }
    22  
    23  func vmRead(pid int, addr uintptr, buff []byte) (int, error) {
    24  	l := len(buff)
    25  	localIov := getIovecs(&buff[0], l)
    26  	remoteIov := getIovecs((*byte)(unsafe.Pointer(addr)), l)
    27  	n, _, err := processVMReadv(pid, localIov, remoteIov, uintptr(0))
    28  	if err == 0 {
    29  		return int(n), nil
    30  	}
    31  	return int(n), err
    32  }
    33  
    34  func getIovecs(base *byte, l int) []unix.Iovec {
    35  	return []unix.Iovec{getIovec(base, l)}
    36  }
    37  
    38  func vmReadStr(pid int, addr uintptr, buff []byte) error {
    39  	// Deal with unaligned addr
    40  	n := 0
    41  	r := pageSize - int(addr%uintptr(pageSize))
    42  	if r == 0 {
    43  		r = pageSize
    44  	}
    45  
    46  	for len(buff) > 0 {
    47  		if l := len(buff); r < l {
    48  			r = l
    49  		}
    50  
    51  		nn, err := vmRead(pid, addr+uintptr(n), buff[:r])
    52  		if err != nil {
    53  			return err
    54  		}
    55  
    56  		if hasNull(buff[:nn]) {
    57  			return nil
    58  		}
    59  
    60  		n += nn
    61  		buff = buff[nn:]
    62  		r = pageSize
    63  	}
    64  	return nil
    65  }
    66  
    67  func hasNull(buff []byte) bool {
    68  	for _, b := range buff {
    69  		if b == 0 {
    70  			return true
    71  		}
    72  	}
    73  	return false
    74  }
    75  
    76  func clen(b []byte) int {
    77  	for i := 0; i < len(b); i++ {
    78  		if b[i] == 0 {
    79  			return i
    80  		}
    81  	}
    82  	return len(b) + 1
    83  }