?? trclib.c
字號:
/* trcLib.c - ColdFire stack trace library *//* Copyright 1984-2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,16jan02,rec fix name length for symFindByValue01a,17mar00,dra Created from T1.0.1 ColdFire and T2 m68k ports.*//*This module provides a 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 "regs.h"#include "stdio.h"#include "symLib.h"#include "sysSymTbl.h"#include "private/funcBindP.h"#define MAX_TRACE_DEPTH 40 /* maximum number of levels of stack to trace *//* instruction words */#define LINK_A6 0x4e56 /* LINK A6,... */#define RTS 0x4e75 /* RTS */#define JSR_ABS 0x4eb9 /* JSR abs */#define ADD_W 0xdefc /* ADD.W */#define ADD_L 0xdffc /* ADD.L */#define ADDQ_W 0x504f /* ADDQ.W A7 */#define ADDQ_L 0x508f /* ADDQ.L A7 */#define LEA_A7 0x4fef /* LEA $x(A7),A7 */#define MOVE_L_A7 0x2e80 /* MOVE.L xxx,(A7) */#define MOVE_L_A6_A7 0x2e75 /* MOVE.L (xxx,A6),A7 *//* globals */int trcDefaultArgs = 5; /* default # of args to print if trc * can't figure out how many *//* forward static functions */static void trcStackLvl (int *fp, INSTR *pc, int depth, FUNCPTR printRtn);static void trcDefaultPrint (INSTR *callAdrs, INSTR *funcAdrs, int nargs, int *args);static INSTR *trcFindCall (INSTR *returnAdrs);static INSTR *trcFindDest (INSTR *callAdrs);static int trcCountArgs (INSTR *returnAdrs);static INSTR *trcFindFuncStart (int *fp, INSTR *pc);static INSTR *trcFollowBra (INSTR *adrs);/********************************************************************************* 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.** This routine prints a list of the nested routine calls that are on the* stack, showing each routine with its parameters.** The stack being traced should be quiescent. The caller should avoid* tracing its own stack.** PRINT ROUTINE* In order to allow symbolic or alternative printout formats, the call to* this routine includes the <printRtn> parameter, which specifies a* user-supplied routine to be called at each nesting level to print out the* routine name and its arguments. This routine should be declared as* follows:* .ne 7* .CS* void printRtn (callAdrs, rtnAdrs, nargs, args)* INSTR *callAdrs; /@ address from which routine was called ** int rtnAdrs; /@ address of routine called ** int nargs; /@ number of arguments in call ** int *args; /@ pointer to arguments ** .CE* If <printRtn> is NULL, a default routine will be used that prints out just* the call address, the function address, and the arguments as hexadecimal* values.** CAVEAT* In order to do the trace, a number of 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. Most VxWorks assembly* language routines include LINK instructions for exactly this reason.* However, routines written in other languages, strange entries into* routines, or tasks with corrupted stacks can confuse the trace. Also, all* parameters are assumed to be 32-bit quantities, therefore structures* passed as parameters will be displayed as a number of long integers.** .ne 14* EXAMPLE* The following sequence can be used to trace a VxWorks task given a pointer* to the task's TCB:* .CS* REG_SET regSet; /@ task's data registers *** taskRegsGet (taskId, ®Set);* trcStack (®Set, (FUNCPTR)NULL, taskId);* .CE** RETURNS: N/A** SEE ALSO: tt()** NOMANUAL*/void trcStack ( REG_SET *pRegSet, /* pointer to register set */ FUNCPTR printRtn, /* routine to print single function call */ int tid /* task's id */ ) { int val; /* address gotten from symbol table */ char name[MAX_SYS_SYM_LEN+1]; /* string associated with val */ SYM_TYPE type; /* type associated with val */ INSTR instr; /* next instruction */ int stackSave; FAST INSTR *pc = pRegSet->pc; FAST int *fp = (int *) pRegSet->fpReg; FAST int *sp = (int *) pRegSet->spReg; /* use default print routine if none specified */ if (printRtn == NULL) printRtn = (FUNCPTR) trcDefaultPrint; /* * if the current routine doesn't have a stack frame, then we fake one * by putting the old one on the stack and making fp point to that; * we KNOW we don't have a stack frame in a few restricted but useful * cases: * 1) we are at a LINK or RTS instruction, * 2) we are the first instruction of a subroutine (this may NOT be * a LINK instruction with some compilers) */ instr = *trcFollowBra (pc); if ((instr == LINK_A6) || (instr == RTS) || ((sysSymTbl != NULL) && (_func_symFindByValue != NULL) && ((* _func_symFindByValue) (sysSymTbl, (int) pc, name, &val, &type) == OK) && (val == (int) pc))) { /* no stack frame - fake one */ stackSave = *(sp - 1); /* save value we're going to clobber */ *(sp - 1) = (int)fp; /* make new frame pointer by */ /* sticking old one on stack */ fp = sp - 1; /* and pointing to it */ trcStackLvl (fp, pc, 0, printRtn); /* do stack trace */ *(sp - 1) = stackSave; /* restore stack */ } else { trcStackLvl (fp, pc, 0, printRtn); /* do stack trace */ } }/************************************************************************** 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 ( FAST int *fp, /* stack frame pointer (A6) */ INSTR *pc, /* program counter */ int depth, /* recursion depth */ FUNCPTR printRtn /* routine to print single function call */ ) { FAST INSTR *returnAdrs; if (fp == NULL) return; /* stack is untraceable */ returnAdrs = (INSTR *) *(fp + 1); /* handle oldest calls first, up to MAX_TRACE_DEPTH of them */ if ((*fp != NULL) && (depth < MAX_TRACE_DEPTH)) trcStackLvl ((int *) *fp, returnAdrs, depth + 1, printRtn); (* printRtn) (trcFindCall (returnAdrs), trcFindFuncStart (fp, pc), trcCountArgs (returnAdrs), fp + 2); }/********************************************************************************* trcDefaultPrint - print a function call** 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.*/LOCAL void trcDefaultPrint ( INSTR *callAdrs, /* address from which function was called */ INSTR *funcAdrs, /* address of function called */ FAST int nargs, /* number of arguments in function call */ int *args /* pointer to function args */ ) { FAST int ix; BOOL doingDefault = FALSE; /* if there is no printErr routine do nothing */ if (_func_printErr == NULL) return; /* print call address and function address */ (* _func_printErr) ("%6x: %x (", callAdrs, funcAdrs); /* if no args are specified, print out default number (see doc at top) */ if ((nargs == 0) && (trcDefaultArgs != 0)) { doingDefault = TRUE; nargs = trcDefaultArgs; (* _func_printErr) ("["); } /* print args */ for (ix = 0; ix < nargs; ++ix) { if (ix != 0) (* _func_printErr) (", ");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -