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