首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

ELF 文件格式深度解析:從目標文件到可執行文件

     編輯:關於C語言

前言

ELF(Executable and Linkable Format)是 UNIX 系統通用的可執行文件標準格式,分為三種類型:可重定位目標文件、可執行文件、共享庫。本文通過分析匯編生成的 max.o 與鏈接後的 max,揭示匯編、鏈接、加載執行的完整過程。

一、ELF 的雙重視角:Section 與 Segment

ELF 文件根據使用階段呈現兩種視圖:

  • 鏈接視圖(靜態):由 Section Header Table 描述的 Section 集合。匯編器、鏈接器關注符號表、重定位表、代碼段、數據段等 Section。
  • 執行視圖(動態):由 Program Header Table 描述的 Segment 集合。加載器關注權限、加載地址、對齊等 Segment 信息。

ELF 雙視圖示意

關鍵點:

  • ELF Header 標識體系結構、操作系統,指明兩張表的文件偏移。
  • 目標文件必有 Section Header Table;可執行文件必有 Program Header Table;共享庫兩者皆有。
  • Section 經合併形成 Segment:屬性相同(如可讀可寫)的 Section 歸屬同一 Segment;僅供鏈接用的 Section(如 .symtab)不屬於任何 Segment,不加載入內存。

二、目標文件 max.o 分析

1. ELF Header 與 Section Header Table

ELF Header 信息

操作系統:UNIX,架構:80386。8 個 Section Header,文件偏移 0xc8,每項 40 字節。無 Program Header。

2. 關鍵 Section 詳解

Section Header 列表

  • .text、.data:源碼中 .section 聲明的段。
  • .bss:未初始化全局變量,文件中不佔空間,僅在 Section Header 中記錄大小,加載時清零。
  • .shstrtab、.strtab:分別存儲 Section 名稱與符號名稱的字符串表(以 \0 結尾)。
  • .symtab:符號表。Ndx 指示所在 Section 索引,Value 為相對地址。_start 為全局符號,其餘局部。
  • .rel.text:重定位表,記錄 .text 中需修正的地址位置(如訪問 .data 符號的指令)。

目標文件佈局 hexdump 輸出

3. 反匯編對比

反匯編結果

符號已被替換為相對地址(如 je 23)。跳轉指令使用相對偏移,內存訪問指令地址為 0,待鏈接器修正。

三、可執行文件 max 分析

1. ELF Header 變化

可執行文件 ELF Header

  • Type 變為 EXEC,Entry point 為 0x8048074(_start 地址)。
  • 新增 Program Header Table(2 項),減少 Section Header(刪除 .bss、.rel.text)。

2. Section Header Table 更新

.text 加載地址 0x8048074,.data 為 0x80490a0。符號表 Value 變為絕對地址,新增 __bss_start、_edata、_end 供加載器初始化 .bss。

3. Program Header Table 與內存映射

Program Header Table

  • Segment 1:.text + ELF Header + Program Header Table,加載至 0x08048000,權限 R X,文件大小 0x9e。
  • Segment 2:.data,加載至 0x080490a0,權限 R W,文件大小 0x38。
  • 對齊 0x1000(4KB 頁),滿足 MMU 頁級權限保護。文件偏移與內存偏移保持一致(0xa0),簡化加載器實現。

內存頁映射

4. 鏈接器的重定位動作

跳轉指令:使用相對偏移(PC-relative),指令機器碼 無需修改,反匯編顯示的目標地址因基址改變而不同。
內存訪問指令:mov 0x0(,%edi,4), %eax 中的 32 位立即數地址從 0x00000000 修正為 0x080490a0(小端序 a0 90 04 08)。

鏈接器依據 .rel.text 重定位條目精確定位需修正處:

Offset 0x08, 0x17  →  對應兩條 mov 指令中的 00 00 00 00 位置
Type R_386_32       →  32 位絕對地址重定位
Sym.Value 0         →  .data 段相對地址
Sym.Name .data      →  目標段

重定位表 反匯編對比 指令修正詳情

四、總結

  • 目標文件以 Section 為單位組織,保留符號、重定位信息供鏈接器處理。
  • 可執行文件以 Segment 為單位組織,按頁對齊映射內存,權限隔離,符號解析為絕對地址。
  • 鏈接器核心工作:合併 Section、分配虛擬地址、修正重定位項、生成 Program Header Table。
  • 加載器核心工作:按 Program Header Table 映射 Segment、設置頁權限、跳轉 Entry Point 執行。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved