|
|
1.1 root 1: /*
2: * Copyright (c) 1983 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[] = "@(#)runtime.sun.c 5.2 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Runtime organization dependent routines, mostly dealing with
26: * activation records.
27: */
28:
29: #include "defs.h"
30: #include "runtime.h"
31: #include "process.h"
32: #include "machine.h"
33: #include "events.h"
34: #include "mappings.h"
35: #include "symbols.h"
36: #include "tree.h"
37: #include "eval.h"
38: #include "operators.h"
39: #include "object.h"
40: #include <sys/param.h>
41: #include <signal.h>
42:
43: #ifndef public
44: typedef struct Frame *Frame;
45:
46: #include "machine.h"
47: #endif
48:
49: #define NSAVEREG 14
50:
51: struct Frame {
52: Address save_fp; /* frame pointer */
53: Address save_pc; /* program counter */
54: Word save_reg[NSAVEREG]; /* not necessarily there */
55: integer nargwords; /* computed, not stored */
56: };
57:
58: private Frame curframe = nil;
59: private struct Frame curframerec;
60: private Boolean walkingstack = false;
61:
62: #define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp)
63:
64: private boolean inSignalHandler (addr)
65: Address addr;
66: {
67: Symbol f;
68:
69: #ifdef IRIS
70: return false;
71: #else /* sun */
72: f = whatblock(addr);
73: return (boolean) (f != nil and streq(symname(f), "_sigtramp"));
74: #endif
75: }
76:
77: typedef struct {
78: Node callnode;
79: Node cmdnode;
80: boolean isfunc;
81: } CallEnv;
82:
83: private CallEnv endproc;
84:
85: /*
86: * Set a frame to the current activation record.
87: */
88:
89: private getcurframe(frp)
90: Frame frp;
91: {
92: register int i;
93:
94: checkref(frp);
95: frp->save_fp = reg(FRP);
96: frp->save_pc = reg(PROGCTR);
97: for (i = 0; i < NSAVEREG; i++) {
98: frp->save_reg[i] = reg(i);
99: }
100: if (frp->save_fp == nil) {
101: frp->nargwords = 0;
102: } else {
103: findnumargs(frp);
104: }
105: }
106:
107: /*
108: * Get the saved registers from one frame to another
109: * given mask specifying which registers were actually saved.
110: */
111:
112: #define bis(b, n) ((b & (1 << (n))) != 0)
113:
114: private getsaveregs (newfrp, frp, mask)
115: Frame newfrp, frp;
116: integer mask;
117: {
118: integer i, j;
119:
120: j = 0;
121: for (i = 0; i < NSAVEREG; i++) {
122: if (bis(mask, i)) {
123: newfrp->save_reg[i] = frp->save_reg[j];
124: ++j;
125: }
126: }
127: }
128:
129: /*
130: * Return a pointer to the next activation record up the stack.
131: * Return nil if there is none.
132: * Writes over space pointed to by given argument.
133: */
134:
135: private Frame nextframe(frp)
136: Frame frp;
137: {
138: Frame newfrp;
139: struct Frame frame;
140: integer mask;
141: Address prev_frame, callpc, higher_fp, higher_pc;
142: static integer ntramp = 0;
143:
144: newfrp = frp;
145: prev_frame = frp->save_fp;
146:
147: /*
148: * The check for interrupt generated frames is taken from adb with only
149: * partial understanding. If you're in "sub" and on a sigxxx "sigsub"
150: * gets control, then the stack does NOT look like <main, sub, sigsub>.
151: *
152: * As best I can make out it looks like:
153: *
154: * <main, (machine check exception block + sub), sysframe, sigsub>.
155: *
156: * When the signal occurs an exception block and a frame for the routine
157: * in which it occured are pushed on the user stack. Then another frame
158: * is pushed corresponding to a call from the kernel to sigsub.
159: *
160: * The addr in sub at which the exception occured is not in sub.save_pc
161: * but in the machine check exception block. It is at the magic address
162: * fp + 84.
163: *
164: * The current approach ignores the sys_frame (what adb reports as sigtramp)
165: * and takes the pc for sub from the exception block. This allows the
166: * "where" command to report <main, sub, sigsub>, which seems reasonable.
167: */
168:
169: nextf:
170: if (prev_frame + sizeof(struct Frame) <= USRSTACK) {
171: dread(&frame, prev_frame, sizeof(struct Frame));
172: } else if (USRSTACK - prev_frame > 2 * sizeof(Word)) {
173: dread(&frame, prev_frame, USRSTACK - prev_frame);
174: } else {
175: frame.save_fp = nil;
176: }
177: if (ntramp == 1) {
178: dread(&callpc, prev_frame + 92, sizeof(callpc));
179: } else {
180: callpc = frame.save_pc;
181: }
182: if (frame.save_fp == nil or frame.save_pc == (Address) -1) {
183: newfrp = nil;
184: } else {
185: if (inSignalHandler(callpc)) {
186: # ifdef sun
187: Address scp;
188:
189: dread(&scp, prev_frame + 16, sizeof(scp));
190: dread(&callpc,
191: &(((struct sigcontext *)scp)->sc_pc), sizeof(Word)
192: );
193: # endif /* sun */
194: }
195: frame.save_pc = callpc;
196: ntramp = 0;
197: higher_fp = frp->save_fp;
198: higher_pc = frp->save_pc;
199: newfrp->save_fp = frame.save_fp;
200: newfrp->save_pc = frame.save_pc;
201: findnumargs(newfrp);
202: findsavedregs(newfrp, higher_fp, higher_pc);
203: }
204: return newfrp;
205: }
206:
207: /*
208: * Finding the saved registers and number of arguments passed to
209: * the current procedure is painful for the 68000.
210: *
211: * This is a version of the way adb for the 68000 does this.
212: */
213:
214: #define HIWORD 0xffff0000
215: #define LOWORD 0x0000ffff
216: #define LINKA6 0x4e560000 /* link a6,#x */
217: #define ADDLSP 0xdffc0000 /* addl #x,sp */
218: #define ADDWSP 0xdefc0000 /* addw #x,sp */
219: #define LEASP 0x4fef0000 /* lea sp@(x),sp*/
220: #define TSTBSP 0x4a2f0000 /* tstb sp@(x) */
221: #define INSMSK 0xfff80000
222: #define MOVLSP 0x2e800000 /* movl dx,sp@ */
223: #define MOVLD0 0x20000000 /* movl d0,dx */
224: #define MOVLA0 0x20400000 /* movl d0,ax */
225: #define MVLMSK 0xf1ff0000
226: #define MOVEML 0x48d70000 /* moveml #x,sp@ */
227: #define JSR 0x4eb80000 /* jsr x.[WL] */
228: #define JSRPC 0x4eba0000 /* jsr PC@( ) */
229: #define LONGBIT 0x00010000
230: #define BSR 0x61000000 /* bsr x */
231: #define BYTE3 0x0000ff00
232: #define LOBYTE 0x000000ff
233: #define ADQMSK 0xf1ff0000
234: #define ADDQSP 0x508f0000 /* addql #x,sp */
235: #define ADDQWSP 0x504f0000 /* addqw #x,sp */
236:
237: private int savedregsmask;
238: private int savedregp;
239:
240: /*
241: * Find out how many words of arguments were passed to
242: * the current procedure.
243: */
244:
245: private findnumargs (newfrp)
246: Frame newfrp;
247: {
248: integer val;
249: integer instruc;
250: Address addr;
251:
252: dread(&addr, newfrp->save_fp + sizeof(Address), sizeof(addr));
253: iread(&instruc, addr, sizeof(instruc));
254: if ((instruc&MVLMSK) == MOVLA0 or (instruc&MVLMSK) == MOVLD0) {
255: addr += 2;
256: iread(&instruc, addr, sizeof(instruc));
257: }
258: if ((instruc&ADQMSK) == ADDQSP or (instruc&ADQMSK) == ADDQWSP){
259: val = (instruc >> (16+9)) & 07;
260: if (val == 0) {
261: val = 8;
262: }
263: } else if ((instruc&HIWORD) == ADDLSP){
264: iread(&val, addr + 2, sizeof(val));
265: } else if ((instruc&HIWORD) == ADDWSP || (instruc&HIWORD) == LEASP){
266: val = instruc&LOWORD;
267: } else {
268: val = 0;
269: }
270: newfrp->nargwords = val / sizeof(Word);
271: }
272:
273: /*
274: * Get the saved registers for the given Frame.
275: */
276:
277: private findsavedregs (newfrp, higher_fp, higher_pc)
278: Frame newfrp;
279: register Address higher_fp, higher_pc;
280: {
281: int val, regp, i;
282: Address addr;
283: Symbol func;
284: Address calladdr;
285: int instruc;
286:
287: /*
288: * Find the entry point of the current procedure.
289: * This is done by finding the procedure for the higher frame's pc
290: * and taking its starting address.
291: */
292: func = whatblock(higher_pc, true);
293: calladdr = codeloc(func) - FUNCOFFSET;
294:
295: /*
296: * Look at the entry code for the current procedure
297: * to determine which registers were saved, and where they are.
298: *
299: * First find the size of the activation record.
300: */
301: addr = calladdr;
302: iread(&instruc, addr, sizeof(instruc));
303: if ((instruc&HIWORD) == LINKA6) {
304: if ((instruc &= LOWORD) == 0) {
305: /* look for addl */
306: addr += 4;
307: iread(&instruc, addr, sizeof(instruc));
308: if ((instruc&HIWORD) == ADDLSP) {
309: iread(&instruc, addr + 2, sizeof(instruc));
310: addr += 6;
311: } else {
312: instruc = 0;
313: }
314: } else {
315: /* link offset was non-zero -- sign extend it */
316: instruc <<= 16;
317: instruc >>= 16;
318: }
319: /* we now have the negative frame size */
320: regp = higher_fp + instruc;
321: savedregp = regp;
322: }
323:
324: /*
325: * Now find which registers were saved.
326: * (expecting a probe instruction next)
327: */
328: iread(&instruc, addr, sizeof(instruc));
329: if ((instruc&HIWORD) == TSTBSP) {
330: addr += 4;
331: iread(&instruc, addr, sizeof(instruc));
332: }
333: /*
334: * expect either a moveml or a movl next
335: */
336: if ((instruc&INSMSK) == MOVLSP){
337: /*
338: * Only one register saved.
339: */
340: i = (instruc>>16) & 07;
341: dread(&(newfrp->save_reg[i]), regp, sizeof(Word));
342: savedregsmask = 1 << i;
343: } else if ((instruc&HIWORD) == MOVEML) {
344: /*
345: * Saving multiple registers or unoptimized code
346: */
347: val = instruc & LOWORD;
348: savedregsmask = val;
349: i = 0;
350: while (val != 0) {
351: if (val&1) {
352: dread(&(newfrp->save_reg[i]), regp, sizeof(Word));
353: regp += sizeof(Word);
354: }
355: val >>= 1;
356: ++i;
357: }
358: } else {
359: savedregsmask = 0;
360: }
361: }
362:
363: /*
364: * Get the current frame information in the given Frame and store the
365: * associated function in the given value-result parameter.
366: */
367:
368: private getcurfunc (frp, fp)
369: Frame frp;
370: Symbol *fp;
371: {
372: getcurframe(frp);
373: *fp = whatblock(frp->save_pc);
374: }
375:
376: /*
377: * Return the frame associated with the next function up the call stack, or
378: * nil if there is none. The function is returned in a value-result parameter.
379: * For "inline" functions the statically outer function and same frame
380: * are returned.
381: */
382:
383: public Frame nextfunc (frp, fp)
384: Frame frp;
385: Symbol *fp;
386: {
387: Symbol t;
388: Frame nfrp;
389:
390: t = *fp;
391: checkref(t);
392: if (isinline(t)) {
393: t = container(t);
394: nfrp = frp;
395: } else {
396: nfrp = nextframe(frp);
397: if (nfrp == nil) {
398: t = nil;
399: } else {
400: t = whatblock(nfrp->save_pc);
401: }
402: }
403: *fp = t;
404: return nfrp;
405: }
406:
407: /*
408: * Return the frame associated with the given function.
409: * If the function is nil, return the most recently activated frame.
410: *
411: * Static allocation for the frame.
412: */
413:
414: public Frame findframe(f)
415: Symbol f;
416: {
417: Frame frp;
418: static struct Frame frame;
419: Symbol p;
420: Boolean done;
421:
422: frp = &frame;
423: getcurframe(frp);
424: if (f != nil) {
425: if (f == curfunc and curframe != nil) {
426: *frp = *curframe;
427: } else {
428: done = false;
429: p = whatblock(frp->save_pc);
430: do {
431: if (p == f) {
432: done = true;
433: } else if (p == program) {
434: done = true;
435: frp = nil;
436: } else {
437: frp = nextfunc(frp, &p);
438: if (frp == nil) {
439: done = true;
440: }
441: }
442: } while (not done);
443: }
444: }
445: return frp;
446: }
447:
448: /*
449: * Set the registers according to the given frame pointer.
450: */
451:
452: public getnewregs (addr)
453: Address addr;
454: {
455: struct Frame frame;
456: integer i, j, mask;
457:
458: dread(&frame, addr, sizeof(frame));
459: setreg(FRP, frame.save_fp);
460: setreg(PROGCTR, frame.save_pc);
461: pc = frame.save_pc;
462: setcurfunc(whatblock(pc));
463: }
464:
465: /*
466: * Find the return address of the current procedure/function.
467: */
468:
469: public Address return_addr()
470: {
471: Frame frp;
472: Address addr;
473: struct Frame frame;
474:
475: frp = &frame;
476: getcurframe(frp);
477: frp = nextframe(frp);
478: if (frp == nil) {
479: addr = 0;
480: } else {
481: addr = frp->save_pc;
482: }
483: return addr;
484: }
485:
486: /*
487: * Push the value associated with the current function.
488: */
489:
490: public pushretval(len, isindirect)
491: integer len;
492: boolean isindirect;
493: {
494: Word r0;
495:
496: r0 = reg(0);
497: if (isindirect) {
498: rpush((Address) r0, len);
499: } else {
500: switch (len) {
501: case sizeof(char):
502: push(char, r0);
503: break;
504:
505: case sizeof(short):
506: push(short, r0);
507: break;
508:
509: default:
510: if (len == sizeof(Word)) {
511: push(Word, r0);
512: } else if (len == 2*sizeof(Word)) {
513: push(Word, r0);
514: push(Word, reg(1));
515: } else {
516: error("[internal error: bad size %d in pushretval]", len);
517: }
518: break;
519: }
520: }
521: }
522:
523: /*
524: * Return the base address for locals in the given frame.
525: */
526:
527: public Address locals_base(frp)
528: Frame frp;
529: {
530: return (frp == nil) ? reg(FRP) : frp->save_fp;
531: }
532:
533: /*
534: * Return the base address for arguments in the given frame.
535: */
536:
537: public Address args_base(frp)
538: Frame frp;
539: {
540: return (frp == nil) ? reg(FRP) : frp->save_fp;
541: }
542:
543: /*
544: * Return saved register n from the given frame.
545: */
546:
547: public Word savereg(n, frp)
548: integer n;
549: Frame frp;
550: {
551: Word w;
552:
553: if (frp == nil) {
554: w = reg(n);
555: } else {
556: switch (n) {
557: case FRP:
558: w = frp->save_fp;
559: break;
560:
561: case STKP:
562: w = reg(STKP);
563: break;
564:
565: case PROGCTR:
566: w = frp->save_pc;
567: break;
568:
569: default:
570: assert(n >= 0 and n < NSAVEREG);
571: w = frp->save_reg[n];
572: break;
573: }
574: }
575: return w;
576: }
577:
578: /*
579: * Return the nth argument to the current procedure.
580: */
581:
582: public Word argn(n, frp)
583: integer n;
584: Frame frp;
585: {
586: Address argaddr;
587: Word w;
588:
589: argaddr = args_base(frp) + 4 + (n * sizeof(Word));
590: dread(&w, argaddr, sizeof(w));
591: return w;
592: }
593:
594: /*
595: * Return the number of words of arguments passed to the procedure
596: * associated with the given frame (it's a macro for the VAX).
597: */
598:
599: public integer nargspassed (frp)
600: Frame frp;
601: {
602: integer n;
603: struct Frame frame;
604:
605: if (frp == nil) {
606: getcurframe(&frame);
607: n = frame.nargwords;
608: } else {
609: n = frp->nargwords;
610: }
611: return n;
612: }
613:
614: /*
615: * Print a list of currently active blocks starting with most recent.
616: */
617:
618: public wherecmd()
619: {
620: walkstack(false);
621: }
622:
623: /*
624: * Print the variables in the given frame or the current one if nil.
625: */
626:
627: public dump (func)
628: Symbol func;
629: {
630: Symbol f;
631: Frame frp;
632:
633: if (func == nil) {
634: f = curfunc;
635: if (curframe != nil) {
636: frp = curframe;
637: } else {
638: frp = findframe(f);
639: }
640: } else {
641: f = func;
642: frp = findframe(f);
643: }
644: showaggrs = true;
645: printcallinfo(f, frp);
646: dumpvars(f, frp);
647: }
648:
649: /*
650: * Dump all values.
651: */
652:
653: public dumpall ()
654: {
655: walkstack(true);
656: }
657:
658: /*
659: * Walk the stack of active procedures printing information
660: * about each active procedure.
661: */
662:
663: private walkstack(dumpvariables)
664: Boolean dumpvariables;
665: {
666: Frame frp;
667: boolean save;
668: Symbol f;
669: struct Frame frame;
670:
671: if (notstarted(process) or isfinished(process)) {
672: error("program is not active");
673: } else {
674: save = walkingstack;
675: walkingstack = true;
676: showaggrs = dumpvariables;
677: frp = &frame;
678: getcurfunc(frp, &f);
679: for (;;) {
680: printcallinfo(f, frp);
681: if (dumpvariables) {
682: dumpvars(f, frp);
683: putchar('\n');
684: }
685: frp = nextfunc(frp, &f);
686: if (frp == nil or f == program) {
687: break;
688: }
689: }
690: if (dumpvariables) {
691: printf("in \"%s\":\n", symname(program));
692: dumpvars(program, nil);
693: putchar('\n');
694: }
695: walkingstack = save;
696: }
697: }
698:
699: /*
700: * Print out the information about a call, i.e.,
701: * routine name, parameter values, and source location.
702: */
703:
704: private printcallinfo (f, frp)
705: Symbol f;
706: Frame frp;
707: {
708: Lineno line;
709: Address savepc;
710:
711: savepc = frp->save_pc;
712: if (frp->save_fp != reg(FRP)) {
713: savepc -= 1;
714: }
715: printname(stdout, f);
716: if (not isinline(f)) {
717: printparams(f, frp);
718: }
719: line = srcline(savepc);
720: if (line != 0) {
721: printf(", line %d", line);
722: printf(" in \"%s\"\n", srcfilename(savepc));
723: } else {
724: printf(" at 0x%x\n", savepc);
725: }
726: }
727:
728: /*
729: * Set the current function to the given symbol.
730: * We must adjust "curframe" so that subsequent operations are
731: * not confused; for simplicity we simply clear it.
732: */
733:
734: public setcurfunc (f)
735: Symbol f;
736: {
737: curfunc = f;
738: curframe = nil;
739: }
740:
741: /*
742: * Return the frame for the current function.
743: * The space for the frame is allocated statically.
744: */
745:
746: public Frame curfuncframe ()
747: {
748: static struct Frame frame;
749: Frame frp;
750:
751: if (curframe == nil) {
752: frp = findframe(curfunc);
753: curframe = &curframerec;
754: *curframe = *frp;
755: } else {
756: frp = &frame;
757: *frp = *curframe;
758: }
759: return frp;
760: }
761:
762: /*
763: * Set curfunc to be N up/down the stack from its current value.
764: */
765:
766: public up (n)
767: integer n;
768: {
769: integer i;
770: Symbol f;
771: Frame frp;
772: boolean done;
773:
774: if (not isactive(program)) {
775: error("program is not active");
776: } else if (curfunc == nil) {
777: error("no current function");
778: } else {
779: i = 0;
780: f = curfunc;
781: frp = curfuncframe();
782: done = false;
783: do {
784: if (frp == nil) {
785: done = true;
786: error("not that many levels");
787: } else if (i >= n) {
788: done = true;
789: curfunc = f;
790: curframe = &curframerec;
791: *curframe = *frp;
792: showaggrs = false;
793: printcallinfo(curfunc, curframe);
794: } else if (f == program) {
795: done = true;
796: error("not that many levels");
797: } else {
798: frp = nextfunc(frp, &f);
799: }
800: ++i;
801: } while (not done);
802: }
803: }
804:
805: public down (n)
806: integer n;
807: {
808: integer i, depth;
809: Frame frp, curfrp;
810: Symbol f;
811: struct Frame frame;
812:
813: if (not isactive(program)) {
814: error("program is not active");
815: } else if (curfunc == nil) {
816: error("no current function");
817: } else {
818: depth = 0;
819: frp = &frame;
820: getcurfunc(frp, &f);
821: if (curframe == nil) {
822: curfrp = findframe(curfunc);
823: curframe = &curframerec;
824: *curframe = *curfrp;
825: }
826: while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) {
827: frp = nextfunc(frp, &f);
828: ++depth;
829: }
830: if (f == nil or n > depth) {
831: error("not that many levels");
832: } else {
833: depth -= n;
834: frp = &frame;
835: getcurfunc(frp, &f);
836: for (i = 0; i < depth; i++) {
837: frp = nextfunc(frp, &f);
838: assert(frp != nil);
839: }
840: curfunc = f;
841: *curframe = *frp;
842: showaggrs = false;
843: printcallinfo(curfunc, curframe);
844: }
845: }
846: }
847:
848: /*
849: * Find the entry point of a procedure or function.
850: */
851:
852: public findbeginning (f)
853: Symbol f;
854: {
855: if (isinternal(f)) {
856: f->symvalue.funcv.beginaddr += 18; /* VAX only */
857: } else {
858: /* on 68000's don't add for beginning of program */
859: if (f->symvalue.funcv.beginaddr != CODESTART) {
860: f->symvalue.funcv.beginaddr += FUNCOFFSET;
861: }
862: }
863: }
864:
865: /*
866: * Return the address corresponding to the first line in a function.
867: */
868:
869: public Address firstline(f)
870: Symbol f;
871: {
872: Address addr;
873:
874: addr = codeloc(f);
875: while (linelookup(addr) == 0 and addr < objsize) {
876: ++addr;
877: }
878: if (addr == objsize) {
879: addr = -1;
880: }
881: return addr;
882: }
883:
884: /*
885: * Catcher drops strike three ...
886: */
887:
888: public runtofirst()
889: {
890: Address addr, endaddr;
891:
892: addr = pc;
893: endaddr = objsize + CODESTART;
894: while (linelookup(addr) == 0 and addr < endaddr) {
895: ++addr;
896: }
897: if (addr < endaddr) {
898: stepto(addr);
899: }
900: }
901:
902: /*
903: * Return the address corresponding to the end of the program.
904: *
905: * We look for the entry to "exit".
906: */
907:
908: public Address lastaddr()
909: {
910: Symbol s;
911:
912: s = lookup(identname("exit", true));
913: if (s == nil) {
914: panic("can't find exit");
915: }
916: return codeloc(s);
917: }
918:
919: /*
920: * Decide if the given function is currently active.
921: *
922: * We avoid calls to "findframe" during a stack trace for efficiency.
923: * Presumably information evaluated while walking the stack is active.
924: */
925:
926: public Boolean isactive (f)
927: Symbol f;
928: {
929: Boolean b;
930:
931: if (isfinished(process)) {
932: b = false;
933: } else {
934: if (walkingstack or f == program or f == nil or
935: (ismodule(f) and isactive(container(f)))) {
936: b = true;
937: } else {
938: b = (Boolean) (findframe(f) != nil);
939: }
940: }
941: return b;
942: }
943:
944: /*
945: * Evaluate a call to a procedure.
946: */
947:
948: public callproc(exprnode, isfunc)
949: Node exprnode;
950: boolean isfunc;
951: {
952: Node procnode, arglist;
953: Symbol proc;
954: integer argc;
955:
956: procnode = exprnode->value.arg[0];
957: arglist = exprnode->value.arg[1];
958: if (procnode->op != O_SYM) {
959: beginerrmsg();
960: fprintf(stderr, "can't call \"");
961: prtree(stderr, procnode);
962: fprintf(stderr, "\"");
963: enderrmsg();
964: }
965: assert(procnode->op == O_SYM);
966: proc = procnode->value.sym;
967: if (not isblock(proc)) {
968: error("\"%s\" is not a procedure or function", symname(proc));
969: }
970: endproc.isfunc = isfunc;
971: endproc.callnode = exprnode;
972: endproc.cmdnode = topnode;
973: pushenv();
974: pc = codeloc(proc);
975: argc = pushargs(proc, arglist);
976: setreg(FRP, 1); /* have to ensure it's non-zero for return_addr() */
977: beginproc(proc, argc);
978: event_once(
979: build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)),
980: buildcmdlist(build(O_PROCRTN, proc))
981: );
982: isstopped = false;
983: if (not bpact()) {
984: isstopped = true;
985: cont(0);
986: }
987: /*
988: * bpact() won't return true, it will call printstatus() and go back
989: * to command input if a breakpoint is found.
990: */
991: /* NOTREACHED */
992: }
993:
994: /*
995: * Push the arguments on the process' stack. We do this by first
996: * evaluating them on the "eval" stack, then copying into the process'
997: * space.
998: */
999:
1000: private integer pushargs(proc, arglist)
1001: Symbol proc;
1002: Node arglist;
1003: {
1004: Stack *savesp;
1005: int argc, args_size;
1006:
1007: savesp = sp;
1008: if (varIsSet("$unsafecall")) {
1009: argc = unsafe_evalargs(proc, arglist);
1010: } else {
1011: argc = evalargs(proc, arglist);
1012: }
1013: args_size = sp - savesp;
1014: setreg(STKP, reg(STKP) - args_size);
1015: dwrite(savesp, reg(STKP), args_size);
1016: sp = savesp;
1017: return argc;
1018: }
1019:
1020: /*
1021: * Check to see if an expression is correct for a given parameter.
1022: * If the given parameter is false, don't worry about type inconsistencies.
1023: *
1024: * Return whether or not it is ok.
1025: */
1026:
1027: private boolean chkparam (actual, formal, chk)
1028: Node actual;
1029: Symbol formal;
1030: boolean chk;
1031: {
1032: boolean b;
1033:
1034: b = true;
1035: if (chk) {
1036: if (formal == nil) {
1037: beginerrmsg();
1038: fprintf(stderr, "too many parameters");
1039: b = false;
1040: } else if (not compatible(formal->type, actual->nodetype)) {
1041: beginerrmsg();
1042: fprintf(stderr, "type mismatch for %s", symname(formal));
1043: b = false;
1044: }
1045: }
1046: if (b and formal != nil and
1047: isvarparam(formal) and not isopenarray(formal->type) and
1048: not (
1049: actual->op == O_RVAL or actual->nodetype == t_addr or
1050: (
1051: actual->op == O_TYPERENAME and
1052: (
1053: actual->value.arg[0]->op == O_RVAL or
1054: actual->value.arg[0]->nodetype == t_addr
1055: )
1056: )
1057: )
1058: ) {
1059: beginerrmsg();
1060: fprintf(stderr, "expected variable, found \"");
1061: prtree(stderr, actual);
1062: fprintf(stderr, "\"");
1063: b = false;
1064: }
1065: return b;
1066: }
1067:
1068: /*
1069: * Pass an expression to a particular parameter.
1070: *
1071: * Normally we pass either the address or value, but in some cases
1072: * (such as C strings) we want to copy the value onto the stack and
1073: * pass its address.
1074: *
1075: * Another special case raised by strings is the possibility that
1076: * the actual parameter will be larger than the formal, even with
1077: * appropriate type-checking. This occurs because we assume during
1078: * evaluation that strings are null-terminated, whereas some languages,
1079: * notably Pascal, do not work under that assumption.
1080: */
1081:
1082: private passparam (actual, formal)
1083: Node actual;
1084: Symbol formal;
1085: {
1086: boolean b;
1087: Address addr;
1088: Stack *savesp;
1089: integer actsize, formsize;
1090:
1091: if (formal != nil and isvarparam(formal) and
1092: (not isopenarray(formal->type))
1093: ) {
1094: addr = lval(actual->value.arg[0]);
1095: push(Address, addr);
1096: } else if (passaddr(formal, actual->nodetype)) {
1097: savesp = sp;
1098: eval(actual);
1099: actsize = sp - savesp;
1100: setreg(STKP,
1101: reg(STKP) - ((actsize + sizeof(Word) - 1) & ~(sizeof(Word) - 1))
1102: );
1103: dwrite(savesp, reg(STKP), actsize);
1104: sp = savesp;
1105: push(Address, reg(STKP));
1106: if (formal != nil and isopenarray(formal->type)) {
1107: push(integer, actsize div size(formal->type->type));
1108: }
1109: } else if (formal != nil) {
1110: formsize = size(formal);
1111: savesp = sp;
1112: eval(actual);
1113: actsize = sp - savesp;
1114: if (actsize > formsize) {
1115: sp -= (actsize - formsize);
1116: }
1117: } else {
1118: eval(actual);
1119: }
1120: }
1121:
1122: /*
1123: * Evaluate an argument list left-to-right.
1124: */
1125:
1126: private integer evalargs(proc, arglist)
1127: Symbol proc;
1128: Node arglist;
1129: {
1130: Node p, actual;
1131: Symbol formal;
1132: Stack *savesp;
1133: integer count;
1134: boolean chk;
1135:
1136: savesp = sp;
1137: count = 0;
1138: formal = proc->chain;
1139: chk = (boolean) (not nosource(proc));
1140: for (p = arglist; p != nil; p = p->value.arg[1]) {
1141: assert(p->op == O_COMMA);
1142: actual = p->value.arg[0];
1143: if (not chkparam(actual, formal, chk)) {
1144: fprintf(stderr, " in call to %s", symname(proc));
1145: sp = savesp;
1146: enderrmsg();
1147: }
1148: passparam(actual, formal);
1149: if (formal != nil) {
1150: formal = formal->chain;
1151: }
1152: ++count;
1153: }
1154: if (chk) {
1155: if (formal != nil) {
1156: sp = savesp;
1157: error("not enough parameters to %s", symname(proc));
1158: }
1159: }
1160: return count;
1161: }
1162:
1163: /*
1164: * Evaluate an argument list without any type checking.
1165: * This is only useful for procedures with a varying number of
1166: * arguments that are compiled -g.
1167: */
1168:
1169: private integer unsafe_evalargs (proc, arglist)
1170: Symbol proc;
1171: Node arglist;
1172: {
1173: Node p;
1174: integer count;
1175:
1176: count = 0;
1177: for (p = arglist; p != nil; p = p->value.arg[1]) {
1178: assert(p->op == O_COMMA);
1179: eval(p->value.arg[0]);
1180: ++count;
1181: }
1182: return count;
1183: }
1184:
1185: public procreturn(f)
1186: Symbol f;
1187: {
1188: integer retvalsize;
1189: Node tmp;
1190: char *copy;
1191:
1192: flushoutput();
1193: popenv();
1194: if (endproc.isfunc) {
1195: retvalsize = size(f->type);
1196: if (retvalsize > sizeof(long)) {
1197: pushretval(retvalsize, true);
1198: copy = newarr(char, retvalsize);
1199: popn(retvalsize, copy);
1200: tmp = build(O_SCON, copy);
1201: } else {
1202: tmp = build(O_LCON, (long) (reg(0)));
1203: }
1204: tmp->nodetype = f->type;
1205: tfree(endproc.callnode);
1206: *(endproc.callnode) = *(tmp);
1207: dispose(tmp);
1208: eval(endproc.cmdnode);
1209: } else {
1210: putchar('\n');
1211: printname(stdout, f);
1212: printf(" returns successfully\n");
1213: }
1214: erecover();
1215: }
1216:
1217: /*
1218: * Push the current environment.
1219: */
1220:
1221: private pushenv()
1222: {
1223: push(Address, pc);
1224: push(Lineno, curline);
1225: push(String, cursource);
1226: push(Boolean, isstopped);
1227: push(Symbol, curfunc);
1228: push(Frame, curframe);
1229: push(struct Frame, curframerec);
1230: push(CallEnv, endproc);
1231: push(Word, reg(PROGCTR));
1232: push(Word, reg(STKP));
1233: push(Word, reg(FRP));
1234: }
1235:
1236: /*
1237: * Pop back to the real world.
1238: */
1239:
1240: public popenv()
1241: {
1242: String filename;
1243:
1244: setreg(FRP, pop(Word));
1245: setreg(STKP, pop(Word));
1246: setreg(PROGCTR, pop(Word));
1247: endproc = pop(CallEnv);
1248: curframerec = pop(struct Frame);
1249: curframe = pop(Frame);
1250: curfunc = pop(Symbol);
1251: isstopped = pop(Boolean);
1252: filename = pop(String);
1253: curline = pop(Lineno);
1254: pc = pop(Address);
1255: setsource(filename);
1256: }
1257:
1258: /*
1259: * Flush the debuggee's standard output.
1260: *
1261: * This is VERY dependent on the use of stdio.
1262: */
1263:
1264: public flushoutput()
1265: {
1266: Symbol p, iob;
1267: Stack *savesp;
1268:
1269: p = lookup(identname("fflush", true));
1270: while (p != nil and not isblock(p)) {
1271: p = p->next_sym;
1272: }
1273: if (p != nil) {
1274: iob = lookup(identname("_iob", true));
1275: if (iob != nil) {
1276: pushenv();
1277: pc = codeloc(p) - FUNCOFFSET;
1278: savesp = sp;
1279: push(long, address(iob, nil) + sizeof(*stdout));
1280: setreg(STKP, reg(STKP) - sizeof(long));
1281: dwrite(savesp, reg(STKP), sizeof(long));
1282: sp = savesp;
1283: beginproc(p, 1);
1284: stepto(return_addr());
1285: popenv();
1286: }
1287: }
1288: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.