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