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

📄 process.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
extern Intfunc *onsyserr();private badaddr;private read_err(), write_err();/* * Read from the process' instruction area. */public iread(buff, addr, nbytes)char *buff;Address addr;int nbytes;{    Intfunc *f;    f = onsyserr(EIO, read_err);    badaddr = addr;    if (coredump) {	coredump_readtext(buff, addr, nbytes);    } else {	pio(process, PREAD, TEXTSEG, buff, addr, nbytes);    }    onsyserr(EIO, f);}/*  * Write to the process' instruction area, usually in order to set * or unset a breakpoint. */public iwrite(buff, addr, nbytes)char *buff;Address addr;int nbytes;{    Intfunc *f;    if (coredump) {	error("no process to write to");    }    f = onsyserr(EIO, write_err);    badaddr = addr;    pio(process, PWRITE, TEXTSEG, buff, addr, nbytes);    onsyserr(EIO, f);}/* * Read for the process' data area. */public dread(buff, addr, nbytes)char *buff;Address addr;int nbytes;{    Intfunc *f;    f = onsyserr(EIO, read_err);    badaddr = addr;    if (coredump) {	coredump_readdata(buff, addr, nbytes);    } else {	pio(process, PREAD, DATASEG, buff, addr, nbytes);    }    onsyserr(EIO, f);}/* * Write to the process' data area. */public dwrite(buff, addr, nbytes)char *buff;Address addr;int nbytes;{    Intfunc *f;    if (coredump) {	error("no process to write to");    }    f = onsyserr(EIO, write_err);    badaddr = addr;    pio(process, PWRITE, DATASEG, buff, addr, nbytes);    onsyserr(EIO, f);}/* * Trap for errors in reading or writing to a process. * The current approach is to "ignore" read errors and complain * bitterly about write errors. */private read_err(){    /*     * Ignore.     */}private write_err(){    error("can't write to process (address 0x%x)", badaddr);}/* * Ptrace interface. *//* * This magic macro enables us to look at the process' registers * in its user structure. */#define regloc(reg)     (ctob(UPAGES) + ( sizeof(int) * (reg) ))#define WMASK           (~(sizeof(Word) - 1))#define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE))#define FIRSTSIG        SIGINT#define LASTSIG         SIGQUIT#define ischild(pid)    ((pid) == 0)#define traceme()       ptrace(0, 0, 0, 0)#define setrep(n)       (1 << ((n)-1))#define istraced(p)     (p->sigset&setrep(p->signo))/* * Ptrace options (specified in first argument). */#define UREAD   3       /* read from process's user structure */#define UWRITE  6       /* write to process's user structure */#define IREAD   1       /* read from process's instruction space */#define IWRITE  4       /* write to process's instruction space */#define DREAD   2       /* read from process's data space */#define DWRITE  5       /* write to process's data space */#define CONT    7       /* continue stopped process */#define SSTEP   9       /* continue for approximately one instruction */#define PKILL   8       /* terminate the process *//* * Start up a new process by forking and exec-ing the * given argument list, returning when the process is loaded * and ready to execute.  The PROCESS information (pointed to * by the first argument) is appropriately filled. * * If the given PROCESS structure is associated with an already running * process, we terminate it. *//* VARARGS2 */private pstart(p, argv, infile, outfile)Process p;String argv[];String infile;String outfile;{    int status;    if (p->pid != 0) {	pterm(p);    }    psigtrace(p, SIGTRAP, true);    p->pid = vfork();    if (p->pid == -1) {	panic("can't fork");    }    if (ischild(p->pid)) {	traceme();	if (infile != nil) {	    infrom(infile);	}	if (outfile != nil) {	    outto(outfile);	}	execv(argv[0], argv);	write(2, "can't exec ", 11);	write(2, argv[0], strlen(argv[0]));	write(2, "\n", 1);	_exit(1);    }    pwait(p->pid, &status);    getinfo(p, status);    if (p->status != STOPPED) {	error("program could not begin execution");    }    ptraced(p->pid);}/* * Terminate a ptrace'd process. */public pterm (p)Process p;{    integer status;    if (p != nil and p->pid != 0) {	ptrace(PKILL, p->pid, 0, 0);	pwait(p->pid, &status);	unptraced(p->pid);    }}/* * Continue a stopped process.  The first argument points to a Process * structure.  Before the process is restarted it's user area is modified * according to the values in the structure.  When this routine finishes, * the structure has the new values from the process's user area. * * Pcont terminates when the process stops with a signal pending that * is being traced (via psigtrace), or when the process terminates. */private pcont(p, signo)Process p;int signo;{    int s, status;    if (p->pid == 0) {	error("program not active");    }    s = signo;    do {	setinfo(p, s);	if (traceexec) {	    printf("!! pcont from 0x%x with signal %d (%d)\n",		p->reg[PROGCTR], s, p->signo);	    fflush(stdout);	}	sigs_off();	if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) {	    panic("error %d trying to continue process", errno);	}	pwait(p->pid, &status);	sigs_on();	getinfo(p, status);	if (traceexec and not istraced(p)) {	    printf("!! ignored signal %d at 0x%x\n", p->signo, p->reg[PROGCTR]);	    fflush(stdout);	}	s = p->signo;    } while (p->status == STOPPED and not istraced(p));    if (traceexec) {	printf("!! pcont to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo);	fflush(stdout);    }}/* * Single step as best ptrace can. */public pstep(p, signo)Process p;integer signo;{    int status;    setinfo(p, signo);    if (traceexec) {	printf("!! pstep from pc 0x%x with signal %d (%d)\n",	    p->reg[PROGCTR], signo, p->signo);	fflush(stdout);    }    sigs_off();    if (ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo) < 0) {	panic("error %d trying to step process", errno);    }    pwait(p->pid, &status);    sigs_on();    getinfo(p, status);    if (traceexec) {	printf("!! pstep to pc 0x%x on signal %d\n", p->reg[PROGCTR], p->signo);	fflush(stdout);    }    if (p->status != STOPPED) {	error("program unexpectedly exited with %d\n", p->exitval);    }}/* * Return from execution when the given signal is pending. */public psigtrace(p, sig, sw)Process p;int sig;Boolean sw;{    if (sw) {	p->sigset |= setrep(sig);    } else {	p->sigset &= ~setrep(sig);    }}/* * Don't catch any signals. * Particularly useful when letting a process finish uninhibited. */public unsetsigtraces(p)Process p;{    p->sigset = 0;}/* * Turn off attention to signals not being caught. */private Intfunc *sigfunc[NSIG];private sigs_off(){    register int i;    for (i = FIRSTSIG; i < LASTSIG; i++) {	if (i != SIGKILL) {	    sigfunc[i] = signal(i, SIG_IGN);	}    }}/* * Turn back on attention to signals. */private sigs_on(){    register int i;    for (i = FIRSTSIG; i < LASTSIG; i++) {	if (i != SIGKILL) {	    signal(i, sigfunc[i]);	}    }}/* * Get process information from user area. */private int rloc[] ={    R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC};private getinfo(p, status)register Process p;register int status;{    register int i;    Address addr;    p->signo = (status&0177);    p->exitval = ((status >> 8)&0377);    if (p->signo != STOPPED) {	p->status = FINISHED;	p->pid = 0;	p->reg[PROGCTR] = 0;    } else {	p->status = p->signo;	p->signo = p->exitval;	p->exitval = 0;	p->mask = ptrace(UREAD, p->pid, regloc(PS), 0);	for (i = 0; i < NREG; i++) {	    p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0);	    p->oreg[i] = p->reg[i];	}	savetty(stdout, &(p->ttyinfo));	addr = (Address) &(((struct user *) 0)->u_signal[p->signo]);	p->sigstatus = (Address) ptrace(UREAD, p->pid, addr, 0);    }}/* * Set process's user area information from given process structure. */private setinfo(p, signo)register Process p;int signo;{    register int i;    register int r;    if (signo == DEFSIG) {	if (istraced(p) and (p->sigstatus == 0 or p->sigstatus == 1)) {	    p->signo = 0;	}    } else {	p->signo = signo;    }    for (i = 0; i < NREG; i++) {	if ((r = p->reg[i]) != p->oreg[i]) {	    ptrace(UWRITE, p->pid, regloc(rloc[i]), r);	}    }    restoretty(stdout, &(p->ttyinfo));}/* * Return the address associated with the current signal. * (Plus two since the address points to the beginning of a procedure). */public Address usignal (p)Process p;{    Address r;    r = p->sigstatus;    if (r != 0 and r != 1) {	r += 2;    }    return r;}/* * Structure for reading and writing by words, but dealing with bytes. */typedef union {    Word pword;    Byte pbyte[sizeof(Word)];} Pword;/* * Read (write) from (to) the process' address space. * We must deal with ptrace's inability to look anywhere other * than at a word boundary. */private Word fetch();private store();private pio(p, op, seg, buff, addr, nbytes)Process p;PioOp op;PioSeg seg;char *buff;Address addr;int nbytes;{    register int i;    register Address newaddr;    register char *cp;    char *bufend;    Pword w;    Address wordaddr;    int byteoff;    if (p->status != STOPPED) {	error("program is not active");    }    cp = buff;    newaddr = addr;    wordaddr = (newaddr&WMASK);    if (wordaddr != newaddr) {	w.pword = fetch(p, seg, wordaddr);	for (i = newaddr - wordaddr; i < sizeof(Word) and nbytes > 0; i++) {	    if (op == PREAD) {		*cp++ = w.pbyte[i];	    } else {		w.pbyte[i] = *cp++;	    }	    nbytes--;	}	if (op == PWRITE) {	    store(p, seg, wordaddr, w.pword);	}	newaddr = wordaddr + sizeof(Word);    }    byteoff = (nbytes&(~WMASK));    nbytes -= byteoff;    bufend = cp + nbytes;    while (cp < bufend) {	if (op == PREAD) {	    *((Word *) cp) = fetch(p, seg, newaddr);	} else {	    store(p, seg, newaddr, *((Word *) cp));	}	cp += sizeof(Word);	newaddr += sizeof(Word);    }    if (byteoff > 0) {	w.pword = fetch(p, seg, newaddr);	for (i = 0; i < byteoff; i++) {	    if (op == PREAD) {		*cp++ = w.pbyte[i];	    } else {		w.pbyte[i] = *cp++;	    }	}	if (op == PWRITE) {	    store(p, seg, newaddr, w.pword);	}    }}/* * Get a word from a process at the given address. * The address is assumed to be on a word boundary. * * A simple cache scheme is used to avoid redundant ptrace calls * to the instruction space since it is assumed to be pure. * * It is necessary to use a write-through scheme so that * breakpoints right next to each other don't interfere. */private Integer nfetchs, nreads, nwrites;private Word fetch(p, seg, addr)Process p;PioSeg seg;register int addr;{    register CacheWord *wp;    register Word w;    switch (seg) {	case TEXTSEG:	    ++nfetchs;	    wp = &p->word[cachehash(addr)];	    if (addr == 0 or wp->addr != addr) {		++nreads;		w = ptrace(IREAD, p->pid, addr, 0);		wp->addr = addr;		wp->val = w;	    } else {		w = wp->val;	    }	    break;	case DATASEG:	    w = ptrace(DREAD, p->pid, addr, 0);	    break;	default:	    panic("fetch: bad seg %d", seg);	    /* NOTREACHED */    }    return w;}/* * Put a word into the process' address space at the given address. * The address is assumed to be on a word boundary. */private store(p, seg, addr, data)Process p;PioSeg seg;int addr;Word data;{    register CacheWord *wp;    switch (seg) {	case TEXTSEG:	    ++nwrites;	    wp = &p->word[cachehash(addr)];	    wp->addr = addr;	    wp->val = data;	    ptrace(IWRITE, p->pid, addr, data);	    break;	case DATASEG:	    ptrace(DWRITE, p->pid, addr, data);	    break;	default:	    panic("store: bad seg %d", seg);	    /* NOTREACHED */    }}public printptraceinfo(){    printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites);}/* * Redirect input. * Assuming this is called from a child, we should be careful to avoid * (possibly) shared standard I/O buffers. */private infrom (filename)String filename;{    Fileid in;    in = open(filename, 0);    if (in == -1) {	write(2, "can't read ", 11);	write(2, filename, strlen(filename));	write(2, "\n", 1);	_exit(1);    }    fswap(0, in);}/* * Redirect standard output. * Same assumptions as for "infrom" above. */private outto (filename)String filename;{    Fileid out;    out = creat(filename, 0666);    if (out == -1) {	write(2, "can't write ", 12);	write(2, filename, strlen(filename));	write(2, "\n", 1);	_exit(1);    }    fswap(1, out);}/* * Swap file numbers, useful for redirecting standard input or output. */private fswap(oldfd, newfd)Fileid oldfd;Fileid newfd;{    if (oldfd != newfd) {	close(oldfd);	dup(newfd);	close(newfd);    }}

⌨️ 快捷键说明

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