【三、深入浅出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



相关文章
|
5月前
|
前端开发 C语言
gcc动态库升级
gcc动态库升级
|
3月前
|
编译器 Linux C语言
gcc的编译过程
GCC(GNU Compiler Collection)的编译过程主要包括四个阶段:预处理、编译、汇编和链接。预处理展开宏定义,编译将代码转换为汇编语言,汇编生成目标文件,链接将目标文件与库文件合并成可执行文件。
96 11
|
3月前
|
Unix 编译器 Linux
1.8.3 GNU编译器集合和LLVM项目
GNU项目自1987年起致力于开发自由UNIX软件,其成果之一GNU编译器集合(GCC)在指导委员会领导下持续演进,紧跟C语言标准。GCC适用于多种平台如UNIX、Linux和Windows,并常通过gcc或cc命令调用。另一方面,起源于2000年伊利诺伊大学研究项目的LLVM,提供了另一种开源编译器集合,其Clang编译器处理C代码,自2012年起成为FreeBSD默认C编译器,并良好支持最新C标准。
39 1
|
5月前
|
编译器 开发工具 C语言
Gcc 链接文件
Gcc 链接文件
44 4
|
5月前
|
编译器 C语言 C++
MinGW安装gcc
MinGW安装gcc
113 0
|
8月前
|
编译器 Linux 开发工具
|
8月前
|
NoSQL 编译器 开发工具
006.gcc编译器
gcc是什么?
92 0
006.gcc编译器
|
8月前
|
存储 NoSQL 算法
从一个crash问题展开,探索gcc编译优化细节
问题分析的过程也正是技术成长之路,本文以一个gcc编译优化引发的crash为切入点,逐步展开对编译器优化细节的探索之路,在分析过程中打开了新世界的大门……
|
7月前
|
自然语言处理 编译器 Go
GCC:GNU编译器
GCC:GNU编译器
100 0
|
7月前
|
Java 编译器 Linux
技术经验解读:【转载】详解GCC的下载和安装(源码安装)
技术经验解读:【转载】详解GCC的下载和安装(源码安装)
211 0