📄 dbglib.c
字号:
pNextDll = dll_next(pDll); pBp = BP_BASE(pDll); if ((pBp->bp_task == (UINT32) task) && (pBp->bp_addr == (INSTR *) pc) && (pBp->bp_flags == BP_SO)) { wdbDbgBpRemove (pBp); } } taskUnlock (); /* UNLOCK PREEMPTION */ taskIdDefault (task); /* update default task */ pTcb = taskTcb (task); if (pTcb == NULL) return; /* print the registers and disassemble next instruction */ taskRegsShow (task); if ((pTcb->options & VX_FP_TASK) && dbgPrintFpp) { /* * On the other hand fppTaskRegsShow() may modify the FP registers * (this depends of the architecture & compiler: it does happen for * PPC, SH): therefore we need to restore the FP context to what it * was before fppTaskRegsShow() so that the fppSwapHook() will save * the correct value in the TCB when the next FP task is swapped in. * (see also SPR #7983). This is needed because this routine is * executed in the tExcTask context. tExcTask is spawned without the * VX_FP_TASK option. */ fppSave(pTcb->pFpContext); fppTaskRegsShow (task); fppRestore(pTcb->pFpContext); } if ((pTcb->options & VX_DSP_TASK) && dbgPrintDsp && (_func_dspTaskRegsShow != NULL)) { (* _func_dspTaskRegsShow) (task); }#if (CPU_FAMILY==I80X86) if ((pTcb->options & VX_FP_TASK) && dbgPrintSimd && (_func_sseTaskRegsShow != NULL)) { (* _func_sseTaskRegsShow) (task); }#endif /* (CPU_FAMILY==I80X86) */#ifdef _WRS_ALTIVEC_SUPPORT if ((pTcb->options & VX_ALTIVEC_TASK) && dbgPrintAltivec) altivecTaskRegsShow (task);#endif /* _WRS_ALTIVEC_SUPPORT */ (void) dbgList ((INSTR *) pc, 1); nextToDsm = (INSTR *) pc; /* * Reset the flag dbgUnbreakableOld. This flag was set to prevent * encountering breakpoints (for example if ACTION_STOP was not * specified) in this unbreakable routine. */ dbgUnbreakableOld = FALSE; }/********************************************************************************* dbgTyAbort - abort the shell from interrupt level** NOMANUAL*/LOCAL void dbgTyAbort (void) { excJobAdd ((VOIDFUNCPTR)dbgTlTyAbort, 0,0,0,0,0,0); }/********************************************************************************* dbgTlTyAbort - task level portion of shell abort** NOMANUAL*/LOCAL void dbgTlTyAbort (void) { tyAbortFuncSet ((FUNCPTR) NULL); /* cancel abort routine */ /* reset the standard input and output channels in case they are hung up */ ioctl (STD_IN, FIOFLUSH, 0); ioctl (STD_OUT, FIOFLUSH, 0); ioctl (STD_ERR, FIOFLUSH, 0); tt (shellTaskId); if ((taskRestart (shellTaskId)) != ERROR) printErr ("%s restarted.\n", taskName (shellTaskId)); else { printErr ("spawning new shell.\n"); if (shellInit (0, TRUE) == ERROR) printErr ("shell spawn failed!\n"); } tyAbortFuncSet ((FUNCPTR) dbgTyAbort); /* set abort routine */ }/********************************************************************************* l - disassemble and display a specified number of instructions** This routine disassembles a specified number of instructions and displays* them on standard output. If the address of an instruction is entered in* the system symbol table, the symbol will be displayed as a label for that* instruction. Also, addresses in the opcode field of instructions will be* displayed symbolically.** To execute, enter:* .CS* -> l [address [,count]]* .CE* If <address> is omitted or zero, disassembly continues from the previous* address. If <count> is omitted or zero, the last specified count is used* (initially 10). As with all values entered via the shell, the address may* be typed symbolically.** RETURNS: N/A** SEE ALSO: * .pG "Target Shell,"* windsh,* .tG "Shell"*/void l ( INSTR * addr, /* address of first instruction to disassemble */ /* if 0, continue from the last instruction */ /* disassembled on the last call to l */ int count /* number of instruction to disassemble */ /* if 0, use the same as the last call to l */ ) { addr = (INSTR *) ROUND_DOWN (addr, DBG_INST_ALIGN); /* force alignment */ /* set new start address and instruction count if specified */ if ((int) addr != 0) nextToDsm = addr; if (count != 0) dfltCount = count; nextToDsm = dbgList (nextToDsm, dfltCount); /* disassemble n instructions */ }/********************************************************************************* dbgList - disassemble and list n instructions** This routine disassembles some number of instructions, using dsmLib.* The normal user interface is through the routine 'l', rather than through* this routine.** RETURNS: Pointer to instruction following last instruction disassembled.** NOMANUAL*/LOCAL INSTR * dbgList ( INSTR * addr, /* address of first instruction to disassemble */ int count /* number of intructions to dissamble */ ) { char * label; /* pointer to symbol table copy of symbol name string */ void * actVal; /* actual address of symbol found */ SYMBOL_ID symId; /* symbol identifier */ int ix; char demangled[DBG_DEMANGLE_PRINT_LEN + 1]; char * labelToPrint; for (ix = 0; ix < count; ix++) { if ((symFindSymbol (sysSymTbl, NULL, (void *)addr, SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK) && (symNameGet (symId, &label) == OK) && (symValueGet (symId, &actVal) == OK) && (actVal == (void *)addr)) { labelToPrint = cplusDemangle(label, demangled, sizeof (demangled));#if (CPU_FAMILY == SH) printf (" %s:\n", labelToPrint);#else printf (" %s:\n", labelToPrint);#endif } if (_dbgDsmInstRtn == (FUNCPTR) NULL) printErr ("dbgList: no disassembler.\n"); else addr += (*_dbgDsmInstRtn) (addr, (int)addr, dbgPrintAdrs); } return (addr); }/********************************************************************************* dbgPrintAdrs - prints addresses as symbols, if an exact match can be found** NOMANUAL*/LOCAL void dbgPrintAdrs ( int address /* address to print */ ) { char * label; /* pointer to symbol table copy of symbol name string */ void * actVal; /* actual address of symbol found */ SYMBOL_ID symId; /* symbol identifier */ char demangled[DBG_DEMANGLE_PRINT_LEN + 1]; char * labelToPrint; if ((symFindSymbol (sysSymTbl, NULL, (void *)address, SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK) && (symNameGet (symId, &label) == OK) && (symValueGet (symId, &actVal) == OK) && (actVal == (void *)address)) { labelToPrint = cplusDemangle(label, demangled, sizeof (demangled)); printf ("%s", labelToPrint); } else printf ("0x%08x", address); }/********************************************************************************* tt - display a stack trace of a task** This routine displays a list of the nested routine calls that the specified* task is in. Each routine call and its parameters are shown.** If <taskNameOrId> is not specified or zero, the last task referenced is* assumed. The tt() routine can only trace the stack of a task other than* itself. For instance, when tt() is called from the shell, it cannot trace* the shell's stack.** EXAMPLE* .CS* -> tt "logTask"* 3ab92 _vxTaskEntry +10 : _logTask (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)* ee6e _logTask +12 : _read (5, 3f8a10, 20)* d460 _read +10 : _iosRead (5, 3f8a10, 20)* e234 _iosRead +9c : _pipeRead (3fce1c, 3f8a10, 20)* 23978 _pipeRead +24 : _semTake (3f8b78)* value = 0 = 0x0* .CE* This indicates that logTask() is currently in semTake() (with* one parameter) and was called by pipeRead() (with three parameters),* which was called by iosRead() (with three parameters), and so on.** INTERNAL* This higher-level symbolic stack trace is built on top of the* lower-level routines provided by trcLib.** CAVEAT* In order to do the trace, some assumptions are made. In general, the* trace will work for all C language routines and for assembly language* routines that start with a LINK instruction. Some C compilers require* specific flags to generate the LINK first. Most VxWorks assembly language* routines include LINK instructions for this reason. The trace facility* may produce inaccurate results or fail completely if the routine is* written in a language other than C, the routine's entry point is* non-standard, or the task's stack is corrupted. Also, all parameters are* assumed to be 32-bit quantities, so structures passed as parameters will* be displayed as \f2long\fP integers.** RETURNS:* OK, or ERROR if the task does not exist.** SEE ALSO:* .pG "Target Shell,"* windsh,* .tG "Shell"*/STATUS tt ( int taskNameOrId /* task name or task ID */ ) { REG_SET regSet; BOOL resumeIt = FALSE; /* flag to remember if resuming is necessary */ int tid = taskIdFigure (taskNameOrId); /* convert to task id */ if (tid == ERROR) { printErr (DBG_TASK_NOT_FOUND); return (ERROR); } tid = taskIdDefault (tid); /* set default task id */ /* get caller task's id and make sure it is not the task to be traced */ if (tid == taskIdSelf () || tid == 0) { printErr ("Sorry, traces of my own stack begin at tt ().\n"); return (ERROR); } /* make sure the task exists */ if (taskIdVerify (tid) != OK) { printErr ("Can't trace task %#x: invalid task id.\n", tid); return (ERROR); } /* if the task is not already suspended, suspend it while we trace it */ if (!taskIsSuspended (tid)) { resumeIt = TRUE; /* we want to resume it later */ taskSuspend (tid); /* suspend the task if need be */ } /* trace the stack */ taskRegsGet (tid, ®Set); trcStack (®Set, (FUNCPTR) dbgPrintCall, tid); if (resumeIt) taskResume (tid); /* resume task if we suspended it */ return (OK); } /********************************************************************************* dbgPrintCall - print a stack frame** This routine is called by trcStack to print each level in turn.* If nargs is specified as 0, then a default number of args (trcDefaultArgs)* is printed in brackets ("[..]"), since this often indicates that the* number of args is unknown.** NOMANUAL - also used by shellSigHandler*/void dbgPrintCall ( INSTR * callAdrs, /* address from which function was called */ int funcAdrs, /* address of function called */ int nargs, /* number of arguments in function call */ UINT32 * args /* pointer to function args */ ) { int ix; SYMBOL_ID symId; /* symbol identifier */ char * name; /* pointer to symbol tbl copy of function name goes here */ void * val; /* address of named fn goes here */ BOOL doingDefault = FALSE; char demangled [DBG_DEMANGLE_PRINT_LEN + 1]; char * nameToPrint; /* print call address and name of calling function plus offset */ printErr ("%6x ", callAdrs); /* print address from which called */ if ((symFindSymbol (sysSymTbl, NULL, (void *)callAdrs, SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK) && (symNameGet (symId, &name) == OK) && (symValueGet (symId, &val) == OK)) { nameToPrint = cplusDemangle (name, demangled, sizeof (demangled)); printErr ("%-15s+%-3x: ", nameToPrint, (int)callAdrs - (int)val); } else#if CPU_FAMILY == ARM /* make things line up properly */ printErr (" : ");#else printErr (" : ");#endif /* print function address/name */ if ((symFindSymbol (sysSymTbl, NULL, (void *)funcAdrs, SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK) && (symNameGet (symId, &name) == OK) && (symValueGet (symId, &val) == OK) && (val == (void *)funcAdrs)) { nameToPrint = cplusDemangle (name, demangled, sizeof (demangled)); printErr ("%s (", nameToPrint); /* print function name */ } else printErr ("%x (", funcAdrs); /* print function address */ /* if no args are specified, print out default number (see doc at top) */ if ((nargs == 0) && (trcDefaultArgs != 0)) { doingDefault = TRUE; nargs = trcDefaultArgs; printErr ("["); } /* print args */ for (ix = 0; ix < nargs; ix++) { if (ix > 0) printErr (", "); if (args [ix] == 0) printErr ("0"); else if ((symFindSymbol (sysSymTbl, NULL, (void *)args[ix], SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK) && (symNameGet (symId, &name) == OK) && (symValueGet (symId, &val) == OK) && (val == (void *)args [ix])) { nameToPrint = cplusDemangle (name, demangled, sizeof (demangled)); printErr ("&%s", nameToPrint); /* print argument name */ } else printErr ("%x", args [ix]); } if (doingDefault) printErr ("]"); printErr (")\n"); }/******************************************************************************** dbgE - code to support the windview "e" command* * This routine is called each time a windview breakpoint is encountered* This is a temporary solution. This routine should be moved in windview * code.** RETURNS : NA** NOMANUAL*/ LOCAL void dbgE ( EVT_CALL_ARGS * pEvtCallArgs, REG_SET * pRegisters ) { int (*conditionFunc)() = (int (*)())pEvtCallArgs->evtRtn; if (conditionFunc == NULL || conditionFunc (pEvtCallArgs->evtRtnArg) == OK) EVT_CTX_BUF (pEvtCallArgs->eventId, pRegisters->reg_pc, 0, NULL); }/********************************************************************************* dbgTargetNotify - notify the target when a breakpoint is encountered ** This routine is called to notify the shell user through the console* when a breakpoint is encountered. Depending on the type of breakpoint, * the action is different.** RETURNS: N/A.** NOMANUAL*/LOCAL void dbgTargetNotify ( UINT32 flag, /* type of breakpoint (step over, step ...) */ UINT32 addr, /* breakpoint addr */ REG_SET * pRegisters /* task registers before exception */ ) { /* * Prevent excTask to encounter a breakpoint event if there is not * ACTION_STOP. This is necessary to avoid recursive loop if a * NOTIFY breakpoint could be encountered by dbgTlSnglStep or * dbgTlBreak. dbgUnbreakableOld should be restored to FALSE state * in dbgTlSnglStep and dbgTlBreak routines. */ dbgUnbreakableOld = TRUE; /* check the breakpoint flag in order to determine the action to perform */ if (flag & (BP_SO | BP_STEP)) excJobAdd (dbgTlSnglStep, (UINT32) taskIdCurrent, 0, 0, 0, 0, 0); else excJobAdd (dbgTlBreak, (UINT32) taskIdCurrent, (UINT32) pRegisters->pc, addr, 0, 0, 0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -