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