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