diff options
| author | Mikolaj Golub <trociny@FreeBSD.org> | 2013-07-10 19:42:07 +0000 |
|---|---|---|
| committer | Mikolaj Golub <trociny@FreeBSD.org> | 2013-07-10 19:42:07 +0000 |
| commit | cbe481a78e8a2723e4c33ccff06b105932c7767f (patch) | |
| tree | 44cc082995873f3ea22179f095f0caa65919ace7 /lib/libkvm | |
| parent | c8556709eb2fe808224a013126b5620efd1c1f96 (diff) | |
Notes
Diffstat (limited to 'lib/libkvm')
| -rw-r--r-- | lib/libkvm/kvm_proc.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index 31258d7a09be..9de748b30a06 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -712,3 +712,55 @@ kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) { return (kvm_argv(kd, kp, 1, nchr)); } + +/* + * Read from user space. The user context is given by p. + */ +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; + + if (!ISALIVE(kd)) { + _kvm_err(kd, kd->program, + "cannot read user space from dead kernel"); + 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); + 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; + } + + close(fd); + return ((ssize_t)(cp - buf)); +} |
