一步步编写操作系统 47 elf格式文件分析实验
在上一節中,我們講述了elf格式的部分理論知識,為什么是部分呢?因為我們本著“夠用”的原則,只把我們需要了解的部分說完啦。不過,我相信大部分同學僅僅憑上一節中的理論知識還是領悟不到elf本質,咱們在本節開始分析前面咱們寫過的“內核”,讓大家看清elf文件的每一個字節。
為了讓大家看清楚elf文件內部,咱們要用之前的xxd命令,為了方便使用,如很久很久以前所述,已經將其封裝成了xxd.sh腳本,參數1是待查看的文件名,參數2是文件內的起始字節,參數3是查看的連續字節數。腳本是逐字節輸出文件的內容。腳本內容很簡單,就是xxd命令而已:xxd -u -a -g 1 -s $2 -l $3 $1,您也看到了,參數比較多,弄成腳本完全是為了避免每次復雜的參數鍵入。為了讓大家方便使用,我已經將其放到了tool目錄下,腳本中有參數說明,這里不再列出。下面是用此腳本處理kernel.bin的輸出,見圖
之前我們就用過多次xxd命令啦,對于輸出想必大家一定很熟悉啦。腳本的輸出大概分了三部分,最左邊的一列是16進制的地址,或者稱為偏移量最為恰當。中間這一大塊矩陣似的16進制數字是文件中的內容,每兩位16進制數字為一字節,每行共16個字節。最右邊那一列,含有點點的、偶爾伴有可讀字符的部分是字符顯示區,這部分將內容按照字符編碼顯示,當然,前提肯定得是可打印字符,控制字符肯定不行,所以只要不是可顯示的字符便顯示為‘.’。
為了方便大家查看elf文件中各部分屬性,我在各屬性下面用下劃線予以區分。其中,細下劃線屬于elf header的范圍,粗下劃線屬于program header table程序頭表的范圍。在各范圍之中的各屬性,又以明顯的下劃線分隔,相信大家一定能一目了然。
咱們按照從上到下的順序,先從細下劃線的elf header部分說起。
第一行是e_ident數組,前4字節是固定的elf魔數,正如您看到的,它們是0x7f、和字符ELF的ascii:0x45、0x4c、0x46。所以您在顯示區看到了ELF的三個字符。緊跟其后的三個1分別是e_ident[4]、e_ident[5]、e_ident[6]三個成員,代表的意義是32位elf文件、小端字節序、當前版本。后面的9個00是e_ident[7]~ e_ident[15],這些確實都已經初始化為0。
現在看第二行。
第1個下劃線處的內容是02 00,由于是小端字節序,所以其值為0x0002。以下為方便陳述,只說該字節序所表示的數值。這個是e_type屬性,它占2字節,值為2表示類型為ET_EXEC,即可執行文件(有興趣的同學可以自行查看linux下的.o目標文件,其e_type類型是值為1的ET_REL,即待重定位類型)。
本行的第2個下劃線處的內容是0x0003,占2字節。該位置是e_machine屬性,即EM_386,表示該elf文件是運行在Intel 80386平臺。
第3個下劃線處的內容是0x00000001,占4字節。該位置是e_version屬性,即版本信息。
第4個下劃線處的內容是0xc0001500,占4字節,該位置是e_entry屬性,即程序的虛擬入口地址。
第5個下劃線處的內容是0x00000034,占4字節,該位置是e_phoff屬性,表示program header table程序頭表在文件中的偏移量,這里的偏移量是0x34。
現在看第三行。
第1個下劃線處的內容是0x0000055c,占4字節,該位置是e_shoff,表示section header table節頭表在文件內的偏移量,這里的值為0x55c,表示在本文件偏移0x55c字節處為節頭表。之前說過啦,若沒有節頭表,此處便為0。
第2個下劃線處的內容是0x00000000,占4字節,該位置是e_flags屬性。
第3個下劃線處的內容是0x0034,占2字節,該位置是e_ehsize屬性,表示elf header大小是0x34字節。這和前面e_phoff屬性值大小一致,可見,程序頭表緊跟著elf header之后。
第4個下劃線處的內容是0x0020,占2字節,該位置是e_phentsize屬性,即program header的結構:struct Elf32_Phdr的字節大小,值為0x20字節。
第5個下劃線處的內容是0x0002,占2字節,該位置是e_phnum屬性,即程序頭表中段的個數,這里為2個段。
第6個下劃線處的內容是0x0028,占2字節,該位置是e_shentsize屬性,即節頭表中各個節的大小。
現在看第四行。
第1個下劃線處的內容是0x0006,占2字節,該位置是e_shnum屬性,即節頭表中節的個數,這里表示有6個節。
第2個下劃線處的內容是0x0003,占2字節,該位置是e_shstrndx屬性,即string name table在節頭表中的索引為3。
現在開始分析粗下劃線范圍的程序頭表部分。
從第4行到第8行是程序頭表的范圍,前面說過啦,程序頭表中共有2個段,每個段大小是0x20字節。這有兩個粗下劃線,每個占0x20字節。大家注意圖中,在兩個粗下劃線間有個小豎線,這是用來區分兩個段的。豎線左右兩邊各是一個段。
下面咱們按照struct Elf32_Phdr結構來分析,該結構中每個屬性都占4字節,不再贅述?,F在還是繼續說圖的第4行。
第1個粗下劃線值為0x00000001,該位置是p_type屬性,值為1,即表示PT_LOAD類型,可加載程序段,由于kernel.bin已經是鏈接后的可執行程序啦,所以,這PT_LOAD類型符合我們的認知。
第2個粗下劃線值為0x00000000,該位置是p_offset屬性,表示本段在文件內的偏移量。這個偏移量為0,似乎很奇怪,這表示該段的起始是從文件頭開始也算起啦,文件開頭的部分不是elf header嗎?不是代碼啊,這是要鬧哪樣?好吧,到底是什么情況,一會咱們細說。
第3個粗下劃線值為0xc0001000,該位置是p_vaddr屬性,表示本段被加載到內存后的起始虛擬地址??吹竭@里,似乎覺得上面的p_offset為0有那么一點合理啦,結合elf header中的e_entry的值為0xc0101500,不知您想到了點什么。咱們先把剩下的說完。
第4個粗下劃線值為0xc0001000,該位置是p_paddr屬性,它通常和p_vaddr值一致,但該屬性是保留項,咱們不用關注。
第5個粗下劃線值為0x00000505,該位置是p_filesz屬性,表示本段在文件中的字節大小。
第6個粗下劃線值也應該是0x00000505,該位置是p_memsz屬性,表示本段在內存中的大小,因為段無論在哪里,邏輯大小是不變的,故該值等于p_filesz。
第7個粗下劃線值為0x00000005,該位置是p_flags屬性,表示與本段相關的標志。5=4+1=PF_R+PF_X,在此表示可讀,可執行,根據此屬性,我們推測此段為代碼段。
第8個粗下劃線值為0x00001000,該位置是p_align屬性,表示本段對齊的方式。
第一個段咱們說完了,第二個段這里就不解釋啦,留著大家自己練手吧。
總結
以上是生活随笔為你收集整理的一步步编写操作系统 47 elf格式文件分析实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新GDP数据即将出炉,我国二季度经济数
- 下一篇: 从名义GDP总量上看,美国比我国多了7万