📄 process.c
字号:
/* @(#)process.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 * * * * 012 - Added support for vectors. * * (L Miller, 18JAN90) * * * * 011 - Add missing signals. * * (Jon Reeves, May 12, 1989) * * * * 010 - Change format of process id printf * * (David Metsky, Feb 6, 1989) * * * * 009 - Changed signal handlers to void. * * (Mark Parenti, June 9, 1988) * * * * 008 - Made sure the process id is only printed when running * * with xdb. * * (David Metsky, April 14, 1988) * * * * 007 - Added xdb support for I/O window. * * (James Bond (Mike Gancarz), March 15, 1988) * * * * 006 - Re-merged 4.3 changes to fix signal handling. * * (Jon Reeves, July 14, 1987) * * * * 005 - Merged in 4.3 changes. * * (vjh, April 29, 1986) * * * * 004 - Update copyright. * * (vjh, August 23, 1985) * * * * 003 - Nexti at end of program did not work. Fixed next() so * * that dostep() is called only once if inst_tracing is * * true. * * (vjh, April 25, 1985) * * * * 002 - Fixed bug: executing a "next" when at the last line of * * the program caused the message "program unexpectedly * * exited with 5" to appear. This was because the code to * * handle single stepping assumed that there were no bkpts. * * between curpc and nextaddr. In this case, the breakpoint * * at exit() was not reset, so the cleanup code in * * endprogram() was not executed. The fix included removing * * routines contto() and xto(), and modifying stepto() to * * always set/unset all breakpoints. * * (vjh, April 12, 1985) * * * * 001 - Commented out test to reset process signo until * * further notice. Fixes usignal() bug (single stepping - * * dostep() gets into infinite loop). * * (Victoria Holt, April 9, 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[] = "@(#)process.c 2.3 ULTRIX 5/12/89";#endif not lint/* * Process management. * * This module contains the routines to manage the execution and * tracing of the debuggee process. */#include <stdio.h>#include "Xtty.h"#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"#ifndef NOVECTORS#include "/usr/sys/machine/vax/vectors.h"#include <sys/acct.h>#endif /* NOVECTORS */#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>#include <fcntl.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 */ int vcr; /* vector count register */ int ovcr; /* vector count register */ int vlr; /* vector length register */ int ovlr; /* vector length register */ int vaer; /* vector arithmetic exception register */ int ovaer; /* vector arithmetic exception register */ Vquad vmr; /* vector mask register */ Vquad ovmr; /* vector mask register */ Vreg vreg[NREG]; /* process' vector registers */ Vreg ovreg[NREG]; /* vect registers when process last stopped */ short status; /* either STOPPED or FINISHED */ short signo; /* signal that stopped process */ short sigcode; /* extra signal information */ 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 1000 /* maximum number of arguments to RUN */extern int errno;extern char *sys_siglist[];public boolean xdb; /* 007 - xdb specific features */private boolean xdbwinflag = false; /* 007 - if true, then display xdb window */private Boolean just_started;public Boolean never_run;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; never_run = true; 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 (vectorcapable) { for (i = 0; i < NREG; i++) { sprintf(buf, "$v%d", i); defvregname(identname(buf, false), i); process->vreg[i] = new(Vreg); process->ovreg[i] = new(Vreg); } defvcrname(identname("$vcr", false), VCR); defvcrname(identname("$vlr", false), VLR); defvcrname(identname("$vaer", false), VAER); defvmrname(identname("$vmr", false), VMR); } 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;}public Address vregloc(type, i, j)long type, i, j;{ Address addr;#ifndef NOVECTORS switch (type) { case A_VCR: addr = (Address)&((struct vpcontext *) 0)->vpc_vcr; break; case A_VAER: addr = (Address)&((struct vpcontext *) 0)->vpc_vaer; break; case A_VLR: addr = (Address)&((struct vpcontext *) 0)->vpc_vlr; break; case A_VMRLO: addr = (Address)&((struct vpcontext *) 0)->vpc_vmrlo; break; case A_VMRHI: addr = (Address)&((struct vpcontext *) 0)->vpc_vmrhi; break; case A_VREGLO: addr = (Address)&((struct vpcontext *) 0)->vpc_vregs + (i * NVREG * sizeof(Vquad)) + (j * sizeof(Vquad)); break; case A_VREGHI: addr = (Address)&((struct vpcontext *) 0)->vpc_vregs + (i * NVREG * sizeof(Vquad)) + (j * sizeof(Vquad)); addr += sizeof(Vquad) >> 1; break; default: error("internal error on request to locate vector register"); break; } return(addr);#else /* NOVECTORS */ return(-1);#endif /* NOVECTORS */}public Vreg vreg(n)Integer n;{ if (n == VCR) { return((Vreg)process->vcr); } else if (n == VAER) { return((Vreg)process->vaer); } else if (n == VLR) { return((Vreg)process->vlr); } else if (n == VMR) { return((Vreg)&process->vmr); } else { return (process->vreg[n]); }}public Address vregaddr(n)Integer n;{ Address addr; if (n == VCR) { addr = (Address) process->vcr; } else if (n == VAER) { addr = (Address) process->vaer; } else if (n == VLR) { addr = (Address) process->vlr; } else if (n == VMR) { addr = (Address) &process->vmr; } else { addr = (Address) process->vreg[n]; } return addr;}public setvmrreg(n, l)Integer n;long l;{ if(n > 31) { if(l) process->vmr.val[0] |= 1 << (n - 32); else process->vmr.val[0] &= ~(1 << (n - 32)); } else { if(l) process->vmr.val[1] |= 1 << n; else process->vmr.val[1] &= ~(1 << n); }}public setnreg(n, l)Integer n;long l;{ if (n == VCR) { process->vcr = l; } else if (n == VAER) { process->vaer = l; } else if (n == VLR) { process->vlr = l; }}public setvreg(addr, vquad)Address addr;Vquad *vquad;{ *(Vquad *) addr = *vquad;}/* * 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; xdbwinflag = true; /* 007 - causes xdb window to appear later */ fclose(corefile); coredump_close(); } if (remade(objname)) { reinit(argv, infile, outfile); } if (argv == nil) { argv = pargv; pargv[0] = objname; pargv[1] = nil; } else { argv[argc] = nil; } 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);}/* * force a run with a reread of the object file */public forcereread(){ arginit(); modtime = 1;}/* * 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); needruncmd = true; just_started = true; never_run = false; 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 void Intfunc();private Intfunc *dbintr;private void intr();public 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 (not isbperr() or not bpact()) { printstatus(); } } stepover(); } /* NOTREACHED */}/* * This routine is called if we get an interrupt while "running" * 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 void intr(){ signal(SIGINT, intr);}public void 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) { if (p->exitval == 0) { error("program exited"); } else { error("program exited with code %d", p->exitval); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -