2017-06-28 64 views
5

由于故障原因,我希望能够检索并打印当前运行的函数的调用者堆栈。 我曾尝试以下:如何检索当前运行的函数堆栈的堆栈跟踪?

/******************************************************************************* 
* * 
* * xxxTracePrint - stack trace print function 
* * 
* * RETURNS: OK or ERROR 
* */ 

static void xxxTracePrint 
    (
     INSTR *caller, 
      int func, 
       int nargs, 
        int *args 
         ) 
{ 
    char buf [250]; 
    int ix; 
    int len = 0; 

    len += sprintf (&buf [len], "%#10x: %#10x (", (int)caller, func); 
    for (ix = 0; ix < nargs; ix++) { 
     if (ix != 0) 
      len += sprintf (&buf [len], ", "); 
     len += sprintf (&buf [len], "%#x", args [ix]); 
    } 

    len += sprintf (&buf [len], ")\n"); 

    printf (buf); 
} 

/******************************************************************************* 
* * 
* * xxxTrace - stack trace 
* * 
* * RETURNS: OK or ERROR 
* */ 

int xxxTrace(int tcb) 
{ 
    REG_SET regs; 

    if (tcb == 0) 
     return (ERROR); 

    taskRegsGet (tcb, &regs); 
    trcStack (&regs, (FUNCPTR) xxxTracePrint, tcb); 

    return (OK); 
} 

void DbgTest(void) 
{ 
    xxxTrace(taskIdSelf()); 
} 

,但我得到:

JPAX-DP> DbgTest 
trcStack aborted: error in top frame 
value = 0 = 0x0 

这甚至可能吗?我怎样才能做到这一点?我看到,对于taskRegsGet(),他们说:

这个程序只适用于好,如果该任务被称为是在一个稳定的, 执行非状态。例如,自我检查是不可取的, 因为结果是不可预测的。

但我应该采用哪种方法?

编译器是diab和CPU拱powerpc

+0

您可以使用回溯() ,如果它在vxworks中可用,其手册页也有一个工作示例 – Pras

+0

@您是否有权访问surce代码和WindRiver Workbench? – cerr

+0

@cerr是的我可以访问源代码和Windriver工作台 – Harry

回答

1

你提到过,taskRegsGet()提到从当前正在运行的任务中调用是不可取的。不过,我看到有人使用taskDelay(1)和'force context save'注释。我不能把它的信用,我也不知道它是多么可靠,或者什么副作用它可能有,但它可能有助于获取有关当前任务的正确的信息:

taskDelay (1);  /* Force context save */ 
taskRegsGet (0, &regs); /* 0 task-id for myself */ 
trcStack (&regs, NULL, 0); /* NULL function pointer for default print fcn, 0 task-id for myself */ 
1

如果你的编译器是GCC和你的建筑许可证的调用约定它(X86是第一个想到的),我推荐使用__builtin_return_address(unsigned int类型级别)。更多信息可以在这里找到: https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html

+0

不幸的是,我在powerPC和diab编译器 – cerr

+0

虽然更加沉重,并要求一个迭代过程,您可以编写一些内联程序集来将链接寄存器内容移动到可以打印的C变量中。除了使用糟糕的文档内联汇编语法diab支持以外,这种方法的主要缺点是只能找到当前函数的调用者。要获得下一个呼叫,您必须修改调用函数以获取链接寄存器的内容。我已经在ARM和PPC卡中使用了它,但这是一种最后的手段。 – vxWizard

+0

你可以做任务“tt”吗? tx 在vxWorks外壳上。另外尝试设置下面的任务选项,看看它是否有帮助“taskOptionsSet ,2,0”。 –