Linux下面,目標文件、共享對象文件、可執行文件都是使用ELF文件格式來存儲的。程序經過編譯之後會輸出目標文件,然後經過鏈接可以產生可執行文件或者共享對象文件。Linux下面使用的ELF文件和Windows操作系統使用的PE文件都是從Unix系統的COFF文件格式演化來的。
UNIX與Linux操作系統下可執行文件格式解析 http://www.linuxidc.com/Linux/2007-04/3212.htm
我們先來了解一些基本的想法。
首先,最重要的思路是一個程序從人能讀懂的格式轉換為供操作系統執行的二進制格式之後,代碼和數據是分開存放的,之所以這樣設計有這麼幾個原因:
1、程序執行之後,代碼和數據可以被映射到不同屬性的虛擬內存中。因為代碼一般是只讀的,而數據是可讀可寫的;
2、現代CPU有強大的緩存體系。程序和代碼分離可以提高程序的局部性,增加緩存命中的概率;
3、還有最重要的一個原因是當有多個程序副本在運行的時候,只讀部分可以只在內存中保留一份,這樣大大節省了內存。
在ELF的定義中,把他們分開存放的地方稱為一個 Section ,就是一個段。
一個ELF文件中重要的段包括:
.text 段:存儲 只讀程序
.data 段:存儲 已經初始化的全局變量和靜態變量
.bss 段:存儲 未初始化的全局變量和靜態變量,因為這些變量的值為0,所以這個段在文件當中不占據空間
.rodata 段:存儲 只讀數據,比如字符串常量
我們用一個例子來看一下ELF文件的格式到底是什麼。首先,在Linux下編寫一個C程序:SimpleSection.c
int printf(const char *format, ... );
int global_init_var = 16;
int global_unint_var;
void func1 (int );
int main()
{
static int static_var = -32;
static int static_var_uninit;
int a = 1;
int b;
func1(static_var + global_init_var + a + b);
return a;
}
void func1 (int i)
{
printf("%d\n", i);
}
然後,產生目標文件:
[[email protected] Program]# gcc -c SimpleSection.c
[[email protected] Program]# file SimpleSection.o
SimpleSection.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
file命令的結果也告訴我們,這是一個32位ELF的文件,類型是 relocatable ,就是可重定位。所以目標文件又叫做可重定位文件。
elf文件的最開始是elf文件頭信息,32位有52個字節組成。我們可以使用 readelf 工具來查看一下:
[[email protected] Program]# readelf -h SimpleSection.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 224 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 11
Section header string table index: 8
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-09/107418p2.htm