Gcc编译之链接之前的故事


前言

平时写程序,写完之后就是直接点一下编译再运行,就没我们什么事了;但是我们在点编译的时候,大多数软件是在默默调用GCC,那么这背后到底做了什么呢?


一、GCC编译

在linux下使用gcc–help查看帮助

在这里插入图片描述

参数对应操作
-E仅预处理,不编译、汇编和连接
-S预处理和编译,不汇编、链接
-c预处理、编译和汇编,不链接
-o指定输出文件名

图片来源:https://www.cnblogs.com/yanFlyBlog/articles/14988043.html

总结:在编译过程中,使用"-c",“-S”,或"-E"选项可使gcc编译停止在相应阶段,否则编译一步到位生成可执行文件。

二、编译一个小程序

  • 代码如下
#include <stdio.h>
int main()
{
        printf("hello,world");
        return 0;
}

1.预处理

处理以开头的预处理指令,如宏定义和所包含头文件,将被包含的文件插入到对应预处理指令的位置去(此阶段不检查语法)。

  • 在命令行中输入
gcc -E hello.c -o hello.i

预处理之后,将<stdio.h>中所包含文件展开,可使用普通文本文件打开

在这里插入图片描述

2.编译

编 译 过 程 就 是 对 预 处 理 完 的 文 件 进 行 一 系 列 的 词 法 分 析 , 语 法 分 析 , 语 义 分 析 及 优 化 后 生 成 相 应 的 汇 编 代 码。

编译就是把C/C++代码(比如上面的".i"文件)“翻译”成汇编代码

  • 命令行中输入
 gcc -S hello.i -o hello.s

请添加图片描述

注意:在生成汇编文件时,要注意命令行参数-S为大写,而如果输入为小写的话,用文本编辑器打开为乱码;并且在后面生成.o文件时会出错。
其实是因为输入参数区别大小写,当输入为小写时,gcc编译过程没有被截断,直接生成了可执行文件,可直接运行,所以在输入过程中要注意。

3.汇编

  • 生成可重定位文件 hello.o
 gcc -c hello.s -o  hello.o

汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码,生成可重定位文件(一个不带地址信息,ELF格式的二进制文件),包含多个section部分。

  • 可使用Linux 命令readelf查看节区信息
readelf -S hello.o

在这里插入图片描述

  • 关于ELF格式文件详情可参考

ELF文件详解—初步认识

简单了解可重定位目标文件

  • 查看生成的hello.o
 hexdump -C hello.o

在这里插入图片描述

对于可重定位文件,它里面的代码与数据,都是各个文件独立的代码与数据,在一个工程中,可能会存在多个C文件,每个C文件都会被首先编译生成一个可重定位文件,然后经过链接器将这些可重定位文件进行链接,从而生成最终的可执行文件。

4.生成可执行文件

  • 执行命令,生成可执行文件
gcc hello.c -o hello

gcc hello.o -o hello

默认使用动态库链接

  • 可使用命令查看文件所依赖的动态库

在这里插入图片描述
使用命令利用静态库生成可执行文件

gcc -static hello.c -o hello1
  • 查看两者大小

在这里插入图片描述

有关静态库和动态库的生成与使用,可参考我的另一篇博客

GCC的静态库、动态库的生成与使用

三、对比分析

对于可重定位文件(没有地址信息)

  • 各个段没有具体的起始地址,只要段大小信息
  • 各个标识符没有实际地址,只有在段中的偏移地址(相对地址)
  • 段和标识符的实际地址都需要链接器具体制定,这也是链接器的主要作用

对于可执行文件

  • 各个段有自己的起始地址,这些地址就是将来要被加载到内存中的地址(虚拟内存),有了起始地址,才能加载到内存,这是可执行文件与可重定位文件一个区别
  • 可执行文件中的各个符号,都有了正确的地址,以及符号被引用的地方也正确填上了符号的地址

内容来源

软件开发底层知识修炼 九 链接器-可重定位文件与可执行文件


总结

以上是我的一点学习体会,有很多不足之处,关于gcc 的编译过程还有许多地方需要学习,后期在不断学习过程中会不断改进,若有问题欢迎大家留言,一起学习进步,不胜感激!!!

可参考书籍:
嵌入式C语言自我修养:从芯片、编译器到操作系统/王利涛编著 电子出版社
深入理解计算机系统深入理解计算机系统(原书第3版) 机械工业出版社

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值