当前位置:网站首页>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
边栏推荐
- 写博客文档
- 8K HDR!|为 Chromium 实现 HEVC 硬解 - 原理/实测指南
- 极客DIY开源方案分享——数字幅频均衡功率放大器设计(实用的嵌入式电子设计作品软硬件综合实践)
- 网上开户是安全的吗?新手可以开炒股账户吗。
- 关联线探究,如何连接流程图的两个节点
- Internship: gradually moving towards project development
- Importance of EDA tools to chip industry knowledge popularization
- 渗透工具-TrustedSec 公司的渗透测试框架 (PTF)
- Swiftui 4 new features complete toggle and mixed toggle multiple binding components
- 联想电脑怎么连接蓝牙耳机?
猜你喜欢

深度学习 神经网络基础

小鸟逃票登机,如何反思,应如何解决,飞机为何怕小鸟?

RichView 文档中的 ITEM

数据分析师听起来很高大上?了解这几点你再决定是否转型

leetcode刷题:二叉树01(二叉树的前序遍历)

cocoaPods 添加成功后,导入不了头文件或者not found file 报错

After adding cocoapods successfully, the header file cannot be imported or an error is reported in not found file

2022安全员-A证考题及在线模拟考试

8K HDR!| Hevc hard solution for chromium - principle / Measurement Guide

薛定谔的日语学习小程序源码
随机推荐
EURA欧瑞E1000系列变频器使用PID实现恒压供水功能的相关参数设置及接线
Iframe 父子页面通信
How to turn off the boot auto start software in win11
PHP获取微信小程序和小程序商店外链地址
Summary of SQL aggregate query method for yyds dry goods inventory
Penetration tools - trustedsec's penetration testing framework (PTF)
Items in richview documents
Optimization of the problem that the request flow fails to terminate during page switching of easycvr cluster video Plaza
天气预报小程序源码 天气类微信小程序源码
C # joint Halcon application - Dahua camera acquisition class
牛客编程题--必刷101之字符串(高效刷题,举一反三)
三菱PLC FX3U脉冲轴点动功能块(MC_Jog)
Architect graduation summary
leetcode刷题:栈与队列05(逆波兰表达式求值)
Swiftui 4 new features complete toggle and mixed toggle multiple binding components
Using qeventloop to realize synchronous waiting for the return of slot function
联想电脑怎么连接蓝牙耳机?
Getting started with fastdfs
Vulnerability recurrence - Net ueeditor upload
