【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解(一)

简介: 【三、深入浅出GCC编译器】一个源文件到可执行文件是如何生成的:GCC编译工具链及编译参数详解

一、GCC交叉编译工具链

GCC编译工具链包含了GCC编译器在内的一整套工具,主要包含了GCC编译器、Binutils工具集、glibc标准函数库。一般情况下,我们说的GCC编译工具链就是指GCC编译器。

1. GCC编译器

GCC原名为GNU C语言编译器(GNU C Compiler),只能对C语言进行编译等处理。后来随着其功能的扩展,可以支持更多编程语言,如C++、Java、Fortran、Pascal、Objective -C、Ada、Go以及各类处理器架构上的汇编语言等。所以,现在我们所说的GCC是指GNU编译器套件(GNU Compiler Collection),并且现在的GCC还可以进行交叉编译(在一个平台下编译包含另一个平台的代码)。通过下面的命令可以查看GCC版本和GCC的安装路径。

gcc -v

which gcc

C语言编译器是gcc-core,C++语言编译器是gcc-c++。

2. Binutils工具集

(1)链接器与汇编器

binutils(bin utility,GUN二进制工具集),GNU binutils是一组二进制工具集。包括:addr2line ar gprof nm objcopy objdump ranlib size strings strip等。工具集默认在目录 /usr/bin 目录下,在这个工具集中我们必须要知道的工具有两个:ld 链接器和 as 汇编器。这两个工具和我们编译一个源文件息息相关。

as 汇编器用于把汇编文件(汇编语言)转换为目标问价(机器码),完成 .s.o 的工作;

ld 链接器用于把编译生成的多个目标文件链接组织为可执行文件;

这两个工具我们一般不会直接调用,它们大多是在GCC编译文件的时候由GCC编译器调用的。

(2)其它常用工具介绍及用法演示

首先我们准备几个文件,包括.s文件.o文件.c文件.i文和可执行文件,具体这些文件怎么生成,以及这些文件是什么含义在后面的章节有详细介绍(可以先看下一章再返回看本小节)。

① size: 列出文件每个部分的内存大小,如代码段、数据段、总大小等。

输入 size 文件名 就可以看到文件的内存占用情况

text是代码段,用于存放代码;data是用来放已初始化的数据;bss是用来放未初始化的数据。

② readelf: 显示有关ELF格式文件内容的信息。ELF格式是UNIX系统实验室作为应用程序二进制接口开发的。ELF格式是Unix/Linux平台上应用最广泛的二进制工业标准之一。

可以输入 readelf 查看说明及选项参数

readelf -h 显示可执行文件或目标文件的ELF Header的文件头信息(就是ELF文件开始的前52个字节)

③ nm: 查看目标文件中出现的符号(函数、全局变量等)。

上面可以看到,nm列出的信息总共有三列:第一列是指程序运行时的符号所对应的地址,对于函数来说表示的是函数的开始地址,对于变量则表示的是变量的存储地址;第二列是指相应符号是放在内存的哪一个段;第三列则是指符号的名称。这个命令通常会和 addr2line (后面会介绍)一块使用,因为nm列出了符号的地址,但是并没有行号和源文件名称,而 addr2line 可以根据符号地址给出行号和源文件目录及名称。更多信息可以查看man手册

nm只能用于目标文件和可执行文件,对普通文件无效

④ objcopy: 将目标文件的一部分或者全部内容拷贝到另外一个目标文件中,或者实现目标文件的格式转换。可用于目标文件格式转换,如.bin转换成.elf、.elf转换成.bin等。

比如,格式转换命令

objcopy -O binary  xx  xx.bin

⑤ objdump: 显示程序文件相关信息,最主要的作用是反汇编。这里介绍两个常用的选项参数:

可以通过 -d 选项来对可执行文件进行反汇编

也可以对目标文件反汇编

通过 -h 选项查看目标程序中的段信息和调试信息

⑥ addr2line: 将程序地址翻译成文件名和行号;给定地址和可执行文件名称,它使用其中的调试信息判断与此地址有关联的源文件和行号,通常搭配 nm 使用。

这个命令一般用于调试信息时快速定位错误位置。它的命令用法为addr2line 地址 -e 可执行文件名。为演示这个命令用法,首先创建一个文件,这个文件包含一个函数,函数功能为打印函数地址,代码如下

然后编译这个文件,编译时必须要加上 -g 包含调试信息,然后运行,得到打印出的地址

输入命令addr2line 地址 -e 可执行文件名 -f,可以看到文件位置,行号都打印出来了

我么可以确认一下是不是第11行,cat -n 显示行号

⑦ strings: 显示程序文件中的可显示字符串。

可以通过管道和grep过滤自己需要的信息

3. glibc库

glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc和libc都是Linux下的C函数库。libc是Linux下的ANSI C函数库,glibc是Linux下的GUN C函数库。

在CentOS操作系统下,查看glibc的版本

如果你是Ubuntu系统,可以用这个命令

/lib/x86_64-linux-gnu/libc.so.6



相关文章
|
9天前
|
C语言
转载 - gcc/ld 动态连接库和静态连接库使用方法
本文介绍了如何在GCC中实现部分程序静态链接、部分动态链接。使用`-Wl`标志传递链接器参数,`-Bstatic`强制链接静态库,`-Bdynamic`强制链接动态库。
16 0
|
1月前
|
编译器 C语言 C++
列举gcc 常见和有用的编译警告选项
列举gcc 常见和有用的编译警告选项
11 0
|
1月前
|
编译器 C语言
gcc编译警告:warning: suggest parentheses around assignment used as truth value
gcc编译警告:warning: suggest parentheses around assignment used as truth value
18 0
|
1月前
|
编译器 Linux C语言
gcc编译器的使用方法
gcc编译器的使用方法
21 1
|
3月前
|
NoSQL 编译器 开发工具
006.gcc编译器
gcc是什么?
44 0
006.gcc编译器
|
4月前
|
存储 NoSQL 算法
从一个crash问题展开,探索gcc编译优化细节
问题分析的过程也正是技术成长之路,本文以一个gcc编译优化引发的crash为切入点,逐步展开对编译器优化细节的探索之路,在分析过程中打开了新世界的大门……
414 1
|
2月前
|
编译器 C语言
gcc/g++语法
gcc/g++语法
|
4月前
|
C语言
gcc静态编译/usr/bin/ld: cannot find -lc
gcc静态编译/usr/bin/ld: cannot find -lc
|
5月前
|
编译器 程序员 C语言
gcc的编译过程和gcc与g++的区别
gcc的编译过程和gcc与g++的区别
53 0
|
6月前
|
C语言
编译安装gcc
编译安装gcc