計算機原理系列之四 -------- 可重定位文件詳解
在徵得作者同意的情況下,本網站的作品允許非盈利性引用,並請註明出處:「作者:luomuxiaoxiao 轉載自:www.luomuxiaoxiao.com"字樣,以尊重作者的勞動成果。版權歸原作者所有。未經允許,嚴禁轉載。
- 一、生成中間文件
- 二、可重定位文件分析
- 2.1 解析文件頭,說明文件構成
- 2.2 分析ELF文件各部分
- 2.2.1 ELF header
- 2.2.2 section headers table及sections
- 三、參考閱讀
上篇文章我們從整體上介紹了從C文件到可執行文件的編譯過程,並逐個分析了單步編譯時生成的中間文件的類型。為了搞清楚編譯和鏈接過程中主要做了哪些工作, 我們應該首先明白編譯前後,鏈接前後文件內容的改變。根據上篇文章內容,編譯前的文件格式是彙編文件
,編譯後的文件是可重定位文件
。彙編文件就是簡單的文本文件,而可重定位文件是一個ELF格式的二進位文件。因此,本章我們將從ELF文件格式入手分析可重定位文件
的結構。
下面我們以C語言中經典的「hello, world」的產生的可重定位文件為例來說明。使用的環境如下:
- ubuntu 64位操作系統
- gcc作為編譯工具
(版本信息:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10))
一、生成中間文件
我們依然使用計算機原理系列之三 -------- 如何編譯目標文件中的hello.c文件來研究,使用下列命令生成hello.o
:
gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
二、可重定位文件分析
2.1 解析文件頭,說明文件構成
由於可重定位文件類型是ELF格式(關於ELF文件的知識,請閱讀詳解ELF文件),我們可以使用READELF
命令查看其構成。
$ readelf -h hello.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2s complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 672 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 13
Section header string table index: 10
其中,我們關注以下欄位:
Type: REL (Relocatable file)
: 可以看出.o
文件的類型為可重定位文件
;Number of program headers: 0
:可以看出可重定位文件
的program header table
的長度為0。這是因為program header table
保存的是segment
信息,而segment
是為了給載入器提供可執行程序在載入時所需的信息的,又因為可重定位文件本身並不能直接執行,因此在可重定位文件里不需要program header table
;Entry point address: 0x0
: 同上,由於可重定位文件不能直接執行,因此其入口地址為0(默認值);*** of section headers:***
:從ELF文件起始地址偏移672
個位元組處是section header table
的起始地址,section header table
中共有13
項,每項的大小為64 byte
;Size of this header: 64
: ELF文件頭大小為64 byte
。
2.2 分析ELF文件各部分
可重定位文件屬於二進位文件。在linux機器上,可以使用hexdump
命令來查看二進位文件的內容。
$ hexdump -C hello.o
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 01 00 3e 00 01 00 00 00 00 00 00 00 00 00 00 00 |..>.............|
00000020 00 00 00 00 00 00 00 00 a0 02 00 00 00 00 00 00 |................|
00000030 00 00 00 00 40 00 00 00 00 00 40 00 0d 00 0a 00 |....@.....@.....|
00000040 55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 |UH..............|
00000050 00 00 00 5d c3 68 65 6c 6c 6f 2c 20 77 6f 72 6c |...].hello, worl|
... snip ...
這實際上就是hello.o
文件的實際內容。
註: 最前面一列是hexdump命令添加的,並非ELF文件的內容。它是一個十六進位的數字,表示位元組序號。例如,
00000040 55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00
,其中0000040
即0x40
,十進位為64
。表示hello.o
文件的第64
個位元組是『55』
。 最後一部分由兩個『|』
包含的數字和字元也是hexdump命令添加的,它將其左側的十六進位數字轉化成了對應的ASCII字元,所有的控制字元表示為『.』
,所有的可顯示字元表示為對應的字元或圖形。
2.2.1 ELF header
根據ELF文件的結構,ELF文件最開始的部分是ELF header
,它是一個64位元組大小的結構體,也就是對應了hello.o
的前64個字元,即從0000000 - 00000040
的部分。前十六個位元組應該是對應其magic number
的部分。我們注意到,從0000000 - 0000000F
正好就是使用readelf讀出來的magic的值。剩下的部分只要結合struct ElfN_Ehdr
的成員信息和hexdump
命令輸出的內容即可一一驗證。
*** 請點擊下面鏈接繼續閱讀 ***
計算機原理系列之四 --- 可重定位文件詳解
如果你覺得有收穫,請點擊左下角的贊,你的支持是我繼續寫的動力!謝謝!
想第一時間查看我的文章嗎?請關注我的微信公眾號號,搜索「落木蕭蕭技術論壇」,更多精彩文章等你。
微信公眾號
推薦閱讀: