深入了解GCC编译过程

本文围绕Linux下C语言编译过程展开,介绍了gcc驱动程序及编译的四个阶段:预编译、编译、汇编、链接。详细阐述了各阶段操作,如预编译处理指令、编译生成汇编代码、汇编生成机器指令与辅助信息、链接合并文件与符号重定位,还提及静态库和动态库链接。

关于Linux的编译过程,其实只需要使用gcc这个功能,gcc并非一个编译器,是一个驱动程序。其编译过程也很熟悉:预处理–编译–汇编–链接。在接触底层开发甚至操作系统开发时,我们都需要了解这么一个知识点,如何从我们的代码到机器码。这段过程经历了什么,我们的函数变量又是在哪里?一个个好奇心驱使着我写下这篇文章。于博客中有提及Linux的安装以及gcc基本环境搭建、gcc编译流程、常用gcc指令集:https://blog.youkuaiyun.com/Alkaid2000/article/details/128036290?spm=1001.2014.3001.5501

0x01 编译过程

可以使用这么一句指令来观察一个.c文件所需要经历的编译过程:gcc -v main.c

根据gcc的输出可见,对于一个C程序来说,从源代码构建出可执行文件经历了三个阶段:

  • 编译

在这里插入图片描述

gcc使用编译器ccl.exe进行编译,产生的编译代码保存在目录/temp下的文件ccelFAGc.s中。

  • 汇编

在这里插入图片描述

gcc使用汇编器as.exe进行汇编,汇编过程产生汇编文件ccZfpupi.o,将上面生成的ccelFAGc.s进行汇编。

  • 链接

在这里插入图片描述

调用collect2.exe进行链接。实际上这个collect2只是一个辅助程序,最终他将调用链接器ld来完成真正的链接过程。包括框出来的crtend.o、以及启动文件等等,本质上都是ld在进行链接。

事实上,从gcc看到只有这三个过程,但是对于C程序来说,编译过程也分为两个阶段:预编译和编译。所以软件构建过程通常分为四个阶段:预编译、编译、汇编、链接

在这里插入图片描述

可以通过gcc手动控制以上的编译流程,从而留下中间文件以方便研究:

  • gcc HelloWorld.c -E -o HelloWorld.i 预处理:加入头文件,替换宏。
  • gcc HelloWorld.c -S -c -o HelloWorld.s 编译:包含预处理,将 C 程序转换成汇编程序。
  • gcc HelloWorld.c -c -o HelloWorld.o 汇编:包含预处理和编译,将汇编程序转换成可链接的二进制程序。
  • gcc HelloWorld.c -o HelloWorld 链接:包含以上所有操作,将可链接的二进制程序和其它别的库链接在一起,形成可执行的程序文件。

那么接下来使用下面这段程序对于编译过程来做个总结:

hello.c:

#include <stdio.h>
#include "foo.h"

extern int foo2;

int main(int argc,char *argv[])
{
   
   
	int result;
	int r = 5;
#ifdef AREA
	result = PI*r*r;
#else
	result = PI*r*2;
#endif
	return 0;
}

foo.h

#ifndef _FOO_H
#define _FOO_H

#define PI 3.1415926
#define AREA

struct foo_struct{
   
   
	int a;
};

#endif

fool2.c

int foo2 = 20;

void foo2_func(int x)
{
   
   
	int ret = foo2;
}

fool1.c

int fool = 10;

void fool_func()
{
   
   
	int ret = fool;
}

0x02 预编译

C语言中的预编译是以#开头,常用的预编译指令包括#include#define#if等等。在工具链中,一般都提供单独的编译器,比如GCC中提供的编译器为cpp。但是预编译也可以看作编译过程的第一遍,是为编译做的一些工作,所以通常编译器中也包含了预编译的功能。比如前面的gcc并没有单独调用cpp,而是直接调用ccl进行编译,原因就是如上。

gcc -E hello.c -o hello.i

编译之后可以查看文件hello.i

# 7 "foo.h"
struct foo_struct
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑烯烃快去学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值