linux目标文件ELF的格式


 

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">	</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">现在PC上流行的可执行文件格式主要是windows下的PE和linux下的ELF文件,他们都是COFF格式文件变种。目标文件时源代码编译后但未进行链接的那些中间文件,它跟可执行文件的格式几乎没有什么区别,因此目标文件(.o文件)也和可执行文件使用一样的储存格式。</span>

 

在linux中除了可执行文件还有几种文件也是使用ELF格式储存的,其中包括动态库文件(.so),可重定位文件(.o),核心转储文件(进程终止时系统将一些进程信息储存到该类型的文件)。我们可以使用file命令查看文件类型 eg:

 

xiang@xiang:~/workspace/linux$ file prim
prim: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xd54ce2ecedb22482c79f597093ff8c0b8f7c7113, not stripped
xiang@xiang:~/workspace/linux$ 
关于ELF文件的格式,其中包含了文件头(file header),代码段(.text),数据段(.data)未初始化数据段(.bss)等,通过objdump 命令可以查看各个段的信息。

 

 

xiang@xiang:~/workspace/algorithm$ g++ -c prim.cpp -o prim.o
xiang@xiang:~/workspace/algorithm$ objdump -h prim.o

prim.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000031f  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  00000354  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          003d3c21  00000000  00000000  00000360  2**5
                  ALLOC
  3 .rodata       00000008  00000000  00000000  00000360  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .ctors        00000004  00000000  00000000  00000368  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, DATA
  5 .comment      0000002c  00000000  00000000  0000036c  2**0
                  CONTENTS, READONLY
  6 .note.GNU-stack 00000000  00000000  00000000  00000398  2**0
                  CONTENTS, READONLY
  7 .eh_frame     000000dc  00000000  00000000  00000398  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
xiang@xiang:~/workspace/algorithm$ objdump -h prim
1,文件头(file header)在文件头中包含了文件的魔数,机器字长,版本,运行平台,文件类型,入口地址,短信息等内容,其中魔数用于告诉系统文件的类型,如ELF文件的魔数就是DEL符+ELF,

 

2,代码,数据段这些段非常熟悉,需要说明的一点就是.data段包含的是已经初始化的全局变量和静态变量,而。bss段包含的时未初始化的全局变脸和静态变量。其中有些文件中还存在。rodata段,存放只读数据段。另外在.bss段中的变量的默认值为0,因此.bss在elf文件中实际上并不占用空间,只是在装载的时候需要分配虚拟内存空间。

3. 段表,段表是elf文件除了文件头之外最重要的一个数据结构,其中包含了elf的各个段的信息,如每个段的段名,段的长度,在文件中的偏移,读写权限等,elf文件中的段结构就是由段表决定的,编译器,链接器装载器都是通过段表进行访问各个段的,段表的位置文件头中e_shoff决定,是在文件中的相对偏移。

4,重定位表,链接器的作用是链接多个目标文件,在一个文件中变量引用或函数引用可能定义在其他的目标文件中,而这些符号引用需要使用绝对地址。对于这些符号引用需要放在一个特定的段中,这个段就是重定位表。代码段的重定位信息放在.rel.text中,数据段的重定位信息放在.rel.data中。

5,字符串表,在ELF文件中有好多字符串,如段名,变量名,因为字符串的长度往往是不确定的,使用固定的结构来表示比较困难,一种常用的方法就是将所有的字符串放在一个单独的表中,而使用该字符串的地方只需要有个对该字符串的引用就可以了。

6,符号表,为了能将不同的目标文件链接起来,需要解决不同目标文件之间的相互引用问题。为了解决这个问题,在每个文件中存在很多符号表,其中包括全局符号表,外部符号表,局部符号等。其中全局符号包含定义在本目标文件中的全局符号,这些符号可以被其他的目标文件引用,外部符号包含了在本目标文件中引用,却未在本目标文件中定义的符号。

局部符号,指只有在编译单元内部可见的符号,在链接的过程中没有实际作用,链接器一般会忽略他们。

关于符号还涉及函数签名,强符号,弱符号等问题。


 

相关内容