xref: /original-bsd/lib/libkvm/kvm_proc.c (revision 23cd6db2)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms is permitted
6  * provided that all copyright information, including this notice,
7  * is retained in all such forms, and that any documentation,
8  * advertising or other materials related to such distribution and
9  * use acknowledge that the software was
10  * developed by the University of California, Berkeley.  The name
11  * of the University may not be used to endorse or promote products
12  * derived from this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18 
19 
20 #include <machine/pte.h>
21 #include <sys/param.h>
22 #include <sys/user.h>
23 #include <sys/proc.h>
24 #include <sys/file.h>
25 #include <sys/text.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <sys/vmmac.h>
29 #include <sys/ioctl.h>
30 #include <sys/tty.h>
31 #include <kvm.h>
32 #include <ctype.h>
33 #include <cencode.h>
34 #include <nlist.h>
35 #include <pwd.h>
36 #include <strings.h>
37 #include <ndbm.h>
38 #include <limits.h>
39 #include <paths.h>
40 #include <stdio.h>
41 
42 /*
43  * files
44  */
45 static	char *unixf, *memf, *kmemf, *swapf;
46 static	int unixx, mem, kmem, swap;
47 static	DBM *db;
48 /*
49  * flags
50  */
51 static	int deadkernel;
52 static	int kvminit = 0;
53 static	int kvmfilesopen = 0;
54 /*
55  * state
56  */
57 static	struct kinfo_proc *kvmprocbase, *kvmprocptr;
58 static	int kvmnprocs;
59 /*
60  * u. buffer
61  */
62 static union {
63 	struct	user user;
64 	char	upages[UPAGES][NBPG];
65 } user;
66 /*
67  * random other stuff
68  */
69 static	struct pte *Usrptmap, *usrpt;
70 static	int	dmmin, dmmax;
71 static	struct	pte *Sysmap;
72 static	int	Syssize;
73 static	int     pcbpf;
74 static	int     argaddr0;	/* XXX */
75 static	int     argaddr1;
76 static	int	nswap;
77 static	char	*tmp;
78 
79 #define basename(cp)	((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
80 #define	MAXSYMSIZE	256
81 
82 static struct nlist nl[] = {
83 	{ "_Usrptmap" },
84 #define	X_USRPTMAP	0
85 	{ "_usrpt" },
86 #define	X_USRPT		1
87 	{ "_nswap" },
88 #define	X_NSWAP		2
89 	{ "_dmmin" },
90 #define	X_DMMIN		3
91 	{ "_dmmax" },
92 #define	X_DMMAX		4
93 	/*
94 	 * everything here and down, only if a dead kernel
95 	 */
96 	{ "_Sysmap" },
97 #define	X_SYSMAP	5
98 #define	X_DEADKERNEL	X_SYSMAP
99 	{ "_Syssize" },
100 #define	X_SYSSIZE	6
101 	{ "_allproc" },
102 #define X_ALLPROC	7
103 	{ "_zombproc" },
104 #define X_ZOMBPROC	8
105 	{ "_nproc" },
106 #define	X_NPROC		9
107 	{ "" },
108 };
109 
110 static char *savestr();
111 
112 /*
113  * returns 	0 if files were opened now,
114  * 		1 if files were already opened,
115  *		-1 if files could not be opened.
116  */
117 kvm_openfiles(uf, mf, sf)
118 	char *uf, *mf, *sf;
119 {
120 	if (kvmfilesopen)
121 		return (1);
122 	unixx = mem = kmem = swap = -1;
123 	unixf = (uf == NULL) ? _PATH_UNIX : uf;
124 	memf = (mf == NULL) ? _PATH_MEM : mf;
125 
126 	if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
127 		setsyserr("can't open %s", unixf);
128 		goto failed;
129 	}
130 	if ((mem = open(memf, O_RDONLY, 0)) == -1) {
131 		setsyserr("can't open %s", memf);
132 		goto failed;
133 	}
134 	if (sf != NULL)
135 		swapf = sf;
136 	if (mf != NULL) {
137 		deadkernel++;
138 		kmemf = mf;
139 		kmem = mem;
140 		swap = -1;
141 	} else {
142 		kmemf = _PATH_KMEM;
143 		if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
144 			setsyserr("can't open %s", kmemf);
145 			goto failed;
146 		}
147 		swapf = (sf == NULL) ?  _PATH_DRUM : sf;
148 		/*
149 		 * live kernel - avoid looking up nlist entries
150 		 * past X_DEADKERNEL.
151 		 */
152 		nl[X_DEADKERNEL].n_name = "";
153 	}
154 	if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
155 		seterr("can't open %s", swapf);
156 		goto failed;
157 	}
158 	kvmfilesopen++;
159 	return (0);
160 failed:
161 	kvm_close();
162 	return (-1);
163 }
164 
165 static
166 kvm_init(uf, mf, sf)
167 	char *uf, *mf, *sf;
168 {
169 	if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
170 		return (-1);
171 	if (getkvars() == -1)
172 		return (-1);
173 	kvminit = 1;
174 
175 	return (0);
176 }
177 
178 kvm_close()
179 {
180 	if (unixx != -1) {
181 		close(unixx);
182 		unixx = -1;
183 	}
184 	if (kmem != -1) {
185 		if (kmem != mem)
186 			close(kmem);
187 		/* otherwise kmem is a copy of mem, and will be closed below */
188 		kmem = -1;
189 	}
190 	if (mem != -1) {
191 		close(mem);
192 		mem = -1;
193 	}
194 	if (swap != -1) {
195 		close(swap);
196 		swap = -1;
197 	}
198 	if (db != NULL) {
199 		dbm_close(db);
200 		db = NULL;
201 	}
202 	kvminit = 0;
203 	kvmfilesopen = 0;
204 	deadkernel = 0;
205 	if (Sysmap) {
206 		free(Sysmap);
207 		Sysmap = NULL;
208 	}
209 }
210 
211 kvm_nlist(nl)
212 	struct nlist *nl;
213 {
214 	datum key, data;
215 	char dbname[MAXPATHLEN];
216 	char dbversion[LINE_MAX];
217 	char kversion[LINE_MAX];
218 	int dbversionlen;
219 	char symbuf[MAXSYMSIZE+1];
220 	struct nlist nbuf, *n;
221 	int num, did;
222 
223 	if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
224 		return (-1);
225 	if (deadkernel)
226 		goto hard2;
227 	/*
228 	 * initialize key datum
229 	 */
230 	key.dptr = symbuf;
231 	symbuf[0] = KVMDB_NLIST;
232 
233 	if (db != NULL)
234 		goto win;	/* off to the races */
235 	/*
236 	 * open database
237 	 */
238 	sprintf(dbname, "%s/kvm_%s", KVMDBDIR, basename(unixf));
239 	if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
240 		goto hard2;
241 	/*
242 	 * read version out of database
243 	 */
244 	bcopy("VERSION", symbuf+1, sizeof ("VERSION")-1);
245 	key.dsize = (sizeof ("VERSION") - 1) + 1;
246 	data = dbm_fetch(db, key);
247 	if (data.dptr == NULL)
248 		goto hard1;
249 	bcopy(data.dptr, dbversion, data.dsize);
250 	dbversionlen = data.dsize;
251 	/*
252 	 * read version string from kernel memory
253 	 */
254 	bcopy("_version", symbuf+1, sizeof ("_version")-1);
255 	key.dsize = (sizeof ("_version")-1) + 1;
256 	data = dbm_fetch(db, key);
257 	if (data.dptr == NULL)
258 		goto hard1;
259 	if (data.dsize != sizeof (struct nlist))
260 		goto hard1;
261 	bcopy(data.dptr, &nbuf, sizeof (struct nlist));
262 	lseek(kmem, nbuf.n_value, 0);
263 	if (read(kmem, kversion, dbversionlen) != dbversionlen)
264 		goto hard1;
265 	/*
266 	 * if they match, we win - otherwise do it the hard way
267 	 */
268 	if (bcmp(dbversion, kversion, dbversionlen) != 0)
269 		goto hard1;
270 	/*
271 	 * getem from the database.
272 	 */
273 win:
274 	num = did = 0;
275 	for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
276 		int len;
277 		/*
278 		 * clear out fields from users buffer
279 		 */
280 		n->n_type = 0;
281 		n->n_other = 0;
282 		n->n_desc = 0;
283 		n->n_value = 0;
284 		/*
285 		 * query db
286 		 */
287 		if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
288 			seterr("kvm_nlist: symbol too large");
289 			return (-1);
290 		}
291 		strcpy(symbuf+1, n->n_name);
292 		key.dsize = len + 1;
293 		data = dbm_fetch(db, key);
294 		if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
295 			continue;
296 		bcopy(data.dptr, &nbuf, sizeof (struct nlist));
297 		n->n_value = nbuf.n_value;
298 		n->n_type = nbuf.n_type;
299 		n->n_desc = nbuf.n_desc;
300 		n->n_other = nbuf.n_other;
301 		did++;
302 	}
303 	return (num - did);
304 hard1:
305 	dbm_close(db);
306 	db = NULL;
307 hard2:
308 	return (nlist(unixf, nl));	/* XXX seterr if -1 */
309 }
310 
311 kvm_getprocs(what, arg)
312 {
313 	if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
314 		return (NULL);
315 	if (!deadkernel) {
316 		int ret, copysize;
317 
318 		if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
319 			setsyserr("can't get estimate for kerninfo");
320 			return (-1);
321 		}
322 		copysize = ret;
323 		if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize))
324 		     == NULL) {
325 			seterr("out of memory");
326 			return (-1);
327 		}
328 		if ((ret = getkerninfo(what, kvmprocbase, &copysize,
329 		     arg)) == -1) {
330 			setsyserr("can't get proc list");
331 			return (-1);
332 		}
333 		if (copysize % sizeof (struct kinfo_proc)) {
334 			seterr("proc size mismatch");
335 			return (-1);
336 		}
337 		kvmnprocs = copysize / sizeof (struct kinfo_proc);
338 	} else {
339 		int nproc;
340 
341 		if (kvm_read(nl[X_NPROC].n_value, &nproc, sizeof (int)) !=
342 		    sizeof (int)) {
343 			seterr("can't read nproc");
344 			return (-1);
345 		}
346 		if ((kvmprocbase = (struct kinfo_proc *)
347 		     malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
348 			seterr("out of memory (addr: %x nproc = %d)",
349 				nl[X_NPROC].n_value, nproc);
350 			return (-1);
351 		}
352 		kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
353 		realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
354 	}
355 	kvmprocptr = kvmprocbase;
356 
357 	return (kvmnprocs);
358 }
359 
360 /*
361  * XXX - should NOT give up so easily - especially since the kernel
362  * may be corrupt (it died).  Should gather as much information as possible.
363  * Follows proc ptrs instead of reading table since table may go
364  * away soon.
365  */
366 static
367 kvm_doprocs(what, arg, buff)
368 	int what, arg;
369 	char *buff;
370 {
371 	struct proc *p, proc;
372 	register char *bp = buff;
373 	int i = 0;
374 	int doingzomb = 0;
375 	struct eproc eproc;
376 	struct pgrp pgrp;
377 	struct session sess;
378 	struct tty tty;
379 	struct text text;
380 
381 	/* allproc */
382 	if (kvm_read(nl[X_ALLPROC].n_value, &p,
383 	    sizeof (struct proc *)) != sizeof (struct proc *)) {
384 		seterr("can't read allproc");
385 		return (-1);
386 	}
387 
388 again:
389 	for (; p; p = proc.p_nxt) {
390 		if (kvm_read(p, &proc, sizeof (struct proc)) !=
391 		    sizeof (struct proc)) {
392 			seterr("can't read proc at %x", p);
393 			return (-1);
394 		}
395 		switch(ki_op(what)) {
396 
397 		case KINFO_PROC_PID:
398 			if (proc.p_pid != (pid_t)arg)
399 				continue;
400 			break;
401 
402 
403 		case KINFO_PROC_UID:
404 			if (proc.p_uid != (uid_t)arg)
405 				continue;
406 			break;
407 
408 		case KINFO_PROC_RUID:
409 			if (proc.p_ruid != (uid_t)arg)
410 				continue;
411 			break;
412 		}
413 		/*
414 		 * gather eproc
415 		 */
416 		eproc.e_paddr = p;
417 		if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) !=
418 	            sizeof (struct pgrp)) {
419 			seterr("can't read pgrp at %x", proc.p_pgrp);
420 			return (-1);
421 		}
422 		eproc.e_sess = pgrp.pg_session;
423 		eproc.e_pgid = pgrp.pg_id;
424 		eproc.e_jobc = pgrp.pg_jobc;
425 		if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
426 		   != sizeof (struct session)) {
427 			seterr("can't read session at %x", pgrp.pg_session);
428 			return (-1);
429 		}
430 		if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
431 			if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
432 			    != sizeof (struct tty)) {
433 				seterr("can't read tty at %x", sess.s_ttyp);
434 				return (-1);
435 			}
436 			eproc.e_tdev = tty.t_dev;
437 			eproc.e_tsess = tty.t_session;
438 			if (tty.t_pgrp != NULL) {
439 				if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
440 				    pgrp)) != sizeof (struct pgrp)) {
441 					seterr("can't read tpgrp at &x",
442 						tty.t_pgrp);
443 					return (-1);
444 				}
445 				eproc.e_tpgid = pgrp.pg_id;
446 			} else
447 				eproc.e_tpgid = -1;
448 		} else
449 			eproc.e_tdev = NODEV;
450 		if (proc.p_wmesg)
451 			kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
452 		if (proc.p_textp) {
453 			kvm_read(proc.p_textp, &text, sizeof (text));
454 			eproc.e_xsize = text.x_size;
455 			eproc.e_xrssize = text.x_rssize;
456 			eproc.e_xccount = text.x_ccount;
457 			eproc.e_xswrss = text.x_swrss;
458 		} else {
459 			eproc.e_xsize = eproc.e_xrssize =
460 			  eproc.e_xccount = eproc.e_xswrss = 0;
461 		}
462 
463 		switch(ki_op(what)) {
464 
465 		case KINFO_PROC_PGRP:
466 			if (eproc.e_pgid != (pid_t)arg)
467 				continue;
468 			break;
469 
470 		case KINFO_PROC_TTY:
471 			if ((proc.p_flag&SCTTY) == 0 ||
472 			     eproc.e_tdev != (dev_t)arg)
473 				continue;
474 			break;
475 		}
476 
477 		i++;
478 		bcopy(&proc, bp, sizeof (struct proc));
479 		bp += sizeof (struct proc);
480 		bcopy(&eproc, bp, sizeof (struct eproc));
481 		bp+= sizeof (struct eproc);
482 	}
483 	if (!doingzomb) {
484 		/* zombproc */
485 		if (kvm_read(nl[X_ZOMBPROC].n_value, &p,
486 		    sizeof (struct proc *)) != sizeof (struct proc *)) {
487 			seterr("can't read zombproc");
488 			return (-1);
489 		}
490 		doingzomb = 1;
491 		goto again;
492 	}
493 
494 	return (i);
495 }
496 
497 
498 struct proc *
499 kvm_nextproc()
500 {
501 
502 	if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
503 		return (NULL);
504 	if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
505 		seterr("end of proc list");
506 		return (NULL);
507 	}
508 	return((struct proc *)(kvmprocptr++));
509 }
510 
511 struct eproc *
512 kvm_geteproc(p)
513 	struct proc *p;
514 {
515 	return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
516 }
517 
518 kvm_setproc()
519 {
520 
521 	kvmprocptr = kvmprocbase;
522 }
523 
524 kvm_freeprocs()
525 {
526 
527 	if (kvmprocbase) {
528 		free(kvmprocbase);
529 		kvmprocbase = NULL;
530 	}
531 }
532 
533 struct user *
534 kvm_getu(p)
535 	struct proc *p;
536 {
537 	struct pte *pteaddr, apte;
538 	struct pte arguutl[UPAGES+(CLSIZE*2)];
539 	register int i;
540 	int ncl;
541 
542 	if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
543 		return (NULL);
544 	if (p->p_stat == SZOMB) {
545 		seterr("zombie process");
546 		return (NULL);
547 	}
548 	if ((p->p_flag & SLOAD) == 0) {
549 		if (swap < 0) {
550 			seterr("no swap");
551 			return (NULL);
552 		}
553 		(void) lseek(swap, (long)dtob(p->p_swaddr), 0);
554 		if (read(swap, (char *)&user.user, sizeof (struct user)) !=
555 		    sizeof (struct user)) {
556 			seterr("can't read u for pid %d from %s\n",
557 			    p->p_pid, swapf);
558 			return (NULL);
559 		}
560 		pcbpf = 0;
561 		argaddr0 = 0;
562 		argaddr1 = 0;
563 		return (&user.user);
564 	}
565 	pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1];
566 	klseek(kmem, (long)pteaddr, 0);
567 	if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
568 		seterr("can't read indir pte to get u for pid %d from %s",
569 		    p->p_pid, kmemf);
570 		return (NULL);
571 	}
572 	lseek(mem,
573 	    (long)ctob(apte.pg_pfnum+1) - (UPAGES+(CLSIZE*2)) * sizeof (struct pte),
574 		0);
575 	if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
576 		seterr("can't read page table for u of pid %d from %s",
577 		    p->p_pid, memf);
578 		return (NULL);
579 	}
580 	if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
581 		argaddr0 = ctob(arguutl[0].pg_pfnum);
582 	else
583 		argaddr0 = 0;
584 	if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum)
585 		argaddr1 = ctob(arguutl[CLSIZE*1].pg_pfnum);
586 	else
587 		argaddr1 = 0;
588 	pcbpf = arguutl[CLSIZE*2].pg_pfnum;
589 	ncl = (sizeof (struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
590 	while (--ncl >= 0) {
591 		i = ncl * CLSIZE;
592 		lseek(mem, (long)ctob(arguutl[(CLSIZE*2)+i].pg_pfnum), 0);
593 		if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
594 			seterr("can't read page %d of u of pid %d from %s",
595 			    arguutl[CLSIZE+i].pg_pfnum, p->p_pid, memf);
596 			return(NULL);
597 		}
598 	}
599 	return (&user.user);
600 }
601 
602 char *
603 kvm_getargs(p, up)
604 	struct proc *p;
605 	struct user *up;
606 {
607 	char cmdbuf[CLSIZE*NBPG*2];
608 	union {
609 		char	argc[CLSIZE*NBPG*2];
610 		int	argi[CLSIZE*NBPG*2/sizeof (int)];
611 	} argspac;
612 	register char *cp;
613 	register int *ip;
614 	char c;
615 	int nbad;
616 	struct dblock db;
617 	char *file;
618 
619 	if (p->p_stat == SZOMB)
620 		return ("<defunct>");
621 	if (p->p_flag & SWEXIT)
622 		return ("<exiting>");
623 	if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
624 		goto retucomm;
625 	if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
626 		if (swap < 0)
627 			goto retucomm;
628 		vstodb(0, CLSIZE, &up->u_smap, &db, 1);
629 		(void) lseek(swap, (long)dtob(db.db_base), 0);
630 		if (read(swap, (char *)&argspac.argc[NBPG*CLSIZE],
631 			NBPG*CLSIZE) != NBPG*CLSIZE)
632 			goto bad;
633 		vstodb(1, CLSIZE, &up->u_smap, &db, 1);
634 		(void) lseek(swap, (long)dtob(db.db_base), 0);
635 		if (read(swap, (char *)&argspac.argc[0],
636 			NBPG*CLSIZE) != NBPG*CLSIZE)
637 			goto bad;
638 		file = swapf;
639 	} else {
640 		if (argaddr0) {
641 			lseek(mem, (long)argaddr0, 0);
642 			if (read(mem, (char *)&argspac, NBPG*CLSIZE)
643 			    != NBPG*CLSIZE)
644 				goto bad;
645 		} else
646 			bzero(&argspac, NBPG*CLSIZE);
647 		lseek(mem, (long)argaddr1, 0);
648 		if (read(mem, &argspac.argc[NBPG*CLSIZE], NBPG*CLSIZE)
649 		    != NBPG*CLSIZE)
650 			goto bad;
651 		file = memf;
652 	}
653 	ip = &argspac.argi[CLSIZE*NBPG*2/sizeof (int)];
654 	ip -= 2;		/* last arg word and .long 0 */
655 	while (*--ip) {
656 		if (ip == argspac.argi)
657 			goto retucomm;
658 	}
659 	*(char *)ip = ' ';
660 	ip++;
661 	nbad = 0;
662 	for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG*2]; cp++) {
663 		c = *cp & 0177;
664 		if (c == 0)
665 			*cp = ' ';
666 		else if (c < ' ' || c > 0176) {
667 			if (++nbad >= 5*(0+1)) {	/* eflg -> 0 XXX */
668 				*cp++ = ' ';
669 				break;
670 			}
671 			*cp = '?';
672 		} else if (0 == 0 && c == '=') {	/* eflg -> 0 XXX */
673 			while (*--cp != ' ')
674 				if (cp <= (char *)ip)
675 					break;
676 			break;
677 		}
678 	}
679 	*cp = 0;
680 	while (*--cp == ' ')
681 		*cp = 0;
682 	cp = (char *)ip;
683 	(void) strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG*2] - cp);
684 	if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
685 		(void) strcat(cmdbuf, " (");
686 		(void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
687 		(void) strcat(cmdbuf, ")");
688 	}
689 	return (cmdbuf);
690 
691 bad:
692 	seterr("error locating command name for pid %d from %s\n",
693 	    p->p_pid, file);
694 retucomm:
695 	(void) strcpy(cmdbuf, " (");
696 	(void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
697 	(void) strcat(cmdbuf, ")");
698 	return (cmdbuf);
699 }
700 
701 
702 static
703 getkvars()
704 {
705 
706 	if (kvm_nlist(nl) == -1)
707 		return (-1);
708 	if (deadkernel) {
709 		/* We must do the sys map first because klseek uses it */
710 		long	addr;
711 
712 		Syssize = nl[X_SYSSIZE].n_value;
713 		Sysmap = (struct pte *)
714 			calloc((unsigned) Syssize, sizeof (struct pte));
715 		if (Sysmap == NULL) {
716 			seterr("out of space for Sysmap");
717 			return (-1);
718 		}
719 		addr = (long) nl[X_SYSMAP].n_value;
720 		addr &= ~KERNBASE;
721 		(void) lseek(kmem, addr, 0);
722 		if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte))
723 		    != Syssize * sizeof (struct pte)) {
724 			seterr("can't read Sysmap");
725 			return (-1);
726 		}
727 	}
728 	usrpt = (struct pte *)nl[X_USRPT].n_value;
729 	Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
730 	if (kvm_read((long)nl[X_NSWAP].n_value, &nswap, sizeof (long)) !=
731 	    sizeof (long)) {
732 		seterr("can't read nswap");
733 		return (-1);
734 	}
735 	if (kvm_read((long)nl[X_DMMIN].n_value, &dmmin, sizeof (long)) !=
736 	    sizeof (long)) {
737 		seterr("can't read dmmin");
738 		return (-1);
739 	}
740 	if (kvm_read((long)nl[X_DMMAX].n_value, &dmmax, sizeof (long)) !=
741 	    sizeof (long)) {
742 		seterr("can't read dmmax");
743 		return (-1);
744 	}
745 	return (0);
746 }
747 
748 kvm_read(loc, buf, len)
749 	unsigned long loc;
750 	char *buf;
751 {
752 	if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
753 		return (-1);
754 	if (loc & KERNBASE) {
755 		klseek(kmem, loc, 0);
756 		if (read(kmem, buf, len) != len) {
757 			seterr("error reading kmem at %x\n", loc);
758 			return (-1);
759 		}
760 	} else {
761 		lseek(mem, loc, 0);
762 		if (read(mem, buf, len) != len) {
763 			seterr("error reading mem at %x\n", loc);
764 			return (-1);
765 		}
766 	}
767 	return (len);
768 }
769 
770 static
771 klseek(fd, loc, off)
772 	int fd;
773 	off_t loc;
774 	int off;
775 {
776 
777 	if (deadkernel) {
778 		off_t vtophys();
779 
780 		if ((loc = vtophys(loc)) == -1)
781 			return;
782 	}
783 	(void) lseek(fd, (off_t)loc, off);
784 }
785 
786 /*
787  * Given a base/size pair in virtual swap area,
788  * return a physical base/size pair which is the
789  * (largest) initial, physically contiguous block.
790  */
791 static
792 vstodb(vsbase, vssize, dmp, dbp, rev)
793 	register int vsbase;
794 	int vssize;
795 	struct dmap *dmp;
796 	register struct dblock *dbp;
797 {
798 	register int blk = dmmin;
799 	register swblk_t *ip = dmp->dm_map;
800 
801 	vsbase = ctod(vsbase);
802 	vssize = ctod(vssize);
803 	if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
804 		/*panic("vstodb")*/;
805 	while (vsbase >= blk) {
806 		vsbase -= blk;
807 		if (blk < dmmax)
808 			blk *= 2;
809 		ip++;
810 	}
811 	if (*ip <= 0 || *ip + blk > nswap)
812 		/*panic("vstodb")*/;
813 	dbp->db_size = MIN(vssize, blk - vsbase);
814 	dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
815 }
816 
817 /*
818  * This routine was stolen from adb to simulate memory management
819  * on the VAX.
820  */
821 static off_t
822 vtophys(loc)
823 	long loc;
824 {
825 	register p;
826 	off_t newloc;
827 
828 	newloc = loc & ~KERNBASE;
829 	p = btop(newloc);
830 	if ((loc & KERNBASE) == 0) {
831 		seterr("vtophys: translating non-kernel address");
832 		return((off_t) -1);
833 	}
834 	if (p >= Syssize) {
835 		seterr("vtophys: page out of bound (%d>=%d)", p, Syssize);
836 		return((off_t) -1);
837 	}
838 	if (Sysmap[p].pg_v == 0 &&
839 	    (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) {
840 		seterr("vtophys: page not valid");
841 		return((off_t) -1);
842 	}
843 	loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET));
844 	return(loc);
845 }
846 
847 #include <varargs.h>
848 static char errbuf[LINE_MAX];
849 
850 static
851 seterr(va_alist)
852 	va_dcl
853 {
854 	char *fmt;
855 	va_list ap;
856 
857 	va_start(ap);
858 	fmt = va_arg(ap, char *);
859 	(void) vsprintf(errbuf, fmt, ap);
860 	va_end(ap);
861 }
862 
863 static
864 setsyserr(va_alist)
865 	va_dcl
866 {
867 	char *fmt, *cp;
868 	va_list ap;
869 	extern errno;
870 
871 	va_start(ap);
872 	fmt = va_arg(ap, char *);
873 	(void) vsprintf(errbuf, fmt, ap);
874 	for (cp=errbuf; *cp; cp++)
875 		;
876 	sprintf(cp, ": %s", strerror(errno));
877 	va_end(ap);
878 }
879 
880 char *
881 kvm_geterr()
882 {
883 
884 	return (errbuf);
885 }
886