diff options
Diffstat (limited to 'c/src/lib/librdbg/servtgt.c')
-rw-r--r-- | c/src/lib/librdbg/servtgt.c | 552 |
1 files changed, 0 insertions, 552 deletions
diff --git a/c/src/lib/librdbg/servtgt.c b/c/src/lib/librdbg/servtgt.c deleted file mode 100644 index de41abc1a6..0000000000 --- a/c/src/lib/librdbg/servtgt.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - ************************************************************************** - * - * Component: RDB servers - * Module: servtgt.c - * - * $Id$ - * - ************************************************************************** - */ - - -#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. - ---------------------------------------------------------------- */ - -int TgtBreakRestoreOrig (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) - -void TgtBreakCancelStep (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. - ----------------------------------------------------------------------- */ - - void -TgtCreateNew(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. - ----------------------------------------------------------------------- */ - - void -TgtNotifyWaitChange( 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. - ----------------------------------------------------------------------- */ - - void - TgtNotifyAll( 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. - ----------------------------------------------------------------------- */ - -void TgtDelete(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. - ----------------------------------------------------------------------- */ - - int -TgtKillAndDelete( 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. - ----------------------------------------------------------------------- */ - - void -TgtDetachCon( 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 */ - } -} - -/* ----------------------------------------------------------------------- - TgtHandleChildChange - decide what action to take after wait() returns. - Used in the master only. - ----------------------------------------------------------------------- */ - -#ifdef DDEBUG -static 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 - -Boolean TgtHandleChildChange(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. - ----------------------------------------------------------------------- */ - -int TgtDbgPtrace(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 */ |