⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trclib.c

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* trcLib.c - SH stack trace library *//* Copyright 1995-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01k,05apr02,h_k  adjust reserved task params size (SPR #75153).01j,30oct01,jn   use symFindSymbol for symbol lookup (SPR #7453)01i,06dec01,h_k  fixed trcGetFuncInfo for the recursion depth is 0 and added                 Diab support (SPR #69837).01h,10may00,hk   revised trcGetFuncInfo() for GCC 2.96.01g,19apr00,rsh  remove instruction #defines and put them in dsmShLib.h where                 they go01f,24aug99,hk   revised tracing algorithm (TSR#138850 related).01e,14oct96,wt   rewritten.01d,24oct95,sa   modified trcStackLvl(). disable argnument display.01c,02jun95,sa   fixed trcGetFuncInfo(), and speed-up.                 deleted TRC_INDICATE_PROGRESS.01b,03apr95,hk   added progress indicator (enabled by TRC_INDICATE_PROGRESS).01a,17mar95,sa   created from mips version 01p.*//*This module provides the routine trcStack(), which traces a stackgiven the current frame pointer, stack pointer, and program counter.The resulting stack trace lists the nested routine calls and their arguments.This module provides the low-level stack trace facility.A higher-level symbolic stack trace, implemented on top of this facility,is provided by the routine tt() in dbgLib.SEE ALSO:dbgLib, tt(),.pG "Debugging"*/#include "vxWorks.h"#include "symLib.h"#include "sysSymTbl.h"#include "dsmLib.h"#include "taskLib.h"#include "regs.h"#include "stdio.h"#include "vxLib.h"#include "string.h"#ifndef SYM_GLOBAL#define SYM_GLOBAL	0x1#endif#ifndef SYM_TEXT#define SYM_TEXT	0x4#endif#define MAX_TRACE_DEPTH 80 /* maximum number of levels of stack to trace */#define MAX_SCAN_DEPTH		2000		/* search for proc start up to						 * 2000 instructions */#define MAX_PROLOG_INSN	20typedef struct    {    INSTR *entry;		/* function entry address */    INSTR *returnTo;		/* caller's pc to return */    int szNvRegs;		/* size of non-volatile registers on stack */    int szFrame;		/* size of stack frame */    int szSubFrame;		/* size of sub stack frame after prolog code */    BOOL foundSubFrame;		/* TRUE if sub stack frame exists */    BOOL foundAddFrame;		/* TRUE if add stack frame exists */    INT8 frameReg;		/* register used to get a long frame size */    } TRC_INFO;/* globals */int trcDebug = 0;int trcDefaultArgs = 4;			/* default # of args to print if trc					 * can't figure out how many */#define TRC_DEBUG(x)	if (trcDebug) printf x/* forward declarations */LOCAL void trcGetFuncInfo (REG_SET *regs, char *sp, INSTR *pc, int depth,    INSTR **pReturnTo, INSTR **pFuncEntry, int *pFrameSize);LOCAL void trcDefaultPrint (INSTR *callAdrs, INSTR *funcAdrs,     FAST int nargs, int *args);LOCAL void trcStackLvl (char *stackBottom, REG_SET *regs, char *sp,    INSTR *pc, int depth, FUNCPTR printRtn);/********************************************************************************* trcStack - print a trace of function calls from the stack** This routine provides the low-level stack trace function.  A higher-level* symbolic stack trace, built on top of trcStack(), is provided by tt() in* dbgLib.*/void trcStack    (    REG_SET *regs,	/* general purpose registers */    FUNCPTR  printRtn,	/* routine to print single function call */    int      tid	/* task's id */    )    {    char *stackBottom = taskTcb (tid)->pStackBase;    /* use default print routine if none specified */    if (printRtn == NULL)	printRtn = (FUNCPTR) trcDefaultPrint;    /* must perform the trace by searching through code to determine stack     * frames, and unwinding them to determine callers and parameters.      * We subtract a fixed size from stackBottom for the reserved task params     * that are tagged onto every task's main entry point.     */    trcStackLvl (stackBottom - (MAX_TASK_ARGS * sizeof(int)), regs,		(char *)regs->spReg, regs->pc, 0, printRtn);    }/************************************************************************** trcStackLvl - recursive stack trace routine** This routine is recursive, being called once for each level of routine* nesting.  The maximum recursion depth is limited to 40 to prevent* garbage stacks from causing this routine to continue unbounded.* The "depth" parameter on the original call should be 0.*/LOCAL void trcStackLvl    (    char *stackBottom,	/* effective base of task's stack */    REG_SET *regs,	/* current register set */    char *sp,		/* current stack pointer */    INSTR *pc,		/* current program counter */    int depth,		/* recursion depth */    FUNCPTR printRtn 	/* routine to print single function call */    )    {    INSTR *callpc;		/* point where called from */    INSTR *startpc;		/* entry point of the current function */    int frameSize;		/* size, in bytes, of current stack frame */    SYMBOL_ID symId;            /* symbol identifier */    /* stop the unwind if it's obvious that we can't dereference the pc */    if ((pc == NULL) || ((UINT)pc & 0x01))	return;    /* for each subprogram encountered, determine a bunch of info about it.     * Includes where it was called from, its stack frame size and whether     * the frame has already been allocated.     */    trcGetFuncInfo (regs, sp, pc, depth, &callpc, &startpc, &frameSize);    /* Stop the unwind if we can't determine the caller of this function,     * and check the callpc we got back.     */    if ((callpc == NULL) || ((UINT)callpc & 0x01))	return;    /* only continue unwinding if this is not the last stack frame.     * (i.e., the "main" function)     */    TRC_DEBUG (("sp + %d = %p, bottom %p, margin %d\n",		frameSize, sp + frameSize, stackBottom,		stackBottom - (sp + frameSize)));    if ((ULONG)(sp + frameSize) < (ULONG)stackBottom)        {        if (startpc == NULL)            {	    /* unable to determine entry point from code...try the symbol table.	     * Note that the symbol table may yield the wrong entry point if	     * the function name is not in it (such as the case for "static"	     * functions in "C". In this case, we may get the starting address	     * for the previous function in the text section and the trace	     * would yield strange results. */	    if ((sysSymTbl == NULL) ||		(symFindSymbol (sysSymTbl, NULL, (void *)pc, 				SYM_MASK_NONE, SYM_MASK_NONE, &symId) != OK) ||		(symValueGet (symId, (void *)&startpc) != OK))		return;	    }	/* Unwind the stack by adding the determined frame size and	 * place the pc at the point at which this subprogram was called.	 * Keep unwinding until the max number of functions has been reached */	if (depth < MAX_TRACE_DEPTH)            {            trcStackLvl (stackBottom, regs, (char *)(sp + frameSize),                                 callpc, depth + 1, printRtn);            }        }    /* since this is the last frame, we can only determine the entry point     * via the symbol table     */    else if ((sysSymTbl == NULL) ||	     (symFindSymbol (sysSymTbl, NULL, (void *)pc, 			     SYM_MASK_NONE, SYM_MASK_NONE, &symId) != OK) ||	     (symValueGet (symId, (void *)&startpc) != OK))	return;    /* time to print out info about this function including the     * called-from pc, the start of this function, the number of     * actual parameters and their values.     */    (* printRtn) (callpc - 2, startpc, -1, sp + frameSize);    }/****************************************************************************** trcGetFuncInfo - get address from which function was called** Determines specific info about the current function, such as the* address where it was called from, the stack frame size (if any) and* whether the stack frame has already been allocated.*/LOCAL void trcGetFuncInfo    (    REG_SET *regs,      /* current SH register set */    char *sp,           /* current sp */    INSTR *pc,          /* current pc */    int depth,		/* recursion depth */    INSTR **pReturnTo,  /* return address from which this function called */    INSTR **pFuncEntry,	/* return starting address of a function */    int *pFrameSize     /* return stack frame size */    )    {    INSTR *pscan;    TRC_INFO trcInfo;    char *label;	/* pointer to symbol table copy of symbol name */    INSTR *pSymAhead;    SYMBOL_ID symId;    /* symbol identifier */    SYM_TYPE type;	/* symbol type */    int szSubFrameEpilog = 0;    int prStoreCheck = 0;    BOOL inEpilog = FALSE;    BOOL checkDiab = FALSE;    /* If the recursion depth is 0, it is likely to be in a prolog code unless     * it's in a epilog code. Scan forward up to MAX_PROLOG_INSN instructions,     * or until finding an epilog instruction.     */    if (depth == 0)	{	TRC_DEBUG (("<forward scan #%d> sp %p, pc %p, upto %p\n",		    depth, sp, pc, pc + MAX_PROLOG_INSN - 1));	for (pscan = pc; pscan < pc + MAX_PROLOG_INSN; pscan++)	    {	    INSTR insn;	    if (vxMemProbe ((char *)pscan, VX_READ, 2, (char *)&insn) != OK)		{		*pReturnTo = NULL;		return;		}	    else if (insn == INST_PUSH_FP ||		/* mov.l r14,@-r15 */		     insn == INST_PUSH_PR ||		/* sts.l pr,@-r15  */		     insn == INST_SET_FP)		/* mov   r15,r14   */		{		if (trcDebug) dsmInst (&insn, (int)pscan, NULL);		TRC_DEBUG (("<forward scan #%d> pc %p in prolog, pr %p\n",			    depth, pscan, regs->pr));		*pReturnTo  = regs->pr;		*pFuncEntry = NULL;		*pFrameSize = 0;		/* get the closest global function address from current pc */		if ((sysSymTbl == NULL) ||		    (symFindSymbol (sysSymTbl, NULL, (void *)pc, 				    (SYM_GLOBAL | SYM_TEXT), SYM_MASK_ALL, 				    &symId) != OK) ||		    (symNameGet (symId, &label) != OK) ||		    (symValueGet (symId, (void *)&pSymAhead) != OK) || 		    (symTypeGet (symId, &type) != OK))		    {		    return;		    }		trcInfo.szNvRegs = 0;		trcInfo.szFrame = 0;		trcInfo.frameReg = NONE;		/* Scan back the prolog code until beginning of the function. */		for (pscan = pc - 1;pscan > (pc - MAX_SCAN_DEPTH) &&		    (pscan >= pSymAhead); pscan--)		    {		    if (vxMemProbe ((char *)pscan, VX_READ, 2,			(char *)&insn) != OK)			{			return;			}		    else if ((insn & (MASK_ADD_IMM_SP | 0x80)) ==			(INST_ADD_IMM_SP | 0x80))	/* add   #-imm,r15 */			{			if (trcDebug) dsmInst (&insn, (int)pscan, NULL);			trcInfo.szFrame -= (INT8)(insn & 0x00ff);			}		    else if ((insn & MASK_SUB_REG_SP) == INST_SUB_REG_SP)							/* sub rm,r15 */			{			if (trcDebug) dsmInst (&insn, (int)pscan, NULL);			trcInfo.frameReg = (insn & 0x00f0) >> 4;			}		    else if (trcInfo.frameReg != NONE &&			(insn & MASK_MOV_IMM16) == INST_MOV_IMM16 &&			(insn & 0x0f00) == trcInfo.frameReg << 8)						/* mov.w @(disp,PC),Rn*/			{			UINT16 disp = (insn & 0x00ff) << 1;			INT16 imm16;			if (trcDebug) dsmInst (&insn, (int)pscan, NULL);			if (vxMemProbe ((char *)(pscan + 2) + disp,			    VX_READ, 2, (char *)&imm16) != OK)			    imm16 = 0;			TRC_DEBUG (("<backward scan #%d> frame size %d\n",			    depth, imm16));			trcInfo.szFrame = imm16;			}		    else if (insn == INST_PUSH_PR)	/* sts.l pr,@-r15 */			{			if (trcDebug) dsmInst (&insn, (int)pscan, NULL);			trcInfo.szNvRegs = 4;			}		    else if ((insn & MASK_PUSH_REG) == INST_PUSH_REG)							/* mov.l rm,@-r15 */			{			UINT8 rm = (insn & 0x00f0) >> 4;			if (rm >= 8 && rm <= 14)			    {			    if (trcDebug) dsmInst (&insn, (int)pscan, NULL);			    trcInfo.szNvRegs += 4;			    }			if (rm == 8)			/* mov.l r8,@-r15 */			    {			    trcInfo.entry = pscan;			    break;			    }			}		    }		*pFrameSize = trcInfo.szNvRegs + trcInfo.szFrame;		return;		}	    else if (insn == INST_RESTORE_SP ||		/* mov   r14,r15   */		     insn == INST_POP_PR ||		/* lds.l @r15+,pr  */		     insn == INST_POP_FP ||		/* mov.l @r15+,r14 */		     insn == INST_RTS)			/* rts             */		{		if (trcDebug) dsmInst (&insn, (int)pscan, NULL);		TRC_DEBUG (("<forward scan #%d> found epilog at %p\n",			    depth, pscan));		break;		}	    }	TRC_DEBUG (("<forward scan #%d> pc %p not in prolog\n", depth, pc));	}    /* get the closest global function address from current pc */    if ((sysSymTbl == NULL) ||	(symFindSymbol (sysSymTbl, NULL, (void *)pc, 			(SYM_GLOBAL | SYM_TEXT), SYM_MASK_ALL, &symId) != OK) ||	(symNameGet (symId, &label) != OK) ||	(symValueGet (symId, (void *)&pSymAhead) != OK) || 	(symTypeGet (symId, &type) != OK))	{	label = "????";	pSymAhead = NULL;	type = 0;	}    /* We now know that the pc is NOT in a function prolog. Scan backward and     * determine whether it is a C or an assembly function. If this is GNU C,     * we should first find 'mov r15,r14' at the end of prolog. If this is     * Diab C, we should first find 'add -imm,r15', 'sts.l pr,@-r15' or     * 'mov.l r14,@-r15'. Keep track of stack operations otherwise, to get the     * called address of this assembly function.     */    TRC_DEBUG (("<backward scan #%d> sp %p, pc %p, upto %p(%s:%#x)\n",		depth, sp, pc, pSymAhead, label, type));    for (trcInfo.szFrame = 0,	 pscan = pc - 1;	 pscan > pc - MAX_SCAN_DEPTH && pscan >= pSymAhead;	 pscan--)	{	INSTR insn;	if (vxMemProbe ((char *)pscan, VX_READ, 2, (char *)&insn) != OK)	    {	    *pReturnTo = NULL;	    return;	    }	else if (insn == INST_SET_FP)			  /* mov   r15,r14  */	    {	    break;	    }	else if ((insn & MASK_PUSH_REG) == INST_PUSH_REG) /* mov.l rm,@-r15 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -