目前Linux的主要的可執行檔格式是ELF(Executable and Linking Format),ELF為COFF格式的後繼者,主要特徵是可擁有多個section,並且有32-bit與64-bit的數值用以區別其格式屬於32-bit或是64-bit。主要缺點是ELF設計時有一個假設,每個系統只會有一個ABI(Application Binary Interface),但是事實上這是錯的,如SYSV至少就有SVR、Solaris、SCO等ABI。(詳細內容請閱讀參考資料)
-
ELF主要有三種類型的object files:
- A relocatable file holds code and data suitable for linking with other object files to create an executable or a shared object file.
- An executable file holds a program suitable for execution.
- A shared object file holds code and data suitable for linking in two contexts. First, the link editor may process it with other relocatable and shared object files to create another object file. Second, the dynamic linker combines it with an executable file and other shared objects to create a process image.
這是ELF的layout,所謂的Linking View是指以檔案呈現之ELF(左圖),而Execution View則是指被載入到RAM上執行的ELF(右圖)。
-
主要的section包含
- .text,存放程式碼的區域。
- .data用於存放已經初始化的變數。
- .bss用於存放未初始化的變數或者內容初始化為0的,該區域不占檔案空間。
- .rodata用於存放read-only data。
- 其他section和使用者自訂section後面再慢慢介紹。
#include <stdio.h> int i0 = 0; int i1 = 1; static int si0 = 0; static int si1 = 1; const int ci0 = 0; const int ci1 = 1; const static int csi0 = 0; const static int csi1 = 1; int main(void) { return 0; }
objdump -x a.out SYMBOL TABLE: 0000000000601034 l O .bss 0000000000000004 si0 000000000060101c l O .data 0000000000000004 si1 00000000004005b4 l O .rodata 0000000000000004 csi0 00000000004005b8 l O .rodata 0000000000000004 csi1 00000000004005b0 g O .rodata 0000000000000004 ci1 0000000000601030 g O .bss 0000000000000004 i0 00000000004005ac g O .rodata 0000000000000004 ci0 0000000000601018 g O .data 0000000000000004 i1根據前面的規則用const修飾的變數會被放置在.rodata中,有ci0、ci1、csi0、csi1。未初始化的變數或者內容初始化為0的都會被放置在.bss中,有i0、si0。已經初始化的變數則放在.data中,有i1、si1。
-
參考資料:
- 16.3. 為甚麼要用(甚麼是) a.out 和 ELF 執行檔格式?
- 程式設計師的自我修養 - 連結、載入、程式庫, CH3
- Tool Interface Standard (TIS) Executable and Linking Format (ELF)
- wiki, .bss
你好 我最近也在linux的環境下開發嵌入式系統,如果我有某一段程式想要分類在使用者自訂的section中, 能請問該怎麼定義嗎?
回覆刪除https://gcc.gnu.org/onlinedocs/gcc-3.4.3/gcc/Function-Attributes.html
回覆刪除extern void foobar (void) __attribute__ ((section ("bar")));