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的信息:

参考博客:
浙公网安备 33010602011771号