📄 servbkpt.c
字号:
/* ********************************************************************** * * Component: RDB servers * Module: servbkpt.c * * Synopsis: Management of breakpoints * * $Id: servbkpt.c,v 1.3 2002/02/01 17:00:01 joel Exp $ * ********************************************************************** */#include <sys/errno.h>#include <assert.h>#include <rdbg/rdbg.h>#include <rdbg/servrpc.h>/*----- Macros -----*/#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list)#define BKPT_INCR 5 /* how many bkpt slots alloc at a time */#define BKPT_OVER(plst,idx,addr,size) \ ((plst)->break_list[idx].ee_loc + BREAK_SIZE > (UINT32) (addr) \ && (plst)->break_list[idx].ee_loc < (UINT32) (addr) + (size))#define BKPT_SLOTS \ (sizeof ((xdr_break*) 0)->thread_list / \ sizeof ((xdr_break*) 0)->thread_list [0]) /* * BreakAlloc - alloc a breakpoint entry. * * This is a generic routine to insert an entry in the * breakpoint list. It returns the number of entry just * created. It returns -1 if failed. */ static intBreakAlloc (PID_LIST * plst, Boolean normal){ int idx, len; xdr_break *blst; if (!normal) { /* want 0 entry */ if (plst->break_list) { return (0); /* already there */ } idx = 1; /* force alloc below */ } else { for (idx = 1; idx < (int) plst->break_alloc; idx++) { if (plst->break_list[idx].type == BRKT_NONE) { /* * got a free one */ memset (&plst->break_list[idx], 0, sizeof (xdr_break)); return (idx); /* found one */ } } } /* * idx is the requested entry */ if (idx >= (int) plst->break_alloc) { /* need more space */ len = plst->break_alloc + BKPT_INCR; blst = (xdr_break *) Realloc (plst->break_list, len * sizeof (xdr_break)); if (!blst) { return (-1); /* failed, no space */ } plst->break_alloc = len; /* got more */ plst->break_list = blst; /* * Clear new space */ memset (blst + len - BKPT_INCR, 0, BKPT_INCR * sizeof (xdr_break)); idx = len - BKPT_INCR; /* next available */ if (!idx) { idx = 1; /* for normal cases */ } } return (normal ? idx : 0); /* return it */} /* * BreakSet - set a breakpoint in process * * Returns the number or -1/errno. */#ifdef DDEBUGstatic const char *BreakTypes[] = { "NONE", "INSTR", "READ", "WRITE", "ACCESS", "EXEC", "OS_CALL", "OS_SWITCH", "STEPEMUL"};#define BN_MAX (sizeof BreakTypes / sizeof BreakTypes[0])#define BREAK_NAME(t) ((unsigned) (t) < BN_MAX ? BreakTypes[t] : "???")#endif intBreakSet (PID_LIST * plst, int conn_idx, xdr_break * bkpt){ int pid = plst->pid; int type = bkpt->type; void *addr = (void *) bkpt->ee_loc; int idx; int data; DPRINTF (("BreakSet: type %d (%s) at 0x%x th %d ee_type %d len %d " "pass %d curr %d list %d %d %d %d\n", type, BREAK_NAME (type), (int) addr, bkpt->thread_spec, bkpt->ee_type, bkpt->length, bkpt->pass_count, bkpt->curr_pass, bkpt->thread_list[0], bkpt->thread_list[1], bkpt->thread_list[2], bkpt->thread_list[3])); idx = BreakAlloc (plst, True); /* get entry */ if (idx < 0) { /* no memory */ setErrno (ENOMEM); /* set for safety */ return -1; /* return the error */ } data = TgtPtrace (RPT_PEEKTEXT, pid, addr, 0, NULL); /* current */ if (getErrno ()) { return -1; /* failed, return the error */ } if (IS_BREAK (data)) { /* There is already a break here */ DPRINTF (("BreakSet: already have soft bkpt at %x\n", addr)); if (type == BRKT_STEPEMUL) { ++BKPT0 (plst)->pad1; return 1; /* Any non-error value is OK */ } setErrno (EBUSY); return -1; } TgtPtrace (RPT_POKETEXT, pid, addr, SET_BREAK (data), NULL); if (getErrno ()) { return -1; } plst->break_list[idx] = *bkpt; plst->break_list[idx].ee_type = data; /* saved data */ /* * Inform other owners */ if (type != BRKT_STEPEMUL) { TgtNotifyAll (plst - pid_list, BMSG_BREAK, 1 /*added */ , idx, conn_idx, False); } else { ++BKPT0 (plst)->pad1; } /* * Return the number */ setErrno (0); /* Just in case */ return idx;} intBreakSetAt (PID_LIST * plst, int conn_idx, unsigned long addr, break_type type){ xdr_break xb; memset (&xb, 0, sizeof xb); xb.type = type; xb.ee_loc = addr; return BreakSet (plst, conn_idx, &xb);}/*----- Find a breakpoint by address -----*/ intBreakGetIndex (PID_LIST * plst, void *addr){ int idx; int data = -1; if (!plst->break_alloc) { setErrno (EFAULT); return -1; } for (idx = 1; idx < (int) plst->break_alloc; idx++) { if ((u_long) addr == plst->break_list[idx].ee_loc) { data = idx; break; } } return data;}/*----- Getting information about breakpoint -----*/ /* * If data > 0, fill "bkpt" with information about breakpoint * and return the number of the next one. * If data == 0, return the count of breakpoints. */ intBreakGet (const PID_LIST * plst, int data, xdr_break * bkpt){ int idx; if (!data) { /* just count them */ for (idx = 1; idx < (int) plst->break_alloc; idx++) { if (plst->break_list[idx].type != BRKT_NONE) { data++; } } return data; /* count */ } if ((unsigned) data >= plst->break_alloc) { /* * out of range */ setErrno (EFAULT); /* closest match */ return -1; } /* * get it and say which is next */ *bkpt = plst->break_list[data]; for (idx = (int) data + 1; idx < (int) plst->break_alloc; idx++) { if (plst->break_list[idx].type != BRKT_NONE) { return idx; } } return 0; /* otherwise returns 0 for no more */}/*----- Clearing bkpts -----*/ /* * BreakClear - clear one (if data != 0) or all breakpoints * (if data == 0). Return the number of bkpts cleared. * If (data == -1), remove step-emulation breakpoints. */ intBreakClear (PID_LIST * plst, int conn_idx, int data){ int pid_idx = plst - pid_list; int idx; int cleared = 0; int clearStepEmul = 0; int terminated = PROC_TERMINATED (plst); int stepEmulCount = 0; /* * break handle in data */ if (!plst->break_alloc) { /* there are no breaks */ DPRINTF (("BreakClear: no bkpts defined.\n")); setErrno (EFAULT); /* closest match */ return -1; /* return error */ } if (!data) { /* clear all */ idx = 1; data = plst->break_alloc - 1; /* * Inform other owners */ DPRINTF (("BreakClear: clearing all bkpts.\n")); TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr */ , 0, conn_idx, False); } else if (data == -1) { /* clear all step-emul bkpts */ DPRINTF (("BreakClear: removing %d step-emul bkpts\n", BKPT0 (plst)->pad1)); stepEmulCount = BKPT0 (plst)->pad1; BKPT0 (plst)->pad1 = 0; clearStepEmul = 1; idx = 1; data = plst->break_alloc - 1; } else if ((unsigned) data >= plst->break_alloc || plst->break_list[data].type == BRKT_NONE) { /* * out of range */ DPRINTF (("BreakClear: invalid bkpt %d\n", data)); setErrno (EFAULT); /* closest match */ return -1; /* return error */ } else { idx = data; /* * Inform other owners */ TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr */ , idx, conn_idx, False); DPRINTF (("BreakClear: clearing bkpt %d\n", data)); } for (; idx <= data; idx++) { /* clear each one */ int type = plst->break_list[idx].type; if (clearStepEmul && type != BRKT_STEPEMUL) continue; if (type == BRKT_INSTR || (clearStepEmul && type == BRKT_STEPEMUL)) { /* * just patch back */ char *addr = (char *) plst->break_list[idx].ee_loc; int val; if (BKPT0 (plst)->clr_step && BKPT0 (plst)->last_break == idx) { BKPT0 (plst)->clr_step = 0; /* not needed */ } /* * Neighboring bytes can have breakpoints too... */ if (!terminated) { setErrno (0); val = TgtPtrace (RPT_PEEKTEXT, plst->pid, addr, 0, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -