aboutsummaryrefslogtreecommitdiff
path: root/lib/libkvm
diff options
context:
space:
mode:
authorMikolaj Golub <trociny@FreeBSD.org>2013-07-10 19:42:07 +0000
committerMikolaj Golub <trociny@FreeBSD.org>2013-07-10 19:42:07 +0000
commitcbe481a78e8a2723e4c33ccff06b105932c7767f (patch)
tree44cc082995873f3ea22179f095f0caa65919ace7 /lib/libkvm
parentc8556709eb2fe808224a013126b5620efd1c1f96 (diff)
Notes
Diffstat (limited to 'lib/libkvm')
-rw-r--r--lib/libkvm/kvm_proc.c52
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));
+}