C语言编译链接过程(袁春风版)

0x01 一个典型程序的编译、链接过程图示

在这里插入图片描述
hello.c源码

#include <stdio.h>
int main()
{
    printf("Hello World!");
}

gcc命令实际上是具体程序(如cpp、cc1、as等)的包装命令,用户通过gcc命令来使用具体的预处理程序cpp、编译程序cc1、汇编程序as等。

0x02 预处理cpp

1、处理源文件中以“#”开头的预编译指令,包括:

  • 删除“#define”并展开宏定义
  • 处理所有条件预编译指令,如“#if”、“#ifdef”、“#endif”等
  • 插入头文件到“#include”处,可以递归方式进行处理
  • 删除所有的注释,//和/* */
  • 添加行号和文件名标识,以便编译器产生调试用的行号信息
  • 保留所有的#pragma编译指令(编译器需要使用)

2、预处理命令

gcc -E hello.c -o hello.i
cpp hello.c > hello.i

3、查看生成的hello.i文件内容(不包含任何宏定义)

root@kali2020:~# cat hello.i
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
...
extern int __overflow (FILE *, int);
# 873 "/usr/include/stdio.h" 3 4

# 2 "hello.c" 2

# 2 "hello.c"
int main()
{
    printf("Hello World!");
}
0x03 编译cc1

1、编译过程就是将预处理后得到的预处理文件(如hello.i)进行词法分析、语法分析、语义分析并优化,生成汇编文件代码。
2、编译命令

gcc -S hello.i -o hello.s
gcc -S hello.c -o hello.s
/usr/lib/gcc/x86_64-linux-gnu/9/cc1 hello.c

3、查看hello.s,其实是文本文件,汇编语言源程序。

root@kali2020:~# cat hello.s
	.file	"hello.c"
	.text
	.section	.rodata
.LC0:
	.string	"Hello World!"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	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	printf@PLT
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Debian 9.2.1-22) 9.2.1 20200104"
	.section	.note.GNU-stack,"",@progbits
0x04 汇编

1、将汇编源程序转换程机器指令序列的过程。

gcc -c hello.s -o hello.o
gcc -c hello.c -o hello.o
as hello.c -o hello.o

2、查看可重定位的目标文件hello.o

root@kali2020:~# cat hello.o
ELF>�@@
WH��H�=���]�Hello World!GCC: (Debian 9.2.1-22) 9.2.1 20200104zR�A�C
��      $hello.cmain_GLOBAL_OFFSET_TABLE_printf��������
                                                       �������� .symtab.strtab.shstrtab.rela.text.data.bss.rodata.comment.note.GNU-stack.rela.eh_frame @@0
90i'B�W�R@H
�
0x05 链接ld

1、链接过程是将多个可重定位的目标文件合并生成可执行的目标文件。

gcc -static -o myproject main.o test.o
ld -static -o myproject main.o test.o

2、链接操作的步骤
在这里插入图片描述
3、使用链接的好处
在这里插入图片描述
4、链接过程的本质
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值