2013-04-01 69 views
9

在不使用遞歸的C程序中,理論上應該可以計算調用給定函數所需的最大/最差情況堆棧大小,以及任何它呼籲。是否有任何免費的開源工具可以做到這一點,無論是源代碼還是編譯後的ELF文件?MSP430上的C程序所需的最大堆棧大小

另外,有沒有辦法從ELF文件中提取函數的堆棧幀大小,所以我可以嘗試手動解決它?

我在使用MSPGCC 3.2.3編譯MSP430(我知道它是舊版本,但我必須在這種情況下使用它)。要分配的堆棧空間在源代碼中設置,並且應儘可能小,以便其餘內存可用於其他事情。我已經讀過,你需要考慮到中斷使用的堆棧空間,但我使用的系統已經考慮到了這一點 - 我試圖計算出多少額外的空間來添加。另外,我已經讀過函數指針,這很難。在這裏使用函數指針的少數地方,我知道它們可以調用哪些函數,所以如果已知調用函數和調用函數所需的堆棧空間,可以手動考慮這些情況。

靜態分析看起來像是一個比運行時棧繪製更強大的選項,但如果沒有好的方法來靜態執行,在運行時進行處理是一種選擇。

編輯:

我發現GCC的-fstack-usage標誌,它在編譯節省了幀大小爲每個功能。不幸的是,MSPGCC不支持它。但是對於那些試圖在不同平臺上做類似事情的人來說,這可能很有用。

+0

這真的是解決您的問題的方法嗎?我總是非常慷慨,並且用堆疊金絲雀保護它,看它是否完好無損。我認爲這種方法的主要問題是它可能會在以後引發麻煩。比如當你需要用24位PC而不是16位(現在只是一般的8位體驗)來尋求更大的程序存儲空間時,或者你只需​​要一些額外的功能,就可以通過一些額外的調用來實現。然後精確設置的堆棧可能真的回到你身上。當然,如果你擠出最後一點,那麼確定,但我認爲這應該是最後一個。 – Jubatian

+0

「是否有任何免費的開源工具可以做到這一點?」。有一個免費版本(不開放源代碼)的IAR IDE(30天或4K代碼限制),其中鏈接器列表選項生成應用程序的堆棧使用情況。儘管你正在使用GCC,爲了得到Stack Stack(總數和每個函數),代碼大小(總數和每個函數)和其他細節(如內存放置和變量地址和大小等)的詳細信息,可以使用IAR嵌入式工作臺。 – Harikrishnan

+0

[在編譯時檢查堆棧使用情況]可能的重複(http://stackoverflow.com/questions/126036/checking-stack-usage-at-compile-time) – shodanex

回答

0

有趣的問題。

我期望這些信息在調試版本中包含的調試數據中是靜態可用的。

我不得不在DWARF標準簡單介紹一下,它確實指定稱爲DW_AT_frame_baseDW_AT_static_link功能,這可以用於兩個屬性「計算子程序 的相關實例的框架 基礎,立即包圍子程序或入口點「。

+0

謝謝。我不確定這些是多麼有用,但我在DWARF規範中遇到了「調用幀信息」,看起來它可能有更多信息。現在我只需要讓GCC生成.debug_frame部分 - 「-gdwarf-2 -g3」不會這樣做。 – cjc

0

我認爲唯一要做的就是通過靜態分析。您需要考慮所有非靜態局部變量的空間,這些變量大多是指針,但是無論如何將存儲在堆棧中的指針,還需要爲當前運行地址保留空間調用者,因爲它將被編譯器存儲在堆棧中,所以控制可以在函數返回後返回給調用者,並且還需要空間來存放所有函數參數。 基於此,如果您有一個工具可以計算所有參數,自動變量並計算出它們的大小,那麼您應該能夠計算出您需要的最小堆棧框架大小。 請注意,編譯器也可以嘗試爲您的特定架構調整堆棧上的值,這可能會使堆棧空間需求稍微大於您對此計算所期望的值。

0

一些嵌入式IDE可以在運行時給出堆棧使用的信息 我知道IAR嵌入式工作臺支持它。

請注意,您需要考慮中斷是否異步發生,因此請採取最大的堆棧使用情況併爲其添加中斷上下文。如果在ARM處理器中支持嵌套中斷,則還需要考慮這一點。

1

雖然靜態分析是確定最大堆棧使用情況的最佳方法,但您可能不得不求助於實驗方法。這種方法不能保證你的絕對最大值,但可以爲你提供堆棧使用的一個很好的想法。

您可以檢查鏈接腳本以獲取__STACK_END和__STACK_SIZE的位置。您可以使用這些來填充堆棧空間,並使用0xDEAD或0xAA55等容易識別的模式。通過酷刑測試來運行您的代碼,以確保儘可能多地生成中斷。

測試結束後,您可以檢查堆棧空間以查看堆棧的多少被覆蓋。

+0

你甚至可以將它們聲明爲extern。 'extern char __STACK_END;'&__ STACK_END'將是堆棧中最後一個字節的地址 – Michael