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