ELF(Executable and Linking Format)格式教學文件, #2: ELF header 與範例規劃

jollen 發表於 November 22, 2006 11:39 PM

本文接續之前的日記「ELF(Executable and Linking Format)格式教學文件, #1: ELF 簡介」,在了解 ELF 的用途後,再來我們先由「ELF Header」的部份開始看起,我們的目標是寫一個可以將 ELF 執行檔裡所有 section 讀取出來的程式。未來將繼續朝 user-space 的 ELF 處理前進。

如果您是 Jollen 的讀者,或許曾經在書上讀到這個章節,本系統的內容與書上內容大致相仿,但仍有一些小差異,建議您可再讀一次。我希望能以其它的出版形式,將這些內容都與大家分享。

ELF header:檔頭格式

ELF 於 SysV ABI 標準中定義,其中 ELF header 的結構如下表:

Field Description

e_ident

用來辨別檔案是否為ELF,並包含一些machine independent 的資料。

e_type

檔案的類型

e_machine

檔案的平臺

e_version

版本資訊

e_entry

程式的起始位址(process virtual address

e_phoff

program header table的檔案偏移值(offset),單位是bytes。如果沒有program header table則此值為0

e_shoff

section header table的檔案偏移值(offset),單位是bytes。如果沒有section header table則此值為0

e_flags

processor有關的旗標值

e_ehsize

ELF header的長度,單位是bytes

e_phentsize

program header table每個entry的長度(bytes),每個entry的長度都相等。

e_phnum

program header tableentry個數,若無program header table 則此欄的值為0

e_shentsize

section header table每個entry的長度(bytes),每個entry的長度都相等。

e_shnum

section header tableentry個數,若program header table則此欄的值為0

e_shstrndx

section header tableindex值,索引至section name string table entry。如果檔案沒有section name string table,則此欄的值為SHN_UNDEF

ELF 檔案格式最基本的就是它的檔頭(header)部份,ELF header 儲存 object file 的各種資訊。ELF header 的讀取方式非常簡單,我們將會實作讀取 ELF header 的程式,以強化我們所讀到的觀念。

ELF header 的資料結構定義在 elf.h 裡,如下:

/* The ELF file header.  This appears at the start of every ELF file.  */

#define EI_NIDENT (16)

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

Section 與 section header table 的讀取與處理方式,會在介紹完 ELF header 後再做說明。

ELF 的範例程式

本系列日記共有 5 個範例程式,其功能差異整理如下表。

   讀取檔頭  分析檔頭  判斷ELF  處理Section  讀取Strtab  列印節區名稱
loader-0.1.c  ●  ●            
loader-0.2.c  ●  ●  ●         
loader-0.3.c  ●  ●  ●  ●      
loader-0.4.c  ●  ●  ●  ●  ●  ●
loader-0.5.c  ●  ●  ●  ●  ●  ●

為了能了解ELF格式,我們將會實作 6 大項功能如下:

1. 讀取檔頭:讀取 ELF 檔案的檔頭資訊。

2. 分析檔頭:分析讀取的檔頭資訊,例如分析 ELF 執行檔的編碼平臺。

3. 判斷 ELF:判斷所讀取的檔案是否為標準 ELF 格式的檔案。

4. 處理 Section:可以讀取所有 section 的資訊,並做簡單處理,例如找出是 string table 的 section。

5. 讀取 StrTab:讀取 section name string table 裡的資訊。

6. 列印節區名稱:處理 section name string table,可以根據 section name string table 來列印所有 section的名稱(ASCII string)。

我們將會以漸進式的方式來慢慢完成所有的功能,不同版本範例程式間的主要差異將會特別做說明,並詳細解釋新功能的程式實作。

另外,loader-0.4.cloader-0.5.c 看似功能相同,但 loader-0.5.c 主要是為了討論 loader-0.4.c 裡幾個奇怪的地方。我們會在講解loader-0.5.c 程式時再做更詳細的說明。

Loader 在載入 object file 前,必須先由 ELF header 取得 object file 的資訊並且判斷 object file 是否為 ELF 格式的執行檔,然後才能將 object file 載至記憶體。

Also See

Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue

您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw