📄 dbgtasklib.c
字号:
wdbDbgBpRemoveAll(); /* * if Single Step Mode (i.e. Trace Mode) doesn't exist on the CPU, * insert a breakpoint on the next instruction. */#if DBG_NO_SINGLE_STEP taskNpc = wdbDbgGetNpc(&pNewTcb->regs); taskNpcInstr = *taskNpc; usrBreakpointSet (taskNpc, DBG_BREAK_INST);#endif /* DBG_NO_SINGLE_STEP */ taskTraceData = wdbDbgTraceModeSet (&pNewTcb->regs); } else { /* remove breakpoints for old task and install them for new task */ dbgTaskBpInstall((int)pNewTcb); } }/********************************************************************************* dbgBrkIgnoreDefault - true if in situation to ignore breakpoint** This is the default boolean function whose output determines whether the* current task is in a situation where a breakpoint is to be ignored. This* routine is called indirectly via the global variable dbgBrkIgnore from the* routine dbgBreakpoint.** This routine specifies to ignore breakpoints if the breakpoint occurred in* any of these situations:* (1) at interrupt level* (2) within kernel* (3) while task was unbreakable* (4) while preemption was disabled and dbgLockUnbreakable is TRUE* (5) while task was safe from deletion and dbgSafeUnbreakable is TRUE** Note that (3) is actually an assertion because currently breakpoints are* removed when a task is unbreakable. But it might change someday.** MS - removed check for (3) since I want to optionally allow non-breaking* windview "eventpoints" in VX_UNBREAKABLE tasks (e.g., VX_UNBREAKABLE* just means that the eventpoint can't cause the task to stop).** RETURNS :* TRUE if we should ignore the breakpoint FALSE otherwise** NOMANUAL*/LOCAL BOOL dbgBrkIgnoreDefault ( void ) { return ((intCnt > 0) || (kernelState == TRUE) ||#if FALSE (taskIdCurrent->options & VX_UNBREAKABLE) ||#endif /* FALSE */ ((taskIdCurrent->lockCnt != 0) && (dbgLockUnbreakable)) || ((taskIdCurrent->safeCnt != 0) && (dbgSafeUnbreakable))); }/******************************************************************************** dbgTaskBpBreakpoint - generic task breakpoint handling** This routines is the handler for breakpoints. It executes the actions* binded to the breakpoint (notify the host, notify the target, call a * user's specified routine or stop the task).** RETURNS : N/A.** NOMANUAL*/ void dbgTaskBpBreakpoint ( int level, /* level of interupt lock */ void * pInfo, /* pointer on info */ REG_SET * pRegisters, /* task registers before breakpoint exception */ void * pDbgRegs, /* pointer to debug registers */ BOOL hardware /* indicates if it is a hardware breakpoint */ ) { BRKPT bpInfo; /* breakpoint info structure */ UINT32 type = 0; /* breakpoint type */ UINT32 addr; /* breakpoint address */#if !DBG_NO_SINGLE_STEP /* If the os wants us to ignore the break point, then do so */ if (dbgBrkIgnoreDefault ()) { dbgTaskDoIgnore (pRegisters); }#endif /* DBG_NO_SINGLE_STEP */ taskLock(); /* LOCK PREEMPTION */ intUnlock(level); /* * By default (software break point), the break point address is the * pc of the task. */ addr = (UINT32) pRegisters->reg_pc;#if DBG_HARDWARE_BP /* If it is a hardware break point, update type and addr variable. */ if (hardware) wdbDbgHwBpFind (pDbgRegs, &type, &addr);#endif /* DBG_HARDWARE_BP */ /* * Find in the break point list the one we have encountered and fill in the * bpInfo structure. */ wdbDbgBpGet ((INSTR *) addr, (int)taskIdCurrent, type, &bpInfo); /* * On some CPU (eg I960CX), the hardware breakpoint exception is sent only * after the instruction was executed. In that case, we consider that * the breakpoint address is the address where the processor is stopped. */#if DBG_HARDWARE_BP && defined (BRK_INST) if (type == (BRK_INST | BRK_HARDWARE)) addr = (UINT32) pRegisters->reg_pc;#endif /* DBG_HARDWARE_BP && defined (BRK_INST) */ /* * Remove ACTION_STOP action if task is unbreakable. This is usefull * when two or more breakpoints are set at the same address, one with * action stop specified and one without. * XXX : this should be tested in wdbDbgBpGet() but in order to remove * all OS references in this routine used by the standalone agent debugger, * we can't check unbreakable flag in the task TCB. */ if (taskIdCurrent->options & VX_UNBREAKABLE) bpInfo.bp_action &= ~WDB_ACTION_STOP; /* store the break point address */ DBG_INFO(taskIdCurrent)->bpAddr = addr; /* check the action associated to the break point */ if (bpInfo.bp_action & WDB_ACTION_CALL) bpInfo.bp_callRtn (bpInfo.bp_callArg, pRegisters); if (bpInfo.bp_action & WDB_ACTION_NOTIFY) { /* notify the host if the notify function pointer is initialised */ if (_func_dbgHostNotify != NULL) _func_dbgHostNotify (taskIdCurrent, pRegisters, addr); /* notify the target if the notify function pointer is initialised */ if (_func_dbgTargetNotify != NULL) _func_dbgTargetNotify (bpInfo.bp_flags, addr, pRegisters); }#if CPU_FAMILY == MIPS /* * On MIPS CPUs, when a breakpoint exception occurs in a branch delay slot, * the PC has been changed in the breakpoint handler to match with the * breakpoint address. * Once the matching has been made, the PC is modified to have its normal * value (the preceding jump instruction). */ if (pRegisters->cause & CAUSE_BD) /* Are we in a branch delay slot ? */ pRegisters->reg_pc--;#endif /* CPU_FAMILY == MIPS */ if (bpInfo.bp_action & WDB_ACTION_STOP) { DBG_INFO(taskIdCurrent)->wdbRegisters = pRegisters; DBG_INFO(taskIdCurrent)->wdbState |= WDB_CLEANME; taskUnlock(); /* UNLOCK PREEMPTION */ for (;;) taskSuspend((int)taskIdCurrent); } /* !WDB_ACTION_STOP means continue (e.g., step over this break point) */ DBG_INFO(taskIdCurrent)->wdbState |= WDB_STEP_OVER; wdbDbgBpRemoveAll();#if DBG_NO_SINGLE_STEP taskNpc = wdbDbgGetNpc (pRegisters); taskNpcInstr = *taskNpc; usrBreakpointSet (taskNpc, DBG_BREAK_INST);#endif /* DBG_NO_SINGLE_STEP */ taskTraceData = wdbDbgTraceModeSet (pRegisters); intLock(); /* Unlock task without rescheduling */ taskIdCurrent->lockCnt--; /* Indicate change of taskLock state to WindView */ #ifdef WV_INSTRUMENTATION /* windview -level 3 event logging */ EVT_CTX_0 (EVENT_TASKUNLOCK); /* windview -level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_TASK, taskIdCurrent);#endif WDB_CTX_LOAD (pRegisters); }/******************************************************************************** dbgTaskBpTrace - generic task trace (step) handling** This routines is the handler for trace break point.** RETURNS : N/A.** NOMANUAL*/ void dbgTaskBpTrace ( int level, /* level of interupt lock */ void * pInfo, /* pointer to info saved on stack */ REG_SET * pRegisters /* pointer to saved registers */ ) { int wdbState;#if !DBG_NO_SINGLE_STEP if (isrTraceData != 0) dbgTaskDoneIgnore (pRegisters);#else /* DBG_NO_SINGLE_STEP */ usrBreakpointSet (taskNpc, taskNpcInstr);#endif /* !DBG_NO_SINGLE_STEP */ wdbDbgTraceModeClear (pRegisters, taskTraceData); DBG_INFO(taskIdCurrent)->bpAddr = (UINT32) pRegisters->reg_pc; if (DBG_INFO(taskIdCurrent)->wdbState & WDB_STEP_OVER) { DBG_INFO(taskIdCurrent)->wdbState &= ~WDB_STEP_OVER; dbgTaskBpInstall ((int)taskIdCurrent); WDB_CTX_LOAD (pRegisters); } if ((DBG_INFO(taskIdCurrent)->wdbState & WDB_STEP_RANGE) && (DBG_INFO(taskIdCurrent)->wdbEvtList.wdb1 <= (void *) pRegisters->reg_pc) && ((void *) pRegisters->reg_pc < DBG_INFO(taskIdCurrent)->wdbEvtList.wdb2)) {#if DBG_NO_SINGLE_STEP taskNpc = wdbDbgGetNpc(pRegisters); taskNpcInstr = *taskNpc; usrBreakpointSet (taskNpc, DBG_BREAK_INST);#endif /* DBG_NO_SINGLE_STEP */ taskTraceData = wdbDbgTraceModeSet (pRegisters); WDB_CTX_LOAD (pRegisters); } taskLock(); /* LOCK PREEMPTION */ intUnlock(level); /* blindly assume WDB_STEP or WDB_STEP_RANGE was set */ wdbState = DBG_INFO(taskIdCurrent)->wdbState; DBG_INFO(taskIdCurrent)->wdbState &= ~(WDB_STEP_TARGET | WDB_STEP_RANGE); DBG_INFO(taskIdCurrent)->wdbRegisters = pRegisters; DBG_INFO(taskIdCurrent)->wdbState |= WDB_CLEANME; /* check if step was issued from target shell or WDB */ if ((wdbState & WDB_STEP_TARGET) == WDB_STEP_TARGET) { if (_func_dbgTargetNotify != NULL) _func_dbgTargetNotify (BP_STEP, pRegisters->reg_pc, pRegisters); } else { if (_func_dbgHostNotify != NULL) _func_dbgHostNotify (taskIdCurrent, pRegisters, pRegisters->reg_pc); } taskUnlock(); /* UNLOCK PREEMPTION */ for (;;) taskSuspend((int) taskIdCurrent); }#if DBG_NO_SINGLE_STEP/******************************************************************************** dbgTaskBpTrap - Trap handler.** This routine handles bp's and trace's with one function if no trace mode** RETURNS : N/A.** NOMANUAL*/ void dbgTaskBpTrap ( int level, /* level of interupt lock */ INSTR * addr, /* break point address */ void * pInfo, /* pointer on info */ REG_SET * pRegisters, /* task regs before break point exception */ void * pDbgRegs, /* pointer to debug register set */ BOOL hardware /* indicates if it is a hardware break point */ ) { /* remove all break point */ wdbDbgBpRemoveAll (); /* step from a break point we were forced to ignore (e.g., in an ISR)? */ if (isrTraceData != 0) { dbgTaskDoneIgnore (pRegisters); } /* do we have to ignore this break point (e.g., it's in an ISR)? */ if (dbgBrkIgnoreDefault ()) { dbgTaskDoIgnore (pRegisters); } if (DBG_INFO(taskIdCurrent)->wdbState & WDB_STEPING) dbgTaskBpTrace (level, pInfo, pRegisters); else dbgTaskBpBreakpoint (level, pInfo, pRegisters, pDbgRegs, hardware); /* NOTREACHED */ }#endif /* DBG_NO_SINGLE_STEP *//******************************************************************************** dbgTaskDoIgnore - ignore current BP by stepping over it** This routine assumes break point are uninstalled and interrupts* are locked.** RETURNS : N/A.** NOMANUAL*/ LOCAL void dbgTaskDoIgnore ( REG_SET * pRegs /* pointer to saved registers */ ) {#if DBG_NO_SINGLE_STEP if (DBG_INFO(taskIdCurrent)->wdbState & WDB_STEPING) usrBreakpointSet (taskNpc, taskNpcInstr); isrNpc = wdbDbgGetNpc (pRegs); isrNpcInstr = *isrNpc; usrBreakpointSet (isrNpc, DBG_BREAK_INST);#endif /* DBG_NO_SINGLE_STEP */ isrTraceData = wdbDbgTraceModeSet (pRegs); WDB_CTX_LOAD (pRegs); }/******************************************************************************** dbgTaskDoneIgnore - the step over from "dbgTaskDoIgnore" has completed** The step over from "dbgTaskDoIgnore" has completed. We can now clear * trace mode and restore the task break point if we are not stepping.** RETURNS : N/A.** NOMANUAL*/ LOCAL void dbgTaskDoneIgnore ( REG_SET * pRegs /* task registers before exception */ ) { /* clear trace mode */ wdbDbgTraceModeClear (pRegs, isrTraceData); /* we are no longer stepping from ISR */ isrTraceData = 0;#if DBG_NO_SINGLE_STEP /* restore instructions */ usrBreakpointSet (isrNpc, isrNpcInstr); if (DBG_INFO(taskIdCurrent)->wdbState & WDB_STEPING) { if (INT_CONTEXT()) usrBreakpointSet (taskNpc, DBG_BREAK_INST); else DBG_INFO(taskIdCurrent)->wdbState &= ~WDB_STEPING; }#endif /* DBG_NO_SINGLE_STEP */ /* If we are not stepping, install break point for the current task */ if (!(DBG_INFO(taskIdCurrent)->wdbState & WDB_STEPING)) dbgTaskBpInstall ((int)taskIdCurrent); /* reload task context */ WDB_CTX_LOAD (pRegs); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -