GCC 一步到位

GCC 一步到位

GCC 简介

GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在。

Binutils 工具包

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

addr2line

来将程序地址转换成其所对应的程序源文件及所对应的代码行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对应的源代码位置

as

主要用于汇编

ld

主要用于连接

ar

主要用于创建静态库

静态库与动态库

将多个 .o 目标文件生成一个库文件,存在两种类型的库:静态库,动态库

Windows 中,静态库是后缀为 .lib 的文件,共享库是后缀为 .dll 的文件;在 Linux 系统中,静态库后缀为 .a ,动态库后缀为 .so

静态库与动态库对比

代码载入时刻不同

静态库:编译过程中已经被载入可执行程序,体积较大

动态库:可执行程序运行时载入内存,编译过程仅简单引用,代码体积较小

Linux 系统中可以使用 ldd 命令查看可执行程序依赖的共享库

多个程序需要共享库,采用动态库更节省内存

ldd

可以用于查看一个可执行程序的依赖的共享库

objcopy

将一种对象文件翻译成另一种格式,比如将 .bin 转换为 .elf 等

objdump

主要作用是反汇编

readelf

显示有关 ELF 文件的信息

size

列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小等

C 运行库

C 语言标准主要由两部分组成:一部分描述 C 的语法,另一部分描述 C 标准库。C 标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、型声明和宏定义,譬如常见的 printf 函数便是一个 C 标准库函数,其原型定义在 stdio 头文件中。

C 语言的标准仅仅定义了 C 标准库函数原型,并没有提供实现。因此,C 语言编译器通常需要一个 C 运行时库( C Run Time Libray , CRT )的支持。C 运行时库又常简称为 C 运行库。与 C 语言类似,c++ 也定义了自己的标准,同时提供相关支持库,成为 C++ 时运行库

GCC 编译过程

实际上,上述的编译步骤分为四个阶段:

1.预处理(也叫预编译,Preprocessing)

2.编译(Compilation)

3.汇编(Assenbly)

4.连接(Linking)

具体编译过程,查看我的另一篇博客:GCC 编译全过程

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

ELF 文件解析

ELF文件格式如图:

image

位于 ELF Header 和 Section Header Table 之间的都是段(Section)。一个典型的 ELF 文件包含下面几个段:

.text:以编译程序的指令代码段

.rodata:ro 代表 read only ,即只读数据(譬如常数 const 等)

.data:已初始化的 C 程序全局变量和静态局部变量

.bss:未初始化的 C 程序全局变量和静态局部变量

.debug:调试符号表,调试器用此段的信息帮助调试

可以使用以下命令查看各个 Section 的信息:

readelf -S hello

显示内容如下:

image

反汇编 ELF

由于 ELF 文件无法像普通文本一样打开,如果要直接查看一个 ELF 文件包含的指令和数据,需要进行反汇编

使用 objdump -D 反汇编,代码如下:

objdump -D main

显示内容如下:

image

或者使用 objdump -S 将其反汇编并将其 C 语言代码混合显示,代码如下:

gcc -o main -g main.c
objdump -S main

显示内容如下:

image

posted @ 2022-09-22 00:27  ppqppl  阅读(63)  评论(0编辑  收藏  举报