编译与链接原理及ELF格式

本文详细介绍了Linux下C程序从源代码到可执行文件的编译过程,包括预处理、编译、汇编和链接四个步骤。预处理处理头文件和宏定义,编译生成汇编代码,汇编器将汇编代码转换为机器指令,最后链接器合并.o文件并解决符号引用,生成可执行的a.out文件。理解这一过程有助于深入掌握程序构建原理。
摘要由CSDN通过智能技术生成

        在Linux下面我们写一个简单的程序,然后编译运行如下:gcc hello.c 然后生成a.out,通过./a.out执行。

#include <stdio.h>
int main()
{
    printf("hello world");
    return 0;
}

        事实上,上述过程可以分解为4个步骤,分别是预处理(Prepressing) 、编译(Compilation)、汇编(Assembly)和链接(Linking),如图所示。

  • 预编译:首先是源代码文件hello.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。对于C++程序来说,它的源代码文件的扩展名可能是.cpp或.cxx,头文件的扩展名可能是.hpp,而预编译后的文件扩展名是.ii。第一步预编译的过程相当于如下命令(-E表示只进行预编译)∶gcc -E hello.c -o hello.i

        预编译过程主要主要处理源代码文件中的以#开头的预编译指令,比如#include ,#define等,主要处理规则如下:将所有#define删除,并且展开所有宏定义;将#include包含的头文件插入进来,这个过程是递归的;删除所有注释;添加行号和文件名标识,以便于编译器在编译时产生调试用的行号和编译错误和警告显示;保留#pragma编译器指令,因为编译器必须要使用它。

  • 编译: 编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件,这个过程往往是我们所说的整个程序构建的核心部分,也是最复杂的部分之一。我们将在下一节简单介绍编译的具体几个步骤,这涉及编译原理等一些内容。上面的编译过程相当于如下命令:gcc -S hello.i -o hello.s
  • 汇编:汇编器是将汇编代码转变成机器指令,每一个汇编语句几乎都对应一条机器指令。所以汇编器的汇编过程相对于编译器来讲比较简单,它没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一─翻译就可以了,“汇编”这个名字也来源于此。上面的汇编过程我们可以调用汇编器as来完成: as hello.s -o hello.o
  • 链接:连接器将多个.o目标文件链接后生成可执行文件

总结一下,程序编译及链接到底发生了什么?

        编译过程:写好的代码经过 预编译(预处理),编译,汇编,变成二进制可重定位目标文件(win下是*.obj , Linux下是*.o) 。静态库文件(win下是*.lib,linux下是*.a);动态链接库是在运行时候加载的(win下是.DLL,Linux下是.so)

        链接过程: 1.所有.o文件段的合并;符号表的合并,进行符号解析

                           2.符号的重定位(重定向

                        然后输出可执行文件(linux下默认输出a.out,可以用-o 指定名字)

      链接过程会对多有.o的各个段进行合并,还会进行符号表的合并,符号表合并要进行符号解析,就是所有对符号的引用("UND")都要找到符号定义的地方(在代码段上的符号还是数据段上的符号)。符号解析完成后就会给所有符号分配虚拟地址(符号重定向)即符号解析完成后,就会给所有的符号分配虚拟地址,这样一来所有代码中所有使用符号的地方都填写成符号正确的地址了,这个叫做符号的重定向

        通过readelf  -h  mian.o就可以查看ELF头结构的信息。了解Linux下ELF文件结构信息,win下对应就是PE文件格式。

    所以*.o文件的格式组成是:ELF文件头,.text,.data,.bss,.symbal,section table等。符号表中先"UND"表示对符号的引用,而在编译过程中,符号是不分配虚拟地址的。

        ELF目标文件格式的最前部是ELF文件头(ELF Header),它包含了描述整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址等,紧接着是ELF文件各个段。其中ELF文件中与段有关的重要结构就是段表(Section Header Table),该表描述了ELF文件包含的所有段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值