Chinaunix首页 | 论坛 | 博客
  • 博客访问: 569291
  • 博文数量: 169
  • 博客积分: 2656
  • 博客等级: 少校
  • 技术积分: 1685
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 13:03
文章分类

全部博文(169)

文章存档

2011年(1)

2010年(135)

2009年(33)

我的朋友

分类: 嵌入式

2010-05-14 13:10:46

调试的时候经常会遇到一些奇怪的问题,从打印上可以看到调到了某个函数,但不知道是谁调的或在哪个任务,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 */
};
做成相应架构下的命令就可以了。
阅读(2114) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~