commit d7ff1f5448437c7afe491dc0caf01ea418e7ae46 Author: Mikolaj Golub Date: Sun Oct 16 19:25:41 2011 +0300 Make kvm_uread() read from user space using ptrace(2). With this change 'ps -e' does not require procfs(5). diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index 876af50..71809ee 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #define _WANT_PRISON /* make jail.h give us 'struct prison' */ #include #include @@ -66,6 +67,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -958,10 +960,7 @@ ssize_t kvm_uread(kvm_t *kd, const struct kinfo_proc *kp, u_long uva, char *buf, size_t len) { - char *cp; - char procfile[MAXPATHLEN]; - ssize_t amount; - int fd; + struct ptrace_io_desc ioreq; if (!ISALIVE(kd)) { _kvm_err(kd, kd->program, @@ -969,36 +968,34 @@ kvm_uread(kvm_t *kd, const struct kinfo_proc *kp, u_long uva, char *buf, return (0); } - sprintf(procfile, "/proc/%d/mem", kp->ki_pid); - fd = open(procfile, O_RDONLY, 0); - if (fd < 0) { - _kvm_err(kd, kd->program, "cannot open %s", procfile); + if (getpid() == kp->ki_pid) { + bcopy((void *)uva, buf, len); + return ((ssize_t)len); + } + + errno = 0; + ptrace(PT_ATTACH, kp->ki_pid, NULL, 0); + if (errno != 0) { + _kvm_err(kd, kd->program, "cannot attach to the process %d", kp->ki_pid); return (0); } - cp = buf; - while (len > 0) { - errno = 0; - if (lseek(fd, (off_t)uva, 0) == -1 && errno != 0) { - _kvm_err(kd, kd->program, "invalid address (%lx) in %s", - uva, procfile); - break; - } - amount = read(fd, cp, len); - if (amount < 0) { - _kvm_syserr(kd, kd->program, "error reading %s", - procfile); - break; - } - if (amount == 0) { - _kvm_err(kd, kd->program, "EOF reading %s", procfile); - break; - } - cp += amount; - uva += amount; - len -= amount; + if (waitpid(kp->ki_pid, NULL, 0) == -1) + _kvm_err(kd, kd->program, "unexpect stop in waitpid"); + + ioreq.piod_op = PIOD_READ_D; + ioreq.piod_offs = (caddr_t)uva; + ioreq.piod_addr = buf; + ioreq.piod_len = len; + + ptrace(PT_IO, kp->ki_pid, (caddr_t)&ioreq, 0); + + if ((size_t)ioreq.piod_len < len) { + _kvm_err(kd, kd->program, "short read wanted %zu, got %zd", + len, ioreq.piod_len); } - close(fd); - return ((ssize_t)(cp - buf)); + ptrace(PT_DETACH, kp->ki_pid, (caddr_t)1, 0); + + return ((ssize_t)ioreq.piod_len); }