可執行檔案和共享目標檔案(動態鏈結庫)是程式在磁碟中的靜態儲存形式;要執行乙個程式,系統就要先把相應的可執行檔案和共享目標檔案裝載到程序的位址空間中,這樣就形成乙個可執行程序的記憶體空間布局,稱為
程序映象
;乙個已經裝載完成的程序空間中會包含多個不同的
段(segment),比如,**段、資料段、堆疊段,等等;
準備乙個程式的記憶體映象,大體上可以分為兩個步驟:裝載和
鏈結;前者是把目標檔案裝載到記憶體中,後者是解析目標檔案中的符號引用;
乙個可執行檔案及其依賴的共享目標檔案被完全成功地裝載到程序的記憶體位址空間中之後,這個可執行檔案或共享目標檔案中的
程式頭部表
(program header table)就是必須存在的、不可缺少的必需品,程式頭部表是乙個陣列,陣列中的每乙個元素就稱為乙個
程式頭(program header),每乙個程式頭描述乙個
記憶體段(segment)或者一塊用於準備執行程式的資訊;記憶體中的乙個目標檔案中的段包含乙個或多個
節;也就是elf檔案在磁碟中的乙個或多個節可能會被對映到記憶體中的同乙個段中;程式頭只對可執行檔案或共享目標檔案有意義,對於其它型別的目標檔案,該資訊可以忽略;
在目標檔案的elf檔案頭部結構中,成員e_phentsize和e_phnum分別給出程式頭部表中元素(程式頭)的大小和數量;
程式頭使用結構體
elf32_phdr/elf64_phdr
來定義:
struct elf32_phdr
;struct elf64_phdr
;------欄位詳解------
1、p_type
:該欄位指明該程式頭所描述的記憶體段的型別,或者如何解析該程式頭的資訊;取值如下:
pt_null = 0: 該段沒有被使用;
pt_load = 1: 該段是乙個可裝載的記憶體段;
pt_dynamic = 2: 該段描述的是動態鏈結資訊;
pt_interp = 3: 該段描述的是乙個以"\0"結尾的字串,這個字串是乙個elf解析器的路徑;這種段型別只對可執行程式由意義,對其它型別的elf檔案無意義;在乙個elf檔案中它最多只能出現一次,而且必須出現在其它可裝載段的表項之前;
pt_note = 4: 該段描述乙個以"\n"結尾的字串,這個字串包含一些附加的資訊;
pt_shlib = 5: 保留值;
pt_phdr = 6: 此類段如果存在的話,則它表示的是其自身所在的程式頭部表在檔案或記憶體中的位置和大小;這樣的段在檔案中可以不存在,只有當所在的程式頭部表所覆蓋的段只是整個程式的一部分時,才會出現一次這種表項,而且一定會出現在其它可裝載段的表項之前;
pt_tls = 7: thread-local storage segment;
pt_num = 8: number of defined types;
pt_loos = 0x60000000 /* start of os-specific */
pt_gnu_eh_frame = 0x6474e550 /* gcc .eh_frame_hdr segment */
pt_gnu_stack = 0x6474e551 /* indicates stack executability */
pt_gnu_relro = 0x6474e552 /* read-only after relocation */
pt_losunw = 0x6ffffffa
pt_sunwbss = 0x6ffffffa /* sun specific segment */
pt_sunwstack = 0x6ffffffb /* stack segment */
pt_hisunw = 0x6fffffff
pt_hios = 0x6fffffff /* end of os-specific */
pt_loproc = 0x70000000 /* start of processor-specific */
pt_hiproc = 0x7fffffff /* end of processor-specific */
除非有特別要求,否則所有程式頭的段型別欄位p_type都是可選項,不是必須存在的;在所有程式頭都不指定段型別的情況下,程式頭部表中所有的表項都不代表任何特別的型別,而只是作為一種索引,表明其相應的段的大小和位置;
2、p_offset
:該欄位指明該段中內容在檔案中的位置,即,段中內容的起始位置相對於檔案開頭處的偏移量;
3、p_vaddr
:該欄位指明該段中內容的起始位置在程序位址空間中的虛擬位址;
4、p_paddr
:該欄位指明該段中內容的起始位置在程序位址空間中的實體地址;對於目前大多數現代作業系統而言,應用程式中段的實體地址是不可預先得知的,所以,目前這個字段大多數情況下保留不用,或者被作業系統改作它用;
5、p_filesz
:該欄位指明該段中內容在檔案中的大小,也可以是0;單位是位元組;
6、p_memsz
:該欄位指明該段中內容在記憶體映象中的大小,也可以是0;單位是位元組;
7、p_flags
:該欄位指明該段中內容的屬性;取值如下:
pf_x = (1 << 0) /* segment is executable */
pf_w = (1 << 1) /* segment is writable */
pf_r = (1 << 2) /* segment is readable */
pf_maskos = 0x0ff00000 /* os-specific */
pf_maskproc = 0xf0000000 /* processor-specific */
8、p_align
:該欄位指明該段中內容如何在記憶體和檔案中對齊;對於可裝載的段來說,其p_vaddr和p_offset的值至少要向記憶體頁面大小對齊;如果值為0或1,則表明沒有對齊要求,否則,p_align應該是乙個正整數,並且是2的冪次數;p_vaddr和p_offset在對p_align取模後應該相等;備註:
p_type=pt_load時,段的內容會被從檔案中拷貝到記憶體中,如果p_memsz>p_filesz,則在記憶體中多出的儲存空間中填0補充,即,段在記憶體中可以比在檔案中占用更大空間;相反,p_filesz永遠都不應該比p_memsz大,因為這樣的話,在記憶體中就將無法完整地對映段的內容;在程式頭部表中,所有pt_load型別的程式頭都按照p_vaddr的值做公升序排列;
ELF檔案和BIN檔案
檔案的內容 1.bin檔案是 raw binary 檔案,這種檔案只包含機器碼。2.elf檔案除了機器碼外,還包含其它額外的資訊,如段的載入位址,執行位址,重定位表,符號表等。所以elf檔案的體積比對應的bin檔案要大。檔案的執行 1.執行raw binary很簡單,只需要將程式載入到其起始位址,就...
ELF檔案和BIN檔案
檔案的內容 1.bin檔案是 raw binary 檔案,這種檔案只包含機器碼。2.elf檔案除了機器碼外,還包含其它額外的資訊,如段的載入位址,執行位址,重定位表,符號表等。所以elf檔案的體積比對應的bin檔案要大。檔案的執行 1.執行raw binary很簡單,只需要將程式載入到其起始位址,就...
ELF檔案和BIN檔案
檔案的內容 1.bin檔案是 raw binary 檔案,這種檔案只包含機器碼。2.elf檔案除了機器碼外,還包含其它額外的資訊,如段的載入位址,執行位址,重定位表,符號表等。所以elf檔案的體積比對應的bin檔案要大。檔案的執行 1.執行raw binary很簡單,只需要將程式載入到其起始位址,就...