📄 process.c
字号:
* * 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. We can either ignore * breakpoints (stepto) or catch them (contto). */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 { if (runfirst) { fprintf(stderr, "\nEntering debugger ...\n"); printheading(); init(); } 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);}/* * Predicate to test if the reason the process stopped was because * of a breakpoint. If so, as a side effect clear the local copy of * signal handler associated with process. We must do this so as to * not confuse future stepping or continuing by possibly concluding * the process should continue with a SIGTRAP handler. */public boolean isbperr(){ Process p; boolean b; p = process; if (p->status == STOPPED and p->signo == SIGTRAP) { b = true; p->sigstatus = 0; } else { b = false; } return b;}/* * Return the signal number that stopped the process. */public integer errnum (p)Process p;{ return p->signo;}/* * Return the signal code associated with the signal. */public integer errcode (p)Process p;{ return p->sigcode;}/* * 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. */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; badaddr = addr; if (coredump) { f = onsyserr(EFAULT, read_err); coredump_readdata(buff, addr, nbytes); onsyserr(EFAULT, f); } else { f = onsyserr(EIO, read_err); 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. */#define WMASK (~(sizeof(Word) - 1))#define cachehash(addr) ((unsigned) ((addr >> 2) % CACHESIZE))#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 */#ifdef IRIS# define readreg(p, r) ptrace(10, p->pid, r, 0)# define writereg(p, r, v) ptrace(11, p->pid, r, v)#else# define readreg(p, r) ptrace(UREAD, p->pid, regloc(r), 0);# define writereg(p, r, v) ptrace(UWRITE, p->pid, regloc(r), v);#endif/* * 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); cacheflush(p); } fflush(stdout); psigtrace(p, SIGTRAP, true);# ifdef IRIS p->pid = fork();# else p->pid = vfork();# endif if (p->pid == -1) { panic("can't fork"); } if (ischild(p->pid)) { nocatcherrs(); traceme(); if (infile != nil) { infrom(infile); } if (outfile != nil) { outto(outfile); } execv(argv[0], argv); _exit(1); } pwait(p->pid, &status); getinfo(p, status); if (p->status != STOPPED) { beginerrmsg(); fprintf(stderr, "warning: cannot execute %s\n", argv[0]); } else { 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 is 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 (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 mc68000 || m68000 if (p->status == STOPPED and p->signo == SIGTRAP) { p->reg[PROGCTR] += 2; }# endif 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -