GCC常用命令以及它的合作伙伴们


一、GCC简介

GCC是以GPL许可证所发行的自由软件,也是GNU计划的关键部分。GCC的初衷是为GNU操作系统专门编写一款编译器,现已被大多数类Unix操作系统(如Linux、BSD、MacOS X等)采纳为标准的编译器,甚至在微软的
Windows上也可以使用GCC。GCC支持多种计算机体系结构芯片,如x86、ARM、MIPS等,并已被移植到其他多种硬件平台 。

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

二、GCC常用命令

1.简单编译

test.c 代码如下(示例):

#include <stdio>
void main()
{
	printf("Hello Gcc!!!");
}

进行一步到位的编译

gcc test.c -o test

test可执行文件生成成功
在这里插入图片描述

实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)。

1.1 预处理

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

test.i 文件中存放着 test.c 经预处理之后的代码,通过预编译生成 .i 文件,查看 .i 文件部分内容
在这里插入图片描述

1.2 编译为汇编代码

预处理之后,可直接对生成的 test.i 文件编译,生成汇编代码:

gcc -S test.i -o test.s

gcc 的-S 选项,表示在程序编译期间,在生成汇编代码后,停止,-o 输出汇编代码文件。

查看test.s内容
在这里插入图片描述

1.3 汇编

生成的汇编代码文件 test.s,gas 汇编器负责将其编译为目标文件

gcc -c test.s -o test.o

1.4 链接

将生成的 test.o,将其与C标准输入输出库进行连接,最终生成程序 test

gcc test.o -o test

生成的文件通过 ./test 就可以执行

2. 多个程序文件的编译

如果同时处理的文件不止一个,GCC 仍然会按照预处理、编译和链接的过程依次进行。如果深究起 来,上面这条命令大致相当于依次执行如下三条命令:

1.gcc 源文件1 源文件2 -o 生成的可执行文件

gcc test1.c test2.c -o test

2.同时处理的文件不止一个时,GCC 仍然会按照预处理、编译和链接的过程依次进行

gcc -c test1.c -o test1.o 
gcc -c test2.c -o test2.o 
gcc test1.o test2.o -o test

3.检错

gcc -pedantic illcode.c -o illcode

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

gcc -Wall illcode.c -o illcode

-Wall 能够使 GCC 产生尽可能多的警告信息

gcc -Werror test.c -o test

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

4.库文件连接

函数库实际上就是一些头文件(.h)和库文件(so、或 lib、dll)的集合,Linux 下的大多数函数都默认将头文件放到/usr/include/目录下,而库文 件则放到/usr/lib/目录下,当我们需要调用其它函数库时,GCC在编译时就需要使用自己方法进行查找

假设我们要调用目录 /usr/lib 下的库文件libtest.so

①编译成可执行文件
首先我们要进行编译 test.c 为目标文件

gcc -c -I /usr/lib test.c -o test.o

②链接

gcc -L /usr/lib -ltest test.o -o test

③强制链接时使用静态链接库
GCC 在链接时优先使用动态链接库,如果需要的话可以在编译时加上-static 选项,强制使用静态链接库

假设目录 /usr/lib 存在动态库文件libtest.so和静态库文件libtest.a,我们想要调用对应静态库文件,可以用:

gcc -L /usr/lib -static -ltest test.o -o test

静态库链接时搜索路径顺序:

  1. ld 会去找 GCC 命令中的参数-L
  2. 再找 gcc 的环境变量 LIBRARY_PATH
  3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初 compile gcc 时写在程序内的

动态链接时、执行时搜索路径顺序:

  1. 编译目标代码时指定的动态库搜索路径
  2. 环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径
  3. 配置文件/etc/ld.so.conf 中指定的动态库搜索路径
  4. 默认的动态库搜索路径/lib
  5. 默认的动态库搜索路径/usr/lib

三、合作伙伴

GCC不是单枪匹马在战斗,他还有其它合作伙伴。

Binutils:
一组二进制程序处理工具,包括:addr2line、ar、objcopy、objdump、as、ld、 ldd、readelf、 size 等,这 一组工具 是开发和 调试不可 缺少的工具。

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

分析 ELF 文件

链接器链接后生成的最终文件为 ELF 格式可执行文件,一个 ELF 可执行文件通常 被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss 等段。

1.ELF 文件的段

ELF 文件格式如下图所示,位于 ELF Header 和 Section Header Table 之间的都 是段(Section)
在这里插入图片描述

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

使用readelf工具查看各个selection的信息

readelf -S test

在这里插入图片描述

反汇编 ELF

我们如果需要去使用普通文档打开ELF文件,查看相关数据以及指令就需要使用反汇编进行处理

使用objdump工具将ELF文件进行反汇编:

objdump -D test

在这里插入图片描述
可以看到ELF已经被反汇编成功,可以查看相关指令信息了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值