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