ELF(Executable and Linking Format):在计算机科学中,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。内核会根据这些信息加载可执行文件,内核根据这些信息可以知道从文件哪里获取代码,从哪里获取初始化数据,在哪里应该加载共享库等信息。
ELF组成格式:
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。

然而实际上,一个文件中不一定包含全部内容,而且他们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。

ELF文件有下面三种类型
1.目标文件
$ gcc -c test.c
得到的test.o就是目标文件,目标文件通过链接可生成可执行文件。
静态库其实也算目标文件,静态库是通过ar命令将目标打包为.a文件。
如:ar crv libtest.a test.o

2.可执行文件
$gcc -o test test.c
得到的test文件就是可执行的二进制文件。

3.共享库
$ gcc test.c -fPIC -shared -o libtest.so
得到的文件libtest.so就是共享库

readelf命令
可以通过readelf来区分上面三种类型的ELF文件,每种类型文件的头部信息是不一样的。

test.c文件内容:

    #include<stdio.h>
    
    int global_data = 4;
    int global_data_2;
    int main() { 
        int local_data = 3; 
    
        printf("Hello World\n"); 
        printf("global_data = %d\n", global_data); 
        printf("global_data_2 = %d\n", global_data_2); 
        printf("local_data = %d\n", local_data); 
        
        return (0);
    }

$gcc -c test.c
生成目标文件test.o,然后使用readelf对其进行分析。

$readelf -h test.o
下面是输出结果:

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          1112 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 10

$gcc -o test test.c
生成可执行文件test,然后使用readelf对其进行分析。

$readelf -h test
下面是输出结果:

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400490
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6720 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 27

通过上面的信息可以告诉知道:
1.根据Class、Type和Machine,可以知道该文件在X86-64位机器上生成的64位可执行文件。
2.根据Entry point address,可以知道当该程序启动时从虚拟地址0x400490处开始运行。这个地址并不是main函数的地址,而是_start函数的地址,_start由链接器创建,_start是为了初始化程序。通过这个命令可以看到_start函数,objdump -d -j .text test
3.根据Number of program headers,可以知道该程序有9个段。
4.根据Number of section headers,可以知道该程序有30个区。 区中存储的信息是用来链接使用的,主要包括:程序代码、程序数据(变量)、重定向信息等。比如:Code section保存的是代码,data section保存的是初始化或未初始化的数据,等等。

$readelf -h libtest.so
输出结果;

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x6a0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6368 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 26

readelf命令和ELF文件详解 - 姚晓魁的文章 - 知乎
https://zhuanlan.zhihu.com/p/30516267