1、ELF格式檔案的結構和内容
a)現在PC平台流行的可執行檔案格式(Executable)主要是Windows下的PE(Portable Executable)和linux下的ELF(Executable Linkable Format),他們都是COFF(Common file format)的變種。
b)ELF檔案的存儲結構和内容
ELF檔案包含了代碼、資料,而有些更包含了符号表、調試資訊、行号資訊、字元串等。ELF檔案一般将這些資訊按不同的屬性,以段的形式存儲。程式源代碼編譯後的機器指令一般放在代碼段,代碼段常見的名字有“.code”或“.text”。全局變量和局部靜态變量資料經常放在資料段,名字為“.data”。
下面以helloworld.c編譯後生成的helloworld可執行檔案為例來分析:
生成可供調試的可執行檔案:gcc -g helloworld.c -o helloworld
檢視可執行檔案hellworld的結構和内容:readelf –t helloworld
用strip指令删除符号表和調試資訊:
strip helloworld
$readelf –t helloworld
對比上面兩個的輸出結果,strip之後少了.debug_aranges,.debug_info,.debug_abbrev,.debug_str,.debug_line, .debug_loc等調試資訊和.symtab(符号表),.strtab(字元串表)。
2、ELF符号表的構成
對沒有經過strip處理的ELF檔案是存在符号表的。
$readelf –s helloworld
.symtab是符号表。Ndx列是每個符号所在的Section編号,例如main函數在第13個段(.text代碼段)。Value列是每個符号所代表的位址,在目标檔案中,符号位址都是絕對位址,例如main函數的位址是00000000004004f4。從Bind這一列可以看出隻有幾個符号是GLOBAL的,而其它符号是LOCAL的,GLOBAL符号是在彙程式設計式中用.globl訓示聲明過的符号。
3、不同編譯選項對ELF符号表的影響
-s(小寫字元s):
删除可執行程式中的所有符号表和所有重定位資訊。其結果與運作指令 strip 所達到的效果相同。
如:gcc -s helloworld –o helloworld
-Wa,–strip-local-absolute
從輸出符号表中移除局部絕對符号。如gcc -Wa,–strip-local-absolute helloworld.c –o helloworld
-fvisibility-inlines-hidden
預設隐藏所有内聯函數,進而減小導出符号表的大小,既能縮減檔案的大 小,還能提高運作性能,我們強烈建議你在編譯任何共享庫的時候使用該選項。參見 -fvisibility=hidden 選項。(這個是針對C++程式的)g++ -fvisibility-inlines-hidden helloworld.cpp –o helloworld
4、使用strip對可執行檔案進行裁減
strip 指令減少 XCOFF 對象檔案的大小。strip 指令從 XCOFF 對象檔案中有選擇地除去行号資訊、重定位資訊、調試段、typchk 段、注釋段、檔案頭以及所有或部分符号表。 一旦您使用該指令,則很難調試檔案的符号;是以,通常應該隻在已經調試和測試過的生成子產品上使用 strip 指令。使用 strip 指令減少對象檔案所需的存儲量開銷。使用strip大概可以是可執行檔案減少1/3。
用法: strip
file(s)
strip一般有以下選項
-I –input-target= 假定輸入檔案的格式為bfdname
-O –output-target= 以格式bfname建立輸出檔案
-F –target= 設定輸入、輸出的檔案格式為bfdname
-p –preserve-dates 複制上次修改或者操作的時間到輸出檔案中
-R –remove-section= 删除輸出檔案中name段資訊
-s –strip-all 删除所有符号資訊和重定位資訊
-g -S -d –strip-debug 删除所有調試資訊和段資訊
–strip-unneeded 删除所有重定位中不需要的符号資訊
–only-keep-debug 删除調試資訊以外的其他所有資訊
-N –strip-symbol= 不拷貝name符号資訊
-K –keep-symbol= 不去除name符号資訊
–keep-file-symbols 不去除符号資訊
-w –wildcard 在符号中使用通配符
-x –discard-all 去除所有非全局符号
-X –discard-locals 去除所有編譯産生的符号
-v –verbose 列出所有修改過的所有目标檔案
-V –version 顯示版本号
-h –help 顯示幫助
-o 把輸出的檔案名修改成
5、給調試的ELF檔案的符号表“減肥”
對ELF檔案來說,符号表裡的GLOBAL符号和WEAK符号在”.symtab”和”.dynsym”這兩個符号表裡都有,而且删除”.symtab”裡的這些符号,”.dynsym”裡的依然存在。是以可以删除”.symtab”裡的GLOBAL符号和WEAK符号來達到替符号表“減肥”的效果,指令如下:
strip –strip-symbol= elf_file或者strip -N elf_file