Linux系统中c语言源程序的编译过程主要分为四个步骤:预处理、编译、汇编、链接。
预处理阶段的工作内容如下:
gcc -E hello.c -o hello.i
编译阶段的主要功能是将预处理后的高级语言代码编译成汇编语言。
其在shell中的执行命令为gcc -S hello.c -o hello.s -m32
汇编阶段的主要功能是将汇编语言代码汇编成二进制机器码。
其在shell中的执行命令为gcc -c hello.c -o hello.o -m32
链接阶段的主要功能是将各种代码和数据部分收集起来并组合成一个单一文件,这个文件可以被加载到内存中执行。
其在shell中的执行命令为gcc hello.o -o hello -m32 -static
在学习本章内容前,我一直很好奇Linux系统中使用gcc编译成.o格式的二进制文件后为什么无法直接运行,而是还需要进一步执行链接过程,在本章学习了ELF可执行文件后得到了答案。
ELF(Executable and Linking Format)是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东西、以及都以什么样的格式去放这些东西。
ELF文件可分为三类:
ELF文件的主体结构如下图所示:
ELF Header
ELF Header部分长64字节,包括了可执行文件类型(32位/64位),程序入口地址,其他结构部分起始地址、大小、数目等ELF文件的基本数据。
在shell中通过readelf -h hello
命令,查看hello可执行ELF文件的ELF Header部分内容:
Section Header Table
Sections是在ELF文件中,用以装载内容数据的最小容器。在ELF文件里,每一个 sections内都装载了性质属性都一样的内容,如:
1) .text section 里装载了可执行代码;
2) .data section 里面装载了被初始化的数据;
3) .bss section 里面装载了未被初始化的数据;
4) 以 .rec 打头的 sections 里面装载了重定位条目;
5) .symtab 或者 .dynsym section 里面装载了符号信息;
6) .strtab 或者 .dynstr section 里面装载了字符串信息;
7) 其他还有为满足不同目的所设置的section,比方满足调试的目的、满足动态链接与加载的目的等等。
一个ELF文件中到底有哪些具体的 sections,由包含在这个ELF文件中的Section Head Table(SHT)决定。在SHT中,针对每一个section,都设置有一个条目,用以描述对应的这个section,其内容主要包括该section的名称、类型、大小以及在整个ELF文件中的字节偏移位置等等。
在shell中通过readelf -S hello
命令,查看hello可执行ELF文件的Section Head Table部分内容:
可以看到,正如Header中说明的,Section Head Table共有31个Section项。
其中,.symtab
section项存储了程序的字符串表,用readelf -S hello
查看:
Type 列表示符号的种类,Bind 列表示符号的绑定类型,两者共同构成了 st_info 字段。
Program Header Table
在编译器进行链接步骤时,可重定位对象文件中的sections是作为输入,给链接器那去做链接用的,所以这些 sections 也经常被称做输入 section。
而链接器在链接可执行文件或动态库的过程中,会把来自不同可重定位对象文件中的相同名称的 section 合并起来构成同名的section。接着,其又会把带有相同属性(比方都是只读并可加载的)的 section 都合并成所谓 segments(段)。segments 作为链接器的输出,常被称为输出section。
一个单独的 segment 通常会包含几个不同的 sections,比方一个可被加载的、只读的segment 通常就会包括可执行代码section .text、只读的数据section .rodata以及给动态链接器使用的符号section .dymsym等等。section 是被链接器使用的,但是 segments 是被加载器所使用的。加载器会将所需要的 segment 加载到内存空间中运行。和用 sections header table 来指定一个可重定位文件中到底有哪些 sections 一样。在一个可执行文件或者动态库中,也需要有一种信息结构来指出包含有哪些 segments。这种信息结构就是 Program Header Table。
在shell中通过readelf -l hello
命令,查看hello可执行ELF文件的Program Header Table部分内容:
2018-2019-1 20189205 《Linux内核原理与分析》第八周作业
原文:https://www.cnblogs.com/hzj20189205/p/10052010.html