diff options
Diffstat (limited to 'lib/libkvm/kvm_proc.c')
-rw-r--r-- | lib/libkvm/kvm_proc.c | 152 |
1 files changed, 67 insertions, 85 deletions
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index 07b172f..338d217 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -88,18 +88,33 @@ __FBSDID("$FreeBSD$"); static int ticks; static int hz; +static uint64_t cpu_tick_frequency; + +/* + * From sys/kern/kern_tc.c. Depends on cpu_tick_frequency, which is + * read/initialized before this function is ever called. + */ +static uint64_t +cputick2usec(uint64_t tick) +{ + + if (cpu_tick_frequency == 0) + return (0); + if (tick > 18446744073709551) /* floor(2^64 / 1000) */ + return (tick / (cpu_tick_frequency / 1000000)); + else if (tick > 18446744073709) /* floor(2^64 / 1000000) */ + return ((tick * 1000) / (cpu_tick_frequency / 1000)); + else + return ((tick * 1000000) / cpu_tick_frequency); +} /* * Read proc's from memory file into buffer bp, which has space to hold * at most maxcnt procs. */ static int -kvm_proclist(kd, what, arg, p, bp, maxcnt) - kvm_t *kd; - int what, arg; - struct proc *p; - struct kinfo_proc *bp; - int maxcnt; +kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p, + struct kinfo_proc *bp, int maxcnt) { int cnt = 0; struct kinfo_proc kinfo_proc, *kp; @@ -109,13 +124,14 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) struct tty tty; struct vmspace vmspace; struct sigacts sigacts; +#if 0 struct pstats pstats; +#endif struct ucred ucred; struct prison pr; struct thread mtd; struct proc proc; struct proc pproc; - struct timeval tv; struct sysentvec sysent; char svname[KI_EMULNAMELEN]; @@ -128,14 +144,14 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) for (; cnt < maxcnt && p != NULL; p = LIST_NEXT(&proc, p_list)) { memset(kp, 0, sizeof *kp); if (KREAD(kd, (u_long)p, &proc)) { - _kvm_err(kd, kd->program, "can't read proc at %x", p); + _kvm_err(kd, kd->program, "can't read proc at %p", p); return (-1); } if (proc.p_state != PRS_ZOMBIE) { if (KREAD(kd, (u_long)TAILQ_FIRST(&proc.p_threads), &mtd)) { _kvm_err(kd, kd->program, - "can't read thread at %x", + "can't read thread at %p", TAILQ_FIRST(&proc.p_threads)); return (-1); } @@ -157,7 +173,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) if (ucred.cr_prison != NULL) { if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) { _kvm_err(kd, kd->program, - "can't read prison at %x", + "can't read prison at %p", ucred.cr_prison); return (-1); } @@ -215,7 +231,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) if (proc.p_sigacts != NULL) { if (KREAD(kd, (u_long)proc.p_sigacts, &sigacts)) { _kvm_err(kd, kd->program, - "can't read sigacts at %x", proc.p_sigacts); + "can't read sigacts at %p", proc.p_sigacts); return (-1); } kp->ki_sigignore = sigacts.ps_sigignore; @@ -248,7 +264,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) else if (proc.p_pptr) { if (KREAD(kd, (u_long)proc.p_pptr, &pproc)) { _kvm_err(kd, kd->program, - "can't read pproc at %x", proc.p_pptr); + "can't read pproc at %p", proc.p_pptr); return (-1); } kp->ki_ppid = pproc.p_pid; @@ -257,14 +273,14 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) if (proc.p_pgrp == NULL) goto nopgrp; if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) { - _kvm_err(kd, kd->program, "can't read pgrp at %x", + _kvm_err(kd, kd->program, "can't read pgrp at %p", proc.p_pgrp); return (-1); } kp->ki_pgid = pgrp.pg_id; kp->ki_jobc = pgrp.pg_jobc; if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) { - _kvm_err(kd, kd->program, "can't read session at %x", + _kvm_err(kd, kd->program, "can't read session at %p", pgrp.pg_session); return (-1); } @@ -277,13 +293,13 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) { if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) { _kvm_err(kd, kd->program, - "can't read tty at %x", sess.s_ttyp); + "can't read tty at %p", sess.s_ttyp); return (-1); } if (tty.t_dev != NULL) { if (KREAD(kd, (u_long)tty.t_dev, &t_cdev)) { _kvm_err(kd, kd->program, - "can't read cdev at %x", + "can't read cdev at %p", tty.t_dev); return (-1); } @@ -296,7 +312,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) if (tty.t_pgrp != NULL) { if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) { _kvm_err(kd, kd->program, - "can't read tpgrp at %x", + "can't read tpgrp at %p", tty.t_pgrp); return (-1); } @@ -306,7 +322,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt) if (tty.t_session != NULL) { if (KREAD(kd, (u_long)tty.t_session, &sess)) { _kvm_err(kd, kd->program, - "can't read session at %x", + "can't read session at %p", tty.t_session); return (-1); } @@ -369,15 +385,7 @@ nopgrp: kp->ki_lockname, LOCKNAMELEN); kp->ki_lockname[LOCKNAMELEN] = 0; } - /* - * XXX: This is plain wrong, rux_runtime has nothing - * to do with struct bintime, rux_runtime is just a 64-bit - * integer counter of cputicks. What we need here is a way - * to convert cputicks to usecs. The kernel does it in - * kern/kern_tc.c, but the function can't be just copied. - */ - bintime2timeval(&proc.p_rux.rux_runtime, &tv); - kp->ki_runtime = (u_int64_t)tv.tv_sec * 1000000 + tv.tv_usec; + kp->ki_runtime = cputick2usec(proc.p_rux.rux_runtime); kp->ki_pid = proc.p_pid; kp->ki_siglist = proc.p_siglist; SIGSETOR(kp->ki_siglist, mtd.td_siglist); @@ -439,12 +447,8 @@ nopgrp: * Return number of procs read. maxcnt is the max we will read. */ static int -kvm_deadprocs(kd, what, arg, a_allproc, a_zombproc, maxcnt) - kvm_t *kd; - int what, arg; - u_long a_allproc; - u_long a_zombproc; - int maxcnt; +kvm_deadprocs(kvm_t *kd, int what, int arg, u_long a_allproc, + u_long a_zombproc, int maxcnt) { struct kinfo_proc *bp = kd->procbase; int acnt, zcnt; @@ -470,10 +474,7 @@ kvm_deadprocs(kd, what, arg, a_allproc, a_zombproc, maxcnt) } struct kinfo_proc * -kvm_getprocs(kd, op, arg, cnt) - kvm_t *kd; - int op, arg; - int *cnt; +kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt) { int mib[4], st, nprocs; size_t size; @@ -543,7 +544,7 @@ kvm_getprocs(kd, op, arg, cnt) if (size > 0 && kd->procbase->ki_structsize != sizeof(struct kinfo_proc)) { _kvm_err(kd, kd->program, - "kinfo_proc size mismatch (expected %d, got %d)", + "kinfo_proc size mismatch (expected %zu, got %d)", sizeof(struct kinfo_proc), kd->procbase->ki_structsize); return (0); @@ -551,14 +552,15 @@ kvm_getprocs(kd, op, arg, cnt) liveout: nprocs = size == 0 ? 0 : size / kd->procbase->ki_structsize; } else { - struct nlist nl[6], *p; + struct nlist nl[7], *p; nl[0].n_name = "_nprocs"; nl[1].n_name = "_allproc"; nl[2].n_name = "_zombproc"; nl[3].n_name = "_ticks"; nl[4].n_name = "_hz"; - nl[5].n_name = 0; + nl[5].n_name = "_cpu_tick_frequency"; + nl[6].n_name = 0; if (kvm_nlist(kd, nl) != 0) { for (p = nl; p->n_type != 0; ++p) @@ -579,6 +581,11 @@ liveout: _kvm_err(kd, kd->program, "can't read hz"); return (0); } + if (KREAD(kd, nl[5].n_value, &cpu_tick_frequency)) { + _kvm_err(kd, kd->program, + "can't read cpu_tick_frequency"); + return (0); + } size = nprocs * sizeof(struct kinfo_proc); kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size); if (kd->procbase == 0) @@ -596,8 +603,7 @@ liveout: } void -_kvm_freeprocs(kd) - kvm_t *kd; +_kvm_freeprocs(kvm_t *kd) { if (kd->procbase) { free(kd->procbase); @@ -606,10 +612,7 @@ _kvm_freeprocs(kd) } void * -_kvm_realloc(kd, p, n) - kvm_t *kd; - void *p; - size_t n; +_kvm_realloc(kvm_t *kd, void *p, size_t n) { void *np = (void *)realloc(p, n); @@ -631,12 +634,8 @@ _kvm_realloc(kd, p, n) * environment strings. Read at most maxcnt characters of strings. */ static char ** -kvm_argv(kd, kp, addr, narg, maxcnt) - kvm_t *kd; - struct kinfo_proc *kp; - u_long addr; - int narg; - int maxcnt; +kvm_argv(kvm_t *kd, const struct kinfo_proc *kp, u_long addr, int narg, + int maxcnt) { char *np, *cp, *ep, *ap; u_long oaddr = -1; @@ -644,10 +643,13 @@ kvm_argv(kd, kp, addr, narg, maxcnt) char **argv; /* - * Check that there aren't an unreasonable number of agruments, - * and that the address is in user space. + * Check that there aren't an unreasonable number of arguments, + * and that the address is in user space. Special test for + * VM_MIN_ADDRESS as it evaluates to zero, but is not a simple zero + * constant for some archs. We cannot use the pre-processor here and + * for some archs the compiler would trigger a signedness warning. */ - if (narg > 512 || addr < VM_MIN_ADDRESS || addr >= VM_MAXUSER_ADDRESS) + if (narg > 512 || addr + 1 < VM_MIN_ADDRESS + 1 || addr >= VM_MAXUSER_ADDRESS) return (0); /* @@ -807,20 +809,14 @@ kvm_argv(kd, kp, addr, narg, maxcnt) } static void -ps_str_a(p, addr, n) - struct ps_strings *p; - u_long *addr; - int *n; +ps_str_a(struct ps_strings *p, u_long *addr, int *n) { *addr = (u_long)p->ps_argvstr; *n = p->ps_nargvstr; } static void -ps_str_e(p, addr, n) - struct ps_strings *p; - u_long *addr; - int *n; +ps_str_e (struct ps_strings *p, u_long *addr, int *n) { *addr = (u_long)p->ps_envstr; *n = p->ps_nenvstr; @@ -832,8 +828,7 @@ ps_str_e(p, addr, n) * being wrong are very low. */ static int -proc_verify(curkp) - struct kinfo_proc *curkp; +proc_verify(const struct kinfo_proc *curkp) { struct kinfo_proc newkp; int mib[4]; @@ -851,11 +846,8 @@ proc_verify(curkp) } static char ** -kvm_doargv(kd, kp, nchr, info) - kvm_t *kd; - struct kinfo_proc *kp; - int nchr; - void (*info)(struct ps_strings *, u_long *, int *); +kvm_doargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr, + void (*info)(struct ps_strings *, u_long *, int *)) { char **ap; u_long addr; @@ -895,10 +887,7 @@ kvm_doargv(kd, kp, nchr, info) * Get the command args. This code is now machine independent. */ char ** -kvm_getargv(kd, kp, nchr) - kvm_t *kd; - const struct kinfo_proc *kp; - int nchr; +kvm_getargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) { int oid[4]; int i; @@ -957,10 +946,7 @@ kvm_getargv(kd, kp, nchr) } char ** -kvm_getenvv(kd, kp, nchr) - kvm_t *kd; - const struct kinfo_proc *kp; - int nchr; +kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) { return (kvm_doargv(kd, kp, nchr, ps_str_e)); } @@ -969,12 +955,8 @@ kvm_getenvv(kd, kp, nchr) * Read from user space. The user context is given by p. */ ssize_t -kvm_uread(kd, kp, uva, buf, len) - kvm_t *kd; - struct kinfo_proc *kp; - u_long uva; - char *buf; - size_t len; +kvm_uread(kvm_t *kd, const struct kinfo_proc *kp, u_long uva, char *buf, + size_t len) { char *cp; char procfile[MAXPATHLEN]; @@ -998,7 +980,7 @@ kvm_uread(kd, kp, uva, buf, len) while (len > 0) { errno = 0; if (lseek(fd, (off_t)uva, 0) == -1 && errno != 0) { - _kvm_err(kd, kd->program, "invalid address (%x) in %s", + _kvm_err(kd, kd->program, "invalid address (%lx) in %s", uva, procfile); break; } |