⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
/*#@(#)process.c	4.1	Ultrix	7/17/90*//* Copyright (c) 1982 Regents of the University of California */static char sccsid[] = "@(#)process.c 1.12 8/19/83";static char rcsid[] = "$Header: process.c,v 1.3 84/03/27 10:23:24 linton Exp $";/* * Process management. * * This module contains the routines to manage the execution and * tracing of the debuggee process. */#include "defs.h"#include "process.h"#include "machine.h"#include "events.h"#include "tree.h"#include "eval.h"#include "operators.h"#include "source.h"#include "object.h"#include "mappings.h"#include "main.h"#include "coredump.h"#include <signal.h>#include <errno.h>#include <sys/param.h>#include <sys/dir.h>#include <sys/user.h>#include <machine/reg.h>#include <sys/stat.h>#ifndef publictypedef struct Process *Process;Process process;#define DEFSIG -1#include "machine.h"#endif#define NOTSTARTED 1#define STOPPED 0177#define FINISHED 0/* * A cache of the instruction segment is kept to reduce the number * of system calls.  Might be better just to read the entire * code space into memory. */#define CSIZE 1003       /* size of instruction cache */typedef struct {    Word addr;    Word val;} CacheWord;/* * This structure holds the information we need from the user structure. */struct Process {    int pid;			/* process being traced */    int mask;			/* process status word */    Word reg[NREG];		/* process' registers */    Word oreg[NREG];		/* registers when process last stopped */    short status;		/* either STOPPED or FINISHED */    short signo;		/* signal that stopped process */    int exitval;		/* return value from exit() */    long sigset;		/* bit array of traced signals */    CacheWord word[CSIZE];	/* text segment cache */    Ttyinfo ttyinfo;		/* process' terminal characteristics */    Address sigstatus;		/* process' handler for current signal */};/* * These definitions are for the arguments to "pio". */typedef enum { PREAD, PWRITE } PioOp;typedef enum { TEXTSEG, DATASEG } PioSeg;private struct Process pbuf;#define MAXNCMDARGS 100         /* maximum number of arguments to RUN */extern int errno;private Boolean just_started;private int argc;private String argv[MAXNCMDARGS];private String infile, outfile;/* * Initialize process information. */public process_init(){    register Integer i;    Char buf[10];    process = &pbuf;    process->status = (coredump) ? STOPPED : NOTSTARTED;    setsigtrace();    for (i = 0; i < NREG; i++) {	sprintf(buf, "$r%d", i);	defregname(identname(buf, false), i);    }    defregname(identname("$ap", true), ARGP);    defregname(identname("$fp", true), FRP);    defregname(identname("$sp", true), STKP);    defregname(identname("$pc", true), PROGCTR);    if (coredump) {	coredump_readin(process->mask, process->reg, process->signo);	pc = process->reg[PROGCTR];	getsrcpos();    }    arginit();}/* * Routines to get at process information from outside this module. */public Word reg(n)Integer n;{    register Word w;    if (n == NREG) {	w = process->mask;    } else {	w = process->reg[n];    }    return w;}public setreg(n, w)Integer n;Word w;{    process->reg[n] = w;}/* * Begin execution. * * We set a breakpoint at the end of the code so that the * process data doesn't disappear after the program terminates. */private Boolean remade();public start(argv, infile, outfile)String argv[];String infile, outfile;{    String pargv[4];    Node cond;    if (coredump) {	coredump = false;	fclose(corefile);	coredump_close();    }    if (argv == nil) {	argv = pargv;	pargv[0] = objname;	pargv[1] = nil;    } else {	argv[argc] = nil;    }    if (remade(objname)) {	reinit(argv, infile, outfile);    }    pstart(process, argv, infile, outfile);    if (process->status == STOPPED) {	pc = 0;	setcurfunc(program);	if (objsize != 0) {	    cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr()));	    event_once(cond, buildcmdlist(build(O_ENDX)));	}    }}/* * Check to see if the object file has changed since the symbolic * information last was read. */private time_t modtime;private Boolean remade(filename)String filename;{    struct stat s;    Boolean b;    stat(filename, &s);    b = (Boolean) (modtime != 0 and modtime < s.st_mtime);    modtime = s.st_mtime;    return b;}/* * Set up what signals we want to trace. */private setsigtrace(){    register Integer i;    register Process p;    p = process;    for (i = 1; i <= NSIG; i++) {	psigtrace(p, i, true);    }    psigtrace(p, SIGHUP, false);    psigtrace(p, SIGKILL, false);    psigtrace(p, SIGALRM, false);    psigtrace(p, SIGTSTP, false);    psigtrace(p, SIGCONT, false);    psigtrace(p, SIGCHLD, false);}/* * Initialize the argument list. */public arginit(){    infile = nil;    outfile = nil;    argv[0] = objname;    argc = 1;}/* * Add an argument to the list for the debuggee. */public newarg(arg)String arg;{    if (argc >= MAXNCMDARGS) {	error("too many arguments");    }    argv[argc++] = arg;}/* * Set the standard input for the debuggee. */public inarg(filename)String filename;{    if (infile != nil) {	error("multiple input redirects");    }    infile = filename;}/* * Set the standard output for the debuggee. * Probably should check to avoid overwriting an existing file. */public outarg(filename)String filename;{    if (outfile != nil) {	error("multiple output redirect");    }    outfile = filename;}/* * Start debuggee executing. */public run(){    process->status = STOPPED;    fixbps();    curline = 0;    start(argv, infile, outfile);    just_started = true;    isstopped = false;    cont(0);}/* * Continue execution wherever we left off. * * Note that this routine never returns.  Eventually bpact() will fail * and we'll call printstatus or step will call it. */typedef int Intfunc();private Intfunc *dbintr;private intr();#define succeeds    == true#define fails       == falsepublic cont(signo)integer signo;{    integer s;    dbintr = signal(SIGINT, intr);    if (just_started) {	just_started = false;    } else {	if (not isstopped) {	    error("can't continue execution");	}	isstopped = false;	stepover();    }    s = signo;    for (;;) {	if (single_stepping) {	    printnews();	} else {	    setallbps();	    resume(s);	    unsetallbps();	    s = DEFSIG;	    if (bpact() fails) {		printstatus();	    }	}	stepover();    }    /* NOTREACHED */}/* * This routine is called if we get an interrupt while "running" px * but actually in the debugger.  Could happen, for example, while * processing breakpoints. * * We basically just want to keep going; the assumption is * that when the process resumes it will get the interrupt * which will then be handled. */private intr(){    signal(SIGINT, intr);}public fixintr(){    signal(SIGINT, dbintr);}/* * Resume execution. */public resume(signo)int signo;{    register Process p;    p = process;    pcont(p, signo);    pc = process->reg[PROGCTR];    if (p->status != STOPPED) {	if (p->signo != 0) {	    error("program terminated by signal %d", p->signo);	} else if (not runfirst) {	    error("program unexpectedly exited with %d", p->exitval);	}    }}/* * Continue execution up to the next source line. * * There are two ways to define the next source line depending on what * is desired when a procedure or function call is encountered.  Step * stops at the beginning of the procedure or call; next skips over it. *//* * Stepc is what is called when the step command is given. * It has to play with the "isstopped" information. */public stepc(){    if (not isstopped) {	error("can't continue execution");    }    isstopped = false;    dostep(false);    isstopped = true;}public next(){    Address oldfrp, newfrp;    if (not isstopped) {	error("can't continue execution");    }    isstopped = false;    oldfrp = reg(FRP);    do {	dostep(true);	pc = reg(PROGCTR);	newfrp = reg(FRP);    } while (newfrp < oldfrp and newfrp != 0);    isstopped = true;}/* * Continue execution until the current function returns, or, * if the given argument is non-nil, until execution returns to * somewhere within the given function. */public rtnfunc (f)Symbol f;{    Address addr;    Symbol t;    if (not isstopped) {	error("can't continue execution");    } else if (f != nil and not isactive(f)) {	error("%s is not active", symname(f));    } else {	addr = return_addr();	if (addr == nil) {	    error("no place to return to");	} else {	    isstopped = false;	    contto(addr);	    if (f != nil) {		for (;;) {		    t = whatblock(pc);		    addr = return_addr();		if (t == f or addr == nil) break;		    contto(addr);		}	    }	    if (bpact() fails) {		isstopped = true;		printstatus();	    }	}    }}/* * Single-step over the current machine instruction. * * If we're single-stepping by source line we want to step to the * next source line.  Otherwise we're going to continue so there's * no reason to do all the work necessary to single-step to the next * source line. */public stepover(){    Boolean b;    if (traceexec) {	printf("!! stepping over 0x%x\n", process->reg[PROGCTR]);    }    if (single_stepping) {	dostep(false);    } else {	b = inst_tracing;	inst_tracing = true;	dostep(false);	inst_tracing = b;    }    if (traceexec) {	printf("!! stepped over to 0x%x\n", process->reg[PROGCTR]);    }}/* * Resume execution up to the given address.  It is assumed that * no breakpoints exist between the current address and the one * we're stepping to.  This saves us from setting all the breakpoints. */public stepto(addr)Address addr;{    xto(addr, false);}private contto (addr)Address addr;{    xto(addr, true);}private xto (addr, catchbps)Address addr;boolean catchbps;{    Address curpc;    if (catchbps) {	stepover();    }    curpc = process->reg[PROGCTR];    if (addr != curpc) {	if (traceexec) {	    printf("!! stepping from 0x%x to 0x%x\n", curpc, addr);	}	if (catchbps) {	    setallbps();	}	setbp(addr);	resume(DEFSIG);	unsetbp(addr);	if (catchbps) {	    unsetallbps();	}	if (not isbperr()) {	    printstatus();	}    }}/* * Print the status of the process. * This routine does not return. */public printstatus(){    int status;    if (process->status == FINISHED) {	exit(0);    } else {	setcurfunc(whatblock(pc));	getsrcpos();	if (process->signo == SIGINT) {	    isstopped = true;	    printerror();	} else if (isbperr() and isstopped) {	    printf("stopped ");	    printloc();	    putchar('\n');	    if (curline > 0) {		printlines(curline, curline);	    } else {		printinst(pc, pc);	    }	    erecover();	} else {	    fixintr();	    isstopped = true;	    printerror();	}    }}/* * Print out the current location in the debuggee. */public printloc(){    printf("in ");    printname(stdout, curfunc);    putchar(' ');    if (curline > 0 and not useInstLoc) {	printsrcpos();    } else {	useInstLoc = false;	curline = 0;	printf("at 0x%x", pc);    }}/* * Some functions for testing the state of the process. */public Boolean notstarted(p)Process p;{    return (Boolean) (p->status == NOTSTARTED);}public Boolean isfinished(p)Process p;{    return (Boolean) (p->status == FINISHED);}/* * Return the signal number which stopped the process. */public Integer errnum(p)Process p;{    return p->signo;}/* * Return the termination code of the process. */public Integer exitcode(p)Process p;{    return p->exitval;}/* * These routines are used to access the debuggee process from * outside this module. * * They invoke "pio" which eventually leads to a call to "ptrace". * The system generates an I/O error when a ptrace fails.  During reads * these are ignored, during writes they are reported as an error, and * for anything else they cause a fatal error. */

⌨️ 快捷键说明

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