除了最常見的為 .text, .data, .bss 這 3 個段之外,還有其它的一些常見段,如下所示:
.strtab : String Table 字串表,用於儲存 ELF 檔案中用到的各種字串。
.symtab : Symbol Table 符號表,從這裡可以所以檔案中的各個符號。
.shstrtab : 是各個段的名稱表,實際上是由各個段的名字組成的一個字串數組。
.hash : 符號雜湊表。
.line : 調試時的行號表,即原始碼行號與編譯後指令的對應表。
.dynamic : 動態連結資訊。
.debug : 調試資訊。
.comment : 存放編譯器版本資訊,比如 "GCC:(GNU)4.2.0"。
.plt 和 .got : 動態連結的跳轉表和全域入口表。
.init 和 .fini : 程式初始化和終結程式碼片段。
.rodata1 : Read Only Data,唯讀資料區段,存放字串常量,全域 const 變數,該段和 .rodata 一樣。
由上可見,這些段的名字前都有一個 '.' 點符號首碼,其義表示這些段的名字為系統所保留。應用程式可以使用非系統保留的名字作為自己的自訂段名,但是自訂的段名就不能使用 '.' 符號作為首碼,否則容易和系統保留的段名衝突。
一個 ELF 檔案中允許存在兩個及以上的同名段,比如可能會看到多個 .text 段。
可以用 objcopy 命令將一個普通二進位檔案,片,多媒體之類的東西作為目標檔案中的一個段。製作方法如下:
[beyes@beyes ELF]$ objcopy -I binary -O elf32-i386 -B i386 mypic.jpg temp.o
[beyes@beyes ELF]$ objdump -t temp.o
temp.o: file format elf32-i386
SYMBOL TABLE:
00000000 l d .data 00000000 .data
00000000 g .data 00000000 _binary_mypic_jpg_start
00011855 g .data 00000000 _binary_mypic_jpg_end
00011855 g *ABS* 00000000 _binary_mypic_jpg_size
objcopy 命令用於將目標檔案的的部分或全部內容拷貝到另一個目標檔案中,並可以實現格式的變換。
上面的 objcopy 命令中:
-I 選項表示指定輸入的目標檔案格式。
-O 選項表示指定輸出的目標檔案格式。
-B 選項指定要欲轉入目標檔案的輸入檔案的適用平台。這裡指定 i386 表示該圖片格式適用於 i386 平台。但由於 objcopy 所使用的 BFD 庫中已經識別了 i386 平台,所以這裡不用 -B 選項也是可以的。
在使用 objcopy 將圖片檔案轉換進目標檔案 temp.o 中後,預設會用 _binary_objfile_start 和 _binary_objfile_end 來標識被轉換檔在記憶體中的起始地址,結束位址;以及使用 _binary_objfile_size 來表示大小。
自訂段
通常,在 gcc 編譯出來的目標檔案中,代碼一般是放到 .text 段,全域變數和靜態變數被放到 .data 和 .bss 段。這隻是預設行為,我們有時可能希望變數或某些代碼放在一個自訂的段中去以實現某些特定功能,比如為了滿足某些硬體的記憶體和 I/O 地址布局,或者像 Linux 核心中用來完成一些初始化和使用者控制項複製時出現的錯誤異常等。GCC 提供了一個擴充機制,使得我們可以將變數放在我們自訂的段中。如下程式碼範例:
#include <stdio.h> __attribute__((section("myvarsection"))) int global_var = 18; __attribute__((section("myfuncsection"))) void hello(void); void hello(void){ printf ("hello world\n"); printf ("my global_var:%d\n", global_var); } int main(){ hello(); return 0;}
查看相應的目標檔案:
[beyes@beyes ELF]$ objdump -h sefsec.o
sefsec.o: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000012 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**2
ALLOC
3 myvarsection 00000004 00000000 00000000 00000048 2**2
CONTENTS, ALLOC, LOAD, DATA
4 .rodata 0000001e 00000000 00000000 0000004c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 myfuncsection 0000002b 00000000 00000000 0000006a 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
6 .comment 0000002e 00000000 00000000 00000095 2**0
CONTENTS, READONLY
7 .note.GNU-stack 00000000 00000000 00000000 000000c3 2**0
CONTENTS, READONLY
8 .eh_frame 00000058 00000000 00000000 000000c4 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
程式中使用 GCC 的擴充機制 __attribute__((section()) 來自訂自己的段。