1代码
点击查看代码1:编译**sum.cpp**int gdata=https://www.huyubaike.com/biancheng/10;int sum(int a,int b){return a+b;}**main.cpp**extern int gdata;int sum(int , int );int data=20;int main(){int a =gdata;int b=data;int ret=sum(a,b);return 0;}
文章插图
文章插图
需要关注的几个点1: .o 文件的格式组成是什么样子?2: .exe 文件的组成格式是什么样子?3: "所有.o文件段的合并 符号表合并后,进行符号解析"4: "符号的重定位(重定向)"5: "符号表的输出"=> "符号"6: 符号什么时候分配虚拟地址?
预编译以#开头的命令
除#pragma lib-> 链接阶段处理除#pragma link-> 链接阶段处理
编译语法分析,语义分析,代码优化 gccg++
编译后生成相应平台的 汇编代码X86 和 AT&T
链接链接所有 .o文件和 静态库文件
文章插图
文章插图
文章插图
文章插图
.o 文件 主要是由以下组成elf 文件头.text.data.bss.symbal.section table....
符号表中,在自己文件中定义的,那就是符号定义,如果是引用外部的就 是 "UND"符号引用符号表中的符号 都没有分配地址,如下图,所以编译过程中,符号是不分配虚拟地址的,是在链接的时候分配
文章插图
文章插图
经过了上面的 预编译-》编译-》汇编 各个阶段后 下面开始进入了 链接阶段
main.o 文件sum.o 文件上面我们看到 .o 文件是由各个段组成的,所以进入链接阶段的时候第一步 将各个.o 文件 的各个段合并
main.o 文件的 .text段与sum.o 文件的 .text 段合并main.o 文件的 .data段与sum.o 文件的 .data 段合并main.o 文件的 .bss段与sum.o 文件的 .bss段合并main.o 文件的符号表与sum.o文件的符号表 段合并
第二步 非常重要的一点是 在main.o文件的符号表与sum.o文件的符号表段合并的时候,需要进行符号解析 。什么是"符号解析"?所有对符号的引用,都要找到该符号定义的地方“符号的引用” 即符号为 UND形式, 要找到该符号定义的地方即要找到该符号是在.text 段中定义还是在.data段中定义,例如:链接器发现main.o文件的sum函数和gdata是UND形式的,那么链接器会去其他文件中找到sum和gdata的定义,如果没找到,那么链接器报错"符号未定义",如果链接器找到了多个,那么链接器也会报错 “符号重定义” , 所以在整个工程中,全局的名字是不能重名的,否则会产生冲突.
符号解析成功以后 就开始回给所有的符号分配地址
第三步 "符号重定向"在符号解析成功以后并且给所有的符号分配地址后,需要继续做 "符号重定向"在我们指令编译汇编生成.O文件的时候,生成的指令中的符号的地址都是用0 代理,如下图
文章插图
现在我们需要将给符号分配好的地址 将指令中的这些0地址重新修正
现在我看下链接后的情况符号表情况
文章插图
指令情况
文章插图
所以现在我们知道 “符号是在什么时候分配地址”, 在链接第一阶段 符号解析成功后
【<三>从编译器角度理解C++代码编译和链接原理】
文章插图
可执行文件 a.out和 .O文件的组成方式很像,但是还是有一点区别
文章插图
在a.out 可执行文件中 增加了 “program headers” , a.out 文件中不是 所有的内容都会加载到内存中的,这个"program headers"中指定了需要加载哪些到内存中
推荐阅读
- <一>关于进程虚拟地址空间区域内存划分和布局
- 三星S21和三星S21Ultra哪个好?三星S21和三星S21Ultra对比
- 简析 Linux 的 CPU 时间
- Bug改不完,迭代总延期,咋办?
- 三国杀玩法及卡牌介绍(三国杀108张牌明细)
- 六人国战怎么玩三国杀(三国杀国战版本怎么玩)
- 从源码分析 MGR 的新主选举算法
- 不准备再来三亚的可以省略 三亚免税店什么最值得买? 优惠部分— 提前办好会员卡见图三
- 2000-3000左右性价比最高的手机2022-两三千手机推荐
- 小米11pro、三星s21+、苹果12和三星note20ultra哪个好-购机建议