ELF文件格式与程序的编译链接

本文详细探讨了从源代码到可执行程序的编译链接过程,包括预处理、编译、汇编和链接四个阶段。文章重点分析了ELF文件格式,通过section header table和符号表揭示了程序的组织结构。讨论了全局符号、局部符号、COMMON类型的未初始化全局变量在不同编译器中的处理方式,以及链接过程中的空间分配、符号解析和重定位步骤。此外,还介绍了链接规则,特别是强符号和弱符号的选择策略。
摘要由CSDN通过智能技术生成

说明:本文的讨论基于一个运行linux的x86系统环境,使用标准ELF文件格式。讨论集中在32位代码,在x86-64系统上用gcc -m32产生32位代码。若编译时发生/usr/include/features.h:364:25: fatal error: sys/cdefs.h: 没有那个文件或目录,则使用命令sudo apt-get install libc6-dev-i386解决。 ELF文件格式与相关命令详见http://blog.csdn.net/li_xiang_li/article/details/50528307

一. 由源代码到可执行程序经历了什么

源代码:    

    //main.c
    int add(int a,int b);
    static int si;//.bss
    extern int buf[];
    int *copy = &buf[0];//.rel.data
    int main()
    {
        int a = 3;
        int b = 5;
        int c = add(a,b);//.rel.text
        char *s = "hello c";//.rodata
        static int si;//.bss
        return 0;
    }

    //add.c
    int buf[2];
    int add(int a,int b)
    {
        return (a+b);
    }

    //makefile(为了简化讨论,makefile文件中没有添加-g选项)
    all:main
    main:main.o add.o
        gcc -o main main.o add.o -m32
    main.o:main.c
        gcc -c main.c -m32
    add.o:add.c
        gcc -c add.c -m32
    clean:
        rm -rf *.o main
  • 从源代码到可执行程序所要经历的过程概述:

    这里写图片描述

    源代码(.c .cpp .h)经过c预处理器(cpp)后生成.i文件,编译器(cc1、cc1plus)编译.i文件后生成.s文件,汇编器(as)汇编.s文件后生成.o文件,链接器(ld)链接.o文件生成可执行文件。gcc是对cpp、cc1(cc1plus)、as、ld这些后台程序的包装,它会根据不同的参数要求去调用后台程序。以helloworld程序为例,使用gcc -o hello hello.c时加上-v选项可观察到详细的步骤。也可使用gcc分别进行以上四步骤,预编译gcc -E hello.c -o hello.i,编译gcc -S hello.i -o hello.s,汇编gcc -c hello.s -o hello.o,链接gcc -o hello hello.o

    有兴趣的话可以尝试验证以下预处理、编译、汇编、链接的详细过程及结果。使用cpp对c文件进行预处理用vim查看.i文件,使用cc1编译.i文件用vim查看.s文件,使用as汇编.s文件,最终使用ld手动链接相关文件生成可执行文件。(过程较为复杂,可参考-v选项后的结果)

    这里写图片描述

二、 由ELF文件看程序的编译链接
程序的编译涉及词法分析、语法分析、语义分析等过程,详情参见《编译原理》。

1.以下分析一下编译完成之后的ELF文件:

readelf -S add.o查看section header table

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值