2008-10-14 78 views
10

我正在生成一個在ARM處理器上運行的十六進制文件,我希望該文件在32K以下。它目前比這個要大得多,我想知道是否有人會對減少它的最好方法有什麼建議?減少可執行文件大小的過程

這裏是我到目前爲止已經完成

  1. 所以我跑「大小」它來確定十六進制文件有多大。
  2. 然後'大小'再次看看有多大的每個目標文件是鏈接來創建十六進制文件。看起來大部分大小來自外部庫。
  3. 然後我用'readelf'來查看哪些函數佔用了最多的內存。
  4. 我通過代碼搜索,看看我是否可以調用這些函數。

這裏是我卡住的地方,有一些函數,我不直接調用(例如_vfprintf),我找不到調用它,所以我可以刪除調用(因爲我認爲我不需要它)。

那麼接下來的步驟是什麼?

感謝您的幫助。

應對答案:

  • 正如我可以看到有函數被調用它佔用了大量的內存。我不能找到什麼叫它。
  • 我想省略這些功能(如果可能的話),但我找不到什麼叫他們!我猜可以從任意數量的庫函數中調用。
  • 鏈接器正在按照需要工作,我認爲它只包含相關的庫文件。你如何知道是否只包含相關功能?你能爲此設置一個旗幟嗎?
  • 我使用GCC
+0

也許你已經知道這一個,也許它是有幫助的:http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html – Matthias 2012-04-26 19:56:12

回答

11

一般列表:

  • 請確保您有禁用
  • 編譯的編譯器和連接調試選項,並鏈接了所有大小選項開啓(-Os在GCC)的
  • 運行strip可執行文件
  • 生成映射文件並檢查函數大小。你可以讓你的鏈接器生成你的映射文件(使用ld時爲-M),或者你可以在最終的可執行文件上使用objdump(注意,這隻適用於未被剪切的可執行文件!)這實際上並不能解決問題,但它會讓你知道最壞的罪犯。
  • 使用nm來調查從每個對象文件中調用的符號。這應該有助於查找誰不想調用的調用函數。

在原來的問題是一個只包括相關功能的子問題。 gcc將包含每個使用的目標文件中的所有函數。換句話說,如果你有一個包含10個函數的目標文件,即使實際調用了1個函數,你的可執行文件中也會包含所有10個函數。

標準庫(例如libc)會將函數分割成許多單獨的對象文件,然後將其存檔。然後將可執行文件鏈接到存檔。 通過分割成許多目標文件,鏈接器只能包含實際調用的函數。 (這假設你是靜態鏈接的)

沒有理由不能做同樣的伎倆。當然,你可以爭辯說,如果函數沒有被調用,你可以自己刪除它們。

如果你正在靜態鏈接其他庫,你可以運行上面列出的工具,以確保它們遵循類似的規則。

-1

你可以看看像executable compression

+0

如果_running_程序不應該超過32K。 – 2008-10-14 11:38:54

+0

如果它一次只解壓縮32k的話。 – TraumaPony 2008-10-14 14:00:35

+0

或者代碼必須是可ROM的。 – 2011-07-19 16:15:34

2

只是仔細檢查和記錄以備將來參考,但是您是否使用Thumb指令?它們是正常指令的16位版本。有時您可能需要2 16位指令,因此它不會在代碼空間中節省50%。

體面的鏈接器應該只需要所需的功能。但是,您可能需要編譯器連接設置才能爲單個鏈接打包函數。

1

好的,最後我把項目簡化爲最簡單的形式,然後逐個緩慢地添加文件,直到我想刪除的函數出現在'readelf'文件中。然後,當我收到文件時,我評論了所有內容,然後慢慢添加回來,直到該功能再次彈出。所以最終我發現了什麼叫它,並刪除了所有這些電話......現在它按需運作......甜蜜!

但必須是一個更好的方法來做到這一點。

5

假設您使用的是GCC,另一個可以節省工作量的優化是-ffunction-sections,-Wl,-gc-sections。儘管如此,一個好的工具鏈並不需要被告知。

說明:GNU ld鏈接部分和GCC爲每個轉換單元發出一個部分,除非您另有說明。但在C++中,依賴關係圖中的節點是對象和函數。

2

在深度嵌入式項目中,我總是儘量避免使用任何標準庫函數。即使像「strtol()」這樣簡單的函數也會破壞二進制大小。如果可能的話,只需簡單地避開這些電話在最深入的嵌入式項目中,您不需要多功能的「printf()」或動態內存分配(許多控制器具有32kb或更少的RAM)。

而不是僅使用「printf()」我使用一個非常簡單的自定義「printf()」,此函數只能打印十六進制或十進制格式的數字。大多數數據結構都是在編譯時預先分配的。

1

Andrew EdgeCombe有一個很棒的列表,但是如果你真的想要刮掉每一個最後的字節,sstrip是一個很好的工具,從列表中缺少,並且可以削減幾個kB。

例如,當在strip本身上運行時,it can shave off ~2kB

從舊的自述(參見評論在this間接源文件的頂部):

sstrip是一個小工具,其去除在 ELF文件的結尾不屬於的部分的內容該程序的內存映像。

大多數ELF可執行文件都是使用程序頭表和 節頭表構建的。但是,只有前者需要以 的順序才能加載,鏈接和執行程序。 sstrip嘗試 提取ELF頭,程序頭表和其內容, 將所有其他內容留在位桶中。它只能刪除 部分發生在最後的文件,在要保存的部分之後。然而, 這幾乎總是包含部分頭表,並偶爾會有幾個隨機部分在運行程序時不使用。

請注意,由於它刪除的某些信息,帶有一些工具的sstrip可執行文件是rumoured to have issues。這在源代碼的評論中有更多的討論。

另外...對於娛樂/瘋狂閱讀如何使盡可能小的可執行文件,this article值得一讀。

0

要回答這個特定的需求:

•我想省略這些功能(如果可能的話),但我找不到什麼 打電話給他們!可以從任意數量的庫函數中調用I 的猜測。

如果您想分析您的代碼庫以查看誰調用了什麼,調用給定函數的人以及類似的東西,那麼SciTools提供了一個名爲「Understanding C」的出色工具。

https://scitools.com/

我都經常用它在過去進行靜態代碼分析。它確實可以幫助確定庫依賴樹。它允許輕鬆瀏覽上下調用樹等等。

他們提供有限的時間評估,那麼你必須購買許可證。