c,c++编译过程
【摘要】 c,c++编译过程
#预处理,编译,汇编,链接
- 预处理
gcc -E hello.cpp -o hello.i
- 处理#include ,宏定义
- 编译
gcc -S hello.i -o hello.s
- 实际调用ccl
- 生成汇编代码
- 汇编
gcc -c hello.s -o hello.o
- 生成机器指令
- 链接
ld
- 静态链接
- 地址和空间分配,符号决议,重定位
- 动态链接
- 静态链接
#目标文件格式
- 目标文件分类
- 可重定位文件 .o文件
- 可执行文件
- 共享目标文件 .so文件
- 核心转储文件 coredump文件
- 目标文件分段
- text段(程序指令)
- .data段(已经初始化值的全局变量和局部静态变量)
- .bss段(未初始化的全局变量和局部静态变量),没有内容,不占空间,因为这些值默认都是0
- 文件格式查看
gcc -c hello.cpp
生成hello.oobjdump -h hello.o
查看各个段的大小,起始位置objdump -d -s hello.o
查看汇编代码readelf -h hello.o
查看文件的基本信息readelf -S hello.o
查看文件的具体段的分布readelf -s hello.o
查看文件的变量函数
- 强符号和弱符号
- 初始化了的全局变量是强符号
- 弱符号的使,通过 __attribute__((weak))指定此引用为弱引用,如果外部没有定义,可以链接出错,但是引用为空,如果外部有定义,正常运行,引用不为空,自己代码可以声明一个外部库的弱引用,如果为空,说明运行时没有外部库,可以执行自己另外的逻辑,达到一定的动态化
#静态链接过程
- 将每个.o文件的相同的段放在一起并合并,并根据每个文件的符号定义和引用,建立一个全局符号表
- 对每个.o文件,
- 根据自己在合并之后的位置,更新自己的地址为原地址加现在在合并文件中的起始地址
- 读取文件的重定位表中的每一项
objdump -r a.o
,在全局符号表中查找,并进行重定位
#动态链接过程
- 对于可共享的so文件,按照不同的段区分,数据段是每个个进程各自拥有一份,程序指令段需要编译此so的时候就编译为地址无关代码,
- so编译的具体过程是:凡是调用了本so外部的变量函数,都通过一个GOT表指针间接访问,而GOT表是此时未初始化的,而且GOT是放在数据段的
- Program装载这个so的时候,每个进程拥有自己的数据段和GOT,然后根据此时so的内存位置,填写GOT,此时Program调用的so的指令部分是多个进程共享的.但是指令访问数据函数的时候,会拿各自进程自己的GOT表,所以对数据的操作是各个进程独立的。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)