?? trclib.c
字號:
/* trcLib.c - PowerPC stack trace library *//* Copyright 1984-1994 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02b,27feb96,ms reworked findFuncStart.02a,01feb96,ms rewritten.01c,16jan95,caf disabled stack trace support for now.01b,05dec94,caf added cast to trcStack().01a,07nov94,yao written.*//*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 "taskLib.h"#include "regs.h"#include "string.h"#include "private/funcBindP.h"#include "dbgLib.h"#include "sysSymTbl.h"#include "vxLib.h"/* definitions */#define MAX_TRACE_DEPTH 80 /* maximum stack frames to trace */#define MAX_SCAN_DEPTH 250 /* maximum distance to scan text */#define MAX_PROLOGUE_SIZE 20 /* maximum size of function prologue */#define FP_FROM_STACK(sp) (*(char **)(sp))#define RETURN_PC_FROM_STACK(sp) (*(INSTR **)((sp) + 4))#define BOGUS_SP(sp,low,high) (((int)(sp) % 8) || ((sp) < (low)) || \ ((sp) > (high)) || (sp == 0))#define BOGUS_PC(pc, junk) (vxMemProbe((char *)(pc), VX_READ, 4, \ (char *)&(junk)) == ERROR)/* some dissassembly macros */#define INST_LWZX_SP _OP(31, 55) | (1 << 21)#define INST_LWZUX_SP _OP(31, 23) | (1 << 21)#define INST_LWZX_SP_MASK 0xffe007fe#define INST_LWZ_SP_MASK 0xffe00000#define STW(reg) ((36 << 26) | ((reg) << 21))#define STW_REG_MASK 0xffe00000/* globals */int trcDefaultArgs = 0; /* default # of args to print */int trcScanDepth = MAX_SCAN_DEPTH;/* forward declarations */static int trcGetArgs (INSTR *procAddr, char *sp, int *args);static INSTR * trcFindFuncStart (INSTR *pc, INSTR *returnPc);static void trcDefaultPrint (INSTR *callAdrs, INSTR *funcAdrs, int nargs, int *args);static void trcStackLvl (INSTR *pc, INSTR *returnPc, char *sp, char *fp, char *stackBottom, int depth, FUNCPTR printRtn);static STATUS trcInfoGet (int tid, REG_SET * pRegs, INSTR ** pPc, INSTR ** pReturnPc, char ** pSp, char ** pFp);/********************************************************************************* 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 this, is provided* by tt() in dbgLib.* * The routine prints a list of the nested routine calls that are on the stack,* showing each routine call with its parameters.** The stack being traced should be quiescent. The caller should avoid tracing* its own stack.** PRINT ROUTINE* 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 5* .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 is used that prints out just* the call address, function address, and arguments as hexadecimal values.** CAVEAT* There is no way to determine the function arguments unless the* code is compiled with debugging (e.g., "-gdwarf).** 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, tid);** .CE** RETURNS: N/A** SEE ALSO: tt()* * NOMANUAL*/void trcStack ( REG_SET * pRegs, /* general purpose registers */ FUNCPTR printRtn, /* routine to print single function call */ int tid /* task's id */ ) { char *stackBottom = taskTcb (tid)->pStackBase; char *sp; /* current stack pointer */ char *fp; /* frame pointer (previous sp) */ INSTR *pc; /* current program counter */ INSTR *returnPc; /* return address */ /* get info on the top level stack frame */ if (trcInfoGet (tid, pRegs, &pc, &returnPc, &sp, &fp) == ERROR) { if (_func_printErr != NULL) _func_printErr ("trcStack aborted: error in top frame\n"); return; } /* use default print routine if none specified */ if (printRtn == NULL) printRtn = (FUNCPTR) trcDefaultPrint; /* do the recursive stack trace. */ trcStackLvl (pc, returnPc, sp, fp, stackBottom, 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.*/static void trcStackLvl ( INSTR *pc, /* current program counter location */ INSTR *returnPc, /* return address */ char *sp, /* stack pointer */ char *fp, /* frame pointer (previous stack pointer) */ char *stackBottom, /* effective base of task's stack */ int depth, /* recursion depth */ FUNCPTR printRtn /* routine to print single function call */ ) { char * prevFp = NULL; INSTR * prevReturnPc; int args[MAX_TASK_ARGS]; INSTR * procAddr; int nArgs; /* recursive trace if depth not maxed and framepointer is valid */ if (depth < MAX_TRACE_DEPTH) { prevFp = FP_FROM_STACK(fp); if (BOGUS_SP (prevFp, fp, stackBottom)) return; prevReturnPc = RETURN_PC_FROM_STACK(prevFp); if (!BOGUS_PC (prevReturnPc, procAddr)) trcStackLvl (returnPc, prevReturnPc, fp, prevFp, stackBottom, depth+1, printRtn); } /* get the current routine's starting address */ procAddr = trcFindFuncStart (pc, returnPc); /* get the function arguments */ nArgs = trcGetArgs (procAddr, sp, args); (* printRtn) (returnPc, procAddr, nArgs, args); }/********************************************************************************* 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.*/static void trcDefaultPrint ( INSTR *callAdrs, /* address from which function was called */ INSTR *funcAdrs, /* address of function called */ int nargs, /* number of arguments in function call */ int *args /* pointer to function args */ ) { int ix; BOOL doingDefault = FALSE; if (!_func_printErr) 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 (", "); _func_printErr ("%x", args[ix]); } if (doingDefault) _func_printErr ("]"); _func_printErr (")\n"); }/******************************************************************************** trcFindFuncStart - get starting address of a procedure.** Given a "pc" value, determine the address of the procedure* containing that pc.* We try several methods until one succeeds.* 1) First check the returnPc to see if we got to the current proc* via a branch instruction. If so we can determine the procedure* address accuratly.* 2) If there is no branch instruction found, scan backwards up to* trcScanDepth bytes looking for a "stwu sp, xxx(sp)" instruction,* and assume that instruction is the proc entry.** RETURNS: The starting address of the procedure, or NULL if it couldn't* be found.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -