调试的时候经常会遇到一些奇怪的问题,从打印上可以看到调到了某个函数,但不知道是谁调的或在哪个任务,tt虽然可以查看调用栈,但有诸多的限制并且只能查看处于挂起或者阻塞状态的任务。下面的代码可以查看任意函数的调用栈,只要把usrGetCallersPC加到目标函数中,调用栈就会自动记录下来,然后使用usrPrintCallStack可以查看每一级的函数名。缺省记录10级调用关系,如果不够可以根据自己的需要调节。
#include "vxWorks.h"
#include "iv.h"
#include "esf.h"
#include "intLib.h"
#include "ioLib.h"
#include "memLib.h"
#include "dbgLib.h"
#include "dsmLib.h"
#include "regs.h"
#include "shellLib.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "trcLib.h"
#include "tyLib.h"
#include "usrLib.h"
#include "vxLib.h"
#include "private/cplusLibP.h"
#include "private/windLibP.h"
#include "private/taskLibP.h"
#include "private/funcBindP.h"
#include "private/dbgLibP.h"
#include "wdb/wdbDbgLib.h"
typedef int (*USRFUNCPTR) (void); /* ptr to function returning int */
unsigned long usrGetCallSp[] =
{
0x38610000, /* addi r3,r1,0 */
0x4e800020 /* blr */
};
unsigned long gszUsrCallStack[100][10];
unsigned long gulUsrCallStackIndex = 0;
void usrGetCallersPC(unsigned long ulArrayNum)
{
unsigned long i;
unsigned long *pulSP;
/* 限制调用层次 */
if ((10 < ulArrayNum)||(ulArrayNum == 0))
{
ulArrayNum = 10;
}
memset((char *)&(gszUsrCallStack[gulUsrCallStackIndex]), 0, 10 * 4);
pulSP = (unsigned long *)(((USRFUNCPTR)(&usrGetCallSp))());
/* 忽略上层调用函数 */
pulSP = (unsigned long *)*pulSP; /* 上层函数的栈顶, *( pulSP + 1 )上层本函数地址 */
for ( i = 0; i < ulArrayNum; i++ )
{
if ( 0 != *pulSP )
{
gszUsrCallStack[gulUsrCallStackIndex][i] = *( pulSP + 1 );
pulSP = (unsigned long *)*pulSP;
}
else
{
gszUsrCallStack[gulUsrCallStackIndex][i] = 0;
}
}
gulUsrCallStackIndex++;
gulUsrCallStackIndex = gulUsrCallStackIndex%100;
}
void usrPrintCallStack()
{
int iLoop, i;
SYMBOL_ID symId;
char * name;
void * val;
char demangled [256 + 1];
char * nameToPrint;
extern SYMTAB_ID sysSymTbl;
for (iLoop = 0; iLoop < gulUsrCallStackIndex; iLoop++)
{
/* print call address and name of calling function plus offset */
printf ("\r\n\r\nCall stack index %d: ", iLoop);
for (i = 0; i < 10; i++)
{
if (gszUsrCallStack[iLoop][i] == 0)
{
break;
}
if ((symFindSymbol (sysSymTbl, NULL, (void *)gszUsrCallStack[iLoop][i], SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK)
&&(symNameGet (symId, &name) == OK)
&&(symValueGet (symId, &val) == OK))
{
nameToPrint = cplusDemangle (name, demangled, sizeof (demangled));
printErr ("\r\n0x%08x %-15s+%-3x: ", gszUsrCallStack[iLoop][i], nameToPrint, (int)gszUsrCallStack[iLoop][i] - (int)val);
}
else
printf ("\r\n%x", gszUsrCallStack[iLoop][i]);
}
}
}
忘了提醒,上面的函数仅限于PowerPC架构,如果使用arm或者其他架构,需要更改下面的数组
unsigned long usrGetCallSp[] =
{
0x38610000, /* addi r3,r1,0 */
0x4e800020 /* blr */
};
做成相应架构下的命令就可以了。
阅读(2189) | 评论(0) | 转发(2) |