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