142661Sbostic /*-
261278Sbostic * Copyright (c) 1989, 1992, 1993
361278Sbostic * The Regents of the University of California. All rights reserved.
440256Smarc *
553658Sbostic * This code is derived from software developed by the Computer Systems
653658Sbostic * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
753658Sbostic * BG 91-66 and contributed to Berkeley.
853658Sbostic *
942661Sbostic * %sccs.include.redist.c%
1040256Smarc */
1140256Smarc
1242661Sbostic #if defined(LIBC_SCCS) && !defined(lint)
13*67724Smckusick static char sccsid[] = "@(#)kvm_proc.c 8.4 (Berkeley) 08/20/94";
1442661Sbostic #endif /* LIBC_SCCS and not lint */
1540256Smarc
1653121Smckusick /*
1753121Smckusick * Proc traversal interface for kvm. ps and w are (probably) the exclusive
1853121Smckusick * users of this code, so we've factored it out into a separate module.
1953121Smckusick * Thus, we keep this grunge out of the other kvm applications (i.e.,
2053121Smckusick * most other applications are interested only in open/close/read/nlist).
2153121Smckusick */
2253121Smckusick
2340256Smarc #include <sys/param.h>
2449251Skarels #include <sys/user.h>
2540256Smarc #include <sys/proc.h>
2653121Smckusick #include <sys/exec.h>
2753121Smckusick #include <sys/stat.h>
2840256Smarc #include <sys/ioctl.h>
2940256Smarc #include <sys/tty.h>
3053723Smckusick #include <unistd.h>
3149251Skarels #include <nlist.h>
3241007Smarc #include <kvm.h>
3340256Smarc
3453121Smckusick #include <vm/vm.h>
3553121Smckusick #include <vm/vm_param.h>
3653121Smckusick #include <vm/swap_pager.h>
3748619Skarels
3858898Smckusick #include <sys/sysctl.h>
3948619Skarels
4053121Smckusick #include <limits.h>
4153617Ssklower #include <db.h>
4253121Smckusick #include <paths.h>
4341007Smarc
4453121Smckusick #include "kvm_private.h"
4540256Smarc
4653121Smckusick static char *
kvm_readswap(kd,p,va,cnt)4753121Smckusick kvm_readswap(kd, p, va, cnt)
4853121Smckusick kvm_t *kd;
4953121Smckusick const struct proc *p;
5053121Smckusick u_long va;
5153121Smckusick u_long *cnt;
5253121Smckusick {
5353121Smckusick register int ix;
5453121Smckusick register u_long addr, head;
5553121Smckusick register u_long offset, pagestart, sbstart, pgoff;
5653121Smckusick register off_t seekpoint;
5753121Smckusick struct vm_map_entry vme;
5853121Smckusick struct vm_object vmo;
5953121Smckusick struct pager_struct pager;
6053121Smckusick struct swpager swap;
6153121Smckusick struct swblock swb;
6253121Smckusick static char page[NBPG];
6342939Sbostic
6453121Smckusick head = (u_long)&p->p_vmspace->vm_map.header;
6540256Smarc /*
6653121Smckusick * Look through the address map for the memory object
6753121Smckusick * that corresponds to the given virtual address.
6853121Smckusick * The header just has the entire valid range.
6940256Smarc */
7053121Smckusick addr = head;
7153121Smckusick while (1) {
7253121Smckusick if (kvm_read(kd, addr, (char *)&vme, sizeof(vme)) !=
7353121Smckusick sizeof(vme))
7453121Smckusick return (0);
7540256Smarc
7653121Smckusick if (va >= vme.start && va <= vme.end &&
7753121Smckusick vme.object.vm_object != 0)
7853121Smckusick break;
7946642Sbostic
8053121Smckusick addr = (u_long)vme.next;
8153121Smckusick if (addr == 0 || addr == head)
8253121Smckusick return (0);
8340256Smarc }
8453121Smckusick /*
8553121Smckusick * We found the right object -- follow shadow links.
8653121Smckusick */
8753121Smckusick offset = va - vme.start + vme.offset;
8853121Smckusick addr = (u_long)vme.object.vm_object;
8953121Smckusick while (1) {
9053121Smckusick if (kvm_read(kd, addr, (char *)&vmo, sizeof(vmo)) !=
9153121Smckusick sizeof(vmo))
9253121Smckusick return (0);
9353121Smckusick addr = (u_long)vmo.shadow;
9453121Smckusick if (addr == 0)
9553121Smckusick break;
9653121Smckusick offset += vmo.shadow_offset;
9740256Smarc }
9853121Smckusick if (vmo.pager == 0)
9953121Smckusick return (0);
10040256Smarc
10153121Smckusick offset += vmo.paging_offset;
10241007Smarc /*
10353121Smckusick * Read in the pager info and make sure it's a swap device.
10441007Smarc */
10553121Smckusick addr = (u_long)vmo.pager;
10653121Smckusick if (kvm_read(kd, addr, (char *)&pager, sizeof(pager)) != sizeof(pager)
10753121Smckusick || pager.pg_type != PG_SWAP)
10853121Smckusick return (0);
10941007Smarc
11041007Smarc /*
11153121Smckusick * Read in the swap_pager private data, and compute the
11253121Smckusick * swap offset.
11341007Smarc */
11453121Smckusick addr = (u_long)pager.pg_data;
11553121Smckusick if (kvm_read(kd, addr, (char *)&swap, sizeof(swap)) != sizeof(swap))
11653121Smckusick return (0);
11753121Smckusick ix = offset / dbtob(swap.sw_bsize);
11853121Smckusick if (swap.sw_blocks == 0 || ix >= swap.sw_nblocks)
11953121Smckusick return (0);
12040256Smarc
12153121Smckusick addr = (u_long)&swap.sw_blocks[ix];
12253121Smckusick if (kvm_read(kd, addr, (char *)&swb, sizeof(swb)) != sizeof(swb))
12353121Smckusick return (0);
12440256Smarc
12553121Smckusick sbstart = (offset / dbtob(swap.sw_bsize)) * dbtob(swap.sw_bsize);
12653121Smckusick sbstart /= NBPG;
12753121Smckusick pagestart = offset / NBPG;
12853121Smckusick pgoff = pagestart - sbstart;
12940256Smarc
13053121Smckusick if (swb.swb_block == 0 || (swb.swb_mask & (1 << pgoff)) == 0)
13153121Smckusick return (0);
13240256Smarc
13353121Smckusick seekpoint = dbtob(swb.swb_block) + ctob(pgoff);
13453121Smckusick errno = 0;
13553121Smckusick if (lseek(kd->swfd, seekpoint, 0) == -1 && errno != 0)
13653121Smckusick return (0);
13753121Smckusick if (read(kd->swfd, page, sizeof(page)) != sizeof(page))
13853121Smckusick return (0);
13953121Smckusick
14053121Smckusick offset %= NBPG;
14153121Smckusick *cnt = NBPG - offset;
14253121Smckusick return (&page[offset]);
14340256Smarc }
14440256Smarc
14553121Smckusick #define KREAD(kd, addr, obj) \
14653121Smckusick (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj))
14753121Smckusick
14840256Smarc /*
14953121Smckusick * Read proc's from memory file into buffer bp, which has space to hold
15053121Smckusick * at most maxcnt procs.
15140256Smarc */
15253121Smckusick static int
kvm_proclist(kd,what,arg,p,bp,maxcnt)15353121Smckusick kvm_proclist(kd, what, arg, p, bp, maxcnt)
15453121Smckusick kvm_t *kd;
15540256Smarc int what, arg;
15653121Smckusick struct proc *p;
15753121Smckusick struct kinfo_proc *bp;
15853121Smckusick int maxcnt;
15940256Smarc {
16053121Smckusick register int cnt = 0;
16140256Smarc struct eproc eproc;
16240256Smarc struct pgrp pgrp;
16340256Smarc struct session sess;
16440256Smarc struct tty tty;
16553121Smckusick struct proc proc;
16640256Smarc
167*67724Smckusick for (; cnt < maxcnt && p != 0; p = proc.p_list.le_next) {
16853121Smckusick if (KREAD(kd, (u_long)p, &proc)) {
16953121Smckusick _kvm_err(kd, kd->program, "can't read proc at %x", p);
17040256Smarc return (-1);
17140256Smarc }
17253121Smckusick if (KREAD(kd, (u_long)proc.p_cred, &eproc.e_pcred) == 0)
17353121Smckusick KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
17453121Smckusick &eproc.e_ucred);
17553121Smckusick
17658898Smckusick switch(what) {
17740256Smarc
17858898Smckusick case KERN_PROC_PID:
17940256Smarc if (proc.p_pid != (pid_t)arg)
18040256Smarc continue;
18140256Smarc break;
18240256Smarc
18358898Smckusick case KERN_PROC_UID:
18448619Skarels if (eproc.e_ucred.cr_uid != (uid_t)arg)
18548619Skarels continue;
18648619Skarels break;
18748619Skarels
18858898Smckusick case KERN_PROC_RUID:
18948619Skarels if (eproc.e_pcred.p_ruid != (uid_t)arg)
19048619Skarels continue;
19148619Skarels break;
19248619Skarels }
19353121Smckusick /*
19453121Smckusick * We're going to add another proc to the set. If this
19553121Smckusick * will overflow the buffer, assume the reason is because
19653121Smckusick * nprocs (or the proc list) is corrupt and declare an error.
19753121Smckusick */
19853121Smckusick if (cnt >= maxcnt) {
19953121Smckusick _kvm_err(kd, kd->program, "nprocs corrupt");
20053121Smckusick return (-1);
20140256Smarc }
20240256Smarc /*
20340256Smarc * gather eproc
20440256Smarc */
20540256Smarc eproc.e_paddr = p;
20653121Smckusick if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) {
20753121Smckusick _kvm_err(kd, kd->program, "can't read pgrp at %x",
20853121Smckusick proc.p_pgrp);
20940256Smarc return (-1);
21040256Smarc }
21140256Smarc eproc.e_sess = pgrp.pg_session;
21240256Smarc eproc.e_pgid = pgrp.pg_id;
21340256Smarc eproc.e_jobc = pgrp.pg_jobc;
21453121Smckusick if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
21553121Smckusick _kvm_err(kd, kd->program, "can't read session at %x",
21653121Smckusick pgrp.pg_session);
21740256Smarc return (-1);
21840256Smarc }
21964638Sbostic if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) {
22053121Smckusick if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
22153121Smckusick _kvm_err(kd, kd->program,
22253121Smckusick "can't read tty at %x", sess.s_ttyp);
22340256Smarc return (-1);
22440256Smarc }
22540256Smarc eproc.e_tdev = tty.t_dev;
22640256Smarc eproc.e_tsess = tty.t_session;
22740256Smarc if (tty.t_pgrp != NULL) {
22853121Smckusick if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
22953121Smckusick _kvm_err(kd, kd->program,
23053121Smckusick "can't read tpgrp at &x",
23140256Smarc tty.t_pgrp);
23240256Smarc return (-1);
23340256Smarc }
23440256Smarc eproc.e_tpgid = pgrp.pg_id;
23540256Smarc } else
23640256Smarc eproc.e_tpgid = -1;
23740256Smarc } else
23840256Smarc eproc.e_tdev = NODEV;
23951393Smarc eproc.e_flag = sess.s_ttyvp ? EPROC_CTTY : 0;
24051393Smarc if (sess.s_leader == p)
24151393Smarc eproc.e_flag |= EPROC_SLEADER;
24240256Smarc if (proc.p_wmesg)
24353121Smckusick (void)kvm_read(kd, (u_long)proc.p_wmesg,
24453121Smckusick eproc.e_wmesg, WMESGLEN);
24553121Smckusick
24653121Smckusick #ifdef sparc
24753121Smckusick (void)kvm_read(kd, (u_long)&proc.p_vmspace->vm_rssize,
24853121Smckusick (char *)&eproc.e_vm.vm_rssize,
24953121Smckusick sizeof(eproc.e_vm.vm_rssize));
25053121Smckusick (void)kvm_read(kd, (u_long)&proc.p_vmspace->vm_tsize,
25153121Smckusick (char *)&eproc.e_vm.vm_tsize,
25253121Smckusick 3 * sizeof(eproc.e_vm.vm_rssize)); /* XXX */
25348619Skarels #else
25453121Smckusick (void)kvm_read(kd, (u_long)proc.p_vmspace,
25553121Smckusick (char *)&eproc.e_vm, sizeof(eproc.e_vm));
25648619Skarels #endif
25753121Smckusick eproc.e_xsize = eproc.e_xrssize = 0;
25853121Smckusick eproc.e_xccount = eproc.e_xswrss = 0;
25940256Smarc
26058898Smckusick switch (what) {
26140256Smarc
26258898Smckusick case KERN_PROC_PGRP:
26340256Smarc if (eproc.e_pgid != (pid_t)arg)
26440256Smarc continue;
26540256Smarc break;
26640256Smarc
26758898Smckusick case KERN_PROC_TTY:
26864638Sbostic if ((proc.p_flag & P_CONTROLT) == 0 ||
26940256Smarc eproc.e_tdev != (dev_t)arg)
27040256Smarc continue;
27140256Smarc break;
27240256Smarc }
27364638Sbostic bcopy(&proc, &bp->kp_proc, sizeof(proc));
27464638Sbostic bcopy(&eproc, &bp->kp_eproc, sizeof(eproc));
27553121Smckusick ++bp;
27653121Smckusick ++cnt;
27740256Smarc }
27853121Smckusick return (cnt);
27940256Smarc }
28040256Smarc
28153121Smckusick /*
28253121Smckusick * Build proc info array by reading in proc list from a crash dump.
28353121Smckusick * Return number of procs read. maxcnt is the max we will read.
28453121Smckusick */
28553121Smckusick static int
kvm_deadprocs(kd,what,arg,a_allproc,a_zombproc,maxcnt)28653121Smckusick kvm_deadprocs(kd, what, arg, a_allproc, a_zombproc, maxcnt)
28753121Smckusick kvm_t *kd;
28853121Smckusick int what, arg;
28953121Smckusick u_long a_allproc;
29053121Smckusick u_long a_zombproc;
29153121Smckusick int maxcnt;
29240256Smarc {
29353121Smckusick register struct kinfo_proc *bp = kd->procbase;
29453121Smckusick register int acnt, zcnt;
29553121Smckusick struct proc *p;
29640256Smarc
29753121Smckusick if (KREAD(kd, a_allproc, &p)) {
29853121Smckusick _kvm_err(kd, kd->program, "cannot read allproc");
29953121Smckusick return (-1);
30040256Smarc }
30153121Smckusick acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt);
30253121Smckusick if (acnt < 0)
30353121Smckusick return (acnt);
30440256Smarc
30553121Smckusick if (KREAD(kd, a_zombproc, &p)) {
30653121Smckusick _kvm_err(kd, kd->program, "cannot read zombproc");
30753121Smckusick return (-1);
30853121Smckusick }
30953121Smckusick zcnt = kvm_proclist(kd, what, arg, p, bp + acnt, maxcnt - acnt);
31053121Smckusick if (zcnt < 0)
31153121Smckusick zcnt = 0;
31240256Smarc
31353121Smckusick return (acnt + zcnt);
31440256Smarc }
31540256Smarc
31653121Smckusick struct kinfo_proc *
kvm_getprocs(kd,op,arg,cnt)31753121Smckusick kvm_getprocs(kd, op, arg, cnt)
31853121Smckusick kvm_t *kd;
31953121Smckusick int op, arg;
32053121Smckusick int *cnt;
32140256Smarc {
32258898Smckusick int mib[4], size, st, nprocs;
32340256Smarc
32453121Smckusick if (kd->procbase != 0) {
32553121Smckusick free((void *)kd->procbase);
32653121Smckusick /*
32753121Smckusick * Clear this pointer in case this call fails. Otherwise,
32853121Smckusick * kvm_close() will free it again.
32953121Smckusick */
33053121Smckusick kd->procbase = 0;
33140256Smarc }
33253121Smckusick if (ISALIVE(kd)) {
33353121Smckusick size = 0;
33458898Smckusick mib[0] = CTL_KERN;
33558898Smckusick mib[1] = KERN_PROC;
33658898Smckusick mib[2] = op;
33758898Smckusick mib[3] = arg;
33858898Smckusick st = sysctl(mib, 4, NULL, &size, NULL, 0);
33958898Smckusick if (st == -1) {
34053121Smckusick _kvm_syserr(kd, kd->program, "kvm_getprocs");
34153121Smckusick return (0);
34253121Smckusick }
34358898Smckusick kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
34453121Smckusick if (kd->procbase == 0)
34553121Smckusick return (0);
34658898Smckusick st = sysctl(mib, 4, kd->procbase, &size, NULL, 0);
34758898Smckusick if (st == -1) {
34853121Smckusick _kvm_syserr(kd, kd->program, "kvm_getprocs");
34953121Smckusick return (0);
35053121Smckusick }
35153121Smckusick if (size % sizeof(struct kinfo_proc) != 0) {
35253121Smckusick _kvm_err(kd, kd->program,
35353121Smckusick "proc size mismatch (%d total, %d chunks)",
35453121Smckusick size, sizeof(struct kinfo_proc));
35553121Smckusick return (0);
35653121Smckusick }
35753121Smckusick nprocs = size / sizeof(struct kinfo_proc);
35853121Smckusick } else {
35953121Smckusick struct nlist nl[4], *p;
36040256Smarc
36153121Smckusick nl[0].n_name = "_nprocs";
36253121Smckusick nl[1].n_name = "_allproc";
36353121Smckusick nl[2].n_name = "_zombproc";
36453121Smckusick nl[3].n_name = 0;
36548619Skarels
36653121Smckusick if (kvm_nlist(kd, nl) != 0) {
36753121Smckusick for (p = nl; p->n_type != 0; ++p)
36853121Smckusick ;
36953121Smckusick _kvm_err(kd, kd->program,
37053121Smckusick "%s: no such symbol", p->n_name);
37153121Smckusick return (0);
37248619Skarels }
37353121Smckusick if (KREAD(kd, nl[0].n_value, &nprocs)) {
37453121Smckusick _kvm_err(kd, kd->program, "can't read nprocs");
37553121Smckusick return (0);
37653121Smckusick }
37753121Smckusick size = nprocs * sizeof(struct kinfo_proc);
37853121Smckusick kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
37953121Smckusick if (kd->procbase == 0)
38053121Smckusick return (0);
38149251Skarels
38253121Smckusick nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
38353121Smckusick nl[2].n_value, nprocs);
38453121Smckusick #ifdef notdef
38553121Smckusick size = nprocs * sizeof(struct kinfo_proc);
38653121Smckusick (void)realloc(kd->procbase, size);
38749251Skarels #endif
38848619Skarels }
38953121Smckusick *cnt = nprocs;
39053121Smckusick return (kd->procbase);
39148619Skarels }
39253121Smckusick
39353121Smckusick void
_kvm_freeprocs(kd)39453121Smckusick _kvm_freeprocs(kd)
39553121Smckusick kvm_t *kd;
39640256Smarc {
39753121Smckusick if (kd->procbase) {
39853121Smckusick free(kd->procbase);
39953121Smckusick kd->procbase = 0;
40041007Smarc }
40140256Smarc }
40240256Smarc
40353617Ssklower void *
_kvm_realloc(kd,p,n)40453121Smckusick _kvm_realloc(kd, p, n)
40553121Smckusick kvm_t *kd;
40653121Smckusick void *p;
40753617Ssklower size_t n;
40840256Smarc {
40953121Smckusick void *np = (void *)realloc(p, n);
41040256Smarc
41153121Smckusick if (np == 0)
41253121Smckusick _kvm_err(kd, kd->program, "out of memory");
41353121Smckusick return (np);
41440256Smarc }
41540256Smarc
41653121Smckusick #ifndef MAX
41753121Smckusick #define MAX(a, b) ((a) > (b) ? (a) : (b))
41853121Smckusick #endif
41940256Smarc
42053121Smckusick /*
42153121Smckusick * Read in an argument vector from the user address space of process p.
42253121Smckusick * addr if the user-space base address of narg null-terminated contiguous
42353121Smckusick * strings. This is used to read in both the command arguments and
42453121Smckusick * environment strings. Read at most maxcnt characters of strings.
42553121Smckusick */
42653121Smckusick static char **
kvm_argv(kd,p,addr,narg,maxcnt)42753121Smckusick kvm_argv(kd, p, addr, narg, maxcnt)
42853121Smckusick kvm_t *kd;
42953121Smckusick struct proc *p;
43053121Smckusick register u_long addr;
43153121Smckusick register int narg;
43253121Smckusick register int maxcnt;
43340256Smarc {
43453121Smckusick register char *cp;
43553121Smckusick register int len, cc;
43653121Smckusick register char **argv;
43750392Smarc
43853121Smckusick /*
43953121Smckusick * Check that there aren't an unreasonable number of agruments,
44053121Smckusick * and that the address is in user space.
44153121Smckusick */
44253121Smckusick if (narg > 512 || addr < VM_MIN_ADDRESS || addr >= VM_MAXUSER_ADDRESS)
44353121Smckusick return (0);
44453121Smckusick
44553121Smckusick if (kd->argv == 0) {
44653121Smckusick /*
44753121Smckusick * Try to avoid reallocs.
44853121Smckusick */
44953121Smckusick kd->argc = MAX(narg + 1, 32);
45053121Smckusick kd->argv = (char **)_kvm_malloc(kd, kd->argc *
45153121Smckusick sizeof(*kd->argv));
45253121Smckusick if (kd->argv == 0)
45353121Smckusick return (0);
45453121Smckusick } else if (narg + 1 > kd->argc) {
45553121Smckusick kd->argc = MAX(2 * kd->argc, narg + 1);
45653617Ssklower kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
45753617Ssklower sizeof(*kd->argv));
45853121Smckusick if (kd->argv == 0)
45953121Smckusick return (0);
46040256Smarc }
46153121Smckusick if (kd->argspc == 0) {
46253121Smckusick kd->argspc = (char *)_kvm_malloc(kd, NBPG);
46353121Smckusick if (kd->argspc == 0)
46453121Smckusick return (0);
46553121Smckusick kd->arglen = NBPG;
46640256Smarc }
46753121Smckusick cp = kd->argspc;
46853121Smckusick argv = kd->argv;
46953121Smckusick *argv = cp;
47053121Smckusick len = 0;
47153121Smckusick /*
47253121Smckusick * Loop over pages, filling in the argument vector.
47353121Smckusick */
47453121Smckusick while (addr < VM_MAXUSER_ADDRESS) {
47553121Smckusick cc = NBPG - (addr & PGOFSET);
47653121Smckusick if (maxcnt > 0 && cc > maxcnt - len)
47753121Smckusick cc = maxcnt - len;;
47853121Smckusick if (len + cc > kd->arglen) {
47953121Smckusick register int off;
48053121Smckusick register char **pp;
48153121Smckusick register char *op = kd->argspc;
48240256Smarc
48353121Smckusick kd->arglen *= 2;
48453121Smckusick kd->argspc = (char *)_kvm_realloc(kd, kd->argspc,
48553121Smckusick kd->arglen);
48653121Smckusick if (kd->argspc == 0)
48753121Smckusick return (0);
48853121Smckusick cp = &kd->argspc[len];
48953121Smckusick /*
49053121Smckusick * Adjust argv pointers in case realloc moved
49153121Smckusick * the string space.
49253121Smckusick */
49353121Smckusick off = kd->argspc - op;
49453121Smckusick for (pp = kd->argv; pp < argv; ++pp)
49553121Smckusick *pp += off;
49653121Smckusick }
49753121Smckusick if (kvm_uread(kd, p, addr, cp, cc) != cc)
49853121Smckusick /* XXX */
49953121Smckusick return (0);
50053121Smckusick len += cc;
50153121Smckusick addr += cc;
50250392Smarc
50353121Smckusick if (maxcnt == 0 && len > 16 * NBPG)
50453121Smckusick /* sanity */
50553121Smckusick return (0);
50650392Smarc
50753121Smckusick while (--cc >= 0) {
50853121Smckusick if (*cp++ == 0) {
50953121Smckusick if (--narg <= 0) {
51053121Smckusick *++argv = 0;
51153121Smckusick return (kd->argv);
51253121Smckusick } else
51353121Smckusick *++argv = cp;
51453121Smckusick }
51540256Smarc }
51653121Smckusick if (maxcnt > 0 && len >= maxcnt) {
51753121Smckusick /*
51853121Smckusick * We're stopping prematurely. Terminate the
51953121Smckusick * argv and current string.
52053121Smckusick */
52153121Smckusick *++argv = 0;
52253121Smckusick *cp = 0;
52353121Smckusick return (kd->argv);
52440256Smarc }
52540256Smarc }
52640256Smarc }
52740256Smarc
52853121Smckusick static void
ps_str_a(p,addr,n)52953121Smckusick ps_str_a(p, addr, n)
53053121Smckusick struct ps_strings *p;
53153121Smckusick u_long *addr;
53253121Smckusick int *n;
53340256Smarc {
53453121Smckusick *addr = (u_long)p->ps_argvstr;
53553121Smckusick *n = p->ps_nargvstr;
53653121Smckusick }
53741007Smarc
53853121Smckusick static void
ps_str_e(p,addr,n)53953121Smckusick ps_str_e(p, addr, n)
54053121Smckusick struct ps_strings *p;
54153121Smckusick u_long *addr;
54253121Smckusick int *n;
54353121Smckusick {
54453121Smckusick *addr = (u_long)p->ps_envstr;
54553121Smckusick *n = p->ps_nenvstr;
54640256Smarc }
54740256Smarc
54840256Smarc /*
54953121Smckusick * Determine if the proc indicated by p is still active.
55053121Smckusick * This test is not 100% foolproof in theory, but chances of
55153121Smckusick * being wrong are very low.
55240256Smarc */
55353121Smckusick static int
proc_verify(kd,kernp,p)55453121Smckusick proc_verify(kd, kernp, p)
55553121Smckusick kvm_t *kd;
55653121Smckusick u_long kernp;
55753121Smckusick const struct proc *p;
55840256Smarc {
55953121Smckusick struct proc kernproc;
56040256Smarc
56153121Smckusick /*
56253121Smckusick * Just read in the whole proc. It's not that big relative
56353121Smckusick * to the cost of the read system call.
56453121Smckusick */
56553121Smckusick if (kvm_read(kd, kernp, (char *)&kernproc, sizeof(kernproc)) !=
56653121Smckusick sizeof(kernproc))
56753121Smckusick return (0);
56853121Smckusick return (p->p_pid == kernproc.p_pid &&
56953121Smckusick (kernproc.p_stat != SZOMB || p->p_stat == SZOMB));
57040256Smarc }
57140256Smarc
57253121Smckusick static char **
kvm_doargv(kd,kp,nchr,info)57353121Smckusick kvm_doargv(kd, kp, nchr, info)
57453121Smckusick kvm_t *kd;
57553121Smckusick const struct kinfo_proc *kp;
57653121Smckusick int nchr;
57753121Smckusick int (*info)(struct ps_strings*, u_long *, int *);
57848619Skarels {
57953121Smckusick register const struct proc *p = &kp->kp_proc;
58053121Smckusick register char **ap;
58153121Smckusick u_long addr;
58253121Smckusick int cnt;
58353121Smckusick struct ps_strings arginfo;
58448619Skarels
58553121Smckusick /*
58653121Smckusick * Pointers are stored at the top of the user stack.
58753121Smckusick */
58853121Smckusick if (p->p_stat == SZOMB ||
58953121Smckusick kvm_uread(kd, p, USRSTACK - sizeof(arginfo), (char *)&arginfo,
59053121Smckusick sizeof(arginfo)) != sizeof(arginfo))
59153121Smckusick return (0);
59253121Smckusick
59353121Smckusick (*info)(&arginfo, &addr, &cnt);
59453121Smckusick ap = kvm_argv(kd, p, addr, cnt, nchr);
59553121Smckusick /*
59653121Smckusick * For live kernels, make sure this process didn't go away.
59753121Smckusick */
59853121Smckusick if (ap != 0 && ISALIVE(kd) &&
59953121Smckusick !proc_verify(kd, (u_long)kp->kp_eproc.e_paddr, p))
60053121Smckusick ap = 0;
60153121Smckusick return (ap);
60248619Skarels }
60353121Smckusick
60453121Smckusick /*
60553121Smckusick * Get the command args. This code is now machine independent.
60653121Smckusick */
60753121Smckusick char **
kvm_getargv(kd,kp,nchr)60853121Smckusick kvm_getargv(kd, kp, nchr)
60953121Smckusick kvm_t *kd;
61053121Smckusick const struct kinfo_proc *kp;
61153121Smckusick int nchr;
61240256Smarc {
61353121Smckusick return (kvm_doargv(kd, kp, nchr, ps_str_a));
61440256Smarc }
61540256Smarc
61653121Smckusick char **
kvm_getenvv(kd,kp,nchr)61753121Smckusick kvm_getenvv(kd, kp, nchr)
61853121Smckusick kvm_t *kd;
61953121Smckusick const struct kinfo_proc *kp;
62053121Smckusick int nchr;
62140256Smarc {
62253121Smckusick return (kvm_doargv(kd, kp, nchr, ps_str_e));
62340256Smarc }
62440256Smarc
62553121Smckusick /*
62653121Smckusick * Read from user space. The user context is given by p.
62753121Smckusick */
62853121Smckusick ssize_t
kvm_uread(kd,p,uva,buf,len)62953121Smckusick kvm_uread(kd, p, uva, buf, len)
63053121Smckusick kvm_t *kd;
63153121Smckusick register struct proc *p;
63253121Smckusick register u_long uva;
63353121Smckusick register char *buf;
63453121Smckusick register size_t len;
63540256Smarc {
63653121Smckusick register char *cp;
63740256Smarc
63853121Smckusick cp = buf;
63953121Smckusick while (len > 0) {
64053121Smckusick u_long pa;
64153121Smckusick register int cc;
64253121Smckusick
64353121Smckusick cc = _kvm_uvatop(kd, p, uva, &pa);
64453121Smckusick if (cc > 0) {
64553121Smckusick if (cc > len)
64653121Smckusick cc = len;
64753121Smckusick errno = 0;
64853121Smckusick if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) {
64953121Smckusick _kvm_err(kd, 0, "invalid address (%x)", uva);
65053121Smckusick break;
65153121Smckusick }
65253121Smckusick cc = read(kd->pmfd, cp, cc);
65353121Smckusick if (cc < 0) {
65453121Smckusick _kvm_syserr(kd, 0, _PATH_MEM);
65553121Smckusick break;
65653121Smckusick } else if (cc < len) {
65753121Smckusick _kvm_err(kd, kd->program, "short read");
65853121Smckusick break;
65953121Smckusick }
66053121Smckusick } else if (ISALIVE(kd)) {
66153121Smckusick /* try swap */
66253121Smckusick register char *dp;
66353121Smckusick int cnt;
66440256Smarc
66553121Smckusick dp = kvm_readswap(kd, p, uva, &cnt);
66653121Smckusick if (dp == 0) {
66753121Smckusick _kvm_err(kd, 0, "invalid address (%x)", uva);
66853121Smckusick return (0);
66953121Smckusick }
67053121Smckusick cc = MIN(cnt, len);
67153121Smckusick bcopy(dp, cp, cc);
67253121Smckusick } else
67353121Smckusick break;
67453121Smckusick cp += cc;
67553121Smckusick uva += cc;
67653121Smckusick len -= cc;
67753121Smckusick }
67853121Smckusick return (ssize_t)(cp - buf);
67940256Smarc }
680