当前位置:网站首页>GCC编译
GCC编译
2022-07-01 19:31:00 【Day-3】
1 GCC编译过程
首先我们来看GCC的编译过程。hello.c文件内容如下。
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
gcc hello.c -o hello -save-temps --verbose
在编译的时候添加两个编译选项,第一个选项是将编译过程中的生成的中间文件保存下来,第二个用于查看GCC编译的详细工作流程。
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: …/src/configure -v --with-pkgversion=‘Ubuntu 9.3.0-10ubuntu2’ --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)
COLLECT_GCC_OPTIONS=‘-o’ ‘hello’ ‘-save-temps’ ‘-v’ ‘-mtune=generic’ ‘-march=x86-64’
/usr/lib/gcc/x86_64-linux-gnu/9/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu hello.c -mtune=generic -march=x86-64 -fpch-preprocess -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o hello.i
ignoring nonexistent directory “/usr/local/include/x86_64-linux-gnu”
ignoring nonexistent directory “/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed”
ignoring nonexistent directory “/usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/…/x86_64-linux-gnu/include”
#include “…” search starts here:
#include <…> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/9/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
COLLECT_GCC_OPTIONS=‘-o’ ‘hello’ ‘-save-temps’ ‘-v’ ‘-mtune=generic’ ‘-march=x86-64’
/usr/lib/gcc/x86_64-linux-gnu/9/cc1 -fpreprocessed hello.i -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o hello.s
GNU C17 (Ubuntu 9.3.0-10ubuntu2) version 9.3.0 (x86_64-linux-gnu)
compiled by GNU C version 9.3.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C17 (Ubuntu 9.3.0-10ubuntu2) version 9.3.0 (x86_64-linux-gnu)
compiled by GNU C version 9.3.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 18dc4c39b54390aa2b5013fb4339d43f
COLLECT_GCC_OPTIONS=‘-o’ ‘hello’ ‘-save-temps’ ‘-v’ ‘-mtune=generic’ ‘-march=x86-64’
as -v --64 -o hello.o hello.s
GNU汇编版本 2.34 (x86_64-linux-gnu) 使用BFD版本 (GNU Binutils for Ubuntu) 2.34
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/…/lib/:/lib/x86_64-linux-gnu/:/lib/…/lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/…/lib/:/usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS=‘-o’ ‘hello’ ‘-save-temps’ ‘-v’ ‘-mtune=generic’ ‘-march=x86-64’
/usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=hello.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o hello /usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/…/lib -L/lib/x86_64-linux-gnu -L/lib/…/lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/…/lib -L/usr/lib/gcc/x86_64-linux-gnu/9/…/…/… hello.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/…/…/…/x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS=‘-o’ ‘hello’ ‘-save-temps’ ‘-v’ ‘-mtune=generic’ ‘-march=x86-64’
在这段信息中,我们可以发现。GCC编译过程主要包括四个过程,即预处理阶段(Preprocess),编译阶段(Compile),汇编(Assemble)和链接(Link),分别使用了ccll,as和collect2。
其中,ccl是编译器,用于将源文件hello.c编译为hello.s;as是汇编器,将hello.s汇编为hello.o,链接器collect是对ld命令的封装,用于将C语言运行时库中的目标文件以及所需的动态链接库链接到可执行hello。
2 预处理阶段
主要处理源码中以#开头的预处理指令,将其转换后直接插入程序文本中,得到另外一个C程序,通常以i作为扩展名,在命令中添加编译选项e可以单独执行预处理。
gcc -E hello.c -o hello.i
一些处理规则:
- 递归处理“#include”预处理指令,将对应的文件内容复制到该指令的位置。
- 删除所有的“”define#指令,并在其被引用的位置递归的展开所有的宏定义
- 处理所有的条件预处理指令
- 删除所有注释
- 添加行号和文件名标识
3 编译阶段
单独执行指令
gcc -S hello.i -o -masm=intel -fno-asynchronous-unwind-tables
第一个编译选项是将文件指定为我们熟悉的intel,第二个编译选项则用于生成没有cfi宏的汇编指令,以提高可读性。
生成的hello.s文件中的内容:
.file "hello.c"
.text
.section .rodata
.LC0:
.string "Hello World!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rdi
movl $0, %eax
call [email protected]
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 9.3.0-10ubuntu2) 9.3.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
4 汇编阶段
gcc -c hello.c -o hello.o
gcc -c hello.s -o hello.o
这两条指令都是可以的。此时的目标文件hello.o是一个可重定位的文件,可以使用objdump命令来查看其内容。
Documents$ objdump -sd hello.o -M intel
hello.o: 文件格式 elf64-x86-64
Contents of section .text:
0000 f30f1efa 554889e5 488d3d00 000000b8 ....UH..H.=.....
0010 00000000 e8000000 00b80000 00005dc3 ..............].
Contents of section .rodata:
0000 48656c6c 6f20576f 726c6421 00 Hello World!.
Contents of section .comment:
0000 00474343 3a202855 62756e74 7520392e .GCC: (Ubuntu 9.
0010 332e302d 31307562 756e7475 32292039 3.0-10ubuntu2) 9
0020 2e332e30 00 .3.0.
Contents of section .note.gnu.property:
0000 04000000 10000000 05000000 474e5500 ............GNU.
0010 020000c0 04000000 03000000 00000000 ................
Contents of section .eh_frame:
0000 14000000 00000000 017a5200 01781001 .........zR..x..
0010 1b0c0708 90010000 1c000000 1c000000 ................
0020 00000000 20000000 00450e10 8602430d .... ....E....C.
0030 06570c07 08000000 .W......
Disassembly of section .text:
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push rbp
5: 48 89 e5 mov rbp,rsp
8: 48 8d 3d 00 00 00 00 lea rdi,[rip+0x0] # f <main+0xf>
f: b8 00 00 00 00 mov eax,0x0
14: e8 00 00 00 00 call 19 <main+0x19>
19: b8 00 00 00 00 mov eax,0x0
1e: 5d pop rbp
1f: c3 ret
此时由于还未进行链接,对象文件中符号的虚拟地址无法确定,于是我们看到字符串“hello World”的地址为0x0000,作为参数传递字符串地址的rdi寄存器被设置为0x0,而“call puts”指令中函数puts()的地址被设置为下一条指令的地址0xe。
5 链接阶段
GCC默认使用动态链接,添加编译选项“static”可指定为静态链接。
gcc hello.o -o hello -static
边栏推荐
- leetcode刷题:栈与队列03(有效的括号)
- 《軟件工程導論(第六版)》 張海藩 複習筆記
- 数据分析师听起来很高大上?了解这几点你再决定是否转型
- ORA-01950
- 强大的万年历微信小程序源码-支持多做流量主模式
- After adding cocoapods successfully, the header file cannot be imported or an error is reported in not found file
- 8K HDR!|为 Chromium 实现 HEVC 硬解 - 原理/实测指南
- Oracle 死锁测试
- 3D panoramic model display visualization technology demonstration
- Target detection - Yolo series
猜你喜欢
Use Zadig to build a continuous delivery platform from 0 to 1
Getting started with fastdfs
新牛牛盲盒微信小程序源码_支持流量变现,带完整素材图片
Importance of EDA tools to chip industry knowledge popularization
Learn white box test case design from simple to deep
Past and present life of product modular design
如何用OpenMesh创建一个四棱锥
收藏:存储知识全面总结
leetcode刷题:二叉树02(二叉树的中序遍历)
What if the win11 shortcut key switching input method doesn't respond? Shortcut key switching input method does not respond
随机推荐
多个张量与多个卷积核做卷积运算的输出结果
deb文件安装
运动捕捉系统原理
基于图的 Affinity Propagation 聚类计算公式详解和代码示例
2022安全员-A证考题及在线模拟考试
大厂做狼,小厂做狗?
MySQL数据库驱动(JDBC Driver)jar包下载
After adding cocoapods successfully, the header file cannot be imported or an error is reported in not found file
Learn white box test case design from simple to deep
Importance of EDA tools to chip industry knowledge popularization
2022年高处安装、维护、拆除考题模拟考试平台操作
PLC模拟量输入 模拟量转换FB S_ITR(三菱FX3U)
新牛牛盲盒微信小程序源码_支持流量变现,带完整素材图片
leetcode刷题:栈与队列01(用栈实现队列)
想请教一下,券商选哪个比较好尼?本人小白不懂,现在网上开户安全么?
《軟件工程導論(第六版)》 張海藩 複習筆記
ORA-01950
Getting started with fastdfs
STC 32-bit 8051 single chip microcomputer development example tutorial three program compilation setting and download
On the usage of a magic function