目录
一、Gcc编译器
(一)、Gcc简介
(二)、Gcc编译语言:C 运行库
(三)、Gcc相关命令说明:Binutils
二、使用Gcc编译实例1
(一)、程序编写
(二)、使用Gcc编译
(三)、对ELF 文件进行分析
三、使用Gcc编译实例2
(一)、程序编写
(二)、程序编译
(三)、多个程序文件的编译
(四)、纠错
(五)、库文件链接
四、实验总结
五、参考文献
一、Gcc编译器
(一)、Gcc简介
GCC(GNU C Compiler)是编译工具。将 C/C++语言编写的程序 转换成为处理器能够执行的二进制代码的过程即由编译器完成。
GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语 言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在。
(二)、Gcc编译语言:C 运行库
C 语言标准主要由两部分组成:一部分描述 C 的语法,另一部分描述 C 标准库。 C 标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏定义,譬如常见的 printf 函数便是一个 C 标准库函数,其原型定义 在 stdio 头文件中。
C 语言标准仅仅定义了 C 标准库函数原型,并没有提供实现。因此,C 语言编译 器通常需要一个 C 运行时库(C Run Time Libray,CRT)的支持。C 运行时库又 常简称为 C 运行库。与 C 语言类似,C++也定义了自己的标准,同时提供相关支 持库,称为 C++运行时库。
(三)、Gcc相关命令说明:Binutils
1. addr2line:用 来将程序 地址转 换成其所 对应的程 序源文 件及所对 应的代 码 行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对 应的源代码位置。
2. as:主要用于汇编。
3. ld:主要用于链接。
4. ar:主要用于创建静态库。
5. ldd:可以用于查看一个可执行程序依赖的共享库。
6. objcopy:将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或 者将.elf 转换成.bin 等。
7. objdump:主要的作用是反汇编。
8. readelf:显示有关 ELF 文件的信息。
9. size:列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小 等。
关于ar 创建静态库的说明:
1. 如果要将多个 .o 目标文件生成一个库文件,则存在两 种类型的库,一种是静态库,另一种动态库。
2.在 windows中静态库是以 .lib 为后缀的文件,共享库是以.dll为后缀的文件。 在 linu中静态库是以.a为后缀的文 ,共享库是以.so为后缀的文件。
3.静态库和动态库的不同点在于代码载入的时刻不同。静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。共享库的代码在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。在Linux系统中,可以用ldd命令查看一个可执行程序依赖的共享库。
4.如果一个系统中存在多个需要同时运行的程序且这些程序之间存在共享库,那么采用动态库的形式将更节省内存。
二、使用Gcc编译实例1
(一)、程序编写
代码如下:
#include <stdio.h>
int main(void)
{
printf("Hello World! \n");
return 0;
}
(二)、使用Gcc编译
1.编译预处理
(1) 将所有的#define 删除,并且展开所有的宏定义,并且处理所有的条件预编 译指令,比如#if #ifdef #elif #else #endif 等。
(2) 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
(3) 删除所有注释“//”和“”。
(4) 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
将源文件 hello.c 文件预处理生成 hello.i ;GCC 的选项-E 使 GCC 在进行完预处理后即停止。
gcc -E hello.c -o hello.i

注:hello.i是一个可打开文件。可以打开分析其包含的具体内容
2.编译处理
编译过程就是对预处理完的文件进行一系列的词法分析,语法分析,语义分析及 优化后生成相应的汇编代码。
将预处理生成的 hello.i 文件编译生成汇编程序 hello.s ;GCC 的选项-S 使 GCC 在执行完编译后停止,生成汇编程序。
gcc -S hello.i -o hello.s
注:hello.s文件可打开,其中为hello.c对应的汇编语言。
3.汇编处理
汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o 的目标文件中。由于每一个汇编语句几乎都对应一条处理器指令,因此,汇编相 对于编译过程比较简单,通过调用 Binutils 中的汇编器 as 根据汇编指令和处理 器指令的对照表一一翻译即可。
当程序由多个源代码文件构成时,每个文件都要先完成汇编工作,生成.o 目标 文件后,才能进入下一步的链接工作。注意:目标文件已经是最终程序的某一部 分了,但是在链接之前还不能执行。
将编译生成的 hello.s 文件汇编生成目标文件 hello.o ;GCC 的选项-c 使 GCC 在执行完汇编后停止,生成目标文件
gcc -c hello.s -o hello.o
或者使用 Binutils 中的 as 将 hello.s 文件汇编生成目标文件
as -c hello.s -o hello.o
注意:hello.o 目标文件为 ELF(Executable and Linkable Format)格式的可 重定向文件。
4. 链接
链接的具体说明请参考资料“Linux GCC常用命令.pdf”和“GCC编译器背后的故事.pdf”
gcc hello.c -o hello
size hello
ldd hello
(三)、对ELF 文件进行分析
1.认识并理解ELF文件的段
一个典型的 ELF 文件包含下面几个段:
.text:已编译程序的指令代码段。
.rodata:ro 代表 read only,即只读数据(譬如常数 const)。
.data:已初始化的 C 程序全局变量和静态局部变量。
.bss:未初始化的 C 程序全局变量和静态局部变量。
.debug:调试符号表,调试器用此段的信息帮助调试。
可以采用下述代码具体查看段的信息
readelf -S hello
2.反汇编 ELF
由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。
使用下述代码进行反汇编
objdump -D hello
使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:
gcc -o hello -g hello.c
objdump -S hello
三、使用Gcc编译实例2
(一)、程序编写
HL.c
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
(二)、程序编译
与实例1的操作方法相同,分别为预处理、编译、汇编、链接四个步骤。相关代码如下
gcc -E HL.c -o HL.i 或 gcc -E HL.c
gcc -S HL.i -o HL.s
gcc -c HL.s -o HL.o
gcc HL.o -o HL
执行./HL结果为:
(三)、多个程序文件的编译
将HL.c和hello.c同时编译,并生成test可执行文件:
gcc HL.c hello.c -o test
(四)、纠错
gcc -pedantic illcode.c -o illcode
-pedantic 编译选项并不能保证被编译程序与 ANSI/ISO C 标准的完全兼容,它仅仅只能用来帮助 Linux 程序员离这个目标越来越近。或者换句话说,-pedantic 选项能够帮助程序员发现一些不符合 ANSI/ISO C 标准的代码,但不是全部,事实上只有 ANSI/ISO C 语言标准中要求进行编译器诊断的 那些情况,才有可能被 GCC 发现并提出警告。
gcc -Wall illcode.c -o illc
除了-pedantic 之外,GCC 还有一些其它编译选项也能够产生有用的警告信息。这些选项大多以-W 开头,其中最有价值的当数-Wall 了,使用它能够使 GCC 产生尽可能多的警告信息。
gcc -Werror test.c -o test
在编译程序时带上-Werror 选项,那 么 GCC 会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。
(五)、库文件链接
1.编译成可执行文件
gcc –c –I /usr/dev/mysql/include HL.c –o HL
2.把所有目标文件链接成可执行文件
gcc –L /usr/dev/mysql/lib –lmysqlclient HL.o –o HL
3.制链接时使用静态链接库
gcc –L /usr/dev/mysql/lib –static –lmysqlclient HL.o –o HL
四、实验总结
通过本次实验,加强了我在Linux系统上进行编程的能力,使我回顾并深入了Linux系统上gcc的编译命令及操作流程,同时使我了解并熟悉了对库的链接的使用,深层次的理解了程序编写到编译及最后执行的过程。
五、参考文献
浏览
https://mooc1.chaoxing.com/ueditorupload/read?objectId=b9616c5b28b9b0b12e4df8411148087e&fileOriName=GCC%E7%BC%96%E8%AF%91%E5%99%A8%E8%83%8C%E5%90%8E%E7%9A%84%E6%95%85%E4%BA%8B.pdf浏览
https://mooc1.chaoxing.com/ueditorupload/read?objectId=94fdef0ff9306a1d78c5d95704d1e248&fileOriName=Linux%20GCC%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4.pdf基于Ubuntu实操三:认识Gcc编译器的使用_Lc-Yusheng的博客-CSDN博客一、认识Gcc编译器1.GCC的定义及发展GCC(GNU C Compiler)是编译工具。本文所要介绍的将 C/C++语言编写的程序 转换成为处理器能够执行的二进制代码的过程即由编译器完成。GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而
https://blog.csdn.net/qq_47946816/article/details/120633692?spm=1001.2014.3001.5501gcc生成静态库.a和动态库.so_Harriet的博客-CSDN博客请说明可执行程序是如何被组装的?1)阅读、理解和学习材料“用gcc生成静态库和动态库.pdf”和“静态库.a与.so库文件的生成与使用.pdf”,请在Linux系统(Ubuntu)下如实仿做一遍。2)在第一次作业的程序代码基础进行改编,除了x2x函数之外,再扩展写一个x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 mai.
https://blog.csdn.net/qq_43279579/article/details/109026927