date and time created 86/03/02 15:30:40 by sam
[unix-history] / usr / src / old / analyze / analyze.c
CommitLineData
761330fe
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
f6d84e07 13#ifndef lint
761330fe
DF
14static char sccsid[] = "@(#)analyze.c 5.1 (Berkeley) %G%";
15#endif not lint
f6d84e07
SL
16
17/*
18 * Analyze - analyze a core (and optional paging area) saved from
19 * a virtual Unix system crash.
20 */
c4589a32
BJ
21#include <stdio.h>
22#include <sys/param.h>
23#include <sys/dir.h>
0bc29a7d 24#include <machine/pte.h>
c4589a32
BJ
25#include <nlist.h>
26#include <sys/map.h>
27#include <sys/user.h>
28#include <sys/proc.h>
29#include <sys/text.h>
30#include <sys/cmap.h>
31#include <sys/vm.h>
32
c4589a32
BJ
33int Dflg;
34int dflg;
35int vflg;
36int mflg;
37int fflg;
38int sflg;
abf78ad6 39int uflg;
c4589a32
BJ
40
41/* use vprintf with care; it plays havoc with ``else's'' */
42#define vprintf if (vflg) printf
43
db770cb2 44#ifdef vax
c4589a32 45#define clear(x) ((int)x & 0x7fffffff)
db770cb2
SL
46#else
47#define clear(x) ((int)x)
48#endif
c4589a32 49
a4412164 50struct proc *proc, *aproc;
8fc75516 51int nproc;
a4412164 52struct text *text, *atext;
8fc75516
BJ
53int ntext;
54struct mapent *swapmap;
55int nswapmap;
f6d84e07 56int dmmin, dmmax, dmtext;
c4589a32 57struct cmap *cmap;
abf78ad6 58int ecmx;
c4589a32
BJ
59struct pte *usrpt;
60struct pte *Usrptma;
61int firstfree;
62int maxfree;
63int freemem;
64struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG];
65int pid;
66
67struct paginfo {
68 char z_type;
69 char z_count;
70 short z_pid;
71 struct pte z_pte;
72} *paginfo;
73#define ZLOST 0
74#define ZDATA 1
75#define ZSTACK 2
76#define ZUDOT 3
77#define ZPAGET 4
78#define ZTEXT 5
79#define ZFREE 6
80#define ZINTRAN 7
81
c4589a32
BJ
82struct dblks {
83 short d_first;
84 short d_size;
85 char d_type;
86 char d_index;
8fc75516 87} *dblks;
c4589a32
BJ
88int ndblks;
89
90#define DFREE 0
91#define DDATA 1
92#define DSTACK 2
93#define DTEXT 3
94#define DUDOT 4
95#define DPAGET 5
96
97union {
db770cb2 98 char buf[UPAGES][NBPG];
c4589a32
BJ
99 struct user U;
100} u_area;
101#define u u_area.U
102
103int fcore = -1;
104int fswap = -1;
105
106struct nlist nl[] = {
107#define X_PROC 0
108 { "_proc" },
109#define X_USRPT 1
110 { "_usrpt" },
111#define X_PTMA 2
abf78ad6 112 { "_Usrptmap" },
c4589a32 113#define X_FIRSTFREE 3
abf78ad6 114 { "_firstfree" },
c4589a32
BJ
115#define X_MAXFREE 4
116 { "_maxfree" },
117#define X_TEXT 5
118 { "_text" },
119#define X_FREEMEM 6
120 { "_freemem" },
121#define X_CMAP 7
122 { "_cmap" },
123#define X_ECMAP 8
124 { "_ecmap" },
125#define X_SWAPMAP 9
126 { "_swapmap" },
8fc75516
BJ
127#define X_NPROC 10
128 { "_nproc" },
129#define X_NTEXT 11
130 { "_ntext" },
131#define X_NSWAPMAP 12
132 { "_nswapmap" },
f6d84e07
SL
133#define X_DMMIN 13
134 { "_dmmin" },
135#define X_DMMAX 14
136 { "_dmmax" },
137#define X_DMTEXT 15
138 { "_dmtext" },
139 { "" }
c4589a32
BJ
140};
141
142main(argc, argv)
143 int argc;
144 char **argv;
145{
146 register struct nlist *np;
147 register struct proc *p;
148 register struct text *xp;
149 register struct pte *pte;
150 register int i;
151 int w, a;
152
db770cb2
SL
153#ifdef DEBUG
154 setbuf(stdout, NULL);
155#endif
c4589a32
BJ
156 argc--, argv++;
157 while (argc > 0 && argv[0][0] == '-') {
158 register char *cp = *argv++;
159 argc--;
160 while (*++cp) switch (*cp) {
161
162 case 'm':
163 mflg++;
164 break;
165
166 case 'v':
167 vflg++;
168 break;
169
170 case 's':
171 if (argc < 2)
172 goto usage;
173 if ((fswap = open(argv[0], 0)) < 0) {
174 perror(argv[0]);
175 exit(1);
176 }
177 argc--,argv++;
178 sflg++;
179 break;
180
181 case 'f':
182 fflg++;
183 break;
184
185 case 'D':
186 Dflg++;
187 break;
188
189 case 'd':
190 dflg++;
191 break;
192
abf78ad6
BJ
193 case 'u':
194 uflg++;
195 break;
196
c4589a32
BJ
197 default:
198 goto usage;
199 }
200 }
201 if (argc < 1) {
202usage:
203 fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n");
204 exit(1);
205 }
206 close(0);
207 if ((fcore = open(argv[0], 0)) < 0) {
208 perror(argv[0]);
209 exit(1);
210 }
211 nlist(argc > 1 ? argv[1] : "/vmunix", nl);
212 if (nl[0].n_value == 0) {
213 fprintf(stderr, "%s: bad namelist\n",
214 argc > 1 ? argv[1] : "/vmunix");
215 exit(1);
216 }
f6d84e07 217 for (np = nl; np->n_name && *np->n_name; np++)
c4589a32
BJ
218 vprintf("%8.8s %x\n", np->n_name ,np->n_value );
219 usrpt = (struct pte *)clear(nl[X_USRPT].n_value);
220 Usrptma = (struct pte *)clear(nl[X_PTMA].n_value);
221 firstfree = get(nl[X_FIRSTFREE].n_value);
222 maxfree = get(nl[X_MAXFREE].n_value);
223 freemem = get(nl[X_FREEMEM].n_value);
f6d84e07
SL
224 dmmin = get(nl[X_DMMIN]);
225 dmmax = get(nl[X_DMMAX]);
226 dmtext = get(nl[X_DMTEXT]);
c4589a32
BJ
227 paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo));
228 if (paginfo == NULL) {
229 fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree);
230 exit(1);
231 }
232 vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n",
233 usrpt, Usrptma, firstfree, maxfree, freemem);
a4412164 234 {
8fc75516
BJ
235 lseek(fcore, (long)clear(nl[X_PROC].n_value), 0);
236 read(fcore, (char *)&aproc, sizeof aproc);
237 lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0);
238 read(fcore, (char *)&nproc, sizeof nproc);
239 printf("%d procs\n", nproc);
240 proc = (struct proc *)calloc(nproc, sizeof (struct proc));
241 lseek(fcore, (long)clear(aproc), 0);
242 if (read(fcore, (char *)proc, nproc * sizeof (struct proc))
243 != nproc * sizeof (struct proc)) {
c4589a32
BJ
244 perror("proc read");
245 exit(1);
8fc75516 246 }
c4589a32 247 }
a4412164 248 {
8fc75516
BJ
249 lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0);
250 read(fcore, (char *)&atext, sizeof atext);
251 lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0);
252 read(fcore, (char *)&ntext, sizeof ntext);
253 printf("%d texts\n", ntext);
254 text = (struct text *)calloc(ntext, sizeof (struct text));
255 lseek(fcore, (long)clear(atext), 0);
256 if (read(fcore, (char *)text, ntext * sizeof (struct text))
257 != ntext * sizeof (struct text)) {
c4589a32
BJ
258 perror("text read");
259 exit(1);
8fc75516 260 }
c4589a32
BJ
261 }
262 i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value));
abf78ad6 263 ecmx = i / sizeof (struct cmap);
c4589a32
BJ
264 cmap = (struct cmap *)calloc(i, 1);
265 if (cmap == NULL) {
266 fprintf(stderr, "not enough mem for %x bytes of cmap\n", i);
267 exit(1);
268 }
269 lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0);
270 if (read(fcore, (char *)cmap, i) != i) {
271 perror("cmap read");
272 exit(1);
273 }
8fc75516
BJ
274 { struct mapent *aswapmap;
275 lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0);
276 read(fcore, (char *)&aswapmap, sizeof aswapmap);
277 lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0);
278 read(fcore, (char *)&nswapmap, sizeof nswapmap);
279 nswapmap--;
280 printf("%d swapmap entries\n", nswapmap);
281 swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent));
282 dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks));
283 lseek(fcore, (long)clear(aswapmap+1), 0);
284 if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent))
285 != nswapmap * sizeof (struct mapent)) {
c4589a32
BJ
286 perror("swapmap read");
287 exit(1);
8fc75516 288 }
c4589a32 289 }
8fc75516 290 for (p = &proc[1]; p < proc+nproc; p++) {
c4589a32
BJ
291 p->p_p0br = (struct pte *)clear(p->p_p0br);
292 p->p_addr = (struct pte *)clear(p->p_addr);
293 if (p->p_stat == 0)
294 continue;
295 printf("proc %d ", p->p_pid);
296 if (p->p_stat == SZOMB) {
297 printf("zombie\n");
298 continue;
299 }
300 if (p->p_flag & SLOAD) {
301 printf("loaded, p0br %x, ", p->p_p0br);
302 printf("%d pages of page tables:", p->p_szpt);
303 a = btokmx(p->p_p0br);
304 for (i = 0; i < p->p_szpt; i++) {
305 w = get(&Usrptma[a + i]);
306 printf(" %x", w & PG_PFNUM);
307 }
308 printf("\n");
309 for(i = 0; i < p->p_szpt; i++) {
310 w = get(&Usrptma[a + i]);
311 if (getpt(w, i))
312 count(p, (struct pte *)&w, ZPAGET);
313 }
314 } else {
315 /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */
316 i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize));
317 printf("swapped, swaddr %x\n", p->p_swaddr);
db770cb2 318 duse(p->p_swaddr, ctod(clrnd(UPAGES)), DUDOT, p - proc);
c4589a32 319 duse(p->p_swaddr + ctod(UPAGES),
db770cb2
SL
320 ctod(clrnd(i - p->p_tsize / NPTEPG)),
321 DPAGET, p - proc);
c4589a32
BJ
322 /* i, DPAGET, p - proc); */
323 }
324 p->p_p0br = (struct pte *)p0br;
325 p->p_addr = uaddr(p);
db770cb2
SL
326 if (p->p_textp)
327 p->p_textp = &text[p->p_textp - atext];
c4589a32
BJ
328 if (p->p_pid == 2)
329 continue;
330 if (getu(p))
331 continue;
332 u.u_procp = p;
333 pdmap();
334 if ((p->p_flag & SLOAD) == 0)
335 continue;
336 pid = p->p_pid;
337 for (i = 0; i < p->p_tsize; i++) {
338 pte = tptopte(p, i);
339 if (pte->pg_fod || pte->pg_pfnum == 0)
340 continue;
341 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans)
342 count(p, pte, ZINTRAN);
343 else
344 count(p, pte, ZTEXT);
345 }
346 vprintf("\n");
347 for (i = 0; i < p->p_dsize; i++) {
348 pte = dptopte(p, i);
349 if (pte->pg_fod || pte->pg_pfnum == 0)
350 continue;
351 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans)
352 count(p, pte, ZINTRAN);
353 else
354 count(p, pte, ZDATA);
355 }
356 vprintf("\n");
357 for (i = 0; i < p->p_ssize; i++) {
358 pte = sptopte(p, i);
359 if (pte->pg_fod || pte->pg_pfnum == 0)
360 continue;
361 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans)
362 count(p, pte, ZINTRAN);
363 else
364 count(p, pte, ZSTACK);
365 }
366 vprintf("\n");
367 for (i = 0; i < UPAGES; i++)
368 count(p, &p->p_addr[i], ZUDOT);
369 vprintf("\n");
370 vprintf("\n");
371 }
8fc75516 372 for (xp = &text[0]; xp < text+ntext; xp++)
c4589a32 373 if (xp->x_iptr) {
db770cb2
SL
374 int size = ctod(xp->x_size);
375
f6d84e07 376 for (i = 0; i < size; i += dmtext)
c4589a32 377 duse(xp->x_daddr[i],
f6d84e07
SL
378 (size - i) > dmtext
379 ? dmtext : size - i,
c4589a32
BJ
380 DTEXT, xp - text);
381 if (xp->x_flag & XPAGI)
db770cb2
SL
382 duse(xp->x_ptdaddr,
383 ctod(clrnd(ctopt(xp->x_size))),
c4589a32
BJ
384 DTEXT, xp - text);
385 }
386 dmcheck();
387 fixfree();
388 summary();
389 exit(0);
390}
391
392pdmap()
393{
394 register struct text *xp;
395
396 if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0)
397 return;
398 if (Dflg)
399 printf("disk for pid %d", u.u_procp->p_pid);
400 if ((xp = u.u_procp->p_textp) && Dflg)
401 ptdmap(xp->x_daddr, xp->x_size);
402 pdmseg("data", &u.u_dmap, DDATA);
403 pdmseg("stack", &u.u_smap, DSTACK);
404 if (Dflg)
405 printf("\n");
406}
407
408ptdmap(dp, size)
409 register daddr_t *dp;
410 int size;
411{
412 register int i;
413 int rem;
414
415 if (Dflg)
416 printf(" text:");
417 for (i = 0, rem = size; rem > 0; i++) {
418 if (Dflg)
f6d84e07
SL
419 printf(" %x<%x>", dp[i], rem < dmtext ? rem : dmtext);
420 rem -= rem < dmtext ? rem : dmtext;
c4589a32
BJ
421 }
422}
423
424pdmseg(cp, dmp, type)
425 char *cp;
426 struct dmap *dmp;
427{
428 register int i;
429 int b, rem;
430
431 if (Dflg)
432 printf(", %s:", cp);
f6d84e07 433 b = dmmin;
c4589a32
BJ
434 for (i = 0, rem = dmp->dm_size; rem > 0; i++) {
435 if (Dflg)
436 printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b);
437 duse(dmp->dm_map[i], b, type, u.u_procp - proc);
438 rem -= b;
f6d84e07 439 if (b < dmmax)
c4589a32
BJ
440 b *= 2;
441 }
442}
443
444duse(first, size, type, index)
445{
446 register struct dblks *dp;
447
448 if (fswap == -1)
449 return;
450 dp = &dblks[ndblks];
8fc75516
BJ
451 if (++ndblks > 2*nswapmap) {
452 fprintf(stderr, "too many disk blocks\n");
c4589a32
BJ
453 exit(1);
454 }
455 dp->d_first = first;
456 dp->d_size = size;
457 dp->d_type = type;
458 dp->d_index = index;
459}
460
461dsort(d, e)
462 register struct dblks *d, *e;
463{
464
465 return (e->d_first - d->d_first);
466}
467
468dmcheck()
469{
8fc75516 470 register struct mapent *smp;
c4589a32
BJ
471 register struct dblks *d, *e;
472
473 for (smp = swapmap; smp->m_size; smp++)
474 duse(smp->m_addr, smp->m_size, DFREE, 0);
f6d84e07 475 duse(ctod(CLSIZE), dmtext - ctod(CLSIZE), DFREE, 0);
c4589a32
BJ
476 qsort(dblks, ndblks, sizeof (struct dblks), dsort);
477 d = &dblks[ndblks - 1];
478 if (d->d_first > 1)
479 printf("lost swap map: start %x size %x\n", 1, d->d_first);
480 for (; d > dblks; d--) {
481 if (dflg)
482 dprint(d);
483 e = d - 1;
484 if (d->d_first + d->d_size > e->d_first) {
485 printf("overlap in swap mappings:\n");
486 dprint(d);
487 dprint(e);
488 } else if (d->d_first + d->d_size < e->d_first) {
489 printf("lost swap map: start %x size %x\n",
490 d->d_first + d->d_size,
491 e->d_first - (d->d_first + d->d_size));
492 }
493 }
494 if (dflg)
495 dprint(dblks);
496 if (sflg)
497 printf("swap space ends at %x\n", d->d_first + d->d_size);
498}
499
500char *dnames[] = {
501 "DFREE",
502 "DDATA",
503 "DSTACK",
504 "DTEXT",
505 "DUDOT",
506 "DPAGET",
507};
508
509dprint(d)
510 register struct dblks *d;
511{
512
513 printf("at %4x size %4x type %s", d->d_first, d->d_size,
514 dnames[d->d_type]);
515 switch (d->d_type) {
516
517 case DSTACK:
518 case DDATA:
519 printf(" pid %d", proc[d->d_index].p_pid);
520 break;
521 }
522 printf("\n");
523}
524
525getpt(x, i)
526 int x, i;
527{
528
529 lseek(fcore, (long)ctob((x & PG_PFNUM)), 0);
530 if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) {
531 perror("read");
532 fprintf(stderr, "getpt error reading frame %x\n", clear(x));
533 return (0);
534 }
535 return (1);
536}
537
538checkpg(p, pte, type)
539 register struct pte *pte;
540 register struct proc *p;
541 int type;
542{
543 char corepg[NBPG], swapg[NBPG];
544 register int i, count, dblock;
545 register int pfnum = pte->pg_pfnum;
546
547 if (type == ZPAGET || type == ZUDOT)
548 return (0);
549 lseek(fcore, (long)(NBPG * pfnum), 0);
550 if (read(fcore, corepg, NBPG) != NBPG){
551 perror("read");
552 fprintf(stderr, "Error reading core page %x\n", pfnum);
553 return (0);
554 }
555 switch (type) {
556
557 case ZDATA:
558 if (ptetodp(p, pte) >= u.u_dmap.dm_size)
559 return (0);
560 break;
561
562 case ZTEXT:
563 break;
564
565 case ZSTACK:
566 if (ptetosp(p, pte) >= u.u_smap.dm_size)
567 return (0);
568 break;
569
570 default:
571 return(0);
572 break;
573 }
574 dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap);
575 vprintf(" %x", dblock);
576 if (pte->pg_fod || pte->pg_pfnum == 0)
577 return (0);
578 if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm)
579 return (0);
db770cb2 580 lseek(fswap, (long)(DEV_BSIZE * dblock), 0);
c4589a32
BJ
581 if (read(fswap, swapg, NBPG) != NBPG) {
582 fprintf(stderr,"swap page %x: ", dblock);
583 perror("read");
584 }
585 count = 0;
586 for (i = 0; i < NBPG; i++)
587 if (corepg[i] != swapg[i])
588 count++;
589 if (count == 0)
590 vprintf("\tsame");
591 return (count);
592}
593
594getu(p)
595 register struct proc *p;
596{
597 int i, w, cc, errs = 0;
598
abf78ad6
BJ
599 if (uflg && (p->p_flag & SLOAD))
600 printf("pid %d u. pages:", p->p_pid);
c4589a32
BJ
601 for (i = 0; i < UPAGES; i++) {
602 if (p->p_flag & SLOAD) {
abf78ad6
BJ
603 if (uflg)
604 printf(" %x", p->p_addr[i].pg_pfnum);
c4589a32
BJ
605 lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0);
606 if (read(fcore, u_area.buf[i], NBPG) != NBPG)
607 perror("core u. read"), errs++;
608 } else if (fswap >= 0) {
609 lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0);
610 if (read(fswap, u_area.buf[i], NBPG) != NBPG)
611 perror("swap u. read"), errs++;
612 }
613 }
abf78ad6
BJ
614 if (uflg && (p->p_flag & SLOAD))
615 printf("\n");
c4589a32
BJ
616 return (errs);
617}
618
619char *typepg[] = {
620 "lost",
621 "data",
622 "stack",
623 "udot",
624 "paget",
625 "text",
626 "free",
627 "intransit",
628};
629
630count(p, pte, type)
631 struct proc *p;
632 register struct pte *pte;
633 int type;
634{
635 register int pfnum = pte->pg_pfnum;
636 register struct paginfo *zp = &paginfo[pfnum];
637 int ndif;
638#define zprintf if (type==ZINTRAN || vflg) printf
639
640 if (type == ZINTRAN && pfnum == 0)
641 return;
642 zprintf("page %x %s", pfnum, typepg[type]);
643 if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) {
644 zprintf("\n");
645 } else {
646 if (vflg == 0 && type != ZINTRAN)
647 printf("page %x %s,", pfnum, typepg[type]);
648 printf(" %d bytes differ\n",ndif);
649 }
650 if (pfnum < firstfree || pfnum > maxfree) {
651 printf("page number out of range:\n");
652 printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid);
653 return;
654 }
655 if (bad(zp, type)) {
656 printf("dup page pte %x", *(int *)pte);
657 dumpcm("", pte->pg_pfnum);
658 dump(zp);
659 printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid);
660 return;
661 }
662 zp->z_type = type;
663 zp->z_count++;
664 zp->z_pid = pid;
665 zp->z_pte = *pte;
666}
667
668bad(zp, type)
669 struct paginfo *zp;
670{
671 if (type == ZTEXT) {
672 if (zp->z_type != 0 && zp->z_type != ZTEXT)
673 return (1);
674 return (0);
675 }
676 return (zp->z_count);
677}
678
679dump(zp)
680 struct paginfo *zp;
681{
682
683 printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid);
684}
685
686summary()
687{
688 register int i;
689 register struct paginfo *zp;
690 register int pfnum;
691
abf78ad6 692 for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) {
c4589a32
BJ
693 zp = &paginfo[i];
694 if (zp->z_type == ZLOST)
695 dumpcm("lost", i);
696 pfnum = pgtocm(i);
697 if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS)
698 dumpcm("locked", i);
699 if (mflg)
700 dumpcm("mem", i);
701 }
702}
703
704char *tynames[] = {
705 "sys",
706 "text",
707 "data",
708 "stack"
709};
710dumpcm(cp, pg)
711 char *cp;
712 int pg;
713{
714 int pslot;
715 int cm;
716 register struct cmap *c;
717
c4589a32 718 cm = pgtocm(pg);
abf78ad6 719 printf("cm %x %s page %x ", cm, cp, pg);
c4589a32
BJ
720 c = &cmap[cm];
721 printf("\t[%x, %x", c->c_page, c->c_ndx);
a4412164
BJ
722 if (c->c_type == CSYS)
723 goto skip;
724 if (c->c_type != CTEXT) {
725 if (c->c_ndx >= nproc) {
726 printf(" [text c->c_ndx %d?]", c->c_ndx);
727 goto skip;
728 }
c4589a32 729 printf(" (=pid %d)", proc[c->c_ndx].p_pid);
a4412164
BJ
730 } else {
731 if (c->c_ndx >= ntext) {
732 printf(" [text c->c_ndx %d?]", c->c_ndx);
733 goto skip;
734 }
735 pslot= (text[c->c_ndx].x_caddr - aproc);
c4589a32
BJ
736 printf(" (=pid");
737 for(;;) {
738 printf(" %d", proc[pslot].p_pid);
739 if (proc[pslot].p_xlink == 0)
740 break;
a4412164 741 pslot= (proc[pslot].p_xlink - aproc);
c4589a32
BJ
742 }
743 printf(")");
744 }
a4412164 745skip:
c4589a32
BJ
746 printf("] ");
747 printf(tynames[c->c_type]);
748 if (c->c_free)
749 printf(" free");
750 if (c->c_gone)
751 printf(" gone");
752 if (c->c_lock)
753 printf(" lock");
754 if (c->c_want)
755 printf(" want");
756 if (c->c_intrans)
757 printf(" intrans");
758 if (c->c_blkno)
759 printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev);
abf78ad6
BJ
760 if (c->c_hlink) {
761 printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink));
762 if (c->c_hlink > ecmx)
763 printf(" <<<");
764 }
c4589a32
BJ
765 printf("\n");
766}
767
768fixfree()
769{
770 register int i, next, prev;
771
772 next = CMHEAD;
773 for (i=freemem/CLSIZE; --i >=0; ) {
774 prev = next;
775 next = cmap[next].c_next;
776 if (cmap[next].c_free == 0) {
777 printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next));
778 dumpcm("bad free link in", cmtopg(prev));
779 dumpcm("to non free block", cmtopg(next));
780 }
781 if (cmtopg(next) > maxfree) {
782 printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next));
783 dumpcm("bad link in", cmtopg(prev));
784 }
785 paginfo[cmtopg(next)].z_type = ZFREE;
786 if (fflg)
787 dumpcm("free", cmtopg(next));
788 paginfo[cmtopg(next)+1].z_type = ZFREE;
789 if (fflg)
790 dumpcm("free", cmtopg(next)+1);
791 }
792}
793
794get(loc)
795unsigned loc;
796{
797 int x;
798
799 lseek(fcore, (long)clear(loc), 0);
800 if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) {
801 perror("read");
802 fprintf(stderr, "get failed on %x\n", clear(loc));
803 return (0);
804 }
805 return (x);
806}
807/*
808 * Convert a virtual page number
809 * to its corresponding disk block number.
810 * Used in pagein/pageout to initiate single page transfers.
811 */
812vtod(p, v, dmap, smap)
813 register struct proc *p;
814 register struct dmap *dmap, *smap;
815{
816 struct dblock db;
817
db770cb2
SL
818 if (isatsv(p, v)) {
819 v = ctod(vtotp(p, v));
f6d84e07 820 return(p->p_textp->x_daddr[v / dmtext] + v % dmtext);
db770cb2 821 }
c4589a32 822 if (isassv(p, v))
db770cb2 823 vstodb(ctod(vtosp(p, v)), ctod(1), smap, &db, 1);
c4589a32 824 else
db770cb2 825 vstodb(ctod(vtodp(p, v)), ctod(1), dmap, &db, 0);
c4589a32
BJ
826 return (db.db_base);
827}
828
829/*
830 * Convert a pte pointer to
831 * a virtual page number.
832 */
833ptetov(p, pte)
834 register struct proc *p;
835 register struct pte *pte;
836{
837
838 if (isatpte(p, pte))
839 return (tptov(p, ptetotp(p, pte)));
840 else if (isadpte(p, pte))
841 return (dptov(p, ptetodp(p, pte)));
842 else
843 return (sptov(p, ptetosp(p, pte)));
844}
845
846/*
847 * Given a base/size pair in virtual swap area,
848 * return a physical base/size pair which is the
849 * (largest) initial, physically contiguous block.
850 */
851vstodb(vsbase, vssize, dmp, dbp, rev)
852 register int vsbase;
853 int vssize;
854 register struct dmap *dmp;
855 register struct dblock *dbp;
856{
f6d84e07 857 register int blk = dmmin;
c4589a32
BJ
858 register swblk_t *ip = dmp->dm_map;
859
860 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
861 panic("vstodb");
862 while (vsbase >= blk) {
863 vsbase -= blk;
f6d84e07 864 if (blk < dmmax)
c4589a32
BJ
865 blk *= 2;
866 ip++;
867 }
868 dbp->db_size = min(vssize, blk - vsbase);
869 dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase);
870}
871
872panic(cp)
873 char *cp;
874{
875 printf("panic!: %s\n", cp);
876}
877
878min(a, b)
879{
880 return (a < b ? a : b);
881}