📄 dbgtasklib.c
字号:
/* dbgTaskLib.c - Task breakpoint handling *//* Copyright 1984-1998 Wind River Systems, Inc. *//*modification history--------------------01e,03feb99,cpd Fix for SPR24102: Added Windview instrumentation when lockCnt is directly decremented, rather than taskUnlock.01d,19jan99,elg Restore PC for MIPS (SPR 24356)01c,21apr98,dbt code cleanup.01b,13mar98,dbt moved _func_wdbIsNowExternal to wdbDbgLib.c (scalability problem).01a,05dec97,dbt written based on wdbTaskBpLib.c.*//*DESCRIPTIONThis library contains routines for task mode debugging. Those routinesare all OS specific and are used by both target shell debugger and WDB debugger in task mode.The facilities provided by routines in this library are : - task deletion and switch handling. - breakpoint exceptions handling. - task continue and task step handling.INTERNALWe should avoid all direct calls to WDB routines without using a pointer.This is necessary because target shell debugger and WDB debugger must beindependant.Since target shell debugger is based on WDB debugger, it is normal to seereferences to some WDB defines (WDB_CTX_LOAD for example) in this file.*/#include "vxWorks.h"#include "taskLib.h"#include "regs.h"#include "stddef.h"#include "sigLib.h"#include "taskLib.h"#include "taskHookLib.h"#include "intLib.h"#include "stdio.h"#include "string.h"#include "wdb/wdbDbgLib.h"#include "private/taskLibP.h"#include "private/kernelLibP.h"/* defines */#define DBG_INFO(p) (&((WIND_TCB *)(p))->wdbInfo)/* externals */extern FUNCPTR _func_wdbIsNowExternal; /* pointer on wdbIsNowExternal() routine *//* globals */int dbgLockUnbreakable; /* taskLock()'ed tasks are unbreakable */int dbgSafeUnbreakable; /* taskSafe()'ed tasks are unbreakable */int dbgUnbreakableOld; /* unbreakable even if !WDB_ACTION_STOP */FUNCPTR _func_dbgHostNotify = NULL; /* routine to call to notify the host when a breakpoint is encountered */FUNCPTR _func_dbgTargetNotify = NULL; /* routine to call to notify the target when a breakpoint is encountered *//* locals */static int taskTraceData;static int isrTraceData;#if DBG_NO_SINGLE_STEPstatic INSTR * taskNpc; /* next pc of the task */static INSTR taskNpcInstr; /* next instruction of the task */static INSTR * isrNpc; /* next pc at interrrupt level */static INSTR isrNpcInstr; /* next instruction at int. level */#endif /* DBG_NO_SINGLE_STEP *//* forward static declarations */LOCAL void dbgTaskDoIgnore (REG_SET * pRegs);LOCAL void dbgTaskDoneIgnore (REG_SET * pRegs);LOCAL void dbgTaskSwitch (WIND_TCB * pOldTcb, WIND_TCB * pNewTcb);LOCAL void dbgTaskDeleteHook (WIND_TCB * pTcb);LOCAL void dbgTaskBpInstall (int tid);LOCAL BOOL dbgBrkIgnoreDefault (void);/******************************************************************************** dbgTaskBpHooksInstall - install tasking breakpoint hooks** This routine installs breakpoint hooks. One for task switch, one for* task deletion and one for modification of task flags.** RETURNS : N/A.** NOMANUAL*/ void dbgTaskBpHooksInstall ( void ) { static BOOL dbgTaskBpHooksInstalled = FALSE; if (!dbgTaskBpHooksInstalled) { /* task switch hook */ taskSwitchHookAdd ((FUNCPTR) dbgTaskSwitch); /* task delete hook */ taskDeleteHookAdd ((FUNCPTR) dbgTaskDeleteHook); /* set break remove/install hook routine for taskOptionsSet */ taskBpHookSet ((FUNCPTR) dbgTaskBpInstall); dbgTaskBpHooksInstalled = TRUE; } }/********************************************************************************* dbgTaskCont - Handle a continue request** The dbgTaskCont() function is used to continue a task.** RETURNS : * WDB_ERR_INVALID_CONTEXT if the task is not suspended or * if we can't resume it. OK otherwise.** NOMANUAL*/STATUS dbgTaskCont ( UINT32 taskId /* Id of task to continue */ ) { if (!taskIsSuspended(taskId)) return (WDB_ERR_INVALID_CONTEXT); /* * Check if there is a breakpoint at current pc or if the last * encountered breakpoint still exist (needed for data access * breakpoints). */ taskLock (); /* LOCK PREEMPTION */ if ((wdbDbgBpFind ((INSTR *)(((WIND_TCB *)taskId)->regs.reg_pc), taskId) == OK) || (wdbDbgBpFind ((INSTR *)(DBG_INFO(taskId)->bpAddr), taskId) == OK)) { DBG_INFO((WIND_TCB *)(taskId))->wdbState |= WDB_STEP_OVER; } taskUnlock (); /* UNLOCK PREEMPTION */ if (taskResume (taskId) != OK) return (WDB_ERR_INVALID_CONTEXT); return (OK); }/********************************************************************************* dbgTaskStep - Handle a step request** The dbgTaskStep() function is used to step a task.** RETURNS : * WDB_ERR_INVALID_CONTEXT if the task is not suspended or * if we can't resume it. OK otherwise.** NOMANUAL*/STATUS dbgTaskStep ( UINT32 contextId, /* Id of task to step */ UINT32 startAddr, /* start address */ UINT32 endAddr /* end address */ ) { if (!taskIsSuspended(contextId)) return (WDB_ERR_INVALID_CONTEXT); if (startAddr == 0 && endAddr == 0) DBG_INFO(contextId)->wdbState |= WDB_STEP; else { if (DBG_INFO(contextId)->wdbState & WDB_QUEUED) return (WDB_ERR_INVALID_CONTEXT); DBG_INFO(contextId)->wdbState |= WDB_STEP_RANGE; DBG_INFO(contextId)->wdbEvtList.wdb1 = (void *) startAddr; DBG_INFO(contextId)->wdbEvtList.wdb2 = (void *) endAddr; } if (taskResume (contextId) != OK) return (WDB_ERR_INVALID_CONTEXT); return (OK); }/******************************************************************************** dbgTaskDeleteHook - remove task-specific BP's when a task exits** This hook removes the task-specific breakpoints when a task exits.** RETURNS : N/A** NOMANUAL*/ LOCAL void dbgTaskDeleteHook ( WIND_TCB * pTcb /* TCB of the deleted task */ ) { dll_t * pDll; dll_t * pDllNext; int level; /* remove events still queued in the task TCB */ level = intLock (); if (DBG_INFO(pTcb)->wdbState & WDB_QUEUED) { DBG_INFO(taskIdCurrent)->wdbState &= ~WDB_QUEUED; dll_remove ((dll_t *)&(DBG_INFO(pTcb)->wdbEvtList)); } intUnlock (level); /* delete task specific breakpoints */ taskLock (); /* LOCK PREEMPTION */ for (pDll = dll_head(&bpList); pDll != dll_end(&bpList); pDll = pDllNext) { pDllNext = dll_next(pDll); /* We remove only breakpoints specific to deleted task. */ if (BP_BASE(pDll)->bp_task == (int) pTcb) wdbDbgBpRemove (BP_BASE(pDll)); } taskUnlock (); /* UNLOCK PREEMPTION */ }/******************************************************************************** dbgTaskBpInstall - install breakpoints for the current task** This routine installs BP's for the new task and remove ones for * the old task.** RETURNS : N/A.** NOMANUAL*/ LOCAL void dbgTaskBpInstall ( int tid /* id of the task */ ) { dll_t * pDll; BOOL stepping; /* task is stepping */ BOOL breakable; /* task is breakable */ BOOL bpi; /* breakpoint is installed */ int level; /* interrupt lock level */ BRKPT * pBp; WIND_TCB * pTcb = (tid == 0 ? taskIdCurrent : (WIND_TCB *)tid);#if DBG_HARDWARE_BP DBG_REGS dbgRegs; memset (&dbgRegs, 0, sizeof (DBG_REGS)); /* clean debug registers */ wdbDbgRegsClear ();#endif /* DBG_HARDWARE_BP */ stepping = DBG_INFO(pTcb)->wdbState & WDB_STEPING; breakable = !(pTcb->options & VX_UNBREAKABLE); for (pDll = dll_head(&bpList); pDll != dll_end(&bpList); pDll = dll_next(pDll)) { pBp = BP_BASE(pDll); /* should the breakpoint be installed? */ bpi = !(stepping || ((pBp->bp_task != BP_ANY_TASK) && (pBp->bp_task != (int)pTcb)) || ((!breakable) && (pBp->bp_action & WDB_ACTION_STOP)) || ((!breakable) && dbgUnbreakableOld)); if ((pBp->bp_flags & BP_INSTALLED) != bpi) { level = intLock (); if (bpi) { pBp->bp_flags |= BP_INSTALLED; /* execute this only if it is a software breakpoint */ if ((pBp->bp_flags & BRK_HARDWARE) == 0) usrBreakpointSet (pBp->bp_addr, DBG_BREAK_INST); } else { /* execute this only if it is a software breakpoint */ if ((pBp->bp_flags & BRK_HARDWARE) == 0) usrBreakpointSet (BP_BASE(pDll)->bp_addr, BP_BASE(pDll)->bp_instr); BP_BASE(pDll)->bp_flags &= ~BP_INSTALLED; } intUnlock(level); }#if DBG_HARDWARE_BP /* fill dbgRegs structure with the hardware breakpoint */ if (bpi && (pBp->bp_flags & BRK_HARDWARE)) wdbDbgHwBpSet (&dbgRegs, pBp->bp_flags & BRK_HARDMASK, (UINT32) pBp->bp_addr);#endif /* DBG_HARDWARE_BP */ }#if DBG_HARDWARE_BP /* * We now set debug registers of the CPU with the structure we have * filled. This structure contains only hardware breakpoint for the * new task. */ wdbDbgRegsSet (&dbgRegs); /* set debug registers. */#endif /* DBG_HARDWARE_BP */ }/********************************************************************************* dbgTaskSwitch - system task switch routine** Tasking breakpoints are set during context switches using this routine.* This allows breakpoints to not affect certain tasks.** RETURNS : N/A.** NOMANUAL*/LOCAL void dbgTaskSwitch ( WIND_TCB * pOldTcb, /* pointer to tcb of switch-from task */ WIND_TCB * pNewTcb /* pointer to tcb of switch-to task */ ) { /* * don't do task BP switch hook if the agent is in system mode. * This test is only usefull if we use WDB breakpoints. */ if ((_func_wdbIsNowExternal != NULL) && _func_wdbIsNowExternal()) return; /* perform some cleanup on the old task */ if (TASK_ID_VERIFY(pOldTcb) == OK) /* suicide runs delete hook 1st */ { if (DBG_INFO(pOldTcb)->wdbState & WDB_CLEANME) { taskSuspend((int) pOldTcb); taskRegsSet((int) pOldTcb, DBG_INFO(pOldTcb)->wdbRegisters);#if CPU_FAMILY==MC680X0 pOldTcb->foroff = 0;#endif /* CPU_FAMILY==MC680X0 */ DBG_INFO(pOldTcb)->wdbState &= ~WDB_CLEANME; } if (DBG_INFO(pOldTcb)->wdbState & WDB_STEPING) {#if DBG_NO_SINGLE_STEP usrBreakpointSet (taskNpc, taskNpcInstr);#endif /* DBG_NO_SINGLE_STEP */ wdbDbgTraceModeClear (&pOldTcb->regs, taskTraceData); } } /* * Deal with breakpoints for the new task. * If we are stepping, remove all BP's and set trace mode. * If not stepping, install BP's for new task and remove for old task. */ if (DBG_INFO(pNewTcb)->wdbState & WDB_STEPING) { wdbDbgBpRemoveAll(); /* remove all the breakpoints for this task */#if DBG_NO_SINGLE_STEP taskNpc = wdbDbgGetNpc(&pNewTcb->regs); taskNpcInstr = *taskNpc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -