📄 servtgt.c
字号:
/* ----------------------------------------------------------------------- TgtHandleChildChange - decide what action to take after wait() returns. Used in the master only. ----------------------------------------------------------------------- */#ifdef DDEBUGstatic char *LastStartNames[] = { "NONE", "STEP", "CONT", "RANGE", "STEPOFF", "KILLED", "DETACHED"}; char *GetLastStartName (int last_start){ static char buf[32]; strcpy (buf, LastStartNames[last_start & ~LAST_START]); if (last_start & LAST_START) { strcat (buf, "+START"); } return buf;}#endif BooleanTgtHandleChildChange (PID pid, int *status, int *unexp, CPU_Exception_frame * ctx){ /* return False if continue, else stop */ int idx, sig; int bidx = 0; PID_LIST *plst; unsigned long PC; BASE_BREAK *base = NULL; /* break_list[0] is really BASE_BREAK */ int hadStepEmul; int origHadStepEmul; int stopWanted; DPRINTF (("TgtHandleChildChange: pid %d status %x cap\n", (int) pid, *status)); if (unexp) *unexp = 0; /* initialize to ok */ /* * first, find pid in question */ idx = FindPidEntry (pid); if (idx < 0) { /* cannot locate this process */ DPRINTF (("TgtHandleChildChange: unknown process (%s pid)\n", FindPidEntry (pid) >= 0 ? "stale" : "unknown")); if (unexp) *unexp = 1; /* Unexpected change */ return (False); /* unknown: ignore (used to stop and notify) */ } /* * found */ plst = &pid_list[idx]; /* pointer to entry */ /* * first we see if just stopped */ /* * copy ctxt */ CtxToRegs (ctx, &(plst->regs)); stopWanted = plst->stop_wanted; plst->stop_wanted = 0; /* For the next time */ hadStepEmul = BreakClear (plst, -1, -1) > 0; origHadStepEmul = hadStepEmul; /* hadStepEmul is cleared if real bkpt met */ if (STS_SIGNALLED (*status)) { /* stopped, not terminated */ sig = STS_GETSIG (*status); /* signal that stopped us */ /* * now, we read the registers and see what to do next */ if (TgtPtrace (RPT_GETREGS, pid, (void *) &plst->regs, 0, NULL) < 0) { memset (&plst->regs, 0, sizeof (plst->regs)); } /* * Get current thread */ plst->thread = TgtPtrace (RPT_GETTARGETTHREAD, pid, NULL, 0, NULL); if (sig == SIGTRAP) { /* stopped from break/step */ PC = plst->regs.REG_PC; /* * Must check PC to see whether in situations where we had * step emulation we are on a breakpoint or just * have returned from an emulated single-step */ if (BreakIdentify (plst, 0 /*no adjust */ , -1 /*no thread */ ) > 0) { hadStepEmul = 0; } plst->is_step = hadStepEmul || IS_STEP (plst->regs) || plst->last_start == LAST_START; DPRINTF (("TgtHandleChildChange: %s last_start %s\n", plst->is_step ? "step" : "break", GetLastStartName (plst->last_start))); if ((plst->is_step || origHadStepEmul || stopWanted) && (plst->last_start == LAST_STEP || plst->last_start == LAST_STEPOFF || plst->last_start == LAST_RANGE)) { DPRINTF (("TgtHandleChildChange: restoring stepped-off bkpt\n")); BreakSteppedOff (plst); } if (plst->last_start == LAST_STEPOFF && (plst->is_step || origHadStepEmul)) { /* stepped off break and now need cont */ DPRINTF (("TgtHandleChildChange: auto-resuming after step-off\n")); plst->last_start = LAST_CONT; /* convert to normal cont */ if (!stopWanted) { if (TgtPtrace (RPT_CONT, pid, (char *) 1, 0, NULL)) return True; /* tell people */ return (False); /* wait for change */ } DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-off\n", stopWanted)); *status = STS_MAKESIG (stopWanted); return True; /* Stop and notify */ } base = plst->break_list ? ((BASE_BREAK *) plst->break_list) : ((BASE_BREAK *) NULL); /* * now see if step in range */ if (plst->last_start == LAST_RANGE /* step in range */ && (plst->is_step || origHadStepEmul) /* not a breakpoint */ &&PC >= base->range_start && PC <= base->range_end) { /* still in range, keep going */ if (stopWanted) { DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-range\n", stopWanted)); } else { DPRINTF (("TgtHandleChildChange: Reservation at %x\n", plst->regs.REG_PC)); } } if (!plst->is_step) { /* was break */ bidx = BreakIdentify (plst, 1 /*adjust */ , plst->thread); if (bidx == 0) { DPRINTF (("TgtHandleChildChange: forwarding bkpt to kernel\n")); if (unexp) { *unexp = 1; } return False; } if (bidx < 0) { /* Unwanted breakpoint, must step it off */ ptrace_in pin; ptrace_out *out; if (origHadStepEmul) { DPRINTF (("TgtHandleChildChange: bkpt %x becomes step\n", plst->regs.REG_PC)); bidx = -bidx; plst->is_step = 1; base->clr_step = plst->break_list[bidx].type == BRKT_INSTR; base->last_break = bidx; return True; } if (stopWanted) { DPRINTF (("TgtHandleChildChange: stop_wanted %d at bkpt %x\n", stopWanted, plst->regs.REG_PC)); /* * The PC has already been adjusted by BreakIdentify */ *status = STS_MAKESIG (stopWanted); return True; } /* * All the handling is done in ptrace_2_svc() so call it */ bidx = -bidx; DPRINTF (("TgtHandleChildChange: last %d (%s) restarting bkpt %d\n", plst->last_start, GetLastStartName (plst->last_start), bidx)); base->clr_step = 1; base->last_break = bidx; /* remember which one */ plst->running = 0; /* So that ptrace is accepted */ pin.pid = plst->pid; if (plst->last_start == LAST_STEP) { pin.addr.req = RPT_SINGLESTEP; } else { pin.addr.req = RPT_CONT; } pin.addr.ptrace_addr_data_in_u.address = 1; pin.data = 0; pin.flags = PTRFLG_NON_OWNER; out = RPCGENSRVNAME (ptrace_2_svc) (&pin, NULL); if (out->result == 0) return False; /* Continue waiting */ DPRINTF (("TgtHandleChildChange: failed to restart bkpt!\n")); /* * If something went wrong, just stop on breakpoint */ } } } /* * else sig != SIGTRAP */ /* * finally, fill in stop info in break point array base */ if (bidx > 0) { /* store break info */ /* * will need to get off the break for SW breakpoints only */ base->clr_step = plst->break_list[bidx].type == BRKT_INSTR; base->last_break = bidx; /* remember which one */ } else if (base) { /* clear break info */ base->clr_step = False; /* not stopped on break */ base->last_break = 0; } /* * decision to notify owner based on last_start */ } /* stopped */ else { /* terminated */ if (plst->last_start == LAST_START) { /* spawn failed */ TgtNotifyAll (idx, BMSG_EXEC_FAIL, 0, 0, -1, True); plst->running = False; /* not running - dead */ plst->state = *status; /* contains errno in high word */ return (False); } else if ((UCHAR) (plst->last_start & ~LAST_START) < (UCHAR) LAST_KILLED) plst->last_start = LAST_NONE; /* doesn't matter anymore */ else return (False); /* killed and detach already notified */ } return (True); /* stop and notify */}#ifdef DDEBUG/* * TgtDbgPtrace - debug version of ptrace. */ intTgtDbgPtrace (int request, PID pid, char *addr, int data, void *addr2){ int diag; DPRINTF (("TgtDbgPtrace: entered (%s (%d), %d, %x, %d, %x)\n", PtraceName (request), request, pid, (int) addr, data, (int) addr2)); if (request == RPT_WRITETEXT || request == RPT_WRITEDATA) { int i; DPRINTF (("TgtDbgPtrace:")); if (rdb_debug) { for (i = 0; i < data && i < 16; ++i) { printf (" %02x", ((char *) addr2)[i] & 0xFF); } printf ("\n"); } } diag = TgtRealPtrace (request, pid, addr, data, addr2); DPRINTF (("TgtDbgPtrace: returned %d (%x) errno %d\n", diag, diag, getErrno ())); if (request == RPT_GETREGS || request == RPT_GETTHREADREGS || request == RPT_SETREGS || request == RPT_SETTHREADREGS) { /* * Use DPRINTF() so as to have the id prefix */ DPRINTF (("TgtDbgPtrace: (%s) PC = %x, SP = %x, FP = %x\n", PtraceName (request), ((xdr_regs *) addr)->REG_PC, ((xdr_regs *) addr)->REG_SP, ((xdr_regs *) addr)->REG_FP)); } return (diag);}#endif /* DDEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -