【ARM 嵌入式 編譯系列 10 -- GCC 編譯縮減可執行文件 elf 文件大小】

文章目錄

    • GCC 如何縮減可執行文件size
      • 測試代碼

上篇文章:ARM 嵌入式 編譯系列 9-- GCC 編譯符號表(Symbol Table)的詳細介紹
下篇文章:ARM 嵌入式 編譯系列 10.1 – GCC 編譯縮減可執行文件 elf 文件大小

GCC 如何縮減可執行文件size

在開發過程總,總是希望編譯出來的可執行文件盡量小,因為這樣可以節省更多的磁盤空間,那么有什么方法可以縮小可執行文件的大小的

A: 通常我們會首先移除了debug信息,移除了符號表信息,同時我們還希望萬一出事了,比如coredump了,我們能獲取更多的信息。

Linux下是怎么解決這個矛盾的呢
先看第一個問題,移除debug相關信息的影響。

測試代碼

如下實現了測試代碼,main 調用了 foofoo 調用了 bar,其中bar故意訪問了非法地址,為了引起 core dump

#include<stdio.h>
#include<stdlib.h>static int bar(void)
{char *p = NULL;printf("I am bar,I will core dump\n");printf("%s",p);*p =0x0;return 0;
}static int foo(void)
{int i ;printf("I am foo,I will call bar\n");bar();return 0;
}int main(void)
{printf("I am main, I wll can foo\n");foo();return 0;
}

先編譯出一個 debug 版本來,然后我們看到可執行程序的大小為 17464 bytes.

gcc -g test.c -o test
ls -rtl test
-rwxrwxr-x 1 codingcos codingcos 17464  814 09:43 test

再看下 section 信息:

readelf -S test
There are 37 section headers, starting at offset 0x3af8:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.pr[...] NOTE             0000000000000338  000003380000000000000030  0000000000000000   A       0     0     8[ 3] .note.gnu.bu[...] NOTE             0000000000000368  000003680000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000038c  0000038c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003b0  000003b00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003d8  000003d800000000000000c0  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000498  000004980000000000000094  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           000000000000052c  0000052c0000000000000010  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000540  000005400000000000000030  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000570  0000057000000000000000c0  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000630  000006300000000000000030  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000030  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001060  000010600000000000000020  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001080  000010800000000000000174  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         00000000000011f4  000011f4000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  000020000000000000000055  0000000000000000   A       0     0     4[19] .eh_frame_hdr     PROGBITS         0000000000002058  000020580000000000000044  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         00000000000020a0  000020a000000000000000ec  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003db0  00002db00000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003db8  00002db80000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003dc0  00002dc000000000000001f0  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb0  00002fb00000000000000050  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000010  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004010  000030100000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003010000000000000002b  0000000000000001  MS       0     0     1[28] .debug_aranges    PROGBITS         0000000000000000  0000303b0000000000000030  0000000000000000           0     0     1[29] .debug_info       PROGBITS         0000000000000000  0000306b000000000000011a  0000000000000000           0     0     1[30] .debug_abbrev     PROGBITS         0000000000000000  0000318500000000000000cd  0000000000000000           0     0     1[31] .debug_line       PROGBITS         0000000000000000  000032520000000000000076  0000000000000000           0     0     1[32] .debug_str        PROGBITS         0000000000000000  000032c800000000000000ea  0000000000000001  MS       0     0     1[33] .debug_line_str   PROGBITS         0000000000000000  000033b2000000000000003d  0000000000000001  MS       0     0     1[34] .symtab           SYMTAB           0000000000000000  000033f000000000000003a8  0000000000000018          35    20     8[35] .strtab           STRTAB           0000000000000000  0000379800000000000001f5  0000000000000000           0     0     1[36] .shstrtab         STRTAB           0000000000000000  0000398d000000000000016a  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),D (mbind), l (large), p (processor specific)

然后,我們用 strip 命令將 debug info 去除,指令如下:

strip --strip-debug test
ls -rtl test
-rwxrwxr-x 1 codingcos codingcos 15912   814 09:43 test

可執行文件的大小從17464減小到了15912

去除掉 debug info 的 test 和之前的 test 有什么區別呢? 我們看下去除后的 section 信息:

 readelf -S test
There are 31 section headers, starting at offset 0x3668:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.pr[...] NOTE             0000000000000338  000003380000000000000030  0000000000000000   A       0     0     8[ 3] .note.gnu.bu[...] NOTE             0000000000000368  000003680000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000038c  0000038c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003b0  000003b00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003d8  000003d800000000000000c0  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000498  000004980000000000000094  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           000000000000052c  0000052c0000000000000010  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000540  000005400000000000000030  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000570  0000057000000000000000c0  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000630  000006300000000000000030  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000030  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001060  000010600000000000000020  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001080  000010800000000000000174  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         00000000000011f4  000011f4000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  000020000000000000000055  0000000000000000   A       0     0     4[19] .eh_frame_hdr     PROGBITS         0000000000002058  000020580000000000000044  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         00000000000020a0  000020a000000000000000ec  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003db0  00002db00000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003db8  00002db80000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003dc0  00002dc000000000000001f0  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb0  00002fb00000000000000050  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000010  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004010  000030100000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003010000000000000002b  0000000000000001  MS       0     0     1[28] .symtab           SYMTAB           0000000000000000  000030400000000000000330  0000000000000018          29    15     8[29] .strtab           STRTAB           0000000000000000  0000337000000000000001db  0000000000000000           0     0     1[30] .shstrtab         STRTAB           0000000000000000  0000354b000000000000011a  0000000000000000           0     0     1

我們可以看到.debug_aranges .debug_info .debug_abbrev .debug_line .debug_str .debug_line_str debug 相關的 section 都已經不在了,原來的 37個section減少到了31個 sections。

但是我們注意到.symtab .strtab .shstrtab 符號表信息 和 字符串信息還在。此外,可以通過nm命可以看到它們的具體信息這:

[09:53:16]shiqiang.zhu@selab-ThinkStation-P350 (*^~^*) ~/workbase/test> nm test
000000000000038c r __abi_tag
0000000000001169 t bar
0000000000004010 B __bss_start
0000000000004010 b completed.0w __cxa_finalize@GLIBC_2.2.5
0000000000004000 D __data_start
0000000000004000 W data_start
00000000000010b0 t deregister_tm_clones
0000000000001120 t __do_global_dtors_aux
0000000000003db8 d __do_global_dtors_aux_fini_array_entry
0000000000004008 D __dso_handle
0000000000003dc0 d _DYNAMIC
0000000000004010 D _edata
0000000000004018 B _end
00000000000011f4 T _fini
00000000000011ae t foo
0000000000001160 t frame_dummy
0000000000003db0 d __frame_dummy_init_array_entry
0000000000002188 r __FRAME_END__
0000000000003fb0 d _GLOBAL_OFFSET_TABLE_w __gmon_start__
0000000000002058 r __GNU_EH_FRAME_HDR
0000000000001000 T _init
0000000000002000 R _IO_stdin_usedw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTableU __libc_start_main@GLIBC_2.34
00000000000011d1 T mainU printf@GLIBC_2.2.5U puts@GLIBC_2.2.5
00000000000010e0 t register_tm_clones
0000000000001080 T _start
0000000000004010 D __TMC_END__

此時如果執行這個 test 可執行程序,會產生coredump文件,如果使用gdb調試coredump文件的時候,我們可以打印出堆棧信息,因為符號表還在

在往下進行之前我們先學習一個命令: ulimit
ulimit 是 如 Linux 中用于控制shell和其創建的進程可以使用的系統資源。

  • ulimit -c選項則用于設置核心文件(core dump)的最大大小。當一個程序奔潰時,操作系統可以將程序的內存內容和一些調試信息保存到一個核心文件中,以便開發者可以查看這些信息來調試程序。這個文件通常被稱為core dump

使用ulimit -c命令可以查詢或設置 core文件的最大大小。例如:

  • ulimit -c:查詢當前core文件的最大大小。如果返回的是0,那么表示不會生成core文件;
  • ulimit -c unlimited:設置core文件的最大大小為無限,即允許core文件的大小不受限制。

注意: ulimit -c 設置的限制僅對當前shell及其子進程有效,不會影響到其他shell或全局設置。在一些系統中,為了安全考慮,默認可能不啟用 core dump,即使你使用ulimit -c unlimited也不會生成 core文件。在這種情況下,你可能需要修改系統的核心設置或其他配置來啟用core dump。

1)使用ulimit -c查看core dump是否打開。如果結果為0,則表示此功能處于關閉狀態,不會生成core文件, 執行 ulimit -c 1024
2)修改/etc/sysctl.conf文件【sudo vi /etc/sysctl.conf】,添加需要保存的路徑【kernel.core_pattern = /tmp/corefile/core.%e.%t】
3)輸入 sudo sysctl -p /etc/sysctl.conf 命令即刻生效

由于 symtab .strtab .shstrtab 符號表信息 和 字符串信息還在,我們仍然可以使用 gdb 進行調試:

ulimit -c unlimited or ulimit -c 1024gdb -c /tmp/corefile/core.test.1691982639.1098584 test
Core was generated by `./test'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000560eb28091ab in bar () at test.c:10
10          *p =0x0;
(gdb) bt
#0  0x0000560eb28091ab in bar () at test.c:10
#1  0x0000560eb28091d1 in foo () at test.c:19
#2  0x0000560eb28091f4 in main () at test.c:27
(gdb)

雖然 debug 相關section已經去除,但是還有符號表信息,一旦出了core dump還可以進行debug。大部分的發行版的程序都會將符號表信息刪除如果符號表與可執行程序完全隔離,那將是一種什么樣的情況的?請見下篇文章。

上篇文章:ARM 嵌入式 編譯系列 9-- GCC 編譯符號表(Symbol Table)的詳細介紹
下篇文章:ARM 嵌入式 編譯系列 10.1 – GCC 編譯縮減可執行文件 elf 文件大小

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36940.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36940.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36940.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux下在qtcreator中創建qt程序

目錄 1、新建項目 2、單工程項目創建 3、多工程項目創建 4、添加子工程&#xff08;基于多工程目錄結構&#xff09; 5、 .pro文件 1、新建項目 切換到“編輯”界面&#xff0c;點擊菜單欄中的“文件”-“新建文件或項目” 2、單工程項目創建 只有一個工程的項目&#…

Axure RP移動端高保真CRM辦公客戶管理系統原型模板及元件庫

Axure RP移動端高保真CRM辦公客戶管理系統原型模板及元件庫&#xff0c;一套典型的移動端辦公工具型APP Axure RP原型模板&#xff0c;可根據實際的產品需求進行擴展&#xff0c;也可以作為移動端原型設計的參考案例。為提升本作品參考價值&#xff0c;在模板設計過程中盡量追求…

chatGPT應用于房地產行業

作為 2023 年的房地產專業人士&#xff0c;您無疑認識到技術對行業的重大影響。近年來&#xff0c;一項技術進步席卷了世界——人工智能。人工智能徹底改變了房地產業務的各個方面&#xff0c;從簡化管理任務到增強客戶互動。 在本文中&#xff0c;我們將探討幾種巧妙的人工智…

HTML 語言簡介

1.概述 HTML 是網頁使用的語言&#xff0c;定義了網頁的結構和內容。瀏覽器訪問網站&#xff0c;其實就是從服務器下載 HTML 代碼&#xff0c;然后渲染出網頁。 HTML 的全名是“超文本標記語言”&#xff08;HyperText Markup Language&#xff09;&#xff0c;上個世紀90年代…

zabbix自動注冊服務器以及部署代理服務器

文章目錄 Zabbix自動注冊服務器及部署代理服務器一.zabbix自動注冊1.什么是自動注冊2.環境準備3.zabbix客戶端配置4.在 Web 頁面配置自動注冊5.驗證自動注冊 二.部署 zabbix 代理服務器1.分布式監控的作用&#xff1a;2.環境部署3.代理服務器配置4.客戶端配置5.web頁面配置5.1 …

MS9940T 國產 模擬前端AFE芯片 11-15 節鋰電池或磷酸鹽電池管理芯片 替代BQ76940

產品簡述 MS9940T 是模擬前端 (AFE) 芯片&#xff0c;支持11 到 15 組電池串聯。通過 I 2 C &#xff0c;主機控制器 可以使用 MS9940T 來實現電池組管理功能&#xff0c;例如監控&#xff08;電池電壓、電池組電流、電池組 溫度&#xff09;、保護&#xff08;控制…

分類預測 | MATLAB實現GWO-BiLSTM-Attention多輸入分類預測

分類預測 | MATLAB實現GWO-BiLSTM-Attention多輸入分類預測 目錄 分類預測 | MATLAB實現GWO-BiLSTM-Attention多輸入分類預測預測效果基本介紹程序設計參考資料 預測效果 基本介紹 1.GWO-BiLSTM-Attention 數據分類預測程序 2.代碼說明&#xff1a;基于灰狼優化算法&#xff08…

vuejs 設計與實現 - 組件的實現原理

1.渲染組件 如果是組件則&#xff1a;vnode .type的值是一個對象。如下&#xff1a; const vnode {type: MyComponent,}為了讓渲染器能處理組件類型的虛擬節點&#xff0c;我們還需要在patch函數中對組件類型的虛擬節點進行處理&#xff0c;如下&#xff1a; function patc…

CentOS7.9 禁用22端口,使用其他端口替代

文章目錄 業務場景操作步驟修改sshd配置文件修改SELinux開放給ssh使用的端口修改防火墻&#xff0c;開放新端口重啟sshd生效 相關知識點介紹sshd服務SELinux服務firewall.service服務 業務場景 我們在某市實施交通信控平臺項目&#xff0c;我們申請了一臺服務器&#xff0c;用…

學習Vue:列表渲染(v-for)

在 Vue.js 中&#xff0c;實現動態列表的顯示是非常常見的需求。為了達到這個目的&#xff0c;Vue 提供了 v-for 指令&#xff0c;它允許您迭代一個數組或對象&#xff0c;將其元素渲染為列表。然而&#xff0c;在使用 v-for 時&#xff0c;key 屬性的設置也非常重要&#xff0…

微信小程序(原生)搜索功能實現

一、效果圖 二、代碼 wxml <van-searchvalue"{{ keyword }}"shape"round"background"#000"placeholder"請輸入關鍵詞"use-action-slotbind:change"onChange"bind:search"onSearch"bind:clear"onClear&q…

實踐-CNN卷積層

實踐-CNN卷積層 1 卷積層構造2 整體流程3 BatchNormalization效果4 參數對比5 測試效果 1 卷積層構造 2 整體流程 根據網絡結構來寫就可以了。 池化 拉平 訓練一個網絡需要2-3天的時間。用經典網絡來&#xff0c;一些細節沒有必要去扣。 損失函數&#xff1a; fit模型&…

運維監控學習筆記1

1、監控對象&#xff1a; 1、監控對象的理解&#xff1b;CPU是怎么工作的&#xff1b; 2、監控對象的指標&#xff1a;CPU使用率&#xff1b;上下文切換&#xff1b; 3、確定性能基準線&#xff1a;CPU負載多少才算高&#xff1b; 2、監控范圍&#xff1a; 1、硬件監控&#x…

線性掃描寄存器分配算法介紹

線性掃描寄存器分配 文章目錄 線性掃描寄存器分配1. 算法介紹2. 相關概念3. 算法的實現3.1 偽代碼3.2 圖示 參考文獻 論文地址&#xff1a; Linear Scan Register Allocation ? 我們描述了一種稱為線性掃描的快速全局寄存器分配的新算法。該算法不基于圖形著色&#xff0c;而…

echarts3d柱狀圖

//畫立方體三個面 const CubeLeft echarts.graphic.extendShape({shape: {x: 0,y: 0,width: 9.5, //柱狀圖寬zWidth: 4, //陰影折角寬zHeight: 3, //陰影折角高},buildPath: function (ctx, shape) {const api shape.api;const xAxisPoint api.coord([shape.xValue, 0]);con…

陪診小程序開發|陪診陪護小程序讓看病不再難

陪診小程序通過與醫療機構的合作&#xff0c;整合了醫療資源&#xff0c;讓用戶能夠更加方便地獲得專業醫療服務。用戶不再需要面對繁瑣的掛號排隊&#xff0c;只需通過小程序預約服務&#xff0c;便能夠享受到合適的醫療資源。這使得用戶的就醫過程變得簡單高效&#xff0c;并…

Redis使用規范及優化

緩存設計 緩存方案 普通緩存 查詢數據時&#xff0c;先查找緩存&#xff0c;如果有延長緩存時間并返回。如果沒有&#xff0c;再去查找數據庫&#xff0c;將查詢的數據再寫到緩存&#xff0c;同時設置過期時間。如果是靜態熱點數據&#xff0c;可以不設置緩存失效時間。 冷…

IntelliJ最佳插件

基于 IntelliJ 平臺的 JetBrains IDE 可能是當今最常見的 IDE 之一。它們的受歡迎程度在 JVM 語言社區中尤其明顯&#xff0c;IntelliJ IDEA 仍然是大多數開發人員的首選 IDE。所有這一切都是在一些新競爭對手的出現和老競爭對手克服以前的缺點并重新加入競爭者的情況下實現的。…

【EI/SCOPUS檢索】第三屆計算機視覺、應用與算法國際學術會議(CVAA 2023)

第三屆計算機視覺、應用與算法國際學術會議&#xff08;CVAA 2023) The 3rd International Conference on Computer Vision, Application and Algorithm 2023年第三屆計算機視覺、應用與算法國際學術會議&#xff08;CVAA 2023&#xff09;主要圍繞計算機視覺、計算機應用、計…

PPT顏色又丑又亂怎么辦?

一、設計一套PPT時&#xff0c;可以從這5個方面進行設計 二、PPT顏色 &#xff08;一&#xff09;、PPT常用顏色分類 一個ppt需要主色、輔助色、字體色、背景色即可。 &#xff08;二&#xff09;、搭建PPT色彩系統 設計ppt時&#xff0c;根據如下幾個步驟&#xff0c;依次選…