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