天天看點

linux 重定位表 符号表,ELF格式檔案符号表分析

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