2023年12月2日发(作者:)

Linux可执行文件格式

Elf 也就是 “Executable and Linking Format.”

Elf 起源于Unix,经改进应用于FreeBSD和Linux等现有类Unix操作系统。

微软的PE格式也学习了ELF格式的优点。

ELF文档服务于在不同的操作系统上目标文件的创建或者执行文件的开发。它分以下三个部分:

“目标文件”描述了ELF目标文件格式三种主要的类型。

“程序装载和动态连接”描述了目标文件的信息和系统在创建运行时程序的行为。

“C 语言库”列出了所有包含在libsys中的符号、标准的ANSIC和libc的运行程序,还有libc运行程序所需的全局的数据符号。

三种主要类型:

一个可重定位文件(relocatable file)保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享文件。

一个可执行文件(executable file)保存着一个用来执行的程序,该文件指出了exec(BA_OS)如何来创建程序进程映象。

一个共享目标文件(shared object file)保存着代码和合适的数据,用来被下面的两个链接器链接。第一个是链接编辑器,可以和其他的重定位和共享目标文件来创建另一个目标文件。第二个是动态链接器,联合一个可执行文件和其他的共享目标文件来创建一个进程映象。

ELF的结构

ELF header

Program header table

(optional)

Section 1

Section n

Section header table

ELF头

#define EI_NIDENT 16

typedef struct {

e_ident[EI_NIDENT];

e_type;

unsigned char

Elf32_Half

Segment 1

Segment 2

Section header table

(optional)

ELF header

Program header table •

Elf32_Half e_machine;

Elf32_Word

Elf32_Addr

Elf32_Off

Elf32_Off

e_version;

e_entry;

e_phoff;

e_shoff;

Elf32_Word e_flags;

Elf32_Half e_ehsize;

Elf32_Half e_phentsize;

Elf32_Half e_phnum;

Elf32_Half e_shentsize;

Elf32_Half e_shnum;

Elf32_Half e_shstrndx;

} Elf32_Ehdr;

常用标示

名称

EI_MAG0

EI_MAG1

EI_MAG2

EI_MAG3

EI_CLASS

EI_DATA

EI_VERSION

偏移量

0

1

2

3

4

5

6

目的

e_ident[EI_MAG0] to e_ident[EI_MAG3]:文件的前4个字符保存一个魔术数(magic

number),用来确定该文件是否为ELF的目标文件。参见表7-7

e_ident[EI_CLASS],用来确定文件的类型或者说是容量。参见表1-8

e_ident[EI_DATA]指定了在目标文件中特定处理器数据的编码方式。参见表1-9

e_ident[EI_VERSION]表明了ELF头的版本号。现在这个变量的值一定要设为EV_CURRENT,参见表7-5

EI_OSABI

EI_PAD

7

9

操作系统和ABI的标识

ABI版本

e_ident[EI_PAD]标识了在e_ident中开始的未使用的字节,那些字节保留并被设置为0。程序把它们从目标文件中读出但应该忽略。如果当前未被使用的字节有了新的定义,EI_PAD变量将会被改变。

EI_NIDENT

16

e_ident[]的长度

EI_ABIVERSION 8

一个目标文件的节头表可以让我们定位所有的节。节头表是一个Elf32_Shdr结构的数组。一个节头表的索引是这个数组的下标。

ELF头结构中的e_shoff成员给出了节头表的偏移量(从文件开始计数)。

e_shnum告诉我们节头表中包含了多少个表项;

e_shentsize 给出了每个表项的长度。某些节头表索引是保留的,这些索引在目标文件中没有与之对应的节。

typedef struct {

Elf32_Word

Elf32_Word

Elf32_Word

Elf32_Addr

Elf32_Off

Elf32_Word

Elf32_Word

Elf32_Word

Elf32_Word

Elf32_Word

} Elf32_Shdr;

sh_name;

sh_type;

sh_flags;

sh_addr;

sh_offset;

sh_size;

sh_link;

sh_info;

sh_addralign;

sh_entsize;

字符串表

• 字符串表节(String table sections)保存着以NULL终止的一系列字符,一般我们称为字符串。目标文件使用这些字符串来表示符号和节名。一个字符串的引用是一个字符串表节的索引。

字符表

一个目标文件的符号表(symbol table)保存了定位和重定位程序的定义和引用的信息。一个符号表索引是相应的下标。0表项特指了该表的第一个表项,就象未定义的符号索引一样。

重定位(Relocation)

• 重定位(Relocation)是链接符号引用和符号定义的过程。比如,当一个程序调用一个函数的时候,相关的调用必须在执行时把控制传送到正确的目标地址。换句话说,重定位文件应当包含如何修改他们的节内容的信息,从而允许可执行文件或共享目标文件为一个进程的程序映像保存正确的信息。

程序头

• 一个可执行的或共享的目标文件的程序头表是一个结构数组,每一个结构描述一个段或其他系统准备执行该程序所需要的信息。一个目标文件段包含一个或多个部分(就象下面的“段目录”所描述的那样)。程序头仅仅对于可执行或共享的目标文件有•

意义。

typedef struct {

Elf32_Word

Elf32_Off

Elf32_Addr

Elf32_Addr

Elf32_Word

p_type;

p_offset;

p_vaddr;

p_paddr;

p_filesz; •

Elf32_Word

Elf32_Word

Elf32_Word

} Elf32_Phdr;

p_memsz;

p_flags;

p_align;

段内容实例

Text Segment Data Segment

程序载入

当创建或增加一个进程映像的时候,系统在逻辑上将拷贝一个文件的段到一个虚拟的内存段

动态链接

• 程序解释器(Progam Interpreter)

– 系统为解释器“编写”了一个内存映像,而不是使用原始的可执行文件的段映像。此时该解释器就负责接收来自系统的控制并且为应用程序提供一个环境变量。

动态链接器(Dynamic Linker)

– 当使用动态链接方式建立一个可执行文件时,链接器把一个PT_INTERP类型的元素加到可执行文件中,告诉系统像该系统的解释器一样调用动态链接器。

• 动态节(Dynamic Section)

– 如果一个目标文件参与动态的链接,它的程序头表将有一个类型为PT_DYNAMIC的元素。该“段”包含了.dynamic节。一个_DYNAMIC特别的符号,表明了该节包含了以下结构的一个数组。

• 共享目标的依赖关系(Shared Object Dependencies)

– 当链接器处理一个文档库时,它取出库中成员并且把它们拷贝到一个输出的目标文件中。当运行时没有包括一个动态链接器的时候,那些静态的链接服务是可用的。共享目标也提供服务,动态链接器必须把正确的共享目标文件链接到要执行的进程映象中。因此,可执行文件和共享的目标文件之间存在•

着明确的依赖性。

全局偏移量表 (Global Offset Table,GOT)

– 全局偏移量表在私有数据中保存着绝对地址,所以在不影响位置无关性和程序代码段共享能力的情况下应该使地址是可用的。一个程序参考它的GOT(使用位置无关的地址)并提取绝对的地址,所以与重定向无关的位置定位到绝对的位置。

• PLT过程连接表(Procedure Linkage Table)

– 正如GOT重定位把位置无关的地址计算成绝对地址一样,PLT过程链接表重定向那些与位置无关的函数调用到绝对的地址。

简单的C程序及其ELF格式信息

int xx, yy;

main()

{

xx = 1;

yy = 2;

printf ("xx %d yy %dn", xx, yy);

}

ELF头信息

root# objdump -f

: file format elf32-i386

architecture: i386, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED

start address 0x080483dc

程序头

Program Header:

PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2

filesz 0x000000c0 memsz 0x000000c0 flags r-x

INTERP off 0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0

filesz 0x00000019 memsz 0x00000019 flags r--

LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12

filesz 0x00000564 memsz 0x00000564 flags r-x

LOAD off 0x00000564 vaddr 0x08049564 paddr 0x08049564 align 2**12

filesz 0x000000a8 memsz 0x000000cc flags rw-

DYNAMIC off 0x0000059c vaddr 0x0804959c paddr 0x0804959c align 2**2

filesz 0x00000070 memsz 0x00000070 flags rw-

NOTE off 0x00000110 vaddr 0x08048110 paddr 0x08048110 align 2**2

filesz 0x00000018 memsz 0x00000018 flags r--

Dynamic节

Dynamic Section:

NEEDED .4

INIT 0x8048390

FINI 0x8048550

HASH 0x8048128

STRTAB 0x80482c8

SYMTAB 0x80481b8

STRSZ 0xad

SYMENT 0x10

DEBUG 0x0

PLTGOT 0x8049584

PLTRELSZ 0x18

PLTREL 0x11

JMPREL 0x8048378

节头表

Sections:

Idx Name Size VMA LMA File off Algn

0 .interp 00000019 080480f4 080480f4 000000f4 2**0

CONTENTS, ALLOC, LOAD, READONLY, DATA

1 .-tag 00000018 08048110 08048110 00000110 2**2

CONTENTS, ALLOC, LOAD, READONLY, DATA

2 .hash 00000090 08048128 08048128 00000128 2**2

CONTENTS, ALLOC, LOAD, READONLY, DATA

3 .dynsym 00000110 080481b8 080481b8 000001b8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA

4 .dynstr 000000ad 080482c8 080482c8 000002c8 2**0

CONTENTS, ALLOC, LOAD, READONLY, DATA

5 . 00000018 08048378 08048378 00000378 2**2

CONTENTS, ALLOC, LOAD, READONLY, DATA

6 .init 0000000b 08048390 08048390 00000390 2**2

CONTENTS, ALLOC, LOAD, READONLY, CODE

7 .plt 00000040 0804839c 0804839c 0000039c 2**2

CONTENTS, ALLOC, LOAD, READONLY, CODE

8 .text 00000174 080483dc 080483dc 000003dc

CONTENTS, ALLOC, LOAD, READONLY, CODE

9 .fini 00000006 08048550 08048550 00000550 2**2

CONTENTS, ALLOC, LOAD, READONLY, CODE

10 .rodata 0000000e 08048556 08048556 00000556 2**0

CONTENTS, ALLOC, LOAD, READONLY, DATA

11 .data 0000000c 08049564 08049564 00000564 2**2

CONTENTS, ALLOC, LOAD, DATA

12 .eh_frame 00000004 08049570 08049570 00000570 2**2

CONTENTS, ALLOC, LOAD, DATA

13 .ctors 00000008 08049574 08049574 00000574 2**2

CONTENTS, ALLOC, LOAD, DATA

14 .dtors 00000008 0804957c 0804957c 0000057c 2**2

CONTENTS, ALLOC, LOAD, DATA

15 .got 00000018 08049584 08049584 00000584 2**2

CONTENTS, ALLOC, LOAD, DATA

16 .dynamic 00000070 0804959c 0804959c 0000059c 2**2

CONTENTS, ALLOC, LOAD, DATA

17 .bss 00000024 0804960c 0804960c 0000060c 2**2

ALLOC

18 .stab 000001bc 00000000 00000000 0000060c 2**2

CONTENTS, READONLY, DEBUGGING

19 .stabstr 00000388 00000000 00000000 000007c8 2**0

CONTENTS, READONLY, DEBUGGING

20 .comment 000000c8 00000000 00000000 00000b50 2**0

符号表

SYMBOL TABLE:

080480f4 l d .interp 00000000

08048110 l d .-tag 00000000

08048128 l d .hash 00000000

080481b8 l d .dynsym 00000000

080482c8 l d .dynstr 00000000

08048378 l d . 00000000

2**2 08048390 l d .init 00000000

0804839c l

080483dc l

08048550 l

08048556 l

d .plt 00000000

d .text 00000000

d .fini 00000000

d .rodata 00000000

08049564 l d .data 00000000

08049570 l d .eh_frame 00000000

08049574 l d .ctors 00000000

0804957c l d .dtors 00000000

08049584 l d .got 00000000

0804959c l d .dynamic 00000000

• 0804960c l d .bss 00000000

• 00000000 l d .stab 00000000

• 00000000 l d .stabstr 00000000

• 00000000 l d .comment 00000000

• 00000000 l d .note 00000000

• 00000000 l d *ABS* 00000000

• 00000000 l d *ABS* 00000000

• 00000000 l d *ABS* 00000000

• 00000000 l df *ABS* 00000000 crtstuff.c

• 08048460 l .text 00000000 gcc2_compiled.

08049568 l

0804957c l

0804956c l

08048460 l

O .data 00000000 p.3

O .dtors 00000000 __DTOR_LIST__

O .data 00000000 completed.4

F .text 00000000 __do_global_dtors_aux

• 08049570 l O .eh_frame 00000000 __EH_FRAME_BEGIN__

080484b4 l F .text 00000000 fini_dummy

0804960c l O .bss 00000018 object.11

080484bc l F .text 00000000 frame_dummy

080484e0 l F .text 00000000 init_dummy

08049570 l O .data 00000000 force_to_data

08049574 l O .ctors 00000000 __CTOR_LIST__

00000000 l df *ABS* 00000000 crtstuff.c

08048520 l .text 00000000 gcc2_compiled.

08048520 l F .text 00000000 __do_global_ctors_aux

08049578 l O .ctors 00000000 __CTOR_END__

08048548 l F .text 00000000 init_dummy

08049570 l O .data 00000000 force_to_data

08049580 l O .dtors 00000000 __DTOR_END__

08049570 l O .eh_frame 00000000 __FRAME_END__

00000000 l df *ABS* 00000000 p10.c

080483ac F *UND* 00000031 printf

0804959c g O *ABS* 00000000 _DYNAMIC

08048550 g O *ABS* 00000000 _etext 08048390 g F .init 00000000 _init

08049624 g O .bss 00000004 environ

00000000 w *UND* 00000000 __deregister_frame_info

08049630 g O *ABS* 00000000 end

08049628 g O .bss 00000004 xx

08049564 g O .data 00000004 __progname

080483dc g F .text 00000083 _start

0804960c g O *ABS* 00000000 __bss_start

080484e8 g F .text 00000038 main

08048550 g F .fini 00000000 _fini

0804962c g O .bss 00000004 yy

080483bc F *UND* 00000070 atexit

0804960c g O *ABS* 00000000 _edata

08049584 g O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_

08049630 g O *ABS* 00000000 _end

080483cc F *UND* 0000005b exit

00000000 w *UND* 00000000 __register_frame_info

动态符号表

DYNAMIC SYMBOL TABLE:

080483ac DF *UND* 00000031 printf

0804959c g DO *ABS* 00000000 _DYNAMIC

08048550 g DO *ABS* 00000000 _etext

08048390 g DF .init 00000000 _init

08049624 g DO .bss 00000004 environ

00000000 w D *UND* 00000000 __deregister_frame_info

08049630 g DO *ABS* 00000000 end

08049564 g DO .data 00000004 __progname

0804960c g DO *ABS* 00000000 __bss_start

08048550 g DF .fini 00000000 _fini

080483bc DF *UND* 00000070 atexit

0804960c g DO *ABS* 00000000 _edata

08049584 g DO *ABS* 00000000 _GLOBAL_OFFSET_TABLE_

08049630 g DO *ABS* 00000000 _end

080483cc DF *UND* 0000005b exit

00000000 w D *UND* 00000000 __register_frame_info

Debugging Information

int main ()

{ /* 0x80484e8 */

} /* 0x80484e8 */

int main () { /* 0x80484e8 */

/* file /usr/home/shieyuan/test/p10.c line 3 addr 0x80484ee */

/* file /usr/home/shieyuan/test/p10.c line 5 addr 0x80484ee */

/* file /usr/home/shieyuan/test/p10.c line 6 addr 0x80484f8 */

/* file /usr/home/shieyuan/test/p10.c line 7 addr 0x8048502 */

/* file /usr/home/shieyuan/test/p10.c line 8 addr 0x804851e */

/* file /usr/home/shieyuan/test/p10.c line 8 addr 0x804851e */

} /* 0x8048520 */

int xx /* 0x8049628 */;

int yy /* 0x804962c */;

动态重定位表

• DYNAMIC RELOCATION RECORDS

• OFFSET TYPE VALUE

• 08049590 R_386_JUMP_SLOT printf

• 08049594 R_386_JUMP_SLOT atexit

• 08049598 R_386_JUMP_SLOT exit