summaryrefslogtreecommitdiffstats
path: root/lib/libkvm/kvm_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkvm/kvm_proc.c')
-rw-r--r--lib/libkvm/kvm_proc.c152
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;
}
OpenPOWER on IntegriCloud