|
|
1.1 root 1: /*
2: * Copyright (c) 1985 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)tahoe.c 5.8 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Target machine dependent stuff.
26: */
27:
28: #include "defs.h"
29: #include "machine.h"
30: #include "process.h"
31: #include "runtime.h"
32: #include "events.h"
33: #include "main.h"
34: #include "symbols.h"
35: #include "source.h"
36: #include "mappings.h"
37: #include "object.h"
38: #include "keywords.h"
39: #include "ops.h"
40: #include "eval.h"
41: #include <signal.h>
42:
43: #ifndef public
44: typedef unsigned int Address;
45: typedef unsigned char Byte;
46: typedef unsigned int Word;
47:
48: #define NREG 16
49:
50: #define FRP 13
51: #define STKP 14
52: #define PROGCTR 15
53:
54: #define CODESTART 0
55: #define FUNCOFFSET 2
56:
57: #define BITSPERBYTE 8
58: #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
59:
60: /*
61: * This magic macro enables us to look at the process' registers
62: * in its user structure.
63: */
64:
65: #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg)))
66:
67: #define nargspassed(frame) (((argn(-1, frame)&0xffff)-4)/4)
68:
69: #define SYSBASE 0xc0000000 /* base of system address space */
70: #define physaddr(a) ((a) &~ 0xc0000000)
71:
72: #include "source.h"
73: #include "symbols.h"
74: #include <sys/param.h>
75: #include <machine/psl.h>
76: #include <sys/user.h>
77: #undef DELETE /* XXX */
78: #include <sys/vm.h>
79: #include <machine/reg.h>
80: #include <machine/pte.h>
81:
82: Address pc;
83: Address prtaddr;
84:
85: #endif
86:
87: /*
88: * Indices into u. for use in collecting registers values.
89: */
90: public int rloc[] =
91: { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, FP, SP, PC };
92:
93: private Address printop();
94:
95: Optab *ioptab[256]; /* index by opcode to optab */
96: /*
97: * Initialize the opcode lookup table.
98: */
99: public optab_init()
100: {
101: register Optab *p;
102:
103: for (p = optab; p->iname; p++)
104: ioptab[p->val & 0xff] = p;
105: }
106:
107: /*
108: * Decode and print the instructions within the given address range.
109: */
110: public printinst(lowaddr, highaddr)
111: Address lowaddr, highaddr;
112: {
113: register Address addr;
114:
115: for (addr = lowaddr; addr <= highaddr; )
116: addr = printop(addr);
117: prtaddr = addr;
118: }
119:
120: /*
121: * Another approach: print n instructions starting at the given address.
122: */
123: public printninst(count, addr)
124: int count;
125: Address addr;
126: {
127: register Integer i;
128: register Address newaddr;
129:
130: if (count <= 0)
131: error("non-positive repetition count");
132: for (newaddr = addr, i = 0; i < count; i++)
133: newaddr = printop(newaddr);
134: prtaddr = newaddr;
135: }
136:
137: /*
138: * Hacked version of adb's instruction decoder.
139: */
140: private Address printop(addr)
141: Address addr;
142: {
143: register Optab *op;
144: Opcode ins;
145: unsigned char mode;
146: int argtype, amode, argno, argval, r;
147: String reg;
148: Boolean indexf;
149: short offset;
150:
151: argval = 0;
152: indexf = false;
153: printf("%08x ", addr);
154: iread(&ins, addr, sizeof(ins));
155: addr += 1;
156: op = ioptab[ins];
157: printf("%s", op->iname);
158: for (argno = 0; argno < op->numargs; argno++) {
159: if (indexf == true)
160: indexf = false;
161: else
162: printf(argno == 0 ? "\t" : ",");
163: argtype = op->argtype[argno];
164: if (is_branch_disp(argtype))
165: mode = 0xAF + (typelen(argtype) << 5);
166: else
167: iread(&mode, addr, sizeof(mode)), addr += 1;
168: reg = regname[regnm(mode)];
169: amode = addrmode(mode);
170: switch (amode) {
171:
172: case LITSHORT: case LITUPTO31:
173: case LITUPTO47: case LITUPTO63:
174: if (ins == O_KCALL && mode >= 0 && mode < SYSSIZE &&
175: systab[mode])
176: printf("$%s", systab[mode]);
177: else
178: printf("$%x", mode);
179: argval = mode;
180: break;
181:
182: case INDEX:
183: printf("[%s]", reg);
184: indexf = true;
185: argno--;
186: break;
187:
188: case REG:
189: printf("%s", reg);
190: break;
191:
192: case REGDEF:
193: printf("(%s)", reg);
194: break;
195:
196: case AUTODEC:
197: printf("-(%s)", reg);
198: break;
199:
200: case AUTOINC:
201: r = mode & 0xf;
202: if (r == 0xf || r == 8 || r == 9) {
203: int size = (mode&03) + 1;
204:
205: /* immediate mode */
206: printf("$");
207: argval = printdisp(addr, size,
208: regname[PROGCTR], amode);
209: addr += size;
210: } else
211: printf("(%s)+", reg);
212: break;
213:
214: case AUTOINCDEF:
215: if ((mode&0xf) == 0xf) {
216: printf("*$");
217: argval = printdisp(addr, 4, reg, amode);
218: addr += 4;
219: } else
220: printf("*(%s)+", reg);
221: break;
222:
223: case BYTEDISP:
224: argval = printdisp(addr, 1, reg, amode);
225: addr += 1;
226: break;
227:
228: case BYTEDISPDEF:
229: printf("*");
230: argval = printdisp(addr, 1, reg, amode);
231: addr += 1;
232: break;
233:
234: case WORDDISP:
235: argval = printdisp(addr, 2, reg, amode);
236: addr += 2;
237: break;
238:
239: case WORDDISPDEF:
240: printf("*");
241: argval = printdisp(addr, 2, reg, amode);
242: addr += 2;
243: break;
244:
245: case LONGDISP:
246: argval = printdisp(addr, 4, reg, amode);
247: addr += 4;
248: break;
249:
250: case LONGDISPDEF:
251: printf("*");
252: argval = printdisp(addr, 4, reg, amode);
253: addr += 4;
254: break;
255: }
256: }
257: if (ins == O_CASEL)
258: for (argno = 0; argno <= argval; argno++) {
259: iread(&offset, addr, sizeof(offset));
260: printf("\n\t\t%d", offset);
261: addr += 2;
262: }
263: printf("\n");
264: return (addr);
265: }
266:
267: /*
268: * Print the displacement of an instruction that uses displacement
269: * addressing.
270: */
271: private int printdisp(addr, nbytes, reg, mode)
272: Address addr;
273: int nbytes;
274: char *reg;
275: int mode;
276: {
277: char byte;
278: short hword;
279: int argval;
280: Symbol f;
281:
282: switch (nbytes) {
283:
284: case 1:
285: iread(&byte, addr, sizeof(byte));
286: argval = byte;
287: break;
288:
289: case 2:
290: iread(&hword, addr, sizeof(hword));
291: argval = hword;
292: break;
293:
294: case 4:
295: iread(&argval, addr, sizeof(argval));
296: break;
297: }
298: if (reg == regname[PROGCTR] && mode >= BYTEDISP)
299: argval += addr + nbytes;
300: if (reg == regname[PROGCTR]) {
301: f = whatblock((Address) argval + 2);
302: if (codeloc(f) == argval + 2)
303: printf("%s", symname(f));
304: else
305: printf("%x", argval);
306: } else {
307: if (varIsSet("$hexoffsets")) {
308: if (argval < 0)
309: printf("-%x(%s)", -(argval), reg);
310: else
311: printf("%x(%s)", argval, reg);
312: } else
313: printf("%d(%s)", argval, reg);
314: }
315: return (argval);
316: }
317:
318: /*
319: * Print the contents of the addresses within the given range
320: * according to the given format.
321: */
322: typedef struct {
323: String name;
324: String printfstring;
325: int length;
326: } Format;
327:
328: private Format fmt[] = {
329: { "d", " %d", sizeof(short) },
330: { "D", " %ld", sizeof(long) },
331: { "o", " %o", sizeof(short) },
332: { "O", " %lo", sizeof(long) },
333: { "x", " %04x", sizeof(short) },
334: { "X", " %08x", sizeof(long) },
335: { "b", " \\%o", sizeof(char) },
336: { "c", " '%c'", sizeof(char) },
337: { "s", "%c", sizeof(char) },
338: { "f", " %f", sizeof(float) },
339: { "g", " %g", sizeof(double) },
340: { nil, nil, 0 }
341: };
342:
343: private Format *findformat(s)
344: String s;
345: {
346: register Format *f;
347:
348: for (f = &fmt[0]; f->name != nil && !streq(f->name, s); f++)
349: ;
350: if (f->name == nil)
351: error("bad print format \"%s\"", s);
352: return (f);
353: }
354:
355: public Address printdata(lowaddr, highaddr, format)
356: Address lowaddr;
357: Address highaddr;
358: String format;
359: {
360: register int n;
361: register Address addr;
362: register Format *f;
363: int value;
364:
365: if (lowaddr > highaddr)
366: error("first address larger than second");
367: f = findformat(format);
368: n = 0;
369: value = 0;
370: for (addr = lowaddr; addr <= highaddr; addr += f->length) {
371: if (n == 0)
372: printf("%08x: ", addr);
373: dread(&value, addr, f->length);
374: printf(f->printfstring, value);
375: ++n;
376: if (n >= (16 div f->length)) {
377: putchar('\n');
378: n = 0;
379: }
380: }
381: if (n != 0)
382: putchar('\n');
383: prtaddr = addr;
384: return (addr);
385: }
386:
387: /*
388: * The other approach is to print n items starting with a given address.
389: */
390:
391: public printndata(count, startaddr, format)
392: int count;
393: Address startaddr;
394: String format;
395: {
396: register int i, n;
397: register Address addr;
398: register Format *f;
399: register Boolean isstring;
400: char c;
401: union {
402: char charv;
403: short shortv;
404: int intv;
405: float floatv;
406: double doublev;
407: } value;
408:
409: if (count <= 0)
410: error("non-positive repetition count");
411: f = findformat(format);
412: isstring = (Boolean) streq(f->name, "s");
413: n = 0;
414: addr = startaddr;
415: value.intv = 0;
416: for (i = 0; i < count; i++) {
417: if (n == 0)
418: printf("%08x: ", addr);
419: if (isstring) {
420: putchar('"');
421: dread(&c, addr, sizeof(char));
422: while (c != '\0') {
423: printchar(c);
424: ++addr;
425: dread(&c, addr, sizeof(char));
426: }
427: putchar('"');
428: putchar('\n');
429: n = 0;
430: addr += sizeof(String);
431: continue;
432: }
433: dread(&value, addr, f->length);
434: printf(f->printfstring, value);
435: ++n;
436: if (n >= (16 div f->length)) {
437: putchar('\n');
438: n = 0;
439: }
440: addr += f->length;
441: }
442: if (n != 0)
443: putchar('\n');
444: prtaddr = addr;
445: }
446:
447: /*
448: * Print out a value according to the given format.
449: */
450: public printvalue(v, format)
451: long v;
452: String format;
453: {
454: Format *f;
455: char *p, *q;
456:
457: f = findformat(format);
458: if (streq(f->name, "s")) {
459: putchar('"');
460: for (p = (char *) &v, q = p + sizeof(v); p < q; ++p)
461: printchar(*p);
462: putchar('"');
463: } else
464: printf(f->printfstring, v);
465: putchar('\n');
466: }
467:
468: /*
469: * Print out an execution time error.
470: * Assumes the source position of the error has been calculated.
471: *
472: * Have to check if the -r option was specified; if so then
473: * the object file information hasn't been read in yet.
474: */
475: public printerror()
476: {
477: extern Integer sys_nsig;
478: extern String sys_siglist[];
479: integer err;
480:
481: if (isfinished(process)) {
482: err = exitcode(process);
483: if (err) {
484: printf("\"%s\" terminated abnormally (exit code %d)\n",
485: objname, err);
486: erecover();
487: } else
488: printf("\"%s\" terminated normally\n", objname);
489: }
490: if (runfirst) {
491: fprintf(stderr, "Entering debugger ...\n");
492: init();
493: }
494: err = errnum(process);
495: putchar('\n');
496: printsig(err);
497: putchar(' ');
498: printloc();
499: putchar('\n');
500: if (curline > 0)
501: printlines(curline, curline);
502: else
503: printinst(pc, pc);
504: erecover();
505: }
506:
507: /*
508: * Print out a signal.
509: */
510: private String illinames[] = {
511: "reserved addressing fault",
512: "privileged instruction fault",
513: "reserved operand fault"
514: };
515: #define NILLINAMES (sizeof (illinames) / sizeof (illinames[0]))
516:
517: private String fpenames[] = {
518: nil,
519: "integer overflow trap",
520: "integer divide by zero trap",
521: "floating point divide by zero trap",
522: "floating point overflow trap",
523: "floating point underflow trap",
524: };
525: #define NFPENAMES (sizeof (fpenames) / sizeof (fpenames[0]))
526:
527: public printsig(signo)
528: integer signo;
529: {
530: integer code;
531:
532: if (signo < 0 or signo > sys_nsig)
533: printf("[signal %d]", signo);
534: else
535: printf("%s", sys_siglist[signo]);
536: code = errcode(process);
537: if (signo == SIGILL)
538: if (code >= 0 && code < NILLINAMES)
539: printf(" (%s)", illinames[code]);
540: if (signo == SIGFPE)
541: if (code > 0 and code < NFPENAMES)
542: printf(" (%s)", fpenames[code]);
543: }
544:
545: /*
546: * Note the termination of the program. We do this so as to avoid
547: * having the process exit, which would make the values of variables
548: * inaccessible. We do want to flush all output buffers here,
549: * otherwise it'll never get done.
550: */
551: public endprogram()
552: {
553: Integer exitcode;
554:
555: stepto(nextaddr(pc, true));
556: printnews();
557: exitcode = argn(1, nil);
558: if (exitcode != 0)
559: printf("\nexecution completed (exit code %d)\n", exitcode);
560: else
561: printf("\nexecution completed\n");
562: getsrcpos();
563: erecover();
564: }
565:
566: private Address getcall();
567: /*
568: * Single step the machine a source line (or instruction if "inst_tracing"
569: * is true). If "isnext" is true, skip over procedure calls.
570: */
571: public dostep(isnext)
572: Boolean isnext;
573: {
574: register Address addr;
575: register Lineno line;
576: String filename;
577: Address startaddr;
578:
579: startaddr = pc;
580: addr = nextaddr(pc, isnext);
581: if (!inst_tracing && nlhdr.nlines != 0) {
582: line = linelookup(addr);
583: for (; line == 0; line = linelookup(addr))
584: addr = nextaddr(addr, isnext);
585: curline = line;
586: } else
587: curline = 0;
588: stepto(addr);
589: filename = srcfilename(addr);
590: setsource(filename);
591: }
592:
593: private Address findnextaddr();
594: /*
595: * Compute the next address that will be executed from the given one.
596: * If "isnext" is true then consider a procedure call as straight line code.
597: *
598: * We must unfortunately do much of the same work that is necessary
599: * to print instructions. In addition we have to deal with branches.
600: * Unconditional branches we just follow, for conditional branches
601: * we continue execution to the current location and then single step
602: * the machine. We assume that the last argument in an instruction
603: * that branches is the branch address (or relative offset).
604: */
605: public Address nextaddr(startaddr, isnext)
606: Address startaddr;
607: boolean isnext;
608: {
609: Address addr;
610:
611: addr = usignal(process);
612: if (addr == 0 or addr == 1)
613: addr = findnextaddr(startaddr, isnext);
614: return (addr);
615: }
616:
617: /*
618: * Determine if it's ok to skip function f entered by instruction ins.
619: * If so, we're going to compute the return address and step to it.
620: */
621: private boolean skipfunc(ins, f)
622: Opcode ins;
623: Symbol f;
624: {
625:
626: return ((boolean) (!inst_tracing && nlhdr.nlines != 0 &&
627: nosource(curfunc) && canskip(curfunc)));
628: }
629:
630: private Address findnextaddr(startaddr, isnext)
631: Address startaddr;
632: Boolean isnext;
633: {
634: register Address addr;
635: Optab *op;
636: Opcode ins;
637: unsigned char mode;
638: int argtype, amode, argno, argval, nib;
639: String r;
640: Boolean indexf;
641: enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
642:
643: argval = 0;
644: indexf = false;
645: addr = startaddr;
646: iread(&ins, addr, sizeof(ins));
647: switch (ins) {
648:
649: case O_CALLF:
650: case O_CALLS:
651: addrstatus = KNOWN;
652: stepto(addr);
653: pstep(process, DEFSIG);
654: addr = reg(PROGCTR);
655: pc = addr;
656: setcurfunc(whatblock(pc));
657: if (not isbperr()) {
658: printstatus();
659: /* NOTREACHED */
660: }
661: bpact();
662: if (isnext or skipfunc(ins, curfunc)) {
663: addrstatus = KNOWN;
664: addr = return_addr();
665: stepto(addr);
666: bpact();
667: } else
668: callnews(/* iscall = */ true);
669: break;
670:
671: case O_RET:
672: addrstatus = KNOWN;
673: stepto(addr);
674: callnews(/* iscall = */ false);
675: pstep(process, DEFSIG);
676: addr = reg(PROGCTR);
677: pc = addr;
678: if (not isbperr())
679: printstatus();
680: bpact();
681: break;
682:
683: case O_BRB:
684: case O_BRW:
685: case O_JMP:
686: case O_BBSSI:
687: case O_BCC:
688: case O_BCS:
689: case O_BEQL:
690: case O_BGEQ:
691: case O_BGTR:
692: case O_BGTRU:
693: case O_BLEQ:
694: case O_BLEQU:
695: case O_BLSS:
696: case O_BNEQ:
697: case O_BVC:
698: case O_BVS:
699: case O_CASEL:
700: case O_AOBLSS:
701: case O_AOBLEQ:
702: addrstatus = KNOWN;
703: stepto(addr);
704: pstep(process, DEFSIG);
705: addr = reg(PROGCTR);
706: pc = addr;
707: if (not isbperr())
708: printstatus();
709: break;
710:
711: default:
712: addrstatus = SEQUENTIAL;
713: break;
714: }
715: if (addrstatus == KNOWN)
716: return (addr);
717: addr += 1;
718: op = ioptab[ins];
719: for (argno = 0; argno < op->numargs; argno++) {
720: if (indexf == true)
721: indexf = false;
722: argtype = op->argtype[argno];
723: if (is_branch_disp(argtype))
724: mode = 0xAF + (typelen(argtype) << 5);
725: else
726: iread(&mode, addr, sizeof(mode)), addr += 1;
727: r = regname[regnm(mode)];
728: amode = addrmode(mode);
729: switch (amode) {
730:
731: case LITSHORT:
732: case LITUPTO31:
733: case LITUPTO47:
734: case LITUPTO63:
735: argval = mode;
736: break;
737:
738: case INDEX:
739: indexf = true;
740: --argno;
741: break;
742:
743: case REG:
744: case REGDEF:
745: case AUTODEC:
746: break;
747:
748: case AUTOINC:
749: nib = mode & 0xf;
750: if (nib == 0xf || nib == 8 || nib == 9) {
751: int size = (mode&03)+1;
752:
753: argval = getdisp(addr, size,
754: regname[PROGCTR], amode);
755: addr += size;
756: }
757: break;
758:
759: case AUTOINCDEF:
760: if ((mode&0xf) != 0xf)
761: break;
762: argval = getdisp(addr, 4, r, amode);
763: addr += 4;
764: break;
765:
766: case BYTEDISP:
767: case BYTEDISPDEF:
768: argval = getdisp(addr, 1, r, amode);
769: addr += 1;
770: break;
771:
772: case WORDDISP:
773: case WORDDISPDEF:
774: argval = getdisp(addr, 2, r, amode);
775: addr += 2;
776: break;
777:
778: case LONGDISP:
779: case LONGDISPDEF:
780: argval = getdisp(addr, 4, r, amode);
781: addr += 4;
782: break;
783: }
784: }
785: if (ins == O_CALLF or ins == O_CALLS)
786: argval += 2;
787: if (addrstatus == BRANCH)
788: addr = argval;
789: return (addr);
790: }
791:
792: /*
793: * Get the displacement of an instruction that uses displacement addressing.
794: */
795: private int getdisp(addr, nbytes, reg, mode)
796: Address addr;
797: int nbytes;
798: String reg;
799: int mode;
800: {
801: char byte;
802: short hword;
803: int argval;
804:
805: switch (nbytes) {
806:
807: case 1:
808: iread(&byte, addr, sizeof(byte));
809: argval = byte;
810: break;
811:
812: case 2:
813: iread(&hword, addr, sizeof(hword));
814: argval = hword;
815: break;
816:
817: case 4:
818: iread(&argval, addr, sizeof(argval));
819: break;
820: }
821: if (reg == regname[PROGCTR] && mode >= BYTEDISP)
822: argval += addr + nbytes;
823: return (argval);
824: }
825:
826: #define BP_OP O_BPT /* breakpoint trap */
827: #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */
828:
829: /*
830: * Setting a breakpoint at a location consists of saving
831: * the word at the location and poking a BP_OP there.
832: *
833: * We save the locations and words on a list for use in unsetting.
834: */
835: typedef struct Savelist *Savelist;
836:
837: struct Savelist {
838: Address location;
839: Byte save;
840: Byte refcount;
841: Savelist link;
842: };
843:
844: private Savelist savelist;
845:
846: /*
847: * Set a breakpoint at the given address. Only save the word there
848: * if it's not already a breakpoint.
849: */
850: public setbp(addr)
851: Address addr;
852: {
853: Byte w, save;
854: register Savelist newsave, s;
855:
856: for (s = savelist; s != nil; s = s->link)
857: if (s->location == addr) {
858: s->refcount++;
859: return;
860: }
861: iread(&save, addr, sizeof(save));
862: newsave = new(Savelist);
863: newsave->location = addr;
864: newsave->save = save;
865: newsave->refcount = 1;
866: newsave->link = savelist;
867: savelist = newsave;
868: w = BP_OP;
869: iwrite(&w, addr, sizeof(w));
870: }
871:
872: /*
873: * Unset a breakpoint; unfortunately we have to search the SAVELIST
874: * to find the saved value. The assumption is that the SAVELIST will
875: * usually be quite small.
876: */
877: public unsetbp(addr)
878: Address addr;
879: {
880: register Savelist s, prev;
881:
882: prev = nil;
883: for (s = savelist; s != nil; s = s->link) {
884: if (s->location == addr) {
885: iwrite(&s->save, addr, sizeof(s->save));
886: s->refcount--;
887: if (s->refcount == 0) {
888: if (prev == nil)
889: savelist = s->link;
890: else
891: prev->link = s->link;
892: dispose(s);
893: }
894: return;
895: }
896: prev = s;
897: }
898: panic("unsetbp: couldn't find address %d", addr);
899: }
900:
901: /*
902: * Enter a procedure by creating and executing a call instruction.
903: */
904:
905: #define CALLSIZE 7 /* size of call instruction */
906:
907: public beginproc(p, argc)
908: Symbol p;
909: Integer argc;
910: {
911: char save[CALLSIZE];
912: struct {
913: Opcode op;
914: unsigned char numargs;
915: unsigned char mode;
916: char addr[sizeof(long)]; /* unaligned long */
917: } call;
918: long dest;
919:
920: if (4*argc+4 > 256)
921: error("too many parameters (max %d)", 256/4 - 1);
922: pc = 2;
923: iread(save, pc, sizeof(save));
924: call.op = O_CALLF;
925: call.numargs = 4*argc+4;
926: call.mode = 0xef; /* longword relative */
927: dest = codeloc(p) - 2 - (pc + CALLSIZE);
928: mov(&dest, call.addr, sizeof(call.addr));
929: iwrite(&call, pc, sizeof(call));
930: setreg(PROGCTR, pc);
931: pstep(process, DEFSIG);
932: iwrite(save, pc, sizeof(save));
933: pc = reg(PROGCTR);
934: if (not isbperr())
935: printstatus();
936: }
937:
938: /*
939: * Special variables for debugging the kernel.
940: */
941:
942: public integer masterpcbb;
943: public integer slr;
944: public struct pte *sbr;
945: private struct pcb pcb;
946:
947: public getpcb ()
948: {
949: fseek(corefile, masterpcbb & ~0xc0000000, 0);
950: get(corefile, pcb);
951: printf("p0br %lx p0lr %lx p2br %lx p2lr %lx\n",
952: pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p2br, pcb.pcb_p2lr
953: );
954: setreg(0, pcb.pcb_r0);
955: setreg(1, pcb.pcb_r1);
956: setreg(2, pcb.pcb_r2);
957: setreg(3, pcb.pcb_r3);
958: setreg(4, pcb.pcb_r4);
959: setreg(5, pcb.pcb_r5);
960: setreg(6, pcb.pcb_r6);
961: setreg(7, pcb.pcb_r7);
962: setreg(8, pcb.pcb_r8);
963: setreg(9, pcb.pcb_r9);
964: setreg(10, pcb.pcb_r10);
965: setreg(11, pcb.pcb_r11);
966: setreg(12, pcb.pcb_r12);
967: setreg(FRP, pcb.pcb_fp);
968: setreg(STKP, pcb.pcb_ksp);
969: setreg(PROGCTR, pcb.pcb_pc);
970: }
971:
972: public copyregs (savreg, reg)
973: Word savreg[], reg[];
974: {
975: reg[0] = savreg[R0];
976: reg[1] = savreg[R1];
977: reg[2] = savreg[R2];
978: reg[3] = savreg[R3];
979: reg[4] = savreg[R4];
980: reg[5] = savreg[R5];
981: reg[6] = savreg[R6];
982: reg[7] = savreg[R7];
983: reg[8] = savreg[R8];
984: reg[9] = savreg[R9];
985: reg[10] = savreg[R10];
986: reg[11] = savreg[R11];
987: reg[12] = savreg[R12];
988: reg[FRP] = savreg[FP];
989: reg[STKP] = savreg[SP];
990: reg[PROGCTR] = savreg[PC];
991: }
992:
993: /*
994: * Map a virtual address to a physical address.
995: */
996:
997: public Address vmap (addr)
998: Address addr;
999: {
1000: int oldaddr = addr, v;
1001: struct pte pte;
1002:
1003: addr &= ~0xc0000000;
1004: v = btop(addr);
1005: switch (oldaddr&0xc0000000) {
1006:
1007: case 0xc0000000:
1008: /*
1009: * In system space get system pte. If
1010: * valid or reclaimable then physical address
1011: * is combination of its page number and the page
1012: * offset of the original address.
1013: */
1014: if (v >= slr)
1015: goto oor;
1016: addr = ((long)(sbr+v)) &~ 0xc0000000;
1017: goto simple;
1018:
1019: case 0x80000000:
1020: /*
1021: * In p2 spce must not be in shadow region.
1022: */
1023: if (v < pcb.pcb_p2lr)
1024: goto oor;
1025: addr = (long)(pcb.pcb_p2br+v);
1026: break;
1027:
1028: case 0x40000000:
1029: /*
1030: * In p1 space everything is verboten (for now).
1031: */
1032: goto oor;
1033:
1034: case 0x00000000:
1035: /*
1036: * In p0 space must not be off end of region.
1037: */
1038: if (v >= pcb.pcb_p0lr)
1039: goto oor;
1040: addr = (long)(pcb.pcb_p0br+v);
1041: break;
1042: oor:
1043: error("address out of segment");
1044: }
1045: /*
1046: * For p0/p1/p2 address, user-level page table should
1047: * be in kernel vm. Do second-level indirect by recursing.
1048: */
1049: if ((addr & 0xc0000000) != 0xc0000000)
1050: error("bad p0br, p1br, or p2br in pcb");
1051: addr = vmap(addr);
1052: simple:
1053: /*
1054: * Addr is now address of the pte of the page we
1055: * are interested in; get the pte and paste up the
1056: * physical address.
1057: */
1058: fseek(corefile, addr, 0);
1059: if (fread(&pte, sizeof (pte), 1, corefile) != 1)
1060: error("page table botch");
1061: /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
1062: if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0))
1063: error("page not valid/reclaimable");
1064: return ((long)(ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)));
1065: }
1066:
1067: /*
1068: * Extract a bit field from an integer.
1069: */
1070:
1071: public integer extractField (s)
1072: Symbol s;
1073: {
1074: integer nbytes, nbits, n, r, off, len;
1075:
1076: off = s->symvalue.field.offset;
1077: len = s->symvalue.field.length;
1078: nbytes = size(s);
1079: n = 0;
1080: if (nbytes > sizeof(n)) {
1081: printf("[bad size in extractField -- word assumed]\n");
1082: nbytes = sizeof(n);
1083: }
1084: popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
1085: nbits = nbytes * BITSPERBYTE;
1086: r = n >> (nbits - ((off mod nbits) + len));
1087: r &= ((1 << len) - 1);
1088: return r;
1089: }
1090:
1091: /*
1092: * Change the length of a value in memory according to a given difference
1093: * in the lengths of its new and old types.
1094: */
1095:
1096: public loophole (oldlen, newlen)
1097: integer oldlen, newlen;
1098: {
1099: integer i, n;
1100: Stack *oldsp;
1101:
1102: n = newlen - oldlen;
1103: oldsp = sp - oldlen;
1104: if (n > 0) {
1105: for (i = oldlen - 1; i >= 0; i--) {
1106: oldsp[n + i] = oldsp[i];
1107: }
1108: for (i = 0; i < n; i++) {
1109: oldsp[i] = '\0';
1110: }
1111: } else {
1112: for (i = 0; i < newlen; i++) {
1113: oldsp[i] = oldsp[i - n];
1114: }
1115: }
1116: sp += n;
1117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.