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