本节书摘来自华章出版社《编译与反编译技术实战 》一书中的第1章,第1.4节,庞建民 主编 ,刘晓楠 陶红伟 岳 峰 戴超 编著,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
gcc(gnu compiler collection,gnu编译器套件)是由gnu开发的编程语言编译器。它是以gpl许可证发行的自由软件,也是 gnu计划的关键部分。gcc原本作为gnu操作系统的官方编译器,现已被大多数类unix操作系统(如linux、bsd、mac os x等)采纳为标准的编译器,gcc同样适用于微软的windows。
gcc 原名为 gnu c 语言编译器(gnu c compiler),因为它原本只能处理 c语言。随着gcc的快速扩展,其可支持c++,后来又能够支持更多编程语言,如fortran、pascal、objective-c、java、ada、go以及各类处理器架构上的汇编语言等,所以改名为gnu编译器套件。
(1)前端接口
前端将高级语言源码经过词法分析、语法分析生成与高级语言无关的低级中间层表示generic,然后经过单一化赋值转化为另一种中间表示层gimple,在中间层gimple组建控制流程图,并在gimple上进行一系列优化。然后将其转换为更加便于优化的rtl中间表示层。有了与前端无关的中间表示,gcc的前端将不同的高级编程语言转换成这种中间表示,这就是gcc处理器支持多种编程语言的根本原因。
(2)中间接口
中间接口主要在rtl中间表示上进行各种优化,gcc的优化技巧根据版本不同而有很大不同,但都包含了标准的优化算法,如循环优化、公共子表达式删除、指令重排序等。更多的优化方法也在不断地研究中。
(3)后端接口
gcc后端对每条rtl通过模板匹配的方法调用对应的汇编模板生成汇编代码。生成的代码因处理器和结构不同而不同,gcc后端为不同的平台提供了描述指令的汇编模板文件,这样就可以实现对不同平台的支持。这个阶段非常复杂,因为必须要考虑gcc可移植平台的处理器指令集的规格与技术细节,解决指令选择和寄存器分配等问题。
(4)gcc常用的参数
在使用gcc编译器的时候,必须给出一系列必要的调用参数和文件名称。gcc编译器的调用参数大约有100多个,这里只介绍其中最基本、最常用的参数。具体细节内容可参考gcc manual。
gcc最基本的用法是:
gcc [options] [filenames]
其中options就是编译器所需要的参数(也称为编译选项),filenames给出相关的文件名称。
-c:只编译,不链接成为可执行文件,编译器只是由输入的.c等源代码文件生成以.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename:确定输出文件的名称为output_filename,同时这个名称不能与源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g:产生符号调试工具(gnu的gdb)所必要的符号信息,要想对源代码进行调试,必须加入这个选项。
-o:对程序进行优化编译、链接。采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是编译、链接的速度相应地要慢一些。
-o2:比-o更好的优化编译、链接,当然整个编译、链接过程会更慢。
-v:gcc执行时执行的详细过程、gcc及其相关程序的版本号。编译程序时加上该选项可以看到gcc搜索头文件/库文件时使用的搜索路径。