runtime.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,238 行 · 第 1/2 页

C
1,238
字号
/*@(#)runtime.c	4.2  Ultrix  11/9/90*//************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ *									* *			Modification History				* *									* *  007 - fixed 'print function()' and "can't set a breakpoint in * *		  a function and do a 'print function(). also, fixed the  * *		   function return value to be correct.					  * *		  (L Miller, 25JAN90)									* *									* *  006	- Added support for vectors.							* *		  (L Miller, 18JAN90)									* *									* *	005 - Re-merged 4.3 changes to fix: a) dump of variables in	* *	      unnamed blocks was useless ("the mysterious $b" in 001;	* *	      b) $unsafecall wasn't there though it was documented.	* *	      (Jon Reeves, July 14, 1987)				* *									* *	004 - Merged in 4.3 changes.					* *	      (vjh, April 29, 1986)					* *									* *	003 - Fixed bug in down().  Added test for jsb routine when	* *	      determining the start address of a function in		* *	      findbeginning().						* *	      (vjh, August 14, 1985)					* *									* *	002 - Pushretval() now returns a boolean value.  Returns false	* *	      when value is inaccessible; used to panic.		* *	      (vjh, July 18, 1985)					* *									* *	001 - Fixed internal error - unexpected nil frame; occured when * *	      pc pointed to last instruction in main routine - 		* *	      getcurframe() was returning reg[PROGCTR]+1 as save_pc, 	* *	      which in this case is in hyper-space. Modified 		* *	      walkstack():  fixed dependencies on the above; removed	* *	      the mysterious $b# from stack traces.			* *	      (Victoria Holt, April 23, 1985)				* *									* ************************************************************************//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic char sccsid[] = "@(#)runtime.c	2.1	ULTRIX	4/24/89";#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 "main.h"#include "symbols.h"#include "tree.h"#include "eval.h"#include "operators.h"#include "object.h"#include <sys/param.h>#include <sys/vm.h>#ifndef publictypedef struct Frame *Frame;#include "machine.h"#endif#define NSAVEREG 12struct Frame {    integer condition_handler;    integer mask;    Address save_ap;		/* argument pointer */    Address save_fp;		/* frame pointer */    Address save_pc;		/* program counter */    Word save_reg[NSAVEREG];	/* not necessarily there */};private Frame curframe = nil;private struct Frame curframerec;private Boolean walkingstack = false;#define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp)#define isstackaddr(addr) \    (((addr) < 0x80000000) and ((addr) > USRSTACK))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->mask = reg(NREG);    frp->save_ap = reg(ARGP);    frp->save_fp = reg(FRP);    frp->save_pc = reg(PROGCTR);    for (i = 0; i < NSAVEREG; i++) {	frp->save_reg[i] = reg(i);    }}/* * 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;     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:    dread(&frame, prev_frame, sizeof(struct Frame));    if (ntramp == 1) {	dread(&callpc, prev_frame + 84, sizeof(callpc));    } else {	callpc = frame.save_pc;    }    if (frame.save_fp == nil or frame.save_pc == (Address) -1) {	newfrp = nil;    } else if (isstackaddr(callpc)) {	ntramp++;	prev_frame = frame.save_fp;	goto nextf;    } else {	frame.save_pc = callpc;        ntramp = 0;	mask = ((frame.mask >> 16) & 0x0fff);	getsaveregs(newfrp, &frame, mask);	newfrp->condition_handler = frame.condition_handler;	newfrp->mask = mask;	newfrp->save_ap = frame.save_ap;	newfrp->save_fp = frame.save_fp;	newfrp->save_pc = frame.save_pc;    }    return newfrp;}/* * 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(ARGP, frame.save_ap);    setreg(FRP, frame.save_fp);    setreg(PROGCTR, frame.save_pc);    mask = ((frame.mask >> 16) & 0x0fff);    j = 0;    for (i = 0; i < NSAVEREG; i++) {	if (bis(mask, i)) {	    setreg(i, frame.save_reg[j]);	    ++j;	}    }    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 Boolean pushretval(len, isindirect)Integer len;Boolean isindirect;{    Word r0;    Boolean success;    r0 = reg(0);    success = true;    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 {		    success = false;		}		break;	}    }    return success;}/* * 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(ARGP) : frp->save_ap;}/* * 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 ARGP:		w = frp->save_ap;		break;	    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;{    Word w;    dread(&w, args_base(frp) + (n * sizeof(Word)), sizeof(w));    return w;}/* * 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);	}    } else {	f = func;	frp = findframe(f);    }    showaggrs = true;    printcallinfo(f, frp);    dumpvars(f, frp);}/* * Dump all values. */public dumpall (){    walkstack(true);}/* * Walk the stack of active procedures printing information * about each active procedure. */private walkstack(dumpvariables)Boolean dumpvariables;{    Frame frp;    boolean save;    Symbol f;    struct Frame frame;    if (notstarted(process) or isfinished(process)) {	error("program is not active");    } else {	save = walkingstack;	walkingstack = true;	showaggrs = dumpvariables;	frp = &frame;	getcurfunc(frp, &f);	if(!never_run) {		for (;;) {	    	printcallinfo(f, frp);	    	if (dumpvariables) {				dumpvars(f, frp);				putchar('\n');	    	}	    	frp = nextfunc(frp, &f);	    	if (frp == nil or f == program) {				break;	    	}		}	}	if (dumpvariables) {	    printf("in \"%s\":\n", symname(program));	    dumpvars(program, nil);	    putchar('\n');	}	walkingstack = save;    }}/* * Print out the information about a call, i.e., * routine name, parameter values, and source location. */private printcallinfo (f, frp)Symbol f;Frame frp;{    Lineno line;    Address savepc;    savepc = frp->save_pc;    if (frp->save_fp != reg(FRP)) {	savepc -= 1;    }    printname(stdout, f);    if (not isinline(f)) {	printparams(f, frp);    }    line = srcline(savepc);    if (line != 0) {	printf(", line %d", line);	printf(" in \"%s\"\n", srcfilename(savepc));    } else {	printf(" at 0x%x\n", savepc);    }}/* * Set the current function to the given symbol. * We must adjust "curframe" so that subsequent operations are * not confused; for simplicity we simply clear it. */public setcurfunc (f)Symbol f;{    curfunc = f;    curframe = nil;}/* * Return the frame for the current function. * The space for the frame is allocated statically. */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?