2017-06-28 65 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」。 –