可執行文件的建立——預處理、編譯和連接 在object文件中有三種主要的類型。 一個可重定位(relocatable)文件保存着代碼和適當的數據,用來和其餘的object文件一塊兒來建立一個可執行文件或者是一個共享文件。 一個可執行(executable)文件保存着一個用來執行的程序;該文件指出了exec(BA_OS)如何來建立程序進程映象。 一個共享object文件保存着代碼和合適的數據,用來被下面的兩個連接器連接: -第一個是鏈接編輯器[請參看ld(SD_CMD)],能夠和其餘的可重定位和共享object文件來建立其餘的object。 -第二個是動態連接器,聯合一個可執行文件和其餘的共享object文件來建立一個進程映象。 一個object文件被彙編器和聯接器建立, 想要在處理機上直接運行的object文件都是以二進制來存放的。 那些須要抽象機制的程序,好比shell腳本,是不被接受的。
Object文件格式 Linking 視角 Execution 視角 ============ ============== ELF header ELF header Program header table (optional) Program header table Section 1 Segment 1 ... Segment 2 Section n ... Section header table Section header table (optional) 一個ELF頭在文件的開始,保存了路線圖(road map),描述了該文件的組織狀況。 sections保存着object 文件的信息,從鏈接角度看:包括指令,數據,符號表,重定位信息等。特別sections的描述會出項在之後的第一部分。 第二部分討論了段和從程序的執行角度看文件。 假如一個程序頭表(program header table)存在,那麼它告訴系統如何來建立一 個進程的內存映象。被用來創建進程映象(執行一個程序)的文件必需要有一個程 序頭表(program header table);可重定位文件不須要這個頭表。一個 section頭表(section header table)包含了描述文件sections的信息。每一個 section在這個表中有一個入口;每一個入口給出了該section的名字,大小, 等等信息。在聯接過程當中的文件必須有一個section頭表;其餘object文件可要 可不要這個section頭表。 注意: 雖然圖顯示出程序頭表馬上出如今一個ELF頭後,section頭表跟着其餘 section部分出現,事實是的文件是能夠不一樣的。此外,sections和段(segments) 沒有特別的順序。只有ELF頭(elf header)是在文件的固定位置。 數據表示 object文件格式支持8位、32位不一樣的處理器。不過,它試圖努力的在更大 或更小的體系上運行。所以,object文件描繪一些控制數據須要用與機器 無關的格式,使它儘量的用通常的方法甄別object文件和描述他們的內容。 在object文件中剩餘的數據使用目標處理器的編碼方式,無論文件是在哪臺 機子上建立的。
實驗樓環境圖html
1.新的可執行程序是從哪裏開始執行的? 2.爲何execve系統調用返回後新的可執行程序能順利執行? 3.對於靜態連接的可執行程序和動態連接的可執行程序execve系統調用返回時會有什麼不一樣?shell
.ELF可執行文件會被默認映射到0x804800地址 execve內核態,可執行文件覆蓋了原來的,返回時是新的可執行程序,也就是main函數發生的起點,加載新的可執行可執行環境。 須要動態連接的可執行文件先加載連接器ld 命令行參數和環境串都放在用戶態堆棧中。 將CPU控制權交給LD來加載依賴庫並完成動態連接。而後在初始化新程序堆棧時,拷貝進去,先函數調用參數傳遞,在系統調用參數傳遞 shell程序——>execve ——>sys_execve do_execve----> do_execve_common----->exec_vinprm------>search_binary_handler execve系統調用返回到用戶態 棧底pt_regs start_thread(...,elf_entry,....) 經過修改內核堆棧中EIP的值做爲新程序的起點。new ip, new sp. elf_entry是新的可執行程序的起點。 靜態連接:程序開始是從0x8048300或0x8048400,也就是main開始的位置 動態連接:動態連接器的起點。
.ELF可執行文件會被默認映射到0x804800地址
execve內核態,可執行文件覆蓋了原來的,返回時是新的可執行程序,也就是main函數發生的起點,加載新的可執行可執行環境。 shell程序——>execve ——>sys_execve do_execve----> do_execve_common----->exec_vinprm------>search_binary_handler 棧底pt_regs start_thread(...,elf_entry,....) 經過修改內核堆棧中EIP的值做爲新程序的起點。new ip, new sp. elf_entry是新的可執行程序的起點。
靜態連接:程序開始是從0x8048300或0x8048400,也就是main開始的位置
動態連接:須要動態連接的可執行文件先加載連接器ld,先從動態連接器開始,連接完成後,而後才返回到main函數起點。
將CPU控制權交給LD來加載依賴庫並完成動態連接。而後在初始化新程序堆棧時,拷貝進去,先函數調用參數傳遞,在系統調用參數傳遞
**註明「鄭偉 +編輯器
參考資料:函數
【1】http://www.xfocus.net/articles/200105/174.html 【2】http://mooc.study.163.com/learn/USTC-1000029000?tid=2001214000#/learn/hw?id=2001372010
能夠結合實驗截圖、ELF可執行文件格式、用戶態的相關代碼等; 博客內容中須要仔細分析新可執行程序的執行起點及對應的堆棧狀態等。編碼