目录
一、gcc编译器是什么
1.官方定义:GCC(GNU Compiler Collection,GNU编译器套件)是由GNU开发的编程语言编译器。GNU编译器套件包括C、C++、 Objective-C、 Fortran、Java、Ada和Go语言前端,也包括了这些语言的库(如libstdc++,libgcj等。)GCC的初衷是为GNU操作系统专门编写的一款编译器。GNU系统是彻底的自由软件。此处,“自由”的含义是它尊重用户的自由.
二、gcc有什么用
GCC是编译工具(编辑器),能将C语言编写的程序转换为处理器能处理的二进制代码。Binutils:二进制程序处理工具,包括:ar、as、size、ldd等。
(1)as:主用于汇编。
(2)ld:主用于链接。
(3)ar:主用于创建静态库:
若将多个.o目标文件生成一个库文件,则需要静态库和动态库(共享库)。
windows系统下:静态库是.lib为后缀的文件,动态库是.dll为后缀的文件; linux系统下:静态库是.a为后缀的文件,动态库是.so为后缀的文件。
静态库和动态库区别在于代码被载入的时间不同:静态库的代码在编译过程中已被载入可执行程序,所以体积较大。动态库的代码在可执行程序运行时被载入内存,简单引用,体积较小。
linux系统下,可用ldd命令查看可执行程序的共享库。
多个程序同时运行时 ,且包含动态库,则动态库更节省内存。
(4)ldd:可查看可执行程序的动态库。
(5)size:列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段和总大小等。
(6)objdump:反汇编。
(7)readelf:显示有关ELF文件的信息。
三、实际操作
1.编写hello world代码
#include<stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
2.编程过程
(1)预处理
使用gcc进行预处理
gcc -E hello.c -o hello.i
//将源文件hello.c文件预处理生成hello.i文件
//gcc 的选项-E使gcc在进行完预处理后即停止
(2)编译
使用gcc编译命令如下:
gcc -S hello.i -o hello.s
//将预处理生成的hello.i文件编译生成hello.s文件
//gcc的选项-s使gcc在执行完编译后停止,生成汇编程序
(3)汇编
使用gcc汇编命令如下:
gcc -c hello.s -o hello.o
//将编译生成的hello.s文件汇编生成目标文件hello.o
//gcc的选项-c使gcc在执行完汇编后停止,生成目标文件
//或直接调用as进行汇编
as -c hello.s -o hello.o
//使用as将hello.s文件汇编生成目标文件
(4)链接
1、链接也分为动态链接和静态链接:
(1)静态链接:程序在编译阶段直接把静态库加入到可执行文件中去,这样的可执行文件会比较大。
(2)动态链接:程序执行时再从系统中将相应的动态库加入到内存中去。Linux系统中,gcc编译链接时动态库搜索路径的顺序通常为:
1从gcc命令参数-L指定路径寻找;
2再从环境变量LIBRARY_PATH指定的路径寻址;
3再从默认路径/lib、/usr/lib、/usr/local/lib寻找。
Linux系统中,执行二进制文件时的动态库搜索路径的顺序通常为:
1先搜索编译目标代码时指定的动态库搜索路径;
2再从环境变量LD_LIBRARY_PATH指定的路径寻址;
3再从配置文件/etc/ld.so,sonf中指定的动态库搜索路径;
4再从默认路径/lib、/usr/lib寻找。
在Linux系统下,可用ldd命令查看一个可执行程序依赖的动态库。
2、若命令“gcc hello.c -o hello动态库进行链接,生成ELF可执行文件的大小(用size命令查看)和链接的动态库(用ldd命令查看),示例如下:
gcc hello.c -o hello
size hello
ldd hello
3、若使用命令“gcc -static hello.c -o hello”则会使用静态库进行链接,生成ELF可执行文件的大小(用size命令查看)和链接的动态库(用ldd命令查看),示例如下:
gcc -static hello.c -o hello
size hello//可见text的代码尺寸极大
ldd hello//说明没有动态链接库
3.分析ELF文件
(1)ELF文件的组成:
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。
一个典型的ELF文件包含下面几个段:
.text:已编译程序的指令代码段。
.rodata:ro表示read only,即只读数据。
.data:已初始化的C程序全局变量和静态局部变量。
.bss:未初始化的C程序全局变量和静态局部变量。
.debug:调试符号表,调试器用此段的信息帮助调试。
可以使用readelf -S查看其各个section的信息如下:
readelf -S hello
(2)反汇编ELF
因为ELF无法当作普通文件打开,若希望直接查看一个ELF文件包含的指令和数据,则需要用反汇编方法。
使用objdump -D对其进行反汇编,如下所示:
objdump -D hello
部分代码如下:
使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:
gcc -o hello -g hello.c
//要加上-g选项 objdump -S hello
四 、结论
GNUC编译器 即gcc是一个功能强大的ANSI C兼容编译器,会操作其他操作系统下的一种C编译器,就能很快掌握GCC.
五、参考文献
gcc编译器背后的故事