2016-04-24 52 views
3

假設您不僅有可執行文件,還有源代碼文件。C++的計算堆棧需求;如何獲得可讀的符號表?

我的問題是計算正確的堆棧大小正在運行的進程只針對局部變量,返回地址,傳遞參數。我試圖使用由MS開發的VMMap。因爲它可以捕獲系統中分配的內存,並使用堆棧等類別。但是,它還包含警戒頁面,分頁文件等。因此,從VMMap堆棧大小被高估。

我想改變解決問題的方法。我將跟蹤堆棧以使用WinAPI的StackWalker64繪製實際調用樹,並從可執行代碼或源代碼中獲取符號表。但是有一個問題,象ELF這樣的可執行文件的符號表是不可讀的。

現在,我打算申請doxygen這是開源項目與編譯器的詞法分析器。因爲doxygen只提供函數列表及其返回類型和函數參數,所以我不知道局部變量。所以,我還需要詞法分析器來完成符號表的預處理。但它有點複雜。我不確定這是最佳解決方案。 有沒有更好的解決方法?

+0

我已經在過去被分配一個堆棧,用圖案填充,並給予該分配棧上創建線程做到了這一點。這些是嵌入式系統。在運行該應用程序之後,檢查分配的堆棧以找出該模式不再存在的位置,並且該堆棧深度用於應用程序的特定運行。 – dgsomerton

+0

我認爲這是關於固定大小的堆棧分配問題。你的方法必須修改系統的結構。而且它仍然高估了問題。根據堆棧配置大小,堆棧中會有可用內存。 – Hexoul

+1

除非你有真的很好的測試用例,否則你可能會估計錯誤。你需要內部和外部的代碼來測試堆棧分配的高水位標記。 – tadman

回答

1

OP想要做的是靜態計算最壞情況下的堆棧深度。

這很難做到。要做到這一點,他需要:

  • 爲每個函數的源代碼(如用來導出以下事實原料)
  • 爲每個函數
  • 調用圖中的「符號表」(所有聲明)不同編譯單元中的應用程序代碼的
  • 的他有什麼特別的編譯器生成優化代碼

的「符號表」一個低沉的知識需要編譯器精確,使得估計進程知道哪些聲明的數據(概念上)進入堆棧。 OP將需要相當於一個完整的編譯器前端爲他特定的C++方言。 [OP錯誤地認爲一個「詞法分析器」會給他一個符號表。它不會]。

現在考慮構建全局調用圖。基礎看起來很簡單;如果函數「bar」包含「foo(x)」,那麼「bar」將調用「foo」。但是有很多複雜性:重載,虛函數,間接調用和強制轉換。重載大概是通過名稱和類型解析來解決的;這在模板面前會變得混亂(考慮SFINAE)。虛擬功能和間接調用迫使人們構建一個保守的點對點分析器;足夠醜陋的演員可能會迫使假設致電任何參數兼容函數。要點 - 分析儀有不同程度的精確度;低精度可能會產生具有許多虛假(保守)邊緣的調用圖,這會導致估計大小。 編譯器不會提供這個全局調用圖,因爲它只能在單個編譯單元上運行。

最後,我們可以考慮構建堆棧大小估計。這裏需要了解用於表示每個聲明數據類型的大小和對齊方式,以及感興趣的特定編譯器如何將局部變量分配給堆棧。通常順序編碼塊{....} {...}重疊堆棧位置。還需要了解如何評估表達式以及如何傳遞參數,因爲這會影響堆棧使用情況。最後,需要了解編譯器如何分配寄存器以及編譯器可以/應用哪些優化(?),因爲這樣的優化會影響表達式堆棧使用情況以及實際分配給堆棧的多少本地變量。這是一個非常難以理解的知識,唯一值得信賴的知識來源是編譯器本身。與其試圖複製所有這些機制,最好是讓編譯器提供每個函數的實際堆棧大小分配(我相信GCC將這樣做),或者放棄獲得精確結果並保守估計堆棧需求假設每個聲明的本地消耗堆棧空間(在這種情況下,不清楚應該怎麼做來估計表達式堆棧使用情況;可以假定每個變量和中間表達式結果都根據其類型獲取堆棧空間)。

隨着每個函數的堆棧空間的估計,並調用圖,調用圖的一個簡單的分析可以產生從根每次通話鏈棧需求。這些中的最大值是所需的堆棧估計。 (注:假定每個函數都使用其每次調用的完整堆棧需求;這顯然是一個保守的估計)。這部分非常簡單。

總體而言,這是一個複雜的分析。理想情況下,您可以讓編譯器提供堆棧大小估計值和基本的調用圖事實。構建點到點分析很困難,並且隨着應用程序規模變大而變得非常困難。

按理說可以彎曲GCC幫助提供編譯單元級別的數據。 Clang大概是爲了提供相同的數據而設計的。我也沒有提供全球觀點的具體支持 - 以我的知識進行分析。目前還不清楚GCC和Clang處理C++的Windows方言;他們可能會。

我們DMS軟件再造工具包和它的C++前端被設計成提供符號表,名稱解析的結果(例如,過載解析),並且可以容易地提取本地呼叫的事實。它處理C++的GCC和MS方言。 DMS還爲建立全球分析點和全球調用圖提供支持;雖然我們沒有專門用於C++,但我們已經用它來處理大約1600萬行的C應用程序。

所有這些困難解釋了爲什麼人們經常踢和嘗試看看堆棧有多大使用動態分析。如果OP想要一臺靜態分析儀,他需要做好準備投入大量精力來獲得它。