📄 process.c
字号:
pwait(p->pid, &status); sigs_on(); getinfo(p, status); if (p->status == STOPPED and 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 s, status; s = signo; do { setinfo(p, s); if (traceexec) { printf("!! pstep from 0x%x with signal %d (%d)\n", p->reg[PROGCTR], s, 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 (p->status == STOPPED and traceexec and not istraced(p)) { printf("!! pstep 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("!! pstep to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo); fflush(stdout); } if (p->status != STOPPED) { if (p->exitval == 0) { error("program exited\n"); } else { error("program exited with code %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, j; Address addr; int value; 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->sigcode = ptrace(UREAD, p->pid, &((struct user *) 0)->u_code, 0); 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]; } if (vectorcapable && vector_context()) { if(((single_stepping or inst_tracing) and found_a_vec_inst) or (!single_stepping and !inst_tracing)) { for (i = 0; i < NREG; i++) { for (j = 0; j < NVREG; j++) { value = ptrace(VREAD, p->pid, vregloc(A_VREGLO, i, j), 0); p->ovreg[i]->reg[j].val[0] = p->vreg[i]->reg[j].val[0] = value; value = ptrace(VREAD, p->pid, vregloc(A_VREGHI, i, j), 0); p->ovreg[i]->reg[j].val[1] = p->vreg[i]->reg[j].val[1] = value; } } p->ovcr = p->vcr = ptrace(VREAD, p->pid, vregloc(A_VCR, 0, 0), 0); p->ovlr = p->vlr = ptrace(VREAD, p->pid, vregloc(A_VLR, 0, 0), 0); p->ovaer = p->vaer = ptrace(VREAD, p->pid, vregloc(A_VAER, 0, 0), 0); p->ovmr.val[0] = p->vmr.val[0] = ptrace(VREAD, p->pid, vregloc(A_VMRLO, 0, 0), 0); p->ovmr.val[1] = p->vmr.val[1] = ptrace(VREAD, p->pid, vregloc(A_VMRHI, 0, 0), 0); } } 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, j; register int r, s; 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); p->oreg[i] = r; } } if (vectorcapable && vector_context()) { if(((single_stepping or inst_tracing) and found_a_vec_inst) or (!single_stepping and !inst_tracing)) { for (i = 0; i < NREG; i++) { for (j = 0; j < NVREG; j++) { r = p->vreg[i]->reg[j].val[0]; s = p->vreg[i]->reg[j].val[1]; if (r != p->ovreg[i]->reg[j].val[0]) { ptrace(VWRITE, p->pid, vregloc(A_VREGLO, i, j), r); p->ovreg[i]->reg[j].val[0] = r; } if (s != p->ovreg[i]->reg[j].val[1]) { ptrace(VWRITE, p->pid, vregloc(A_VREGHI, i, j), s); p->ovreg[i]->reg[j].val[1] = s; } } } if(p->ovcr != p->vcr) { ptrace(VWRITE, p->pid, vregloc(A_VCR, 0, 0), p->vcr); p->ovcr = p->vcr; } if(p->ovaer != p->vaer) { ptrace(VWRITE, p->pid, vregloc(A_VAER, 0, 0), p->vaer); p->ovaer = p->vaer; } if(p->ovlr != p->vlr) { ptrace(VWRITE, p->pid, vregloc(A_VLR, 0, 0), p->vlr); p->ovlr = p->vlr; } if(p->ovmr.val[0] != p->vmr.val[0]) { ptrace(VWRITE, p->pid, vregloc(A_VMRLO, 0, 0), p->vmr.val[0]); p->ovmr.val[0] = p->vmr.val[0]; } if(p->ovmr.val[1] != p->vmr.val[1]) { ptrace(VWRITE, p->pid, vregloc(A_VMRHI, 0, 0), p->vmr.val[1]); p->ovmr.val[1] = p->vmr.val[1]; } } } 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 */ }}/* * Flush the instruction cache associated with a process. */private cacheflush (p)Process p;{ bzero(p->word, sizeof(p->word));}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); }}/* * The signal is SIGTRAP, caught by the debugger, so reset the * sigstatus field to 0. */public resetsig(p)Process p;{ p->sigstatus = 0;}/* * Signal name manipulation. */private String signames[NSIG] = { 0, "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "LOST", "USR1", "USR2"};/* * Get the signal number associated with a given name. * The name is first translated to upper case if necessary. */public integer siglookup (s)String s;{ register char *p, *q; char buf[100]; integer i; p = s; q = buf; while (*p != '\0') { if (*p >= 'a' and *p <= 'z') { *q = (*p - 'a') + 'A'; } else { *q = *p; } ++p; ++q; } *q = '\0'; p = buf; if (buf[0] == 'S' and buf[1] == 'I' and buf[2] == 'G') { p += 3; } i = 1; for (;;) { if (i >= sizeof(signames) div sizeof(signames[0])) { error("signal \"%s\" unknown", s); i = 0; break; } if (signames[i] != nil and streq(signames[i], p)) { break; } ++i; } return i;}/* * Print all signals being ignored by the debugger. * These signals are auotmatically * passed on to the debugged process. */public printsigsignored (p)Process p;{ printsigs(~p->sigset);}/* * Print all signals being intercepted by * the debugger for the specified process. */public printsigscaught(p)Process p;{ printsigs(p->sigset);}private printsigs (set)integer set;{ integer s; char separator[2]; separator[0] = '\0'; for (s = 1; s < sizeof(signames) div sizeof(signames[0]); s++) { if (set & setrep(s)) { if (signames[s] != nil) { printf("%s%s", separator, signames[s]); separator[0] = ' '; separator[1] = '\0'; } } } if (separator[0] == ' ') { putchar('\n'); }}/* get the vector registers from the coredump file and put them into * the process structure. */put_vregs(f)File f;{ int i, j; Word value; for (i = 0; i < NREG; i++) { for (j = 0; j < NVREG; j++) { value = readvregfromfile(corefile, vregloc(A_VREGLO, i, j)); process->ovreg[i]->reg[j].val[0] = process->vreg[i]->reg[j].val[0] = value; value = readvregfromfile(corefile, vregloc(A_VREGHI, i, j)); process->ovreg[i]->reg[j].val[1] = process->vreg[i]->reg[j].val[1] = value; if(!coredump) return; } } process->ovcr = process->vcr = readvregfromfile(corefile, vregloc(A_VCR, 0, 0)); process->ovaer = process->vaer = readvregfromfile(corefile, vregloc(A_VAER, 0, 0)); process->ovlr = process->vlr = readvregfromfile(corefile, vregloc(A_VLR, 0, 0)); process->ovmr.val[0] = process->vmr.val[0] = readvregfromfile(corefile, vregloc(A_VMRLO, 0, 0)); process->ovmr.val[1] = process->vmr.val[1] = readvregfromfile(corefile, vregloc(A_VMRHI, 0, 0));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -