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