ELF文件格式, ELF文件是什么,里面包含什么内容
原文地址:?http://blog.csdn.net/hhhbbb/article/details/6855004
最近研究了一下elf文件格式,發現好多資料寫的都比較繁瑣,可能會嚴重打擊學習者的熱情,我把自己研究的結果和大家分享,希望我的描述能夠簡潔一些。
一、基礎知識
?????elf是一種文件格式,用于存儲Linux程序. 它內部都有一些什么信息呢?大概包括編制好的計算機指令,數據,計算機在需要的時候把這個文件讀取到內存中,cpu就可以從內存中一條一條的讀取指令來執行了。
????所以說想明白elf格式,我們應該了解一下計算機執行程序需要那些信息。所以這一節,我們補充一些計算機系統的基礎知識。
????進程和虛擬內存:
???????Linux系統給每個進程分配了4GB的空間,其中 0xC0000000到0xFFFFFFFF 這個地址段是留給系統使用的,主要用于系統(linux 內核)和進程通信和交換數據, ??用戶可以使用3GB的空間從(0x00000000-0xBFFFFFFF).
??????其實計算機的內存是沒有那么大的,比如我們實際使用的計算機只有2G,以前更小,只有幾百M,而且一臺計算機上不只運行一個進程,一個占用4G,如果有10個進程,那就得著用40G了,哪有那么打的內存呢?其實這個不要緊,因為操作系統分配給用戶的是虛擬內存,程序要可以使用3個G的內存。至于操作系統怎樣把虛擬內存轉化成物理內存,對于開發應用程序的工程師來說,是不需要了解的。我們直接使用虛擬內存就可以了,而不用擔心其它進程會侵犯到你的內存空間。
????進程的創建和運行進程的創建和運行:
????大致經歷了以下步驟
?????1.用戶請求運行程序時,操作系統會讀取存儲在磁盤上的可執行文件,在linux系統上這個文件就是我們的elf格式文件,為用戶分配4G的虛擬內存空間,
?????2. 根據文件的信息指示,把不同的文件內容放到為你分配的這3G虛擬內存
?????3. 然后根據文件的指示,系統設置設置代碼段和數據段寄存器
?????4.然后根據文件的指示,????跳轉到用戶的代碼的入口地址(一般就是我們的main函數)
?????5.從main開始,計算機就一條一條的執行我們給的指令,處理我們的數據了,直到我們程序結束。雖然在這個過程中,系統會多次切換到其他進程,但對用戶程序來說沒有影響,我們可以認為計算機只為我們服務。
????通過以上我們多次看到計算機是根據文件指示這樣的語言,所以學習elf 首先要理解elf指示了那些信息。
二、可執行的elf文件。
?????elf文件分三種類型: 1、目標文件(通常是.o); 2、可執行文件(我們的運行文件)???3、動態庫(.so)
?????我們先講一下可執行文件。
?????可執行文件一般分成4個部分,能擴展,我們理解這4部分就夠了。
?????1、elf文件頭 ,這個文件是對elf文件整體信息的描述,在32位系統下是56的字節,在64位系統下是64個字節。
對于可執行文件來說,文件頭包含的一下信息與進程啟動相關
e_entry??????程序入口地址e_phoff??????segment偏移e_phnum???segment數量?????2.???segment表, 這個表是加載指示器,操作系統(確切的說是加載器,有些elf文件,比如操作系統內核,是由其他程序加載的),該表的結構非常重要。
typedef struct {Elf64_Word????p_type;????????????/* Segment type */Elf64_Word????p_flags;????????/* Segment flags */??/*segment權限,6表示可讀寫,5表示可讀可執行Elf64_Off????p_offset;????????/* Segment file offset */?????/*段在文件中的偏移*/Elf64_Addr????p_vaddr;????????/* Segment virtual address */???/*虛擬內存地址,這個表示內存中的Elf64_Addr????p_paddr;????????/* Segment physical address??/*物理內存地址,對應用程序來說,這個字段無用*/Elf64_Xword????p_filesz;????????/* Segment size in file */????????/*段在文件中的長度*/Elf64_Xword????p_memsz;????????/* Segment size in memory */???????/在內存中的長度,一般和p_filesz的值一樣*/Elf64_Xword????p_align;????????/* Segment alignment */??????????????????/* 段對齊*/ } Elf64_Phdr;????????3.???elf的主題,對于可執行文件來說,最主要的就是數據段和代碼段
?????4.???section表,對可執行文件來說,沒有用,在鏈接的時候有用,是對代碼段數據段在鏈接是的一種描述。
?????整個elf文件的組成可以使用下圖來描述:? ?
?
? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? 該圖片使用的是Linux C編程作者 宋勁斌的圖片
????????????????上圖program header table 實際上就是我們說的segment table.???segments 是從運行的角度來描述elf文件, sections是從鏈接的角度來描述elf文件的。
????????????????本節我們只將elf文件的執行,所以我們只講segment相關的內容。
??????我們將通過一個例子來講解系統加載elf的過程(64位平臺)。
??????我們編寫一個簡單的匯編程序
?.section .data .global data_item data_item: .long 3,67,28 .section .text .global _start _start:mov $1,%eaxmov $4,%ebxint $0x80?編譯鏈接后生成hello文件,我們分析hello文件.
?執行:readelf -h ../asm/hello?? (readelf -h 是讀取elf文件頭的命令)
ELF Header:Magic:?? 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00? Class:???????????????????????????? ELF64Data:????????????????????????????? 2's complement, little endianVersion:?????????????????????????? 1 (current)OS/ABI:??????????????????????????? UNIX - System VABI Version:?????????????????????? 0Type:????????????????????????????? EXEC (Executable file)Machine:?????????????????????????? Advanced Micro Devices X86-64Version:?????????????????????????? 0x1Entry point address:?????????????? 0x4000b0?????????????????????????????????????? //程序的入口地址是0x4000b0Start of program headers:????????? 64 (bytes into file)??????????????????? //segment表在文件64字節偏移處Start of section headers:????????? 240 (bytes into file)???????????????????? Flags:???????????????????????????? 0x0Size of this header:?????????????? 64 (bytes)??????????????????????????????????????? Size of program headers:?????????? 56 (bytes)???????????????????????????????? //segment頭項的長度是56字節(32系統是32字節) ? Number of program headers:???????? 2Size of section headers:?????????? 64 (bytes)Number of section headers:???????? 6Section header string table index: 3對于程序的裝載,我們關心這三項:
Entry point address:????0x4000b0??????//程序的入口地址是0x4000b0Start of program headers:????64 (bytes into file)????????????//segment表在文件64字節偏移處Size of program headers:???? 56 (bytes)?????????????//segment頭項的長度是56字節(32系統是32字節) ??以上內容告訴我們segment表在文件的64字節處,我們看看64字節處有什么內容。
執行 readelf -l ../asm/hello? 輸出segments信息。(readelf -l 讀取segments)
Program Headers:Type?????????? Offset???????????? VirtAddr?????????? PhysAddrFileSiz??????????? MemSiz????????????? Flags? AlignLOAD?????????? 0x0000000000000000 0x0000000000400000 0x00000000004000000x00000000000000bc 0x00000000000000bc? R E??? 200000LOAD?????????? 0x00000000000000bc 0x00000000006000bc 0x00000000006000bc0x000000000000000c 0x000000000000000c? RW???? 200000Section to Segment mapping:Segment Sections...00???? .text 01???? .data我們看到程序有兩個segment ,分別叫做.text 和.data?
??.text的Offset是0,FileSiz是0x0,MemSiz是0xbc, VirtAddr是0x400000,Flags是R E,表示加載起將把elf文件中從0字節開始直到oxbc處的內容加載到虛擬內存中的0x400000處,占用0xbc長度的內存。設置該內存的權限是RE(可讀,可執行),這一段的內容正好是elf頭,segments table,和代碼段。
???????在看看elfheader 的e_entry??的地址??0x4000b0,這個地址正好是代碼段的起始地址。
??????.data的Offset是0,FileSiz是0xbc,MemSiz是0x0c, VirtAddr是0x6000bc,Flags是R W,表示加載起將把elf文件中從bc字節開始直到oxbc + 0xc處的內容加載到虛擬內存中的0x6000bc處,占用0x0c長度的內存。設置該內存的權限是RE(可讀,可執行)
??????為什么數據段的其實地址是0x6000bc,而不是0x6000000呢,這是由Align決定的,Align決定內存和磁盤以1M為單位進行映射,在文件中.data 和.text處于一個頁面中,在映射的時候,直接把整個頁面都映射到了0x6000000處,所以把數據段的偏移設置成了0x60000bc,0x600000到0x6000bc的內容不使用。
????有了以上內容,系統就可以根據elf文件創建進程了。
?
?
?
總結
以上是生活随笔為你收集整理的ELF文件格式, ELF文件是什么,里面包含什么内容的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信支付-免充值立减与折扣(下篇)
- 下一篇: 阿龙学堂-算法-逻辑回归