ELF格式文件由哪些段组成?

以下内容源于网络资源的学习与整理,如有侵权请告知删除。

参考内容

(1)ELF文件格式解析_elf文件解析_mergerly的博客-CSDN博客

(2)Linux C/C++目标文件、可执行文件分为几段? - 知乎(推荐其博客)

(3)程序的编译、装载与链接

一、ELF格式简介

Linux系统下,C/C++源码进行汇编之后生成的.o目标文件,或者链接之后生成的可执行程序文件,它们一般是ELF文件格式(Executable and Linking Format,可执行与可连接格式)。

Linux上的目标文件(Relocatable File)、可执行文件(Executable File)、动态链接库文件(Shared Object File)、coredump文件(Core Dump File)都是ELF格式。

这类文件是分段进行组织的,段的个数可通过代码控制,但通常一个程序文件中至少包含以下段:

  • text段:代码段,存储编译后的二进制机器码。注意(非静态的)局部变量也放在这个段。
  • data段:数据段,存放初始化后的全局变量、初始化后的局部静态变量。
  • bss段:存储未初始化的全剧变量和局部静态变量(默认值为0)。

本文介绍的是ELF文件的格式,不是介绍程序进程的地址空间分布。不过两者有一定的关系,将来ELF文件被执行时,它所对应的进程地址空间分布中每个区域的内容,就对应着该文件的段内容?

二、举例说明

本文以一个简单的C程序为例,说明C/C++代码跟ELF文件中的段是如何对应的。

//main.c
#include <stdio.h>

long global_n1; // 全局变量默认初始化为0,指针的话就是null
long global_n2 = 10; 

long sum_func(long a, long b)  
{
  static long local_static_n1; // 局部静态变量默认初始化为0
  static long local_static_n2 = 123;
  static long local_static_n3 = 456;
  return a + b;
}

int main(void)
{
  long sum = sum_func(global_n1, global_n2);
  printf("sum=%ld\n", sum);
  return 0;
}

为了简化分析,我们将上述代码编译为目标文件而不是可执行文件,因为编译为可执行文件时,会引入很多另外的符号和段。 

gcc -c -o main.o main.c

然后使用objdump工具查看main.o这个目标文件的反汇编代码,-t选项表示显示符号列表。

xjh@ubuntu:~/iot/tmp$ objdump -t main.o

main.o:     文件格式 elf32-i386

SYMBOL TABLE:
00000000 l    df *ABS*	00000000 main.c
00000000 l    d  .text	00000000 .text
00000000 l    d  .data	00000000 .data
00000000 l    d  .bss	00000000 .bss
00000000 l    d  .rodata	00000000 .rodata
00000004 l     O .data	00000004 local_static_n3.1831
00000008 l     O .data	00000004 local_static_n2.1830
00000000 l     O .bss	00000004 local_static_n1.1829
00000000 l    d  .note.GNU-stack	00000000 .note.GNU-stack
00000000 l    d  .eh_frame	00000000 .eh_frame
00000000 l    d  .comment	00000000 .comment
00000004       O *COM*	00000004 global_n1
00000000 g     O .data	00000004 global_n2
00000000 g     F .text	0000000d sum_func
0000000d g     F .text	0000003f main
00000000         *UND*	00000000 printf


xjh@ubuntu:~/iot/tmp$ 

从中可以知道每个符号(函数名、变量名)位于哪个段:

符号 备注
.data local_static_n3
local_static_n2
global_n2

存放初始化的全局变量、初始化的局部静态变量。

.bss local_static_n1
global_n1
存放未初始化的全局变量、未初始化的局部静态变量。
.text sum_func
main
存放代码

通过size命令可以查看每个段的大小。如下所示,text段的大小173字节(main函数和sum_func函数的二进制代码长度),data段的大小是12字节(上表中的.data段的3个变量的大小),bss段的大小是4字节(上表中.bss段的两个变量的大小)。

xjh@ubuntu:~/iot/tmp$ size main.o
   text	   data	    bss	    dec	    hex	filename
    173	     12	      4	    189	     bd	main.o
xjh@ubuntu:~/iot/tmp$

上面说到将程序编译为可执行文件时,会引入很多另外的符号和段。 现在我们来验证一下。

xjh@ubuntu:~/iot/tmp$ gcc main.o -o main.elf
xjh@ubuntu:~/iot/tmp$ objdump -t main.elf 

main.elf:     文件格式 elf32-i386

SYMBOL TABLE:
08048154 l    d  .interp	00000000              .interp
08048168 l    d  .note.ABI-tag	00000000              .note.ABI-tag
08048188 l    d  .note.gnu.build-id	00000000              .note.gnu.build-id
080481ac l    d  .gnu.hash	00000000              .gnu.hash
080481cc l    d  .dynsym	00000000              .dynsym
0804821c l    d  .dynstr	00000000              .dynstr
08048268 l    d  .gnu.version	00000000              .gnu.version
08048274 l    d  .gnu.version_r	00000000              .gnu.version_r
08048294 l    d  .rel.dyn	00000000              .rel.dyn
0804829c l    d  .rel.plt	00000000              .rel.plt
080482b4 l    d  .init	00000000              .init
080482e0 l    d  .plt	00000000              .plt
08048320 l    d  .text	00000000              .text
080484e4 l    d  .fini	00000000              .fini
080484f8 l    d  .rodata	00000000              .rodata
0804850c l    d  .eh_frame_hdr	00000000              .eh_frame_hdr
08048540 l    d  .eh_frame	00000000              .eh_frame
08049f08 l    d  .init_array	00000000              .init_array
08049f0c l    d  .fini_array	00000000              .fini_array
08049f10 l    d  .jcr	00000000              .jcr
08049f14 l    d  .dynamic	00000000              .dynamic
08049ffc l    d  .got	00000000              .got
0804a000 l    d  .got.plt	00000000              .got.plt
0804a018 l    d  .data	00000000              .data
0804a02c l    d  .bss	00000000              .bss
00000000 l    d  .comment	00000000              .comment
00000000 l    df *ABS*	00000000              crtstuff.c
08049f10 l     O .jcr	00000000              __JCR_LIST__
08048360 l     F .text	00000000              deregister_tm_clones
08048390 l     F .text	00000000              register_tm_clones
080483d0 l     F .text	00000000              __do_global_dtors_aux
0804a02c l     O .bss	00000001              completed.6600
08049f0c l     O .fini_array	00000000              __do_global_dtors_aux_fini_array_entry
080483f0 l     F .text	00000000              frame_dummy
08049f08 l     O .init_array	00000000              __frame_dummy_init_array_entry
00000000 l    df *ABS*	00000000              main.c
0804a024 l     O .data	00000004              local_static_n3.1831
0804a028 l     O .data	00000004              local_static_n2.1830
0804a030 l     O .bss	00000004              local_static_n1.1829
00000000 l    df *ABS*	00000000              crtstuff.c
0804860c l     O .eh_frame	00000000              __FRAME_END__
08049f10 l     O .jcr	00000000              __JCR_END__
00000000 l    df *ABS*	00000000              
08049f0c l       .init_array	00000000              __init_array_end
08049f14 l     O .dynamic	00000000              _DYNAMIC
08049f08 l       .init_array	00000000              __init_array_start
0804a000 l     O .got.plt	00000000              _GLOBAL_OFFSET_TABLE_
080484e0 g     F .text	00000002              __libc_csu_fini
0804a020 g     O .data	00000004              global_n2
00000000  w      *UND*	00000000              _ITM_deregisterTMCloneTable
08048350 g     F .text	00000004              .hidden __x86.get_pc_thunk.bx
0804a018  w      .data	00000000              data_start
00000000       F *UND*	00000000              printf@@GLIBC_2.0
0804a02c g       .data	00000000              _edata
080484e4 g     F .fini	00000000              _fini
0804a018 g       .data	00000000              __data_start
00000000  w      *UND*	00000000              __gmon_start__
0804a01c g     O .data	00000000              .hidden __dso_handle
080484fc g     O .rodata	00000004              _IO_stdin_used
00000000       F *UND*	00000000              __libc_start_main@@GLIBC_2.0
0804a034 g     O .bss	00000004              global_n1
08048470 g     F .text	00000061              __libc_csu_init
0804a038 g       .bss	00000000              _end
08048320 g     F .text	00000000              _start
080484f8 g     O .rodata	00000004              _fp_hw
0804a02c g       .bss	00000000              __bss_start
0804842a g     F .text	0000003f              main
00000000  w      *UND*	00000000              _Jv_RegisterClasses
0804a02c g     O .data	00000000              .hidden __TMC_END__
00000000  w      *UND*	00000000              _ITM_registerTMCloneTable
0804841d g     F .text	0000000d              sum_func
080482b4 g     F .init	00000000              _init


xjh@ubuntu:~/iot/tmp$ 

猜你喜欢

转载自blog.csdn.net/oqqHuTu12345678/article/details/129486106
今日推荐