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