【问题标题】:How can I retrieve a stack trace of the currently running function's stack?如何检索当前正在运行的函数堆栈的堆栈跟踪?
【发布时间】:2017-12-01 04:56:29
【问题描述】:

出于故障排除的原因,我希望能够检索并打印当前正在运行的函数的调用者堆栈。 我尝试了以下方法:

/*******************************************************************************
 * *
 * * 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 arch powerpc

【问题讨论】:

  • 你可以使用 backtrace(),如果它在 vxworks 中可用,它的手册页也有一个工作示例
  • @Harry 你可以访问源代码和 WindRiver Workbench 吗?
  • @cerr 是的,我可以访问源代码和 Windriver 工作台
  • @Harry 我或许可以为您提供帮助,但需要了解您的应用程序的更多细节。让我知道如何在此论坛之外与您联系以进行进一步讨论...
  • @cerr 我的邮件 ID 是 harry19892010@outlook.com

标签: c debugging stack trace vxworks


【解决方案1】:

您提到 taskRegsGet() 提到不建议从当前正在运行的任务中调用。但是,我看到有人使用带有“强制上下文保存”注释的 taskDelay(1)。我不能把它归功于它,我也不知道它有多可靠,或者它可能有什么副作用,但它可能有助于获得有关当前任务的正确信息:

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 */

【讨论】:

    【解决方案2】:

    如果您的编译器是 GCC 并且您的架构的调用约定允许它(首先想到的是 x86),我建议使用 __builtin_return_address( unsigned int level )。更多信息可以在这里找到: https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html.

    【讨论】:

    • 不幸的是,我正在使用 powerPC 和 diab 编译器
    • 虽然操作繁重且需要迭代过程,但您可以编写一些内联程序集来将链接寄存器内容移动到可以打印的 C 变量中。除了使用不良文档内联汇编语法 diab 支持之外,这种方法的主要缺点是您只能找到当前函数的调用者。要获得下一个调用,您必须修改调用函数以获取链接寄存器内容。我已经在 ARM 和 PPC 卡中使用过它,但这是不得已而为之的技术。
    • 你能在任务上做“tt”吗? tt 在 vxWorks shell 上。还可以尝试为任务设置以下选项,看看它是否有助于“taskOptionsSet , 2, 0”。
    猜你喜欢
    • 1970-01-01
    • 2011-10-01
    • 2018-07-13
    • 2010-11-07
    • 2020-07-06
    • 2017-08-31
    • 2011-02-19
    相关资源
    最近更新 更多