xref: /csrg-svn/lib/libkvm/kvm_proc.c (revision 67724)
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