ELF文件格式浅析

ELF文件的作用就不多介绍了。需要说明的是,.c文件生成的.o目标对象文件和可执行文件都属于ELF格式文件,二者的内容当然也有所不同,下面对其进行简单分析。


假设我们有如下C程序:

 1 // simple_section.c
 2 int printf( const char* format, ...);
 3 
 4 int global_init_var = 84;
 5 int global_uninit_var;
 6 
 7 void func1( int i)
 8 {
 9     printf("%d\n", i);
10 }
11 
12 int main(void)
13 {
14     static int static_var = 85;
15     static int static_var2;
16     int a = 1;
17     int b;
18 
19     func1(static_var + static_var2 + a + b);
20 
21     return a;
22 }

gcc -c simple_section.c 编译后生成目标对象文件simple_section.o与 gcc simple_section.c -o simple_section 生成可执行文件simple_section,二者都是ELF格式文件。


1.段(section/segment)

其实我更愿意称section为节,segment为段,不过考虑到许多资料中将二者都叫做段,在不必加以详细区分的情况下,我也就都叫做段吧。

程序中最重要的内容无非就是:数据和指令。

ELF文件由ELF文件头(ELF Header)、各种段/表组成。段中最常用的为代码段(.text)数据段(.data),分别对应指令和数据。其它段都是辅助代码段和数据段的。

通过 readelf -S simple_section.o 命令,查看段表,可以得知ELF文件中段的信息:

 

还可以通过 readelf -S simple_section 查看可执行文件的段表:

其中的.plt、.got和.got.plt是在动态链接中相当重要的段,具体请查看:动态链接浅析 - Hell0er - 博客园 (cnblogs.com)


2.段(头)表(section header table)

各种段的信息由段表组织管理,它描述ELF文件包含的所有段的信息,编译器、链接器和装载器通过段表来定位和访问各个段的属性。

通过 readelf -h simple_section.o 命令,查看ELF文件头,可以得知段表在ELF文件中的位置和大小:

readelf -h simple_section 命令查看simple_section的ELF文件头:

可以看到,在可执行文件中,ELF文件头中的多了Entry point address、XXX of program headers等信息,分别表示程序的入口地址、程序头表的相关信息。

程序头表(program header)与段表(section header)不同,它本质上是用来描述segment的,segment等同于程序,所以将描述segment信息的表称为program header table。


3.总结一下ELF文件格式的布局

链接视图是针对.o目标对象文件和.so共享对象文件的;而执行视图则是针对可执行文件。一个segment由多个section组合而成,即一个segment与多个section相映射,我们可以通过 readelf -l simple_section 命令读取program header table的信息:


参考博客:

posted @ 2023-06-01 15:24  Hell0er  阅读(74)  评论(0)    收藏  举报