/* * Read from user space. The user context is given by pid. */ ssize_t kvm_uread(kvm_t *kd, pid_t pid, u_long uva, char *buf, size_t len) { char *cp; char procfile[MAXPATHLEN]; ssize_t amount; int fd; if (!kvm_ishost(kd)) { /* XXX: vkernels */ _kvm_err(kd, kd->program, "cannot read user space from dead kernel"); return (0); } sprintf(procfile, "/proc/%d/mem", pid); fd = open(procfile, O_RDONLY, 0); if (fd < 0) { _kvm_err(kd, kd->program, "cannot open %s", procfile); close(fd); 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)); }
/* * kvm_getloadavg() -- Get system load averages, from live or dead kernels. * * Put `nelem' samples into `loadavg' array. * Return number of samples retrieved, or -1 on error. */ int kvm_getloadavg(kvm_t *kd, double loadavg[], int nelem) { struct loadavg loadinfo; struct nlist *p; int fscale, i; if (kvm_ishost(kd)) return (getloadavg(loadavg, nelem)); if (kvm_nlist(kd, nl) != 0) { for (p = nl; p->n_type != 0; ++p); _kvm_err(kd, kd->program, "%s: no such symbol", p->n_name); return (-1); } #define KREAD(kd, addr, obj) \ (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) if (KREAD(kd, nl[X_AVERUNNABLE].n_value, &loadinfo)) { _kvm_err(kd, kd->program, "can't read averunnable"); return (-1); } /* * Old kernels have fscale separately; if not found assume * running new format. */ if (!KREAD(kd, nl[X_FSCALE].n_value, &fscale)) loadinfo.fscale = fscale; nelem = MIN(nelem, sizeof(loadinfo.ldavg) / sizeof(fixpt_t)); for (i = 0; i < nelem; i++) loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale; return (nelem); }
struct kinfo_proc * kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt) { int mib[4], st, nprocs; int miblen = ((op & ~KERN_PROC_FLAGMASK) == KERN_PROC_ALL) ? 3 : 4; size_t size; if (kd->procbase != 0) { free((void *)kd->procbase); /* * Clear this pointer in case this call fails. Otherwise, * kvm_close() will free it again. */ kd->procbase = 0; } if (kvm_ishost(kd)) { size = 0; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = op; mib[3] = arg; st = sysctl(mib, miblen, NULL, &size, NULL, 0); if (st == -1) { _kvm_syserr(kd, kd->program, "kvm_getprocs"); return (0); } do { size += size / 10; kd->procbase = (struct kinfo_proc *) _kvm_realloc(kd, kd->procbase, size); if (kd->procbase == 0) return (0); st = sysctl(mib, miblen, kd->procbase, &size, NULL, 0); } while (st == -1 && errno == ENOMEM); if (st == -1) { _kvm_syserr(kd, kd->program, "kvm_getprocs"); return (0); } if (size % sizeof(struct kinfo_proc) != 0) { _kvm_err(kd, kd->program, "proc size mismatch (%zd total, %zd chunks)", size, sizeof(struct kinfo_proc)); return (0); } nprocs = size / sizeof(struct kinfo_proc); } else { struct nlist nl[4], *p; nl[0].n_name = "_nprocs"; nl[1].n_name = "_allproc"; nl[2].n_name = "_zombproc"; nl[3].n_name = 0; if (kvm_nlist(kd, nl) != 0) { for (p = nl; p->n_type != 0; ++p) ; _kvm_err(kd, kd->program, "%s: no such symbol", p->n_name); return (0); } if (KREAD(kd, nl[0].n_value, &nprocs)) { _kvm_err(kd, kd->program, "can't read nprocs"); return (0); } nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value, nl[2].n_value); #ifdef notdef size = nprocs * sizeof(struct kinfo_proc); (void)realloc(kd->procbase, size); #endif } *cnt = nprocs; return (kd->procbase); }
char * kvm_getfiles(kvm_t *kd, int op, int arg, int *cnt) { int mib[2], st, nfiles; size_t size; struct file *fp, *fplim; struct filelist filehead; if (kvm_ishost(kd)) { size = 0; mib[0] = CTL_KERN; mib[1] = KERN_FILE; st = sysctl(mib, 2, NULL, &size, NULL, 0); if (st == -1) { _kvm_syserr(kd, kd->program, "kvm_getfiles"); return (0); } if (kd->argspc == 0) kd->argspc = (char *)_kvm_malloc(kd, size); else if (kd->arglen < size) kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); if (kd->argspc == 0) return (0); kd->arglen = size; st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); if (st == -1 || size < sizeof(filehead)) { _kvm_syserr(kd, kd->program, "kvm_getfiles"); return (0); } filehead = *(struct filelist *)kd->argspc; fp = (struct file *)(kd->argspc + sizeof (filehead)); fplim = (struct file *)(kd->argspc + size); for (nfiles = 0; filehead.lh_first && (fp < fplim); nfiles++, fp++) filehead.lh_first = fp->f_list.le_next; } else { struct nlist nl[3], *p; nl[0].n_name = "_filehead"; nl[1].n_name = "_nfiles"; nl[2].n_name = 0; if (kvm_nlist(kd, nl) != 0) { for (p = nl; p->n_type != 0; ++p) ; _kvm_err(kd, kd->program, "%s: no such symbol", p->n_name); return (0); } if (KREAD(kd, nl[0].n_value, &nfiles)) { _kvm_err(kd, kd->program, "can't read nfiles"); return (0); } size = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); if (kd->argspc == 0) kd->argspc = (char *)_kvm_malloc(kd, size); else if (kd->arglen < size) kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); if (kd->argspc == 0) return (0); kd->arglen = size; nfiles = kvm_deadfiles(kd, op, arg, nl[1].n_value, nfiles); if (nfiles == 0) return (0); } *cnt = nfiles; return (kd->argspc); }