当前位置:网站首页>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
边栏推荐
- 小鸟逃票登机,如何反思,应如何解决,飞机为何怕小鸟?
- 300 linear algebra Lecture 4 linear equations
- Review notes of Zhang Haifan in introduction to software engineering (Sixth Edition)
- Richview RichEdit srichviewedit PageSize page setup and synchronization
- leetcode刷题:栈与队列02(用队列实现栈)
- leetcode刷题:二叉树03(二叉树的后序遍历)
- 关于new Set( )还有哪些是你不知道的
- Is it safe to open an account online? Can a novice open a stock trading account.
- 人脸识别系统 —— OpenCV人脸检测
- 开环和闭环是什么意思?
猜你喜欢

Big factories are wolves, small factories are dogs?

Penetration tools - trustedsec's penetration testing framework (PTF)

Exclusive news: Alibaba cloud quietly launched RPA cloud computer and has opened cooperation with many RPA manufacturers

EDA工具对芯片产业的重要性知识科普

《軟件工程導論(第六版)》 張海藩 複習筆記
![[multithreading] realize the singleton mode (hungry and lazy) realize the thread safe singleton mode (double validation lock)](/img/bf/524e78473625a31c024783ccec8d46.png)
[multithreading] realize the singleton mode (hungry and lazy) realize the thread safe singleton mode (double validation lock)

宅男壁纸大全微信小程序源码-带动态壁纸支持多种流量主

leetcode刷题:栈与队列07(滑动窗口最大值)

Win11 how to hide the taskbar? Win11 method to hide the taskbar

Kuberntes云原生实战一 高可用部署架构
随机推荐
新版Free手机、PC、平板、笔记本四端网站缩略展示图在线一键生成网站源码
On the next generation entrance of the metauniverse -- the implementation of brain computer interface
Customize the insertion of page labels and realize the initial search of similar address books
EURA eurui E1000 series inverter uses PID to realize the relevant parameter setting and wiring of constant pressure water supply function
tensorflow 张量做卷积,输入量与卷积核维度的理解
关于new Set( )还有哪些是你不知道的
Practical project notes (I) -- creation of virtual machine
运动捕捉系统原理
ORA-01950
Face recognition system opencv face detection
Gaussdb (for MySQL):partial result cache, which accelerates the operator by caching intermediate results
8K HDR!|为 Chromium 实现 HEVC 硬解 - 原理/实测指南
STC 32-bit 8051 single chip microcomputer development example tutorial three program compilation setting and download
Detailed explanation and code example of affinity propagation clustering calculation formula based on graph
Develop those things: easycvr platform adds playback address authentication function
PHP获取微信小程序和小程序商店外链地址
考虑关系的图卷积神经网络R-GCN的一些理解以及DGL官方代码的一些讲解
Richview trvdocparameters page parameter settings
Importance of EDA tools to chip industry knowledge popularization
UVM教程
