📄 servtgt.c
字号:
/* ************************************************************************** * * Component: RDB servers * Module: servtgt.c * * $Id: servtgt.c,v 1.3 2002/02/01 17:00:01 joel Exp $ * ************************************************************************** */#include <string.h>#include <sys/errno.h>#include <rdbg/rdbg.h>#include <rdbg/servrpc.h>#include <sys/socket.h>#include <assert.h>#ifdef DDEBUG#define Ptrace TgtDbgPtrace#else#define Ptrace TgtRealPtrace#endif/* * TgtBreakRestoreOrig - Restore original instruction at "addr" * just before single-stepping it. */ intTgtBreakRestoreOrig (int pid, void *addr, void *addr2) /* * Process identifier */ /* * Breakpoint address */ /* * Original instruction or bkpt number */{ int ret; int l; l = (long) Ptrace (RPT_PEEKTEXT, pid, addr, 0, NULL); /* assume ok */ ret = ORG_BREAK (l, (UINT32) addr2); /* reconstruct old instr */ ret = Ptrace (RPT_POKETEXT, pid, addr, ret, NULL); /* poke back old */ return ret;}/* * * TgtBreakCancelStep - Restore the breakpoint at "addr" if the single-step * has failed at the ptrace level. */#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) voidTgtBreakCancelStep (PID_LIST * plst){ assert (plst->break_list); assert (BKPT0 (plst)->clr_step); if (plst->break_list && BKPT0 (plst)->clr_step) { int idx = BKPT0 (plst)->last_break; int data; data = Ptrace (RPT_PEEKTEXT, plst->pid, (char *) plst->break_list[idx].ee_loc, 0, NULL); assert (!IS_BREAK (data)); Ptrace (RPT_POKETEXT, plst->pid, (char *) plst->break_list[idx].ee_loc, (int) SET_BREAK (data), NULL); }}/* * TgtCreateNew - add a new process into the process management lists. */ voidTgtCreateNew (PID pid, int conn, INT32 child, char *name, Boolean spawn){ int idx; for (idx = 0; idx < pid_list_cnt; idx++) if (!pid_list[idx].pid) break; /* find empty */ if (idx >= pid_list_cnt) { /* no empties, add more */ PID_LIST *tmp_pid_list = pid_list; pid_list_cnt += PID_LIST_INC; pid_list = (PID_LIST *) Realloc (pid_list, /* get new or extend */ pid_list_cnt * sizeof (PID_LIST)); if (!pid_list) { /* out of memory */ pid_list_cnt -= PID_LIST_INC; if (pid_list_cnt) { /* realloc failed - malloc again */ pid_list = tmp_pid_list; /* * above relies on old pointer being valid after failed realloc */ } return; /* failed */ } /* * now clear newly added space */ memset (pid_list + pid_list_cnt - PID_LIST_INC, 0, PID_LIST_INC * sizeof (PID_LIST)); idx = pid_list_cnt - PID_LIST_INC; } else /* clear entry we found */ memset (&pid_list[idx], 0, sizeof (PID_LIST)); /* * now fill in empty entry */ pid_list[idx].pid = pid; pid_list[idx].running = 1; /* we have not called wait yet */ pid_list[idx].primary_conn = (UCHAR) conn; /* primary owner */ if (conn != -1) { /* found caller */ pid_list[idx].owners = 1; PIDMAP_SET (conn, idx); /* mask in */ } pid_list[idx].thread = (UINT32) - 1; /* no thread for now */ pid_list[idx].last_start = LAST_START; /* handle MiX bug */ pid_list[idx].name = name ? (char *) StrDup (name) : (char *) NULL;}/* * TgtNotifyWaitChange - send event to clients indicating child changed state. */ voidTgtNotifyWaitChange (PID pid, int status, Boolean exclude){ int conn, idx; idx = FindPidEntry (pid); /* locate the pid that changed */ if (idx < 0) { DPRINTF (("TgtNotifyWaitChange: pid %d not in our list\n", (int) pid)); return; /* not in our list */ } pid_list[idx].running = 0; /* not running */ pid_list[idx].state = status; /* save status of stop/term */ if (!pid_list[idx].owners && !STS_SIGNALLED (status)) TgtDelete (&pid_list[idx], -1, 0); /* terminated and no owners */ else { /* normal cases */ for (conn = 0; conn < conn_list_cnt; conn++) { /* now find all interested clients */ if (!conn_list[conn].in_use /* free entry */ || !PIDMAP_TEST (conn, idx)) continue; /* not using this pid */ if (conn == exclude) continue; /* do not do this one */ TspSendWaitChange (conn, BMSG_WAIT, 1, pid, 0, False); /* notify of change */ } }}/* * TgtNotifyAll - send a message to all clients interested in process. */ voidTgtNotifyAll (int pid_idx, BACK_MSG msg, UINT16 spec, UINT32 context, int exclude, Boolean force){ int conn; DPRINTF (("TgtNotifyAll: msg %d (%s) for pid_idx=%d (%d,%d)\n", msg, BmsgNames[msg], pid_idx, exclude, force)); for (conn = 0; conn < conn_list_cnt; conn++) if (conn_list[conn].in_use /* not free */ && PIDMAP_TEST (conn, pid_idx)) { if (conn != exclude) TspSendWaitChange (conn, msg, spec, pid_list[pid_idx].pid, context, force); }}/* * TgtDelete - mark process as now uncontrolled. * * Notes: * - this function removes a process from the process list. * - the notify argument indicates a message to send if needed. */ voidTgtDelete (PID_LIST * plst, int conn_idx, BACK_MSG notify){ int idx = plst - pid_list, cnt, conn; /* * found */ cnt = pid_list[idx].owners; if (cnt) { /* some connections to break */ for (conn = 0; cnt && conn < conn_list_cnt; conn++) if (conn_list[conn].in_use /* not free */ && PIDMAP_TEST (conn, idx)) { /* found one that uses it */ PIDMAP_CLEAR (conn, idx); if (notify && conn != conn_idx) TspSendWaitChange (conn, notify, 0, plst->pid, 0, True); if (!--cnt) break; } } if (pid_list[idx].name) Free (pid_list[idx].name); /* free string name back */ /* * Free breakpoint list */ if (pid_list[idx].break_list != NULL) { Free (pid_list[idx].break_list); } pid_list[idx].pid = 0; /* gone */}/* * TgtKillAndDelete - kill or detach process and remove entry. */ intTgtKillAndDelete (PID_LIST * plst, struct svc_req *rqstp, Boolean term){ ptrace_in pin; /* used for ptrace call */ ptrace_out *pout; /* * Remove breakpoints */ if (plst->break_alloc > 0) { pin.pid = plst->pid; pin.addr.req = RPT_CLRBREAK; pin.data = 0; /* clear all */ pin.flags = PTRFLG_NON_OWNER; pout = RPCGENSRVNAME (ptrace_2_svc) (&pin, rqstp); if (pout->result < 0) { DPRINTF (("TgtKillAndDelete: RPT_CLRBREAK failed %d\n", getErrno ())); return -1; } } if (term) { /* kill */ pin.addr.ptrace_addr_data_in_u.address = 0; pin.data = -1; /* Don't want notification from slave */ pin.addr.req = RPT_KILL; } else { /* detach */ pin.addr.ptrace_addr_data_in_u.address = 1; pin.data = 0; pin.addr.req = RPT_DETACH; } pin.pid = plst->pid; pin.flags = PTRFLG_FREE | PTRFLG_NON_OWNER; DPRINTF (("TgtKillAndDelete: ptrace_2_svc (%s (%d), %d)\n", PtraceName (pin.addr.req), pin.addr.req, pin.pid)); pout = RPCGENSRVNAME (ptrace_2_svc) (&pin, rqstp); /* start it */ if (pout->errNo == ESRCH && plst->pid) TgtDelete (plst, -1, BMSG_KILLED); /* only entry remains */ return 0;}/* * TgtDetachCon - detach a connection's ownership of a process. */ voidTgtDetachCon (int conn_idx, int pid_idx, Boolean delete){ if ((unsigned) pid_idx >= pid_list_cnt || !pid_list[pid_idx].pid) return; /* not valid */ if (PIDMAP_TEST (conn_idx, pid_idx)) { /* if an owner, release control */ PIDMAP_CLEAR (conn_idx, pid_idx); if (pid_list[pid_idx].owners) pid_list[pid_idx].owners--; if (pid_list[pid_idx].primary_conn == conn_idx) pid_list[pid_idx].primary_conn = NO_PRIMARY; if (delete && !pid_list[pid_idx].owners && PROC_TERMINATED (pid_list + pid_idx)) TgtDelete (&pid_list[pid_idx], -1, 0); /* remove entry */ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -