Home | History | Annotate | Line # | Download | only in libkvm
kvm_proc.c revision 1.30.2.1
      1  1.30.2.1        he /*	$NetBSD: kvm_proc.c,v 1.30.2.1 2000/10/04 16:26:46 he Exp $	*/
      2      1.26   mycroft 
      3      1.26   mycroft /*-
      4      1.26   mycroft  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5      1.26   mycroft  * All rights reserved.
      6      1.26   mycroft  *
      7      1.26   mycroft  * This code is derived from software contributed to The NetBSD Foundation
      8      1.26   mycroft  * by Charles M. Hannum.
      9      1.26   mycroft  *
     10      1.26   mycroft  * Redistribution and use in source and binary forms, with or without
     11      1.26   mycroft  * modification, are permitted provided that the following conditions
     12      1.26   mycroft  * are met:
     13      1.26   mycroft  * 1. Redistributions of source code must retain the above copyright
     14      1.26   mycroft  *    notice, this list of conditions and the following disclaimer.
     15      1.26   mycroft  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.26   mycroft  *    notice, this list of conditions and the following disclaimer in the
     17      1.26   mycroft  *    documentation and/or other materials provided with the distribution.
     18      1.26   mycroft  * 3. All advertising materials mentioning features or use of this software
     19      1.26   mycroft  *    must display the following acknowledgement:
     20      1.26   mycroft  *        This product includes software developed by the NetBSD
     21      1.26   mycroft  *        Foundation, Inc. and its contributors.
     22      1.26   mycroft  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23      1.26   mycroft  *    contributors may be used to endorse or promote products derived
     24      1.26   mycroft  *    from this software without specific prior written permission.
     25      1.26   mycroft  *
     26      1.26   mycroft  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27      1.26   mycroft  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28      1.26   mycroft  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29      1.26   mycroft  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30      1.26   mycroft  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31      1.26   mycroft  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32      1.26   mycroft  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33      1.26   mycroft  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34      1.26   mycroft  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35      1.26   mycroft  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36      1.26   mycroft  * POSSIBILITY OF SUCH DAMAGE.
     37      1.26   mycroft  */
     38      1.16   thorpej 
     39       1.1       cgd /*-
     40       1.1       cgd  * Copyright (c) 1989, 1992, 1993
     41       1.1       cgd  *	The Regents of the University of California.  All rights reserved.
     42       1.1       cgd  *
     43       1.1       cgd  * This code is derived from software developed by the Computer Systems
     44       1.1       cgd  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
     45       1.1       cgd  * BG 91-66 and contributed to Berkeley.
     46       1.1       cgd  *
     47       1.1       cgd  * Redistribution and use in source and binary forms, with or without
     48       1.1       cgd  * modification, are permitted provided that the following conditions
     49       1.1       cgd  * are met:
     50       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     51       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     52       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     53       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     54       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     55       1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     56       1.1       cgd  *    must display the following acknowledgement:
     57       1.1       cgd  *	This product includes software developed by the University of
     58       1.1       cgd  *	California, Berkeley and its contributors.
     59       1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     60       1.1       cgd  *    may be used to endorse or promote products derived from this software
     61       1.1       cgd  *    without specific prior written permission.
     62       1.1       cgd  *
     63       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     64       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     65       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     66       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     67       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     68       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     69       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     70       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     71       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     72       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     73       1.1       cgd  * SUCH DAMAGE.
     74       1.1       cgd  */
     75       1.1       cgd 
     76      1.19     mikel #include <sys/cdefs.h>
     77       1.1       cgd #if defined(LIBC_SCCS) && !defined(lint)
     78      1.16   thorpej #if 0
     79       1.1       cgd static char sccsid[] = "@(#)kvm_proc.c	8.3 (Berkeley) 9/23/93";
     80      1.16   thorpej #else
     81  1.30.2.1        he __RCSID("$NetBSD: kvm_proc.c,v 1.30.2.1 2000/10/04 16:26:46 he Exp $");
     82      1.16   thorpej #endif
     83       1.1       cgd #endif /* LIBC_SCCS and not lint */
     84       1.1       cgd 
     85       1.1       cgd /*
     86       1.1       cgd  * Proc traversal interface for kvm.  ps and w are (probably) the exclusive
     87       1.1       cgd  * users of this code, so we've factored it out into a separate module.
     88       1.1       cgd  * Thus, we keep this grunge out of the other kvm applications (i.e.,
     89       1.1       cgd  * most other applications are interested only in open/close/read/nlist).
     90       1.1       cgd  */
     91       1.1       cgd 
     92       1.1       cgd #include <sys/param.h>
     93       1.1       cgd #include <sys/user.h>
     94       1.1       cgd #include <sys/proc.h>
     95       1.1       cgd #include <sys/exec.h>
     96       1.1       cgd #include <sys/stat.h>
     97       1.1       cgd #include <sys/ioctl.h>
     98       1.1       cgd #include <sys/tty.h>
     99       1.7       cgd #include <stdlib.h>
    100      1.10   mycroft #include <string.h>
    101       1.1       cgd #include <unistd.h>
    102       1.1       cgd #include <nlist.h>
    103       1.1       cgd #include <kvm.h>
    104       1.1       cgd 
    105       1.1       cgd #include <vm/vm.h>
    106       1.1       cgd #include <vm/vm_param.h>
    107       1.1       cgd 
    108      1.23       chs #include <uvm/uvm_extern.h>
    109      1.29       mrg #include <uvm/uvm_amap.h>
    110      1.23       chs 
    111       1.1       cgd #include <sys/sysctl.h>
    112       1.1       cgd 
    113       1.1       cgd #include <limits.h>
    114       1.1       cgd #include <db.h>
    115       1.1       cgd #include <paths.h>
    116       1.1       cgd 
    117       1.1       cgd #include "kvm_private.h"
    118       1.1       cgd 
    119       1.2   mycroft #define KREAD(kd, addr, obj) \
    120      1.28  christos 	(kvm_read(kd, addr, (void *)(obj), sizeof(*obj)) != sizeof(*obj))
    121       1.2   mycroft 
    122      1.20  drochner char		*_kvm_uread __P((kvm_t *, const struct proc *, u_long, u_long *));
    123      1.15       cgd ssize_t		kvm_uread __P((kvm_t *, const struct proc *, u_long, char *,
    124      1.15       cgd 		    size_t));
    125      1.15       cgd 
    126      1.15       cgd static char	**kvm_argv __P((kvm_t *, const struct proc *, u_long, int,
    127      1.15       cgd 		    int));
    128      1.27   thorpej static int	kvm_deadprocs __P((kvm_t *, int, int, u_long, u_long, u_long,
    129      1.27   thorpej 		    int));
    130      1.15       cgd static char	**kvm_doargv __P((kvm_t *, const struct kinfo_proc *, int,
    131      1.15       cgd 		    void (*)(struct ps_strings *, u_long *, int *)));
    132      1.15       cgd static int	kvm_proclist __P((kvm_t *, int, int, struct proc *,
    133      1.15       cgd 		    struct kinfo_proc *, int));
    134      1.15       cgd static int	proc_verify __P((kvm_t *, u_long, const struct proc *));
    135      1.15       cgd static void	ps_str_a __P((struct ps_strings *, u_long *, int *));
    136      1.15       cgd static void	ps_str_e __P((struct ps_strings *, u_long *, int *));
    137       1.2   mycroft 
    138       1.8   mycroft char *
    139       1.8   mycroft _kvm_uread(kd, p, va, cnt)
    140       1.1       cgd 	kvm_t *kd;
    141       1.1       cgd 	const struct proc *p;
    142       1.1       cgd 	u_long va;
    143       1.1       cgd 	u_long *cnt;
    144       1.1       cgd {
    145      1.28  christos 	int true = 1;
    146      1.21     perry 	u_long addr, head;
    147      1.21     perry 	u_long offset;
    148       1.1       cgd 	struct vm_map_entry vme;
    149      1.23       chs 	struct vm_amap amap;
    150      1.23       chs 	struct vm_anon *anonp, anon;
    151      1.23       chs 	struct vm_page pg;
    152      1.28  christos 	u_long slot;
    153       1.1       cgd 
    154       1.6   mycroft 	if (kd->swapspc == 0) {
    155      1.28  christos 		kd->swapspc = (char *)_kvm_malloc(kd, (size_t)kd->nbpg);
    156       1.6   mycroft 		if (kd->swapspc == 0)
    157       1.5   deraadt 			return (0);
    158       1.5   deraadt 	}
    159       1.8   mycroft 
    160       1.1       cgd 	/*
    161       1.1       cgd 	 * Look through the address map for the memory object
    162       1.1       cgd 	 * that corresponds to the given virtual address.
    163       1.1       cgd 	 * The header just has the entire valid range.
    164       1.1       cgd 	 */
    165       1.8   mycroft 	head = (u_long)&p->p_vmspace->vm_map.header;
    166       1.1       cgd 	addr = head;
    167      1.28  christos 	while (true) {
    168       1.2   mycroft 		if (KREAD(kd, addr, &vme))
    169       1.1       cgd 			return (0);
    170       1.1       cgd 
    171      1.23       chs 		if (va >= vme.start && va < vme.end &&
    172      1.23       chs 		    vme.aref.ar_amap != NULL)
    173      1.23       chs 			break;
    174      1.23       chs 
    175       1.1       cgd 		addr = (u_long)vme.next;
    176       1.2   mycroft 		if (addr == head)
    177       1.1       cgd 			return (0);
    178      1.23       chs 
    179       1.1       cgd 	}
    180       1.2   mycroft 
    181       1.1       cgd 	/*
    182      1.23       chs 	 * we found the map entry, now to find the object...
    183      1.23       chs 	 */
    184      1.23       chs 	if (vme.aref.ar_amap == NULL)
    185      1.23       chs 		return NULL;
    186      1.23       chs 
    187      1.23       chs 	addr = (u_long)vme.aref.ar_amap;
    188      1.23       chs 	if (KREAD(kd, addr, &amap))
    189      1.23       chs 		return NULL;
    190      1.23       chs 
    191      1.23       chs 	offset = va - vme.start;
    192      1.29       mrg 	slot = offset / kd->nbpg + vme.aref.ar_pageoff;
    193      1.23       chs 	/* sanity-check slot number */
    194      1.23       chs 	if (slot  > amap.am_nslot)
    195      1.23       chs 		return NULL;
    196      1.23       chs 
    197      1.23       chs 	addr = (u_long)amap.am_anon + (offset / kd->nbpg) * sizeof(anonp);
    198      1.23       chs 	if (KREAD(kd, addr, &anonp))
    199      1.23       chs 		return NULL;
    200      1.23       chs 
    201      1.23       chs 	addr = (u_long)anonp;
    202      1.23       chs 	if (KREAD(kd, addr, &anon))
    203      1.23       chs 		return NULL;
    204      1.23       chs 
    205      1.23       chs 	addr = (u_long)anon.u.an_page;
    206      1.23       chs 	if (addr) {
    207      1.23       chs 		if (KREAD(kd, addr, &pg))
    208      1.23       chs 			return NULL;
    209      1.23       chs 
    210      1.28  christos 		if (pread(kd->pmfd, (void *)kd->swapspc, (size_t)kd->nbpg,
    211      1.24   thorpej 		    (off_t)pg.phys_addr) != kd->nbpg)
    212      1.23       chs 			return NULL;
    213      1.23       chs 	}
    214      1.23       chs 	else {
    215      1.28  christos 		if (pread(kd->swfd, (void *)kd->swapspc, (size_t)kd->nbpg,
    216      1.24   thorpej 		    (off_t)(anon.an_swslot * kd->nbpg)) != kd->nbpg)
    217      1.23       chs 			return NULL;
    218      1.23       chs 	}
    219       1.8   mycroft 
    220       1.2   mycroft 	/* Found the page. */
    221       1.6   mycroft 	offset %= kd->nbpg;
    222       1.6   mycroft 	*cnt = kd->nbpg - offset;
    223      1.28  christos 	return (&kd->swapspc[(size_t)offset]);
    224       1.2   mycroft }
    225       1.1       cgd 
    226       1.1       cgd /*
    227       1.1       cgd  * Read proc's from memory file into buffer bp, which has space to hold
    228       1.1       cgd  * at most maxcnt procs.
    229       1.1       cgd  */
    230       1.1       cgd static int
    231       1.1       cgd kvm_proclist(kd, what, arg, p, bp, maxcnt)
    232       1.1       cgd 	kvm_t *kd;
    233       1.1       cgd 	int what, arg;
    234       1.1       cgd 	struct proc *p;
    235       1.1       cgd 	struct kinfo_proc *bp;
    236       1.1       cgd 	int maxcnt;
    237       1.1       cgd {
    238      1.21     perry 	int cnt = 0;
    239       1.1       cgd 	struct eproc eproc;
    240       1.1       cgd 	struct pgrp pgrp;
    241       1.1       cgd 	struct session sess;
    242       1.1       cgd 	struct tty tty;
    243       1.1       cgd 	struct proc proc;
    244       1.1       cgd 
    245       1.4   mycroft 	for (; cnt < maxcnt && p != NULL; p = proc.p_list.le_next) {
    246       1.1       cgd 		if (KREAD(kd, (u_long)p, &proc)) {
    247  1.30.2.1        he 			_kvm_err(kd, kd->program, "can't read proc at %p", p);
    248       1.1       cgd 			return (-1);
    249       1.1       cgd 		}
    250       1.1       cgd 		if (KREAD(kd, (u_long)proc.p_cred, &eproc.e_pcred) == 0)
    251      1.28  christos 			if (KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
    252      1.28  christos 			    &eproc.e_ucred)) {
    253      1.28  christos 				_kvm_err(kd, kd->program,
    254  1.30.2.1        he 				    "can't read proc credentials at %p", p);
    255      1.28  christos 				return -1;
    256      1.28  christos 			}
    257       1.1       cgd 
    258       1.1       cgd 		switch(what) {
    259       1.1       cgd 
    260       1.1       cgd 		case KERN_PROC_PID:
    261       1.1       cgd 			if (proc.p_pid != (pid_t)arg)
    262       1.1       cgd 				continue;
    263       1.1       cgd 			break;
    264       1.1       cgd 
    265       1.1       cgd 		case KERN_PROC_UID:
    266       1.1       cgd 			if (eproc.e_ucred.cr_uid != (uid_t)arg)
    267       1.1       cgd 				continue;
    268       1.1       cgd 			break;
    269       1.1       cgd 
    270       1.1       cgd 		case KERN_PROC_RUID:
    271       1.1       cgd 			if (eproc.e_pcred.p_ruid != (uid_t)arg)
    272       1.1       cgd 				continue;
    273       1.1       cgd 			break;
    274       1.1       cgd 		}
    275       1.1       cgd 		/*
    276       1.1       cgd 		 * We're going to add another proc to the set.  If this
    277       1.1       cgd 		 * will overflow the buffer, assume the reason is because
    278       1.1       cgd 		 * nprocs (or the proc list) is corrupt and declare an error.
    279       1.1       cgd 		 */
    280       1.1       cgd 		if (cnt >= maxcnt) {
    281       1.1       cgd 			_kvm_err(kd, kd->program, "nprocs corrupt");
    282       1.1       cgd 			return (-1);
    283       1.1       cgd 		}
    284       1.1       cgd 		/*
    285       1.1       cgd 		 * gather eproc
    286       1.1       cgd 		 */
    287       1.1       cgd 		eproc.e_paddr = p;
    288       1.1       cgd 		if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) {
    289  1.30.2.1        he 			_kvm_err(kd, kd->program, "can't read pgrp at %p",
    290       1.1       cgd 				 proc.p_pgrp);
    291       1.1       cgd 			return (-1);
    292       1.1       cgd 		}
    293       1.1       cgd 		eproc.e_sess = pgrp.pg_session;
    294       1.1       cgd 		eproc.e_pgid = pgrp.pg_id;
    295       1.1       cgd 		eproc.e_jobc = pgrp.pg_jobc;
    296       1.1       cgd 		if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
    297  1.30.2.1        he 			_kvm_err(kd, kd->program, "can't read session at %p",
    298       1.1       cgd 				pgrp.pg_session);
    299       1.1       cgd 			return (-1);
    300       1.1       cgd 		}
    301       1.1       cgd 		if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) {
    302       1.1       cgd 			if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
    303       1.1       cgd 				_kvm_err(kd, kd->program,
    304  1.30.2.1        he 					 "can't read tty at %p", sess.s_ttyp);
    305       1.1       cgd 				return (-1);
    306       1.1       cgd 			}
    307       1.1       cgd 			eproc.e_tdev = tty.t_dev;
    308       1.1       cgd 			eproc.e_tsess = tty.t_session;
    309       1.1       cgd 			if (tty.t_pgrp != NULL) {
    310       1.1       cgd 				if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
    311       1.1       cgd 					_kvm_err(kd, kd->program,
    312  1.30.2.1        he 						 "can't read tpgrp at %p",
    313       1.1       cgd 						tty.t_pgrp);
    314       1.1       cgd 					return (-1);
    315       1.1       cgd 				}
    316       1.1       cgd 				eproc.e_tpgid = pgrp.pg_id;
    317       1.1       cgd 			} else
    318       1.1       cgd 				eproc.e_tpgid = -1;
    319       1.1       cgd 		} else
    320       1.1       cgd 			eproc.e_tdev = NODEV;
    321       1.1       cgd 		eproc.e_flag = sess.s_ttyvp ? EPROC_CTTY : 0;
    322       1.1       cgd 		if (sess.s_leader == p)
    323       1.1       cgd 			eproc.e_flag |= EPROC_SLEADER;
    324       1.1       cgd 		if (proc.p_wmesg)
    325       1.1       cgd 			(void)kvm_read(kd, (u_long)proc.p_wmesg,
    326       1.1       cgd 			    eproc.e_wmesg, WMESGLEN);
    327       1.1       cgd 
    328       1.1       cgd 		(void)kvm_read(kd, (u_long)proc.p_vmspace,
    329      1.28  christos 		    (void *)&eproc.e_vm, sizeof(eproc.e_vm));
    330       1.9        pk 
    331       1.1       cgd 		eproc.e_xsize = eproc.e_xrssize = 0;
    332       1.1       cgd 		eproc.e_xccount = eproc.e_xswrss = 0;
    333       1.1       cgd 
    334       1.1       cgd 		switch (what) {
    335       1.1       cgd 
    336       1.1       cgd 		case KERN_PROC_PGRP:
    337       1.1       cgd 			if (eproc.e_pgid != (pid_t)arg)
    338       1.1       cgd 				continue;
    339       1.1       cgd 			break;
    340       1.1       cgd 
    341       1.1       cgd 		case KERN_PROC_TTY:
    342       1.1       cgd 			if ((proc.p_flag & P_CONTROLT) == 0 ||
    343       1.1       cgd 			     eproc.e_tdev != (dev_t)arg)
    344       1.1       cgd 				continue;
    345       1.1       cgd 			break;
    346       1.1       cgd 		}
    347      1.25     perry 		memcpy(&bp->kp_proc, &proc, sizeof(proc));
    348      1.25     perry 		memcpy(&bp->kp_eproc, &eproc, sizeof(eproc));
    349       1.1       cgd 		++bp;
    350       1.1       cgd 		++cnt;
    351       1.1       cgd 	}
    352       1.1       cgd 	return (cnt);
    353       1.1       cgd }
    354       1.1       cgd 
    355       1.1       cgd /*
    356       1.1       cgd  * Build proc info array by reading in proc list from a crash dump.
    357       1.1       cgd  * Return number of procs read.  maxcnt is the max we will read.
    358       1.1       cgd  */
    359       1.1       cgd static int
    360      1.27   thorpej kvm_deadprocs(kd, what, arg, a_allproc, a_deadproc, a_zombproc, maxcnt)
    361       1.1       cgd 	kvm_t *kd;
    362       1.1       cgd 	int what, arg;
    363       1.1       cgd 	u_long a_allproc;
    364      1.27   thorpej 	u_long a_deadproc;
    365       1.1       cgd 	u_long a_zombproc;
    366       1.1       cgd 	int maxcnt;
    367       1.1       cgd {
    368      1.21     perry 	struct kinfo_proc *bp = kd->procbase;
    369      1.27   thorpej 	int acnt, dcnt, zcnt;
    370       1.1       cgd 	struct proc *p;
    371       1.1       cgd 
    372       1.1       cgd 	if (KREAD(kd, a_allproc, &p)) {
    373       1.1       cgd 		_kvm_err(kd, kd->program, "cannot read allproc");
    374       1.1       cgd 		return (-1);
    375       1.1       cgd 	}
    376       1.1       cgd 	acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt);
    377       1.1       cgd 	if (acnt < 0)
    378       1.1       cgd 		return (acnt);
    379       1.1       cgd 
    380      1.27   thorpej 	if (KREAD(kd, a_deadproc, &p)) {
    381      1.27   thorpej 		_kvm_err(kd, kd->program, "cannot read deadproc");
    382      1.27   thorpej 		return (-1);
    383      1.27   thorpej 	}
    384      1.27   thorpej 
    385      1.27   thorpej 	dcnt = kvm_proclist(kd, what, arg, p, bp, maxcnt - acnt);
    386      1.27   thorpej 	if (dcnt < 0)
    387      1.27   thorpej 		dcnt = 0;
    388      1.27   thorpej 
    389       1.1       cgd 	if (KREAD(kd, a_zombproc, &p)) {
    390       1.1       cgd 		_kvm_err(kd, kd->program, "cannot read zombproc");
    391       1.1       cgd 		return (-1);
    392       1.1       cgd 	}
    393      1.27   thorpej 	zcnt = kvm_proclist(kd, what, arg, p, bp + acnt,
    394      1.27   thorpej 	    maxcnt - (acnt + dcnt));
    395       1.1       cgd 	if (zcnt < 0)
    396       1.1       cgd 		zcnt = 0;
    397       1.1       cgd 
    398       1.1       cgd 	return (acnt + zcnt);
    399       1.1       cgd }
    400       1.1       cgd 
    401       1.1       cgd struct kinfo_proc *
    402       1.1       cgd kvm_getprocs(kd, op, arg, cnt)
    403       1.1       cgd 	kvm_t *kd;
    404       1.1       cgd 	int op, arg;
    405       1.1       cgd 	int *cnt;
    406       1.1       cgd {
    407       1.7       cgd 	size_t size;
    408       1.7       cgd 	int mib[4], st, nprocs;
    409       1.1       cgd 
    410       1.1       cgd 	if (kd->procbase != 0) {
    411       1.1       cgd 		free((void *)kd->procbase);
    412       1.1       cgd 		/*
    413       1.1       cgd 		 * Clear this pointer in case this call fails.  Otherwise,
    414       1.1       cgd 		 * kvm_close() will free it again.
    415       1.1       cgd 		 */
    416       1.1       cgd 		kd->procbase = 0;
    417       1.1       cgd 	}
    418       1.1       cgd 	if (ISALIVE(kd)) {
    419       1.1       cgd 		size = 0;
    420       1.1       cgd 		mib[0] = CTL_KERN;
    421       1.1       cgd 		mib[1] = KERN_PROC;
    422       1.1       cgd 		mib[2] = op;
    423       1.1       cgd 		mib[3] = arg;
    424       1.1       cgd 		st = sysctl(mib, 4, NULL, &size, NULL, 0);
    425       1.1       cgd 		if (st == -1) {
    426       1.1       cgd 			_kvm_syserr(kd, kd->program, "kvm_getprocs");
    427       1.1       cgd 			return (0);
    428       1.1       cgd 		}
    429       1.1       cgd 		kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
    430       1.1       cgd 		if (kd->procbase == 0)
    431       1.1       cgd 			return (0);
    432       1.1       cgd 		st = sysctl(mib, 4, kd->procbase, &size, NULL, 0);
    433       1.1       cgd 		if (st == -1) {
    434       1.1       cgd 			_kvm_syserr(kd, kd->program, "kvm_getprocs");
    435       1.1       cgd 			return (0);
    436       1.1       cgd 		}
    437       1.1       cgd 		if (size % sizeof(struct kinfo_proc) != 0) {
    438       1.1       cgd 			_kvm_err(kd, kd->program,
    439       1.1       cgd 				"proc size mismatch (%d total, %d chunks)",
    440       1.1       cgd 				size, sizeof(struct kinfo_proc));
    441       1.1       cgd 			return (0);
    442       1.1       cgd 		}
    443       1.1       cgd 		nprocs = size / sizeof(struct kinfo_proc);
    444       1.1       cgd 	} else {
    445      1.27   thorpej 		struct nlist nl[5], *p;
    446       1.1       cgd 
    447       1.1       cgd 		nl[0].n_name = "_nprocs";
    448       1.1       cgd 		nl[1].n_name = "_allproc";
    449      1.27   thorpej 		nl[2].n_name = "_deadproc";
    450      1.27   thorpej 		nl[3].n_name = "_zombproc";
    451      1.27   thorpej 		nl[4].n_name = 0;
    452       1.1       cgd 
    453       1.1       cgd 		if (kvm_nlist(kd, nl) != 0) {
    454       1.1       cgd 			for (p = nl; p->n_type != 0; ++p)
    455       1.1       cgd 				;
    456       1.1       cgd 			_kvm_err(kd, kd->program,
    457       1.1       cgd 				 "%s: no such symbol", p->n_name);
    458       1.1       cgd 			return (0);
    459       1.1       cgd 		}
    460       1.1       cgd 		if (KREAD(kd, nl[0].n_value, &nprocs)) {
    461       1.1       cgd 			_kvm_err(kd, kd->program, "can't read nprocs");
    462       1.1       cgd 			return (0);
    463       1.1       cgd 		}
    464       1.1       cgd 		size = nprocs * sizeof(struct kinfo_proc);
    465       1.1       cgd 		kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
    466       1.1       cgd 		if (kd->procbase == 0)
    467       1.1       cgd 			return (0);
    468       1.1       cgd 
    469       1.1       cgd 		nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
    470      1.27   thorpej 		    nl[2].n_value, nl[3].n_value, nprocs);
    471       1.1       cgd #ifdef notdef
    472       1.1       cgd 		size = nprocs * sizeof(struct kinfo_proc);
    473       1.1       cgd 		(void)realloc(kd->procbase, size);
    474       1.1       cgd #endif
    475       1.1       cgd 	}
    476       1.1       cgd 	*cnt = nprocs;
    477       1.1       cgd 	return (kd->procbase);
    478       1.1       cgd }
    479       1.1       cgd 
    480       1.1       cgd void
    481       1.1       cgd _kvm_freeprocs(kd)
    482       1.1       cgd 	kvm_t *kd;
    483       1.1       cgd {
    484       1.1       cgd 	if (kd->procbase) {
    485       1.1       cgd 		free(kd->procbase);
    486       1.1       cgd 		kd->procbase = 0;
    487       1.1       cgd 	}
    488       1.1       cgd }
    489       1.1       cgd 
    490       1.1       cgd void *
    491       1.1       cgd _kvm_realloc(kd, p, n)
    492       1.1       cgd 	kvm_t *kd;
    493       1.1       cgd 	void *p;
    494       1.1       cgd 	size_t n;
    495       1.1       cgd {
    496       1.1       cgd 	void *np = (void *)realloc(p, n);
    497       1.1       cgd 
    498       1.1       cgd 	if (np == 0)
    499       1.1       cgd 		_kvm_err(kd, kd->program, "out of memory");
    500       1.1       cgd 	return (np);
    501       1.1       cgd }
    502       1.1       cgd 
    503       1.1       cgd #ifndef MAX
    504       1.1       cgd #define MAX(a, b) ((a) > (b) ? (a) : (b))
    505       1.1       cgd #endif
    506       1.1       cgd 
    507       1.1       cgd /*
    508       1.1       cgd  * Read in an argument vector from the user address space of process p.
    509       1.1       cgd  * addr if the user-space base address of narg null-terminated contiguous
    510       1.1       cgd  * strings.  This is used to read in both the command arguments and
    511       1.1       cgd  * environment strings.  Read at most maxcnt characters of strings.
    512       1.1       cgd  */
    513       1.1       cgd static char **
    514       1.1       cgd kvm_argv(kd, p, addr, narg, maxcnt)
    515       1.1       cgd 	kvm_t *kd;
    516      1.15       cgd 	const struct proc *p;
    517      1.21     perry 	u_long addr;
    518      1.21     perry 	int narg;
    519      1.21     perry 	int maxcnt;
    520      1.21     perry {
    521      1.21     perry 	char *np, *cp, *ep, *ap;
    522      1.28  christos 	u_long oaddr = (u_long)~0L;
    523      1.28  christos 	u_long len;
    524      1.28  christos 	size_t cc;
    525      1.21     perry 	char **argv;
    526       1.1       cgd 
    527       1.1       cgd 	/*
    528       1.1       cgd 	 * Check that there aren't an unreasonable number of agruments,
    529       1.1       cgd 	 * and that the address is in user space.
    530       1.1       cgd 	 */
    531      1.18       gwr 	if (narg > ARG_MAX || addr < kd->min_uva || addr >= kd->max_uva)
    532       1.1       cgd 		return (0);
    533       1.1       cgd 
    534       1.1       cgd 	if (kd->argv == 0) {
    535       1.1       cgd 		/*
    536       1.1       cgd 		 * Try to avoid reallocs.
    537       1.1       cgd 		 */
    538       1.1       cgd 		kd->argc = MAX(narg + 1, 32);
    539       1.1       cgd 		kd->argv = (char **)_kvm_malloc(kd, kd->argc *
    540       1.1       cgd 						sizeof(*kd->argv));
    541       1.1       cgd 		if (kd->argv == 0)
    542       1.1       cgd 			return (0);
    543       1.1       cgd 	} else if (narg + 1 > kd->argc) {
    544       1.1       cgd 		kd->argc = MAX(2 * kd->argc, narg + 1);
    545       1.1       cgd 		kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
    546       1.1       cgd 						sizeof(*kd->argv));
    547       1.1       cgd 		if (kd->argv == 0)
    548       1.1       cgd 			return (0);
    549       1.1       cgd 	}
    550       1.1       cgd 	if (kd->argspc == 0) {
    551      1.28  christos 		kd->argspc = (char *)_kvm_malloc(kd, (size_t)kd->nbpg);
    552       1.1       cgd 		if (kd->argspc == 0)
    553       1.1       cgd 			return (0);
    554       1.6   mycroft 		kd->arglen = kd->nbpg;
    555       1.1       cgd 	}
    556      1.10   mycroft 	if (kd->argbuf == 0) {
    557      1.28  christos 		kd->argbuf = (char *)_kvm_malloc(kd, (size_t)kd->nbpg);
    558      1.10   mycroft 		if (kd->argbuf == 0)
    559      1.10   mycroft 			return (0);
    560      1.10   mycroft 	}
    561      1.10   mycroft 	cc = sizeof(char *) * narg;
    562      1.28  christos 	if (kvm_uread(kd, p, addr, (void *)kd->argv, cc) != cc)
    563      1.10   mycroft 		return (0);
    564      1.10   mycroft 	ap = np = kd->argspc;
    565       1.1       cgd 	argv = kd->argv;
    566       1.1       cgd 	len = 0;
    567       1.1       cgd 	/*
    568       1.1       cgd 	 * Loop over pages, filling in the argument vector.
    569       1.1       cgd 	 */
    570      1.10   mycroft 	while (argv < kd->argv + narg && *argv != 0) {
    571      1.10   mycroft 		addr = (u_long)*argv & ~(kd->nbpg - 1);
    572      1.10   mycroft 		if (addr != oaddr) {
    573      1.28  christos 			if (kvm_uread(kd, p, addr, kd->argbuf,
    574      1.28  christos 			    (size_t)kd->nbpg) != kd->nbpg)
    575      1.10   mycroft 				return (0);
    576      1.10   mycroft 			oaddr = addr;
    577      1.10   mycroft 		}
    578      1.10   mycroft 		addr = (u_long)*argv & (kd->nbpg - 1);
    579      1.28  christos 		cp = kd->argbuf + (size_t)addr;
    580      1.28  christos 		cc = kd->nbpg - (size_t)addr;
    581      1.28  christos 		if (maxcnt > 0 && cc > (size_t)(maxcnt - len))
    582      1.28  christos 			cc = (size_t)(maxcnt - len);
    583      1.10   mycroft 		ep = memchr(cp, '\0', cc);
    584      1.10   mycroft 		if (ep != 0)
    585      1.10   mycroft 			cc = ep - cp + 1;
    586       1.1       cgd 		if (len + cc > kd->arglen) {
    587      1.21     perry 			int off;
    588      1.21     perry 			char **pp;
    589      1.21     perry 			char *op = kd->argspc;
    590       1.1       cgd 
    591       1.1       cgd 			kd->arglen *= 2;
    592       1.1       cgd 			kd->argspc = (char *)_kvm_realloc(kd, kd->argspc,
    593      1.28  christos 			    (size_t)kd->arglen);
    594       1.1       cgd 			if (kd->argspc == 0)
    595       1.1       cgd 				return (0);
    596       1.1       cgd 			/*
    597       1.1       cgd 			 * Adjust argv pointers in case realloc moved
    598       1.1       cgd 			 * the string space.
    599       1.1       cgd 			 */
    600       1.1       cgd 			off = kd->argspc - op;
    601      1.13   mycroft 			for (pp = kd->argv; pp < argv; pp++)
    602       1.1       cgd 				*pp += off;
    603      1.12   mycroft 			ap += off;
    604      1.12   mycroft 			np += off;
    605       1.1       cgd 		}
    606      1.10   mycroft 		memcpy(np, cp, cc);
    607      1.10   mycroft 		np += cc;
    608       1.1       cgd 		len += cc;
    609      1.10   mycroft 		if (ep != 0) {
    610      1.10   mycroft 			*argv++ = ap;
    611      1.10   mycroft 			ap = np;
    612      1.10   mycroft 		} else
    613      1.10   mycroft 			*argv += cc;
    614       1.1       cgd 		if (maxcnt > 0 && len >= maxcnt) {
    615       1.1       cgd 			/*
    616       1.1       cgd 			 * We're stopping prematurely.  Terminate the
    617      1.10   mycroft 			 * current string.
    618       1.1       cgd 			 */
    619      1.10   mycroft 			if (ep == 0) {
    620      1.10   mycroft 				*np = '\0';
    621      1.14   mycroft 				*argv++ = ap;
    622      1.10   mycroft 			}
    623      1.10   mycroft 			break;
    624       1.1       cgd 		}
    625       1.1       cgd 	}
    626      1.10   mycroft 	/* Make sure argv is terminated. */
    627      1.10   mycroft 	*argv = 0;
    628      1.10   mycroft 	return (kd->argv);
    629       1.1       cgd }
    630       1.1       cgd 
    631       1.1       cgd static void
    632       1.1       cgd ps_str_a(p, addr, n)
    633       1.1       cgd 	struct ps_strings *p;
    634       1.1       cgd 	u_long *addr;
    635       1.1       cgd 	int *n;
    636       1.1       cgd {
    637       1.1       cgd 	*addr = (u_long)p->ps_argvstr;
    638       1.1       cgd 	*n = p->ps_nargvstr;
    639       1.1       cgd }
    640       1.1       cgd 
    641       1.1       cgd static void
    642       1.1       cgd ps_str_e(p, addr, n)
    643       1.1       cgd 	struct ps_strings *p;
    644       1.1       cgd 	u_long *addr;
    645       1.1       cgd 	int *n;
    646       1.1       cgd {
    647       1.1       cgd 	*addr = (u_long)p->ps_envstr;
    648       1.1       cgd 	*n = p->ps_nenvstr;
    649       1.1       cgd }
    650       1.1       cgd 
    651       1.1       cgd /*
    652       1.1       cgd  * Determine if the proc indicated by p is still active.
    653       1.1       cgd  * This test is not 100% foolproof in theory, but chances of
    654       1.1       cgd  * being wrong are very low.
    655       1.1       cgd  */
    656       1.1       cgd static int
    657       1.1       cgd proc_verify(kd, kernp, p)
    658       1.1       cgd 	kvm_t *kd;
    659       1.1       cgd 	u_long kernp;
    660       1.1       cgd 	const struct proc *p;
    661       1.1       cgd {
    662       1.1       cgd 	struct proc kernproc;
    663       1.1       cgd 
    664       1.1       cgd 	/*
    665       1.1       cgd 	 * Just read in the whole proc.  It's not that big relative
    666       1.1       cgd 	 * to the cost of the read system call.
    667       1.1       cgd 	 */
    668      1.28  christos 	if (kvm_read(kd, kernp, (void *)&kernproc, sizeof(kernproc)) !=
    669       1.1       cgd 	    sizeof(kernproc))
    670       1.1       cgd 		return (0);
    671       1.1       cgd 	return (p->p_pid == kernproc.p_pid &&
    672       1.1       cgd 		(kernproc.p_stat != SZOMB || p->p_stat == SZOMB));
    673       1.1       cgd }
    674       1.1       cgd 
    675       1.1       cgd static char **
    676       1.1       cgd kvm_doargv(kd, kp, nchr, info)
    677       1.1       cgd 	kvm_t *kd;
    678       1.1       cgd 	const struct kinfo_proc *kp;
    679       1.1       cgd 	int nchr;
    680      1.10   mycroft 	void (*info)(struct ps_strings *, u_long *, int *);
    681       1.1       cgd {
    682      1.21     perry 	const struct proc *p = &kp->kp_proc;
    683      1.21     perry 	char **ap;
    684       1.1       cgd 	u_long addr;
    685       1.1       cgd 	int cnt;
    686       1.1       cgd 	struct ps_strings arginfo;
    687       1.1       cgd 
    688       1.1       cgd 	/*
    689       1.1       cgd 	 * Pointers are stored at the top of the user stack.
    690       1.1       cgd 	 */
    691      1.18       gwr 	if (p->p_stat == SZOMB)
    692      1.18       gwr 		return (0);
    693      1.18       gwr 	cnt = kvm_uread(kd, p, kd->usrstack - sizeof(arginfo),
    694      1.28  christos 	    (void *)&arginfo, sizeof(arginfo));
    695      1.18       gwr 	if (cnt != sizeof(arginfo))
    696       1.1       cgd 		return (0);
    697       1.1       cgd 
    698       1.1       cgd 	(*info)(&arginfo, &addr, &cnt);
    699       1.3   mycroft 	if (cnt == 0)
    700       1.3   mycroft 		return (0);
    701       1.1       cgd 	ap = kvm_argv(kd, p, addr, cnt, nchr);
    702       1.1       cgd 	/*
    703       1.1       cgd 	 * For live kernels, make sure this process didn't go away.
    704       1.1       cgd 	 */
    705       1.1       cgd 	if (ap != 0 && ISALIVE(kd) &&
    706       1.1       cgd 	    !proc_verify(kd, (u_long)kp->kp_eproc.e_paddr, p))
    707       1.1       cgd 		ap = 0;
    708       1.1       cgd 	return (ap);
    709       1.1       cgd }
    710       1.1       cgd 
    711       1.1       cgd /*
    712       1.1       cgd  * Get the command args.  This code is now machine independent.
    713       1.1       cgd  */
    714       1.1       cgd char **
    715       1.1       cgd kvm_getargv(kd, kp, nchr)
    716       1.1       cgd 	kvm_t *kd;
    717       1.1       cgd 	const struct kinfo_proc *kp;
    718       1.1       cgd 	int nchr;
    719       1.1       cgd {
    720       1.1       cgd 	return (kvm_doargv(kd, kp, nchr, ps_str_a));
    721       1.1       cgd }
    722       1.1       cgd 
    723       1.1       cgd char **
    724       1.1       cgd kvm_getenvv(kd, kp, nchr)
    725       1.1       cgd 	kvm_t *kd;
    726       1.1       cgd 	const struct kinfo_proc *kp;
    727       1.1       cgd 	int nchr;
    728       1.1       cgd {
    729       1.1       cgd 	return (kvm_doargv(kd, kp, nchr, ps_str_e));
    730       1.1       cgd }
    731       1.1       cgd 
    732       1.1       cgd /*
    733       1.1       cgd  * Read from user space.  The user context is given by p.
    734       1.1       cgd  */
    735       1.1       cgd ssize_t
    736       1.1       cgd kvm_uread(kd, p, uva, buf, len)
    737       1.1       cgd 	kvm_t *kd;
    738      1.21     perry 	const struct proc *p;
    739      1.21     perry 	u_long uva;
    740      1.21     perry 	char *buf;
    741      1.21     perry 	size_t len;
    742       1.1       cgd {
    743      1.21     perry 	char *cp;
    744       1.1       cgd 
    745       1.1       cgd 	cp = buf;
    746       1.1       cgd 	while (len > 0) {
    747      1.28  christos 		size_t cc;
    748      1.21     perry 		char *dp;
    749      1.15       cgd 		u_long cnt;
    750       1.8   mycroft 
    751       1.8   mycroft 		dp = _kvm_uread(kd, p, uva, &cnt);
    752       1.8   mycroft 		if (dp == 0) {
    753  1.30.2.1        he 			_kvm_err(kd, 0, "invalid address (%lx)", uva);
    754       1.8   mycroft 			return (0);
    755       1.8   mycroft 		}
    756      1.28  christos 		cc = (size_t)MIN(cnt, len);
    757      1.25     perry 		memcpy(cp, dp, cc);
    758       1.1       cgd 		cp += cc;
    759       1.1       cgd 		uva += cc;
    760       1.1       cgd 		len -= cc;
    761       1.1       cgd 	}
    762       1.1       cgd 	return (ssize_t)(cp - buf);
    763       1.1       cgd }
    764