📄 servrpc.c
字号:
out.addr.ptrace_addr_data_out_u.mem.dataNb = 0; else { int maxLen = sizeof(out.addr.ptrace_addr_data_out_u.mem.data) - 1; data = strlen (plst->name); if (data > maxLen) data = maxLen; out.addr.ptrace_addr_data_out_u.mem.dataNb = data + 1; memcpy (out.addr.ptrace_addr_data_out_u.mem.data, plst->name, data + 1); out.addr.ptrace_addr_data_out_u.mem.data[maxLen] = '\0'; } req = 0; break; case RPT_CONTTO: if (BreakSetAt (plst, conn_idx, (u_long) addr, BRKT_STEPEMUL) < 0) { DPRINTF (("ptrace_2_svc: BreakSet failed at %x", addr)); break; } req = RPT_CONT; /* * data can contain a signal number, addr2 is unused */ goto case_RPT_CONT; case RPT_STEPRANGE: /* * convert to step */ if (!data) data = 1; /* should we give an error?? */ BreakStepRange (plst, addr, data); if (getErrno ()) break; req = RPT_SINGLESTEP; /* do by stepping */ addr = (void *) 1; /* start from current PC */ data = -2; /* want non-atomic stepping */ /* * fall through to other exec cases */ case RPT_CONT: case_RPT_CONT: case RPT_SINGLESTEP: if (BreakStepOff (plst, &addr2)) { /* need clear then step off break */ /* * clear break, step, then do exec */ if (addr == (void *) 1) addr = (void *) plst->regs.REG_PC; /* need for patch */ /* * data is always 0, so atomic single-step */ } else if (req == RPT_SINGLESTEP) { data = -2; /* want non-atomic stepping */ } break; /* * now ones where addr points to an output area */ case RPT_PGETTHREADREGS: addr = (void *) out.addr.ptrace_addr_data_out_u.mem.data; if (sizeof(out.addr.ptrace_addr_data_out_u.mem.data) < REG_COUNT * sizeof (int)) { setErrno (EINVAL); break; } if (data == plst->thread) { out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int *) & plst->regs; req = 0; /* force exit */ break; } req = RPT_GETTHREADREGS; break; case RPT_GETTHREADREGS: addr = (void *) &out.addr.ptrace_addr_data_out_u.regs; break; case RPT_GETTHREADNAME: out.addr.ptrace_addr_data_out_u.name = local_buff.t_name; addr = (void *) out.addr.ptrace_addr_data_out_u.name; break; case RPT_THREADLIST: out.addr.ptrace_addr_data_out_u.threads.threads = (ptThreadList) local_buff.t_list; addr = (void *) out.addr.ptrace_addr_data_out_u.threads.threads; break; case RPT_READTEXT: case RPT_READDATA: if ((int) data < 0) { setErrno (EINVAL); break; } addr = (void *) in->addr.ptrace_addr_data_in_u.address; addr2 = (void *) out.addr.ptrace_addr_data_out_u.mem.data; out.addr.ptrace_addr_data_out_u.mem.dataNb = data; break; case RPT_DETACH: /* * Do not allow detaching if breakpoints still there */ if (BreakGet (plst, 0, NULL)) { /* some bkpts still set */ setErrno (EINVAL); /* cannot detach safely */ break; } /* * fall through */ case RPT_KILL: /* * in the event they are trying to detach or kill a terminated process, * we just delete the entry. */ if (PROC_TERMINATED (plst)) { TgtDelete (plst, -1, BMSG_KILLED); /* just blow off */ req = 0; /* now exit */ } break; } if (getErrno ()) { /* failed in code above */ out.result = -1; out.errNo = getErrno (); DPRINTF (("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); return (&out); } else if (!req) { /* bail out now */ DPRINTF (("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); return (&out); } /* * OK, make the call */ out.result = TgtPtrace (req, pid, addr, data, addr2); out.errNo = getErrno (); /* * if no error, cleanup afterwards */ if (getErrno ()) { /* * Remove step-emul breakpoints if any */ if (req == RPT_SINGLESTEP || req == RPT_CONT) { BreakClear (plst, -1, -1); } DPRINTF (("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); return (&out); /* return error */ } switch (in->addr.req) { /* handle some special calls that affect state */ case RPT_CONT: case RPT_STEPRANGE: /* * change to running */ if (in->addr.req == RPT_STEPRANGE) plst->last_start = LAST_RANGE; /* so range steps */ else if (addr2) plst->last_start = LAST_STEPOFF; /* now continue after wait */ else plst->last_start = LAST_CONT; plst->running = 1; /* mark as running */ if (!rqstp) /* Called internally to restart bkpt, no msg to anybody */ break; TgtNotifyAll (pid_idx, BMSG_WAIT, 0, 0, (in->flags & PTRFLG_NON_OWNER) ? -1 : conn_idx, True); break; case RPT_SINGLESTEP: /* * mark as step */ plst->last_start = LAST_STEP; /* so we know how started */ plst->running = 1; /* mark as running (wait should catch fast) */ break; case RPT_DETACH: /* mark as disconnected */ case RPT_KILL: /* mark as killed */ if (in->flags & PTRFLG_FREE) /* notify and delete entry */ TgtDelete (plst, -1, (in->addr.req == RPT_KILL) ? BMSG_KILLED : BMSG_DETACH); else { /* notify and mark */ plst->last_start = (in->addr.req == RPT_KILL) ? LAST_KILLED : LAST_DETACHED; plst->state = -1; plst->running = False; TgtNotifyAll (pid_idx, (in->addr.req == RPT_KILL) ? BMSG_KILLED : BMSG_DETACH, 0, 0, -1, True); } break; case RPT_SETTHREADREGS: case RPT_PSETTHREADREGS: if (data != plst->thread) break; DPRINTF (("ptrace_2_svc: pid %d target thread regs changed!\n", pid)); case RPT_SETREGS: case RPT_PSETREGS: /* * change our buffer as well */ if (plst->regs.REG_PC != ((xdr_regs *) addr)->REG_PC) BreakPcChanged (plst); plst->regs = *(xdr_regs *) addr; /* copy in */ break; /* * case RPT_PGETREGS has been handled locally above */ case RPT_PGETTHREADREGS: /* * We need to update pointer so that XDR works on return */ out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (void *) out.addr.ptrace_addr_data_out_u.mem.data; break; case RPT_PEEKTEXT: case RPT_PEEKDATA: case RPT_READDATA: case RPT_READTEXT: if (req < RPT_READDATA) { /* peek */ /* * addr is start */ data = sizeof (int); addr2 = &out.result; /* data buffer */ /* * Like read: addr is start, data is length, addr2 is buffer */ } BreakHide (plst, addr, data, addr2); break; case RPT_SETTARGETTHREAD: DPRINTF (("ptrace_2_svc: pid %d new target thread %d\n", pid, data)); TgtPtrace (RPT_GETREGS, pid, (char *) &plst->regs, 0, NULL); plst->thread = data; if (plst->break_list) { /* Forget we had to step off breakpoint */ BASE_BREAK *base = (BASE_BREAK *) plst->break_list; DPRINTF (("ptrace_2_svc: clr_step %d last_break %d\n", base->clr_step, base->last_break)); base->clr_step = 0; /* Not stopped on break */ base->last_break = 0; } break; case RPT_THREADLIST: out.addr.ptrace_addr_data_out_u.threads.nbThread = out.result; break; default: break; } /* end switch */ DPRINTF (("ptrace_2_svc 2: result %d errNo %d\n", out.result, out.errNo)); return (&out);}/* ----------------------------------------------------------------------- wait_info_2_svc - non-blocking wait request to check status. ----------------------------------------------------------------------- */ wait_out *RPCGENSRVNAME (wait_info_2_svc) (wait_in * in, struct svc_req *rqstp){ int conn_idx = TspConnGetIndex (rqstp); static wait_out out; /* output of pid and status */ int idx; PID_LIST *plst; memset (&out, 0, sizeof (out)); /* zero for safety */ out.reason = STOP_ERROR; /* assume the worst */ if (conn_idx == -1) { /* no connection, error */ DPRINTF (("wait_info_2_svc: msg from unknown debugger!\n")); out.wait_return = -1; out.errNo = ECHILD; /* closest error */ return (&out); } else { /* see if confirming message received */ if (conn_list[conn_idx].retry) TspMessageReceive (conn_idx, in->pid); } if (!in->pid) { /* warm test verify only */ /* * this call (pid==0) is made to confirm that that connection is still * active. */ /* * we let it fall through as an error since any use other than connection * reset would be an error (there is no pid0). */ } else { /* normal request */ idx = FindPidEntry (in->pid); if (idx >= 0) { /* found process they requested on */ plst = &pid_list[idx]; out.wait_return = plst->running ? 0 : in->pid; /* * return: 0 is running, pid is stopped/term */ out.errNo = 0; out.status = plst->state; /* last stopped reason if stopped */ out.thread = plst->thread; /* current thread (or -1 if none) from stop */ if (!out.wait_return) out.reason = STOP_NONE; /* running, no action */ else if (STS_SIGNALLED (out.status)) { /* stopped on signal */ out.handle = STS_GETSIG (out.status); /* signal number */ if (out.handle == SIGTRAP) if (plst->is_step) { /* single step with hitting a break */ out.reason = STOP_STEP; out.handle = 0; /* no information */ } else { /* stopped on break */ out.reason = STOP_BREAK; if (plst->break_list) out.handle = ((BASE_BREAK *) plst->break_list)->last_break; else out.handle = 0; /* no break */ } else out.reason = STOP_SIGNAL; out.PC = plst->regs.REG_PC; /* copy standard regs */ out.SP = plst->regs.REG_SP; out.FP = plst->regs.REG_FP; } else { /* terminated, so lower use count */ if (plst->last_start == LAST_KILLED) out.reason = STOP_KILLED; else if (plst->last_start == LAST_DETACHED) out.reason = STOP_DETACHED; else if (plst->last_start == LAST_START) { /* failed in exec */ out.reason = STOP_SPAWN_FAILED; out.handle = STS_GETCODE (out.status); /* errno reason */ } else if (STS_TERMONSIG (out.status)) { /* terminated on signal */ out.reason = STOP_TERM_SIG; /* * mask off the core-dumped bit 7 */ out.handle = (int) (unsigned) (u_char) STS_TERMGETSIG (out.status); } else { /* exit(2)ed */ out.reason = STOP_TERM_EXIT; out.handle = STS_GETCODE (out.status); /* code */ } } DPRINTF (("wait_info_2_svc: pid %d return %d status %x errNo %d" " reason %d handle %d pc %x sp %x fp %x thread %d\n", in->pid, out.wait_return, out.status, out.errNo, out.reason, out.handle, out.PC, out.SP, out.FP, out.thread)); return (&out); } } /* * if not found in list, we return error: no such process */ out.wait_return = -1; out.errNo = ESRCH; /* no process */ out.status = 0; return (&out);}/* ----------------------------------------------------------------------- get_signal_names_2_svc - return names for signals ----------------------------------------------------------------------- */static one_signal SignalNames[] = { {SIGILL, "SIGILL/EVT_ILL"}, {SIGTRAP, "SIGTRAP/EVT_BKPT"}, {SIGFPE, "SIGFPE/EVT_FPE"}, {SIGKILL, "SIGKILL/EVT_AKILL"}, {SIGSEGV, "SIGSEGV/EVT_SEGV"}, {17, "SIGSTOP"}, {23, "SIGSTOP"}}; get_signal_names_out *RPCGENSRVNAME (get_signal_names_2_svc) (void * in, struct svc_req * rqstp){ static get_signal_names_out out; out.signals.all_signals_len = sizeof (SignalNames) / sizeof (SignalNames[0]); out.signals.all_signals_val = SignalNames; return (&out);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -