Linux GCC 编译过程分析及常用检错的编译选项

文章目录

  • 简介
  • 一、拆解编译过程
    • 1、准备源程序
    • 2、分析拆解过程
    • 3、 多个程序文件的编译
    • 4、检错的编译选项
      • 1、-pedantic 编译选项
      • 2、-Wall 编译选项
      • 3、-Werror 编译选项
  • 二、分析 ELF 文件
    • 1.ELF 文件格式
    • 2.查看ELF文件的段内容,或查看指令与数据
      • 1、查看ELF文件的段内容
      • 2、查看指令与数据
  • 总结


简介

GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语 言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另 一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在。


一、拆解编译过程

1、准备源程序

Linux GCC 编译过程分析及常用检错的编译选项_第1张图片

一般来说编译一步到位的指令为

gcc test.c -o test

2、分析拆解过程

我们可以拆解成:预处理、编译为汇编代码、汇编、连接等,一步步来编译源程序。

1、预处理命令为:

gcc -E test.c -o test.i 或 gcc -E test.c

命令含义:

将源文件 hello.c 文件预处理生成 hello.i
GCC 的选项-E 使 GCC 在进行完预处理后即停止

预处理过程:

(1)将所有的#define 删除,并且展开所有的宏定义,并且处理所有的条件预编 译指令,比如#if #ifdef #elif #else #endif 等。
(2) 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
(3) 删除所有注释“//”和“/* */”。
(4) 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
(5) 保留所有的#pragma 编译器指令,后续编译过程需要使用它们

查看一下.i文件
Linux GCC 编译过程分析及常用检错的编译选项_第2张图片
打开 test.i 文件一看,就明白了。后 面那条指令,是直接在命令行窗口中输出预处理后的代码.

2、编译为汇编代码

gcc -S test.i -o test.s

命令含义:

将预处理生成的 hello.i 文件编译生成汇编程序 hello.s
gcc 的-S 选项,表示在程序编译期间,在生成汇编代码后,停止,-o 输出汇编代码文件。

处理内容:

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

3、汇编

gcc -c test.s -o test.o

命令含义:

将编译生成的 hello.s 文件汇编生成目标文件 hello.o
GCC 的选项-c 使 GCC 在执行完汇编后停止,生成目标文件

处理内容:

汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o 的目标文件中。

需要注意的是目标文件已经是最终程序的某一部 分了,只是在链接之前还不能执行。
4、链接
链接又分为静态链接与动态链接:
详见:
https://blog.csdn.net/qq_52215423/article/details/127028762

gcc test.o -o test

生成可执行文件后,可以使用 Binutils 的 size 命令查看文件大小和使用 Binutils 的 ldd 命令查看链接的动态库。

size hello
ldd hello

3、 多个程序文件的编译

通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用 GCC 能够很好地管理 这些编译单元.

我们可以使用下面这行命令一步到位:

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

4、检错的编译选项

1、-pedantic 编译选项

示例:

gcc -pedantic illcode.c -o illcode

-pedantic 选项能够帮助程序员发现一些不符合 ANSI/ISO C 标准的代码,但不是全部,事实上只有 ANSI/ISO C 语言标准中要求进行编译器诊断的 那些情况,才有可能被 GCC 发现并提出警告。

2、-Wall 编译选项

示例:

gcc -Wall illcode.c -o illcode

使用它也能够使 GCC 产生尽可能多的警告信息

3、-Werror 编译选项

示例:

gcc -Werror test.c -o test

在编译程序时带上-Werror 选项,那 么 GCC 会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、分析 ELF 文件

1.ELF 文件格式

Linux GCC 编译过程分析及常用检错的编译选项_第3张图片
一个典型的ELF文件包含以下几个段:
说明:

.text:已编译程序的指令代码段。
.rodata:ro 代表 read only,即只读数据(譬如常数 const)。
.data:已初始化的 C 程序全局变量和静态局部变量。
.bss:未初始化的 C 程序全局变量和静态局部变量。
.debug:调试符号表,调试器用此段的信息帮助调试

2.查看ELF文件的段内容,或查看指令与数据

1、查看ELF文件的段内容

可以使用 readelf -S 查看其各个 section 的信息:

$ readelf -S 目标文件

2、查看指令与数据

由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。 使用 objdump -D 对其进行反汇编。

$ objdump -D 目标文件

总结

以上就是今天总结的内容,本文仅仅简单分析了GCC的编译与使用,还有一些检错选项来帮助我们查看警告,还介绍了ELF文件的格式等。

你可能感兴趣的:(Linux,linux,c++)