Linux--编译链接

gcc完成编译链接的大概过程:预编译,编译,汇编,链接

gcc如何完成:

预编译:gcc -E main.c -o main.i
1.#include展开
2.宏替换
3.删除注释
4.处理预编译指令

编译:gcc -S main.i —> main.s
1.进行词法语法的解析
2.代码优化
3.汇总符号 数据(全局 静态)函数会生成符号
4.源码转成汇编指令

汇编:gcc -c main.s -----> main.o
1.汇编指令翻译成二进制
2.生成各个section(段)
3.生成符号表
生成可重定位的二进制目标文件

编译阶段每个源文件都是单独编译的

链接:gcc 所有生成的中间文件 -o 自己命名的文件
所有的.o文件
静态库文件.a
1.合并所有文件的各个section(段),调整段大小的及段起始位置,合并符号表进行符号解析,并给符号分配一个虚拟地址。
2.符号重定位,在使用符号的地方,全部替换成符号的虚拟地址
最终生成a.out,ELF格式的可执行文件

C语言的强弱符号,一强一弱用强,两个弱随便用一个,两个强报错(初始化的叫强符号,未初始化为弱符号)

可一步完成gcc hello.c -o hello

链接时指挥解析GLOBAL符号,不解析LOCAL符号(静态static),静态方法或者静态数据只能在本文件中使用

ELF文件格式 —> 中间文件
objdump hello.o举例
在这里插入图片描述
text 指令段
data 数据段 初始化不为零的 全局 静态
bss 未初始化或者初始化为零的数据 —>节省磁盘空间
rodata (字符常量区)只读数据此文件中就是字符串“hello world”

readelf -h hello.o
文件描述

进程的虚拟地址空间如何划分
每一个进程的虚拟地址空间都是4G 所有进程共享1G内核空间

在这里插入图片描述 从下往上,128M不可访问区,指令段,数据段(bss节省磁盘空间但不节省内存空间),堆区,动态链接库区域,栈区