可執行程式的裝載

來源:互聯網
上載者:User

標籤:

                                                                            可執行程式的裝載

                                                                                                         20135109 高藝桐

                                                                                                        《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 

一、預先處理、編譯、連結和目的檔案的格式

1、1可執行程式是怎麼得來的

  • C代碼經過編譯器的預先處理編譯、編譯成彙編代碼、編譯器將其編譯成目標代碼、連結成可執行檔。
  • 預先處理負責把include的檔案包含進來及宏替換等工作。
  • 預先處理之後的檔案編譯成彙編代碼。
  • 彙編代碼.s編譯成.o

1、2目標檔案格式的ELF

  • 常見的檔案格式:A.out(最古老的)、 COFF 、PE(windows系統)、 ELF(Linux系統)
  • ABI應用程式二進位介面,在目標檔案中已經是二進位相容的格式了,目標檔案適應到某一種CPU體繫結構
  • ELF格式中主要有3種可執行檔:可重定位檔案.o,可執行檔,共用目標檔案

  • 一個ELF頭在檔案的開始,儲存了路線圖,描述了檔案的組織情況
  • 當建立或增加一個進程映像的時候,系統在理論上將拷貝一個檔案的段到一個虛擬記憶體段

1、3靜態連結的ELF可執行檔和進程的地址空間

  • 可執行檔ELF載入到記憶體中去:代碼的資料載入到記憶體中去
  • 預設ELF檔案載入到0x8048000
  • 程式的實際入口0x8048300(啟動一個剛載入過可執行檔之後開始執行的進入點)
  • 一般靜態連結會將所有代碼放在一個程式碼片段
  • 動態連結的進程會有多個程式碼片段

二、可執行程式、共用庫和動態連結

2、1裝載可執行程式之前的動作

  • 可執行程式的執行環境:shell命令列、main函數的參數和execve參數
  • shell本身不限制命令列參數的個數,命令列參數的個數受限於命令本身
  • shell會調用execve將命令列參數和環境傳遞給可執行程式的main函數
  • 命令列參數和環境變數是如何儲存和傳遞的:execve將原來的執行環境覆蓋掉了,shell程式——>execve——>sys_execve然後在初始化新程式堆棧時拷貝進去
  • 先函數調用參數傳遞,再系統調用參數傳遞

2、2裝載動態連結和運行時動態連結應用舉例

  • 動態連結分為:可執行程式裝載時動態連結和運行時動態連結
  • 準備.so檔案——>編譯成libshlbexample.so檔案(共用庫)——>編譯成libdllibexample.so檔案(動態裝載)
  • 編譯main:只提供了shellexample的-L和-l,並沒有提供dllibexample的相關資訊,只指明了-ldl

三、可執行程式的裝載

3、1可執行程式的裝載相關關鍵問題分析

  • execve和fork都是特殊的系統的調用,當前程式執行到execve系統調用時陷入到核心態,execve載入可執行檔把當前進程的可執行檔覆蓋掉,execve返回新的可執行程式的執行起點。

  • int execve(把命令列和環境參數載入進來)
  • sys_execve內部會解析可執行檔格式:do_execve->do_execve_common->exec_binprm
  • search_binaty_handle符合檔案格式,對應的解析模組(根據檔案頭部資訊尋找對應的檔案格式處理模組)
  • 對於ELF格式的可執行檔執行的是load_elf_binary

  • elf_format和init_elf_binfnt是觀察者模式中的觀察者
  • 尋找標頭檔是被觀察者,出現elf格式檔案,觀察者自動執行elf_format模組
  • execve系統調用返回使用者態從哪裡開始執行:load_elf_binary->start_thread(通過修改核心堆棧中EIP的值作為新程式的起點)

3、2sys_execve的內部處理過程

  • search_binary_handler(尋找可執行檔的處理函數) fmt->load_binary(載入可執行程式的處理函數)
  • register_binfmt(註冊結構體變數)
  • kernal_read讀取檔案資訊
  • ELF可執行檔會被預設映射到0x8048000這個地址
  • 需要動態連結的可執行檔先載入連接器ld這個共用庫 load_elf_interp(載入動態連接器的起點)
  • 如果是靜態連結直接進入elf_entry,elf_entry是新程式的起點
  • start_thread(如果是靜態連結,直接指向main8048000;如果可執行檔是動態連結程式庫,指向動態連接器的起點

3、3使用gdb跟蹤sys_execve的內部處理過程

自己實驗:

(1)複製,覆蓋test.c

test.c檔案代碼:

(2)產生根檔案系統時,將init hello放入rootfs地址中,這樣在執行exec檔案時,就自動載入hello檔案

(二)使用gdb跟蹤sys_execve核心功能的處理過程

1、載入符號表,並串連到連接埠1234

2、設定斷點:b sys_execve(可以先停在sys_execve然後再設定其他斷點),b load_elf_binary,b start_thread。

3、執行

4、輸入c繼續執行,輸入指令exec,list查看,按s可以跟蹤進行到do_execve的內部。

3、4可執行程式的裝載與莊生夢蝶的故事

  • 莊周(調用execve的可執行程式)
  • 入睡(調用execve陷入核心)
  • 醒來(系統調用execve返回使用者態)
  • 發現自己是蝴蝶(被execve載入的可執行程式)

3、5淺析動態連結的可執行程式裝載

  •  動態連結的過程,核心做了什嗎?動態連結程式庫的依賴會形成一個圖
  • ELF格式中的,.interp和.dynamic需要依賴動態連結器來解析

  • entry返回到使用者態時不是返回到可執行程式規定的起點,返回到動態連結器的程式入口

  •  

    裝載和連結之後ld將CPU的控制權交給可執行程式

  • 動態連結程式庫的裝載過程是一個圖的遍曆過程

四、總結

1、可執行程式的產生:

C語言代碼-->編譯器預先處理-->編譯成彙編代碼-->彙編器編譯成目標代碼-->連結成可執行檔,再由作業系統載入到記憶體中執行。

2、ELF格式中主要有3種可執行檔:可重定位檔案.o,可執行檔,共用目標檔案。

3、ELF可執行檔會被預設映射到0x8048000這個地址。

4、命令列參數和環境變數是如何進入新程式的堆棧的?

Shell程式-->execve-->sys_execve,然後在初始化新程式堆棧時拷貝進去。

先函數調用參數傳遞,再系統調用參數傳遞。

5、當前程式執行到execve系統調用時陷入核心態,在核心中用execve載入可執行檔,把當前進程的可執行檔覆蓋掉,execve系統調用返回到新的可執行程式的起點。

6、動態連結程式庫的裝載過程是一個圖的遍曆過程,

ELF格式中的.interp和.dynamic需要依賴動態連結器來解析,entry返回到使用者態時不是返回到可執行程式規定的起點,返回到動態連結器的程式入口。

可執行程式的裝載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.