Gcc不是一个人在战斗—GCC编译器背后的故事

一、GCC简介

(一)含义

GCC 原名为 GNU C 语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC 很快地扩展,变得可处理 C++。后来又扩展为能够支持更多编程语言,如Fortran、Pascal、Objective-C、Java、Ada、Go以及各类处理器架构上的汇编语言等,所以改名GNU编译器套件(GNU Compiler Collection)。

(二)常用命令

命令含义
-E仅作预处理,不进行编译、汇编和链接
-S仅编译到汇编语言,不进行汇编和链接
-c编译、汇编到目标代码(也就是计算机可识别的二进制)
-o执行命令后文件的命名
-g生成调试信息
-w不生成任何警告
-Wall生成所有的警告

(三)GCC编译工具

GCC编译工具链是GCC编译器的一整套工具,主要作用就是将源代码转化为可执行应用程序。

GCC编译工具链包括以下三部分:

  • Gcc-Core:GCC编译器,完成预处理和编译过程,将C代码转换为汇编
  • Binutils:包括了链接器ld,汇编器as,目标文件格式查看器readelf等一系列小工具
  • glibc:包含C语言标准库,C中常使用的printf、malloc等函数

1.Gcc-Core

Gcc-Core主要是完成预处理和编译过程,将C代码转化为汇编语言。

2.Binutils

Binutils(bin utility),是GNU二进制工具集,通常跟GCC编译器一起打包安装到系统。在程序开发的时候,可能不会直接调用这些工具,而是在使用Gcc编译指令的时候,由GCC编译器间接调用。
全部的工具,可以通过下面的命令来查看:ls /usr/bin | grep linux-gnu-

常用工具:

  • addr2line:用来将程序地址转换成其所对应的程序源件及所对应的代码行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对应的源代码位置。
  • as:主要用于汇编。
  • ld:主要用于链接。
  • ar:主要用于创建静态库。
  • ldd:可以用于查看一个可执行程序依赖的共享库。
  • objcopy:将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或者将.elf 转换成.bin等。
  • objdump:主要的作用是反汇编。
  • readelf:显示有关 ELF 文件的信息。
  • size:列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小等。

3.glibc库

编写C语言时,所使用的read、write、open、printf等函数,都是基于该库的。在Ubuntu系统中,libc.so.6就是glibc的库文件,我们可以直接执行,查看版本信息。

二、GCC编译过程

(一)简单示例

test.c:

#include <stdio.h>
int main(void)
{
    printf("Hello World!\n");
    return 0;
}

以上程序,一步到位的编译指令是:gcc test.c -o test
实质上,上述编译过程是分为四个阶段进行的:预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)、连接(Linking)。

1.预处理

gcc -E test.c -o test.igcc -E test.c
可以输出test.i文件中存放着test.c经预处理之后的代码。打开test.i文件,看一看,就明白了。后面那条指令,是直接在命令行窗口中输出预处理后的代码。
-E命令,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将stdio.h文件中的内容插入到test.c中。

2.编译

gcc -S test.i -o test.s
预处理后,可直接对生成的test.i文件编译,生成汇编代码。
-S命令,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。

3.汇编

gcc -c test.s -o test.o
对于上一步骤生成的汇编代码文件test.sgas汇编器负责将其编译为目标。

4.链接

gcc test.o -o test
gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
对于上一步骤生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test。最后在命令行窗口中,执行./test,即可得到结果。

(二)多个程序文件编译

通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。
假设有一个由test1.ctest2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序test,一步到位编译命令:gcc test1.c test2.c -o test
如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:
gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o -o test

三、ELF文件

在计算机科学中,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。
是UNIX系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,ABI)而开发和发布的,也是Linux的主要可执行文件格式。

ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。实际上,一个文件中不一定包含全部内容,而且它们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。


参考文献
https://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值