runtime.sun.c
来自「早期freebsd实现」· C语言 代码 · 共 1,303 行 · 第 1/2 页
C
1,303 行
/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)runtime.sun.c 5.2 (Berkeley) 6/1/90";#endif /* not lint *//* * Runtime organization dependent routines, mostly dealing with * activation records. */#include "defs.h"#include "runtime.h"#include "process.h"#include "machine.h"#include "events.h"#include "mappings.h"#include "symbols.h"#include "tree.h"#include "eval.h"#include "operators.h"#include "object.h"#include <sys/param.h>#include <signal.h>#ifndef publictypedef struct Frame *Frame;#include "machine.h"#endif#define NSAVEREG 14struct Frame { Address save_fp; /* frame pointer */ Address save_pc; /* program counter */ Word save_reg[NSAVEREG]; /* not necessarily there */ integer nargwords; /* computed, not stored */};private Frame curframe = nil;private struct Frame curframerec;private Boolean walkingstack = false;#define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp)private boolean inSignalHandler (addr)Address addr;{ Symbol f;#ifdef IRIS return false;#else /* sun */ f = whatblock(addr); return (boolean) (f != nil and streq(symname(f), "_sigtramp"));#endif}typedef struct { Node callnode; Node cmdnode; boolean isfunc;} CallEnv;private CallEnv endproc;/* * Set a frame to the current activation record. */private getcurframe(frp)Frame frp;{ register int i; checkref(frp); frp->save_fp = reg(FRP); frp->save_pc = reg(PROGCTR); for (i = 0; i < NSAVEREG; i++) { frp->save_reg[i] = reg(i); } if (frp->save_fp == nil) { frp->nargwords = 0; } else { findnumargs(frp); }}/* * Get the saved registers from one frame to another * given mask specifying which registers were actually saved. */#define bis(b, n) ((b & (1 << (n))) != 0)private getsaveregs (newfrp, frp, mask)Frame newfrp, frp;integer mask;{ integer i, j; j = 0; for (i = 0; i < NSAVEREG; i++) { if (bis(mask, i)) { newfrp->save_reg[i] = frp->save_reg[j]; ++j; } }}/* * Return a pointer to the next activation record up the stack. * Return nil if there is none. * Writes over space pointed to by given argument. */private Frame nextframe(frp)Frame frp;{ Frame newfrp; struct Frame frame; integer mask; Address prev_frame, callpc, higher_fp, higher_pc; static integer ntramp = 0; newfrp = frp; prev_frame = frp->save_fp;/* * The check for interrupt generated frames is taken from adb with only * partial understanding. If you're in "sub" and on a sigxxx "sigsub" * gets control, then the stack does NOT look like <main, sub, sigsub>. * * As best I can make out it looks like: * * <main, (machine check exception block + sub), sysframe, sigsub>. * * When the signal occurs an exception block and a frame for the routine * in which it occured are pushed on the user stack. Then another frame * is pushed corresponding to a call from the kernel to sigsub. * * The addr in sub at which the exception occured is not in sub.save_pc * but in the machine check exception block. It is at the magic address * fp + 84. * * The current approach ignores the sys_frame (what adb reports as sigtramp) * and takes the pc for sub from the exception block. This allows the * "where" command to report <main, sub, sigsub>, which seems reasonable. */nextf: if (prev_frame + sizeof(struct Frame) <= USRSTACK) { dread(&frame, prev_frame, sizeof(struct Frame)); } else if (USRSTACK - prev_frame > 2 * sizeof(Word)) { dread(&frame, prev_frame, USRSTACK - prev_frame); } else { frame.save_fp = nil; } if (ntramp == 1) { dread(&callpc, prev_frame + 92, sizeof(callpc)); } else { callpc = frame.save_pc; } if (frame.save_fp == nil or frame.save_pc == (Address) -1) { newfrp = nil; } else { if (inSignalHandler(callpc)) {# ifdef sun Address scp; dread(&scp, prev_frame + 16, sizeof(scp)); dread(&callpc, &(((struct sigcontext *)scp)->sc_pc), sizeof(Word) );# endif /* sun */ } frame.save_pc = callpc; ntramp = 0; higher_fp = frp->save_fp; higher_pc = frp->save_pc; newfrp->save_fp = frame.save_fp; newfrp->save_pc = frame.save_pc; findnumargs(newfrp); findsavedregs(newfrp, higher_fp, higher_pc); } return newfrp;}/* * Finding the saved registers and number of arguments passed to * the current procedure is painful for the 68000. * * This is a version of the way adb for the 68000 does this. */#define HIWORD 0xffff0000#define LOWORD 0x0000ffff#define LINKA6 0x4e560000 /* link a6,#x */#define ADDLSP 0xdffc0000 /* addl #x,sp */#define ADDWSP 0xdefc0000 /* addw #x,sp */#define LEASP 0x4fef0000 /* lea sp@(x),sp*/#define TSTBSP 0x4a2f0000 /* tstb sp@(x) */#define INSMSK 0xfff80000#define MOVLSP 0x2e800000 /* movl dx,sp@ */#define MOVLD0 0x20000000 /* movl d0,dx */#define MOVLA0 0x20400000 /* movl d0,ax */#define MVLMSK 0xf1ff0000#define MOVEML 0x48d70000 /* moveml #x,sp@ */#define JSR 0x4eb80000 /* jsr x.[WL] */#define JSRPC 0x4eba0000 /* jsr PC@( ) */#define LONGBIT 0x00010000#define BSR 0x61000000 /* bsr x */#define BYTE3 0x0000ff00#define LOBYTE 0x000000ff#define ADQMSK 0xf1ff0000#define ADDQSP 0x508f0000 /* addql #x,sp */#define ADDQWSP 0x504f0000 /* addqw #x,sp */private int savedregsmask;private int savedregp;/* * Find out how many words of arguments were passed to * the current procedure. */private findnumargs (newfrp)Frame newfrp;{ integer val; integer instruc; Address addr; dread(&addr, newfrp->save_fp + sizeof(Address), sizeof(addr)); iread(&instruc, addr, sizeof(instruc)); if ((instruc&MVLMSK) == MOVLA0 or (instruc&MVLMSK) == MOVLD0) { addr += 2; iread(&instruc, addr, sizeof(instruc)); } if ((instruc&ADQMSK) == ADDQSP or (instruc&ADQMSK) == ADDQWSP){ val = (instruc >> (16+9)) & 07; if (val == 0) { val = 8; } } else if ((instruc&HIWORD) == ADDLSP){ iread(&val, addr + 2, sizeof(val)); } else if ((instruc&HIWORD) == ADDWSP || (instruc&HIWORD) == LEASP){ val = instruc&LOWORD; } else { val = 0; } newfrp->nargwords = val / sizeof(Word);}/* * Get the saved registers for the given Frame. */private findsavedregs (newfrp, higher_fp, higher_pc)Frame newfrp;register Address higher_fp, higher_pc;{ int val, regp, i; Address addr; Symbol func; Address calladdr; int instruc; /* * Find the entry point of the current procedure. * This is done by finding the procedure for the higher frame's pc * and taking its starting address. */ func = whatblock(higher_pc, true); calladdr = codeloc(func) - FUNCOFFSET; /* * Look at the entry code for the current procedure * to determine which registers were saved, and where they are. * * First find the size of the activation record. */ addr = calladdr; iread(&instruc, addr, sizeof(instruc)); if ((instruc&HIWORD) == LINKA6) { if ((instruc &= LOWORD) == 0) { /* look for addl */ addr += 4; iread(&instruc, addr, sizeof(instruc)); if ((instruc&HIWORD) == ADDLSP) { iread(&instruc, addr + 2, sizeof(instruc)); addr += 6; } else { instruc = 0; } } else { /* link offset was non-zero -- sign extend it */ instruc <<= 16; instruc >>= 16; } /* we now have the negative frame size */ regp = higher_fp + instruc; savedregp = regp; } /* * Now find which registers were saved. * (expecting a probe instruction next) */ iread(&instruc, addr, sizeof(instruc)); if ((instruc&HIWORD) == TSTBSP) { addr += 4; iread(&instruc, addr, sizeof(instruc)); } /* * expect either a moveml or a movl next */ if ((instruc&INSMSK) == MOVLSP){ /* * Only one register saved. */ i = (instruc>>16) & 07; dread(&(newfrp->save_reg[i]), regp, sizeof(Word)); savedregsmask = 1 << i; } else if ((instruc&HIWORD) == MOVEML) { /* * Saving multiple registers or unoptimized code */ val = instruc & LOWORD; savedregsmask = val; i = 0; while (val != 0) { if (val&1) { dread(&(newfrp->save_reg[i]), regp, sizeof(Word)); regp += sizeof(Word); } val >>= 1; ++i; } } else { savedregsmask = 0; }}/* * Get the current frame information in the given Frame and store the * associated function in the given value-result parameter. */private getcurfunc (frp, fp)Frame frp;Symbol *fp;{ getcurframe(frp); *fp = whatblock(frp->save_pc);}/* * Return the frame associated with the next function up the call stack, or * nil if there is none. The function is returned in a value-result parameter. * For "inline" functions the statically outer function and same frame * are returned. */public Frame nextfunc (frp, fp)Frame frp;Symbol *fp;{ Symbol t; Frame nfrp; t = *fp; checkref(t); if (isinline(t)) { t = container(t); nfrp = frp; } else { nfrp = nextframe(frp); if (nfrp == nil) { t = nil; } else { t = whatblock(nfrp->save_pc); } } *fp = t; return nfrp;}/* * Return the frame associated with the given function. * If the function is nil, return the most recently activated frame. * * Static allocation for the frame. */public Frame findframe(f)Symbol f;{ Frame frp; static struct Frame frame; Symbol p; Boolean done; frp = &frame; getcurframe(frp); if (f != nil) { if (f == curfunc and curframe != nil) { *frp = *curframe; } else { done = false; p = whatblock(frp->save_pc); do { if (p == f) { done = true; } else if (p == program) { done = true; frp = nil; } else { frp = nextfunc(frp, &p); if (frp == nil) { done = true; } } } while (not done); } } return frp;}/* * Set the registers according to the given frame pointer. */public getnewregs (addr)Address addr;{ struct Frame frame; integer i, j, mask; dread(&frame, addr, sizeof(frame)); setreg(FRP, frame.save_fp); setreg(PROGCTR, frame.save_pc); pc = frame.save_pc; setcurfunc(whatblock(pc));}/* * Find the return address of the current procedure/function. */public Address return_addr(){ Frame frp; Address addr; struct Frame frame; frp = &frame; getcurframe(frp); frp = nextframe(frp); if (frp == nil) { addr = 0; } else { addr = frp->save_pc; } return addr;}/* * Push the value associated with the current function. */public pushretval(len, isindirect)integer len;boolean isindirect;{ Word r0; r0 = reg(0); if (isindirect) { rpush((Address) r0, len); } else { switch (len) { case sizeof(char): push(char, r0); break; case sizeof(short): push(short, r0); break; default: if (len == sizeof(Word)) { push(Word, r0); } else if (len == 2*sizeof(Word)) { push(Word, r0); push(Word, reg(1)); } else { error("[internal error: bad size %d in pushretval]", len); } break; } }}/* * Return the base address for locals in the given frame. */public Address locals_base(frp)Frame frp;{ return (frp == nil) ? reg(FRP) : frp->save_fp;}/* * Return the base address for arguments in the given frame. */public Address args_base(frp)Frame frp;{ return (frp == nil) ? reg(FRP) : frp->save_fp;}/* * Return saved register n from the given frame. */public Word savereg(n, frp)integer n;Frame frp;{ Word w; if (frp == nil) { w = reg(n); } else { switch (n) { case FRP: w = frp->save_fp; break; case STKP: w = reg(STKP); break; case PROGCTR: w = frp->save_pc; break; default: assert(n >= 0 and n < NSAVEREG); w = frp->save_reg[n]; break; } } return w;}/* * Return the nth argument to the current procedure. */public Word argn(n, frp)integer n;Frame frp;{ Address argaddr; Word w; argaddr = args_base(frp) + 4 + (n * sizeof(Word)); dread(&w, argaddr, sizeof(w)); return w;}/* * Return the number of words of arguments passed to the procedure * associated with the given frame (it's a macro for the VAX). */public integer nargspassed (frp)Frame frp;{ integer n; struct Frame frame; if (frp == nil) { getcurframe(&frame); n = frame.nargwords; } else { n = frp->nargwords; } return n;}/* * Print a list of currently active blocks starting with most recent. */public wherecmd(){ walkstack(false);}/* * Print the variables in the given frame or the current one if nil. */public dump (func)Symbol func;{ Symbol f; Frame frp; if (func == nil) { f = curfunc; if (curframe != nil) { frp = curframe; } else { frp = findframe(f);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?