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